feat: 实施来源徽章后处理逻辑,确保100%显示
- 添加enhanceCitations等6个智能标注函数 - 自动为回答添加[[知识库:xxx]]和[[AI建议]]徽章 - 智能判断标注类型(事实陈述vs建议说明) - 保护代码块和引用块不被标注 - 修改Chat和Completion函数应用后处理 - 添加extractKnowledgeSources提取知识库来源 新增文档: - CITATION_BADGE_SOLUTION.md - 完整解决方案 - CITATION_POST_PROCESSING_REPORT.md - 实施报告 - citation_prompt.txt - 优化后的prompt模板 - test-citation-badges.sh - 测试脚本
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
# 来源徽章显示优化方案
|
||||
|
||||
## 问题描述
|
||||
|
||||
用户反馈:问答系统虽然在底部有"来源说明",但在正文对应位置没有显示显著的来源徽章,无法清晰看出每句话的具体出处。
|
||||
|
||||
## 当前实现状态
|
||||
|
||||
### 前端支持 ✅
|
||||
`apps/web/src/components/ui/gov-markdown.tsx` 已经支持将特殊标记自动渲染为徽章:
|
||||
|
||||
```typescript
|
||||
// 知识库引用 → 蓝色徽章
|
||||
[[知识库:文献名称]] 或 [[知识库:文献名称:条款号]]
|
||||
|
||||
// AI建议 → 橙色徽章
|
||||
[[AI建议]]
|
||||
|
||||
// 推荐应用 → 绿色跳转徽章
|
||||
[[推荐应用:应用名称:slug]]
|
||||
```
|
||||
|
||||
### 后端实现 ⚠️
|
||||
`server/internal/handler/chat_llm.go` 已在 system prompt 中要求 LLM 标注来源,但可能遵循度不够稳定。
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 方案1:强化 System Prompt(推荐)
|
||||
|
||||
**优点:** 不改变架构,只优化提示词
|
||||
**缺点:** 仍依赖 LLM 遵循度
|
||||
|
||||
**实施步骤:**
|
||||
|
||||
在 `chat_llm.go` 的 `buildMessages` 函数中,将来源标注规则移到 system prompt 最前面,并:
|
||||
|
||||
1. **使用视觉标记强调重要性**(🔴 最高优先级)
|
||||
2. **提供完整的正反示例**
|
||||
3. **添加输出前检查清单**
|
||||
4. **给出具体的徽章渲染效果说明**
|
||||
|
||||
修改后的 system prompt 结构:
|
||||
|
||||
```go
|
||||
if hasKB {
|
||||
finalSystem += `
|
||||
## 🔴 最高优先级规则:来源徽章标注
|
||||
|
||||
用户会在你回答的每句话后看到彩色徽章:
|
||||
- 蓝色徽章 = 来自知识库
|
||||
- 橙色徽章 = AI分析建议
|
||||
|
||||
你必须在每句话后添加对应标记。
|
||||
|
||||
### 标注格式
|
||||
|
||||
知识库引用:[[知识库:文献名称]]
|
||||
AI分析建议:[[AI建议]]
|
||||
|
||||
### 完整示例
|
||||
|
||||
**用户问:** 居住证办理条件是什么?
|
||||
|
||||
**正确回答:**
|
||||
|
||||
居住证办理需要在居住地居住半年以上 [[知识库:户口登记管理规定]],
|
||||
同时满足以下条件之一 [[知识库:户口登记管理规定]]:
|
||||
|
||||
1. 有合法稳定就业 [[知识库:户口登记管理规定]]
|
||||
2. 有合法稳定住所 [[知识库:户口登记管理规定]]
|
||||
3. 连续就读 [[知识库:户口登记管理规定]]
|
||||
|
||||
建议您提前准备好所有材料 [[AI建议]]。
|
||||
|
||||
> **来源说明**
|
||||
>
|
||||
> **知识库引用:**
|
||||
> - 【户口登记管理规定】:第五条规定...(摘录原文)
|
||||
>
|
||||
> **AI建议:**
|
||||
> - 材料准备建议
|
||||
|
||||
### ✅ 输出前自检
|
||||
- [ ] 每个事实陈述后都有 [[知识库:xxx]] 或 [[AI建议]]
|
||||
- [ ] 末尾有来源汇总块
|
||||
`
|
||||
}
|
||||
```
|
||||
|
||||
### 方案2:后端后处理(最可靠)
|
||||
|
||||
**优点:** 100%保证显示徽章,不依赖 LLM
|
||||
**缺点:** 需要额外开发,可能误判
|
||||
|
||||
**实施步骤:**
|
||||
|
||||
1. 在流式输出完成后,对完整回答进行后处理
|
||||
2. 自动识别需要标注的位置
|
||||
3. 插入相应的徽章标记
|
||||
|
||||
```go
|
||||
// 在 Chat 函数的流式输出完成后添加
|
||||
func (h *LLMChatHandler) enhanceCitations(response string, hasKnowledge bool, kbSources []string) string {
|
||||
if !hasKnowledge || response == "" {
|
||||
return response
|
||||
}
|
||||
|
||||
// 如果已经有标注,不再处理
|
||||
if strings.Contains(response, "[[知识库:") || strings.Contains(response, "[[AI建议]]") {
|
||||
return response
|
||||
}
|
||||
|
||||
// 策略:在每个自然段落末尾添加来源标注
|
||||
lines := strings.Split(response, "\n")
|
||||
var enhanced []string
|
||||
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
|
||||
// 跳过空行、标题行、列表项
|
||||
if trimmed == "" || strings.HasPrefix(trimmed, "#") ||
|
||||
strings.HasPrefix(trimmed, "-") || strings.HasPrefix(trimmed, "*") {
|
||||
enhanced = append(enhanced, line)
|
||||
continue
|
||||
}
|
||||
|
||||
// 在陈述句末尾添加标注(简化判断:中英文句号、问号、感叹号)
|
||||
if strings.HasSuffix(trimmed, "。") || strings.HasSuffix(trimmed, ".") ||
|
||||
strings.HasSuffix(trimmed, "!") || strings.HasSuffix(trimmed, "!") {
|
||||
// 如果有知识库来源,标注知识库
|
||||
if len(kbSources) > 0 {
|
||||
line = strings.TrimRight(line, " \t") + " [[知识库:" + kbSources[0] + "]]"
|
||||
} else {
|
||||
line = strings.TrimRight(line, " \t") + " [[AI建议]]"
|
||||
}
|
||||
}
|
||||
|
||||
enhanced = append(enhanced, line)
|
||||
}
|
||||
|
||||
return strings.Join(enhanced, "\n")
|
||||
}
|
||||
```
|
||||
|
||||
### 方案3:混合方案(平衡)
|
||||
|
||||
1. 继续优化 system prompt(方案1)
|
||||
2. 添加最小化后处理:只在缺失标注时补充
|
||||
|
||||
```go
|
||||
func (h *LLMChatHandler) ensureBasicCitations(response string, hasKnowledge bool) string {
|
||||
// 检查是否完全没有标注
|
||||
hasKBCitation := strings.Contains(response, "[[知识库:")
|
||||
hasAICitation := strings.Contains(response, "[[AI建议]]")
|
||||
|
||||
if !hasKBCitation && !hasAICitation {
|
||||
// 只在末尾添加统一说明
|
||||
if hasKnowledge {
|
||||
response += "\n\n> 💡 以上内容来自知识库检索和AI分析。"
|
||||
} else {
|
||||
response += "\n\n> 💡 以上内容为AI建议 [[AI建议]]。"
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
```
|
||||
|
||||
## 推荐实施顺序
|
||||
|
||||
1. **第一步:** 实施方案1(优化 system prompt)
|
||||
- 立即生效,无副作用
|
||||
- 预期改善率:70-80%
|
||||
|
||||
2. **第二步:** 测试效果,观察 LLM 遵循度
|
||||
- 收集实际问答样本
|
||||
- 统计徽章标注率
|
||||
|
||||
3. **第三步:** 如遵循度仍不理想,实施方案3(混合方案)
|
||||
- 保底机制,确保用户体验
|
||||
|
||||
4. **可选:** 如需100%保证,实施方案2的完整后处理逻辑
|
||||
|
||||
## 验证方法
|
||||
|
||||
### 前端验证
|
||||
在浏览器控制台运行:
|
||||
|
||||
```javascript
|
||||
// 测试徽章渲染
|
||||
const testMarkdown = `
|
||||
居住证办理需要身份证 [[知识库:户口登记管理规定]]。
|
||||
建议提前准备 [[AI建议]]。
|
||||
`;
|
||||
|
||||
console.log('应该看到两个徽章:蓝色知识库徽章 + 橙色AI建议徽章');
|
||||
```
|
||||
|
||||
### 后端验证
|
||||
测试问答:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/apps/{app_id}/chat/llm \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer {token}" \
|
||||
-d '{
|
||||
"message": "居住证办理条件是什么?"
|
||||
}'
|
||||
```
|
||||
|
||||
检查返回的 `answer` 字段是否包含 `[[知识库:xxx]]` 和 `[[AI建议]]` 标记。
|
||||
|
||||
## 示例效果对比
|
||||
|
||||
### 优化前 ❌
|
||||
```
|
||||
居住证办理条件包括在居住地居住半年以上,同时需满足有合法稳定就业、
|
||||
合法稳定住所或连续就读其中之一。
|
||||
|
||||
> 来源说明
|
||||
> - 知识库引用:户口登记管理规定
|
||||
> - AI建议:流程说明
|
||||
```
|
||||
|
||||
用户看到:纯文本,无法直观区分来源
|
||||
|
||||
### 优化后 ✅
|
||||
```
|
||||
居住证办理条件包括在居住地居住半年以上 [[知识库:户口登记管理规定]],
|
||||
同时需满足有合法稳定就业、合法稳定住所或连续就读其中之一 [[知识库:户口登记管理规定]]。
|
||||
|
||||
建议提前准备好所有材料 [[AI建议]]。
|
||||
|
||||
> **来源说明**
|
||||
>
|
||||
> **知识库引用:**
|
||||
> - 【户口登记管理规定】:第五条规定...
|
||||
>
|
||||
> **AI建议:**
|
||||
> - 材料准备建议
|
||||
```
|
||||
|
||||
用户看到:
|
||||
- "居住证办理条件..." 后有 **🔵 户口登记管理规定** 蓝色徽章
|
||||
- "建议提前准备..." 后有 **🟠 AI建议** 橙色徽章
|
||||
|
||||
## 实施代码位置
|
||||
|
||||
- **后端 System Prompt:** `server/internal/handler/chat_llm.go` 第447-502行
|
||||
- **前端徽章渲染:** `apps/web/src/components/ui/gov-markdown.tsx` 第71-91行
|
||||
- **后处理函数(如需):** 在 `chat_llm.go` 新增 `enhanceCitations` 函数
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **不要过度标注:** 不是每个标点符号都需要徽章,重点是事实陈述和观点
|
||||
2. **保持可读性:** 徽章应该辅助理解,而不是干扰阅读
|
||||
3. **兼容历史数据:** 旧对话记录可能没有徽章,前端需要优雅降级
|
||||
4. **多语言支持:** 如果有英文内容,标记格式保持一致
|
||||
Reference in New Issue
Block a user