75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
import { z } from "zod";
|
||
import type { ProviderApiKeys } from "./keys";
|
||
import { generateStructuredObject } from "./generate-structured";
|
||
import { getModel } from "./provider";
|
||
import { HASHTAG_WRITING_RULES } from "./hashtag-rules";
|
||
import { buildSystemPrompt } from "./prompts";
|
||
import { THREADS_MAX_CHARS } from "@/lib/utils";
|
||
|
||
export type OptimizeMode = "polish" | "hook" | "shorter" | "engaging" | "custom";
|
||
|
||
const MODE_INSTRUCTIONS: Record<Exclude<OptimizeMode, "custom">, string> = {
|
||
polish: "整體潤飾:改善語氣流暢度、可讀性與說服力,保留核心觀點。",
|
||
hook: "強化開頭 hook:讓前 1–2 句更有吸引力,讓人想停下來看。",
|
||
shorter: "精簡篇幅:刪除贅字,保留重點,盡量壓到更短但不失完整。",
|
||
engaging: "提升互動感:加入引發留言的問句、觀點或行動呼籲,但不過度推銷。",
|
||
};
|
||
|
||
const optimizeSchema = z.object({
|
||
text: z.string().max(THREADS_MAX_CHARS),
|
||
summary: z.string(),
|
||
});
|
||
|
||
export interface OptimizeInput {
|
||
text: string;
|
||
mode?: OptimizeMode;
|
||
instruction?: string | null;
|
||
persona?: string | null;
|
||
angle?: string | null;
|
||
aiProvider: string;
|
||
aiModel: string;
|
||
apiKeys?: ProviderApiKeys;
|
||
}
|
||
|
||
export async function optimizePost(input: OptimizeInput) {
|
||
const mode = input.mode ?? "polish";
|
||
const modeInstruction =
|
||
mode === "custom"
|
||
? input.instruction?.trim() || "依照使用者指示優化貼文。"
|
||
: MODE_INSTRUCTIONS[mode];
|
||
|
||
const model = getModel(input.aiProvider, input.aiModel, input.apiKeys ?? {});
|
||
|
||
const object = await generateStructuredObject({
|
||
model,
|
||
provider: input.aiProvider,
|
||
modelId: input.aiModel,
|
||
schema: optimizeSchema,
|
||
system: `${buildSystemPrompt(input.persona)}
|
||
|
||
你現在的任務是「優化既有 Threads 貼文草稿」,不是從零重寫。
|
||
- 保留原文核心觀點與事實,不要捏造
|
||
- 優化後必須更符合上方人設,尤其語氣與代表句範例的語感
|
||
- 保留或補上結尾的 1~3 個 #話題標籤,不要優化掉
|
||
${HASHTAG_WRITING_RULES}
|
||
- 輸出繁體中文台灣用語
|
||
- 字數必須 ≤ ${THREADS_MAX_CHARS}
|
||
- summary 用 1–2 句話說明你做了什麼調整`,
|
||
prompt: `請優化以下 Threads 貼文草稿。
|
||
|
||
優化方向:${modeInstruction}
|
||
${input.angle ? `切入角度:${input.angle}` : ""}
|
||
|
||
原文:
|
||
"""
|
||
${input.text}
|
||
"""
|
||
|
||
請輸出優化後的貼文(text)與調整說明(summary)。`,
|
||
});
|
||
|
||
return {
|
||
text: object.text.slice(0, THREADS_MAX_CHARS),
|
||
summary: object.summary,
|
||
};
|
||
} |