107 lines
3.0 KiB
TypeScript
107 lines
3.0 KiB
TypeScript
import type { CallableQAItem } from "./types";
|
|
|
|
export type ChatRole = "assistant" | "user";
|
|
|
|
export type ChatMessage = {
|
|
id: string;
|
|
role: ChatRole;
|
|
content: string;
|
|
source?: string;
|
|
boundary?: string;
|
|
feedback?: "liked" | "disliked";
|
|
createdAt: string;
|
|
};
|
|
|
|
export type ChatSession = {
|
|
id: string;
|
|
title: string;
|
|
preview: string;
|
|
messages: ChatMessage[];
|
|
updatedAt: string;
|
|
questionCount: number;
|
|
};
|
|
|
|
export type SuggestedQuestion = {
|
|
id: string;
|
|
text: string;
|
|
tags: string[];
|
|
};
|
|
|
|
export const suggestedQuestions: SuggestedQuestion[] = [
|
|
{
|
|
id: "parent-child-emotion",
|
|
text: "孩子一写作业就发脾气,我怎么接住他的情绪?",
|
|
tags: ["亲子关系", "情绪"]
|
|
},
|
|
{
|
|
id: "self-growth",
|
|
text: "我知道要行动,但总是拖延,应该先从哪里开始?",
|
|
tags: ["个人成长", "行动力"]
|
|
},
|
|
{
|
|
id: "marriage-talk",
|
|
text: "伴侣不愿意沟通,我怎么表达才不容易吵起来?",
|
|
tags: ["婚姻关系", "沟通"]
|
|
}
|
|
];
|
|
|
|
export const initialMessages: ChatMessage[] = [
|
|
{
|
|
id: "welcome",
|
|
role: "assistant",
|
|
content:
|
|
"你好,我是千问千答助手。你可以把最近遇到的亲子、关系、情绪或行动问题发给我,我会优先基于已审核的答疑资产给你一个可落地的回应。",
|
|
boundary: "当前为 H5 体验版,登录暂用 mock 占位;问答答案只读取后端可调用库。",
|
|
createdAt: "09:30"
|
|
}
|
|
];
|
|
|
|
export function createEmptySession(): ChatSession {
|
|
return {
|
|
id: `session-${Date.now()}`,
|
|
title: "新的问答",
|
|
preview: "还没有开始提问",
|
|
messages: initialMessages,
|
|
updatedAt: new Date().toISOString(),
|
|
questionCount: 0
|
|
};
|
|
}
|
|
|
|
export function summarizeSession(sessionId: string, messages: ChatMessage[]): ChatSession {
|
|
const userMessages = messages.filter((message) => message.role === "user");
|
|
const lastMessage = [...messages].reverse().find((message) => message.role === "assistant" || message.role === "user");
|
|
const firstQuestion = userMessages[0]?.content;
|
|
|
|
return {
|
|
id: sessionId,
|
|
title: firstQuestion ? firstQuestion.slice(0, 24) : "新的问答",
|
|
preview: lastMessage?.content.slice(0, 42) ?? "还没有开始提问",
|
|
messages,
|
|
updatedAt: new Date().toISOString(),
|
|
questionCount: userMessages.length
|
|
};
|
|
}
|
|
|
|
function scoreQuestion(question: string, qa: CallableQAItem): number {
|
|
const haystack = [
|
|
qa.standard_question,
|
|
qa.standard_answer,
|
|
qa.primary_topic,
|
|
qa.course_stage,
|
|
...qa.problem_tags,
|
|
...qa.similar_questions
|
|
].join(" ");
|
|
return Array.from(new Set(question.trim().split(""))).reduce((score, char) => {
|
|
if (!char.trim()) return score;
|
|
return haystack.includes(char) ? score + 1 : score;
|
|
}, 0);
|
|
}
|
|
|
|
export function findQaAnswer(question: string, qaItems: CallableQAItem[]) {
|
|
if (qaItems.length === 0) {
|
|
return null;
|
|
}
|
|
const [best] = [...qaItems].sort((left, right) => scoreQuestion(question, right) - scoreQuestion(question, left));
|
|
return best ?? null;
|
|
}
|