fix(consultation): decouple reply metadata from prompt

This commit is contained in:
Jesse_Chen
2026-08-14 18:01:30 +08:00
parent 0e0268f611
commit 09f811a79e
6 changed files with 88 additions and 13 deletions
+5 -3
View File
@@ -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]],
});
}