fix(consultation): decouple reply metadata from prompt
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
export type ReplyTheme = "career" | "marriage" | "wealth" | "timing" | "general";
|
||||
|
||||
import type { ConsultationReplyMetadata } from "./consultation-reply-metadata.ts";
|
||||
|
||||
const fallbackSuggestions: Record<ReplyTheme, readonly [string, string, string]> = {
|
||||
career: ["我更适合怎样的职业路径?", "未来一年事业上要避开什么?", "我该如何发挥自己的优势?"],
|
||||
marriage: ["我在关系里容易重复什么模式?", "怎样的伴侣更适合我?", "未来一年关系上要注意什么?"],
|
||||
@@ -46,12 +48,12 @@ function stripAgentReplyMetadata(value: string) {
|
||||
return { text, suggestions, title };
|
||||
}
|
||||
|
||||
export function parseAgentReply(value: string, theme: ReplyTheme) {
|
||||
export function parseAgentReply(value: string, theme: ReplyTheme, metadata?: ConsultationReplyMetadata) {
|
||||
const parsed = stripAgentReplyMetadata(value);
|
||||
return {
|
||||
text: parsed.text,
|
||||
suggestions: parsed.suggestions.length === 3 ? parsed.suggestions : [...fallbackSuggestions[theme]],
|
||||
title: parsed.title,
|
||||
suggestions: metadata?.suggestions ?? (parsed.suggestions.length === 3 ? parsed.suggestions : [...fallbackSuggestions[theme]]),
|
||||
title: metadata?.title ?? parsed.title,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { z } from "zod";
|
||||
import type { ReplyTheme } from "./agent-reply.ts";
|
||||
|
||||
export const consultationReplyMetadataSchema = z.object({
|
||||
title: z.string().trim().min(1).max(64),
|
||||
suggestions: z.tuple([
|
||||
z.string().trim().min(1).max(80),
|
||||
z.string().trim().min(1).max(80),
|
||||
z.string().trim().min(1).max(80),
|
||||
]),
|
||||
}).strict();
|
||||
|
||||
export type ConsultationReplyMetadata = z.infer<typeof consultationReplyMetadataSchema>;
|
||||
|
||||
const fallbackSuggestions: Record<ReplyTheme, readonly [string, string, string]> = {
|
||||
career: ["我更适合怎样的职业路径?", "未来一年事业上要避开什么?", "我该如何发挥自己的优势?"],
|
||||
marriage: ["我在关系里容易重复什么模式?", "怎样的伴侣更适合我?", "未来一年关系上要注意什么?"],
|
||||
wealth: ["我的财富增长方式是什么?", "接下来财务上要避开什么?", "我该如何稳定提升收入?"],
|
||||
timing: ["接下来最值得把握的阶段是什么?", "哪些时期更适合主动行动?", "我现在应该优先准备什么?"],
|
||||
general: ["未来一年,事业和收入该关注什么?", "我的关系模式是什么?", "未来哪些阶段值得把握?"],
|
||||
};
|
||||
|
||||
function safeQuestionTitle(question: string) {
|
||||
const normalized = question
|
||||
.replace(/\s+/g, " ")
|
||||
.trim()
|
||||
.replace(/[??!!。.,,;;::]+$/u, "")
|
||||
.replace(/[\p{P}\p{S}]/gu, "")
|
||||
.trim();
|
||||
if (!normalized) return "一般占星咨询";
|
||||
const characters = Array.from(normalized);
|
||||
if (characters.length >= 6) return characters.slice(0, 14).join("");
|
||||
return `${characters.join("")}主题咨询`.slice(0, 14);
|
||||
}
|
||||
|
||||
export function createConsultationReplyMetadata(input: { theme: ReplyTheme; question: string }): ConsultationReplyMetadata {
|
||||
return consultationReplyMetadataSchema.parse({
|
||||
title: safeQuestionTitle(input.question),
|
||||
suggestions: [...fallbackSuggestions[input.theme]],
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user