该功能于4.12实现
一、功能目标:
1.用户能连接大模型进行问答,且对话可自动生成标题
2.用户要能够专门依据此页典籍进行大模型问答,同时也可以实现对鼠标选中语段进行问答,
3.该对话功能还要能实现新建对话,查询往期对话,自动生成对话标题,
4.实现若用户对大模型回答不满意可以重新生成,可以让用户选择哪个对他来说回答更好。
本次主要实现了1.2两个功能
二、功能后端实现
1.架构设计全景图
graph LR
A[HTTP请求] --> B[API网关]
B --> C{路由分发}
C -->|典籍问答| D[ClassicController]
C -->|智能对话| E[QaController]
D --> F[ClassicService]
E --> G[QaService]
G --> H[AIService]
F --> I[ClassicRepository]
G --> J[QaSessionRepository]
G --> K[QaMessageRepository]
2.核心功能实现详解
a.智能会话初始化与标题生成
// QaService.java 核心代码片段
public QaSession createNewSession(Long classicId) {
// 1. 获取典籍上下文
Classic classic = classicRepository.findById(classicId)
.orElseThrow(() -> new ResourceNotFoundException("典籍不存在"));
// 2. 构建初始会话
QaSession session = new QaSession();
session.setClassic(classic);
session.setCreatedAt(Instant.now());
// 3. 动态提示词生成
String prompt = String.format(
"你正在研究《%s》,请生成一个体现核心讨论方向的对话标题,要求:\n" +
"- 不超过15个汉字\n" +
"- 包含典籍关键词\n" +
"- 体现问答特征",
classic.getTitle()
);
// 4. AI服务调用
String rawTitle = aiService.getAIResponse(prompt);
session.setTitle(titleSanitizer.sanitize(rawTitle));
return sessionRepository.save(session);
}
b.典籍上下文问答实现
// 处理两种提问方式的核心逻辑
public QaMessage processQuestion(QaRequest request) {
// 1. 获取基础上下文
QaSession session = sessionRepository.findById(request.sessionId())
.orElseThrow(() -> new SessionNotFoundException("会话不存在"));
// 2. 构建差异化提示词
String contextPrompt = buildContextPrompt(session.getClassic(), request);
// 3. 调用AI服务
String aiResponse = aiService.getAIResponse(contextPrompt);
// 4. 持久化消息
return saveMessageWithContext(session, request, aiResponse);
}private String buildContextPrompt(Classic classic, QaRequest request) {
StringBuilder prompt = new StringBuilder();
// 基础上下文
prompt.append("你正在研究典籍《").append(classic.getTitle()).append("》\n");
prompt.append("典籍基本信息:\n");
prompt.append("- 作者:").append(classic.getAuthor()).append("\n");
prompt.append("- 朝代:").append(classic.getDynasty()).append("\n");
// 处理选中文本
if (request.hasSelection()) {
prompt.append("用户选中的原文段落:\n「").append(request.getSelectedText()).append("」\n");
prompt.append("请结合全文和选段回答以下问题:\n");
} else {
prompt.append("以下是需要回答的问题(请基于典籍完整内容作答):\n");
}
prompt.append("问题:").append(request.getQuestion());
// 追加历史对话上下文
if (request.hasHistory()) {
prompt.append("\n\n历史对话摘要:\n");
prompt.append(historySummarizer.summarize(request.getHistory()));
}
return prompt.toString();
}