Browse Source
refactor(prompt): 提示词改为数据库在线维护,RAG 保真护栏迁出 yml
refactor(prompt): 提示词改为数据库在线维护,RAG 保真护栏迁出 yml
问题:RAG 回答规则有两份重复来源 —— application.yml 的 knowledge.rag.answer-rules 与 RagPromptConfig 的 Java 默认值(逐字重复),改一处等于没改;且改提示词必须动 yml 并重启,与项目「system_config 在线维护、改完即生效」的取向不一致。同时 RagPromptConfig 类注释与 application.yml 里都还写着"注入 ContextualQueryAugmenter 模板",而该组件早已随 RagPipeline 重构移除、全仓已无引用。 - 新增 system_config.ai_rag_answer_rules 键(仅 RAG 分支注入,紧贴【知识库资料】之前), 删除 RagPromptConfig 类与 yml 的 answer-rules 段;保留同节的 knowledge.rag.multiquery.parallel(由 RagPipeline 的 @Value 直绑读取,不依赖任何 @ConfigurationProperties 类,删类无影响) - 取数改为一次批量查询:SystemConfigService 新增 getValues(Collection), ChatPipeline 每请求取 ai_system_prompt + ai_rag_answer_rules 两个键。该方法无缓存, 批量是为了避免 hot path 上多次直查 DB;刻意不引入缓存,以保住"后台改完下一请求即 生效"的语义。规则文本作为形参传给 RagPipeline.buildRagContextBlock(contextText, answerRules),注入位置与生效范围完全不变 - 兜底:ai_rag_answer_rules 被清空时用 RagPipeline.FALLBACK_RAG_ANSWER_RULES (一句极简安全底线,非默认值) - 种子:两个键的初始值写入 DatabaseInitConfig.syncDefaultSystemConfigs 与 init-database.sql,两处逐字一致(脚本比对 8 行 / 4 行通过),均为 ON CONFLICT (config_key) DO NOTHING → 后台在线编辑永不会被重启覆盖,只对"该键不存在" 的新环境生效 - 前端 SystemConfigManager 登记 ai_rag_answer_rules 为 text 型(未登记会被 resolveType 按默认 html 渲染出多余预览框),文本域行高 8/16 → 10/24 - 安全:GET /ai/system-config/{key}(SDK 通用取值口,原意供 SDK 拉 disclaimer)对 ai_system_prompt / ai_rag_answer_rules 返回 403 —— 提示词属商业秘密(见 CLAUDE.md 的 LLM 追踪安全声明),不应经第三方持 Token 即可调的接口读取 - 注释清理:删掉关于 ContextualQueryAugmenter 的过期表述,精简 RagPipeline javadoc 中 对已删除的 qaTemplate / buildRagSystemPrompt 的历史提及(HybridSearch 尚未接入主流程 那条属实,保留) - 文档:CLAUDE.md / AGENTS.md 增加「提示词在线维护(三层分工)」一节、管道图标注提示词 来源,并写明两个键的种子与兜底关系 为什么不把 RAG 规则直接合并进 ai_system_prompt:全局键在所有路径生效,而纯对话/闲聊 路径没有【知识库资料】块,保真护栏("只能依据资料回答""资料不足时…")会指向不存在的 块,把问候语答成"未查到资料";CHITCHAT 通道存在的意义正是自由作答。 验证:mvn clean package -P prod 通过(含前端构建);删除 RagPromptConfig 后全仓 grep 无残留引用;种子两处文本逐字比对通过;应用启动后日志可见新键种子写入。 提示词文案本身的迭代(v4.2)已在管理后台在线完成并实测验证,不在本提交内。 (static/sdk/test.html 仅两条 link 顺序变化,hash 未变,属构建产物顺序抖动)dev
12 changed files with 174 additions and 56 deletions
-
18AGENTS.md
-
18CLAUDE.md
-
5frontend/src/views/SystemConfigManager.vue
-
16src/main/java/com/wok/supportbot/app/ChatPipeline.java
-
35src/main/java/com/wok/supportbot/config/DatabaseInitConfig.java
-
29src/main/java/com/wok/supportbot/config/RagPromptConfig.java
-
19src/main/java/com/wok/supportbot/controller/AiController.java
-
29src/main/java/com/wok/supportbot/rag/RagPipeline.java
-
25src/main/java/com/wok/supportbot/service/SystemConfigService.java
-
11src/main/resources/application.yml
-
23src/main/resources/init-database.sql
-
2src/main/resources/static/sdk/test.html
@ -1,29 +0,0 @@ |
|||||
package com.wok.supportbot.config; |
|
||||
|
|
||||
import lombok.Data; |
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
/** |
|
||||
* RAG 提示词配置 |
|
||||
* 通过 application.yml 的 knowledge.rag.answer-rules 动态调整 RAG 回答规则(保真护栏),无需改代码重新编译。 |
|
||||
*/ |
|
||||
@Component |
|
||||
@ConfigurationProperties(prefix = "knowledge.rag") |
|
||||
@EnableConfigurationProperties(RagPromptConfig.class) |
|
||||
@Data |
|
||||
public class RagPromptConfig { |
|
||||
|
|
||||
/** |
|
||||
* RAG 回答规则(保真护栏),注入 system 提示词与 ContextualQueryAugmenter 自定义模板。 |
|
||||
* 默认值在「忠于资料、不编造」基础上,强调覆盖全部相关要点、不遗漏步骤。 |
|
||||
* yml 未配置时使用此默认值;yml 配置后覆盖。 |
|
||||
*/ |
|
||||
private String answerRules = """ |
|
||||
- 完整性优先:必须覆盖下方【知识库资料】中所有与用户问题相关的要点,按资料本身的条理分点结构化输出;不得只摘取其中一两段或几条而遗漏其余相关的步骤、条件、注意事项、话术示例。多段资料从不同角度回答同一问题时,需综合全部相关内容作答。 |
|
||||
- 忠于资料:只能依据下方【知识库资料】回答,不得调用模型自身记忆补充资料之外的内容;资料中包含流程、步骤、话术、制度等具体内容时,优先逐字引用或完整转述,不得使用未检索到的诗句、篇名、作者或步骤。 |
|
||||
- 来源对应:回答中每个要点都应能在【知识库资料】中找到对应来源;不得让回答内容与下方引用来源不一致,也不得将多步流程压缩到只剩一两条。 |
|
||||
- 资料不足:如果【知识库资料】中没有用户要求的内容,请明确说明未在当前知识库中检索到足够资料,并提示补充或调整知识库。 |
|
||||
- 排版规范:使用 Markdown 结构化输出——分点用有序或无序列表(`1.` / `-`),不同要点之间空一行分段,涉及多来源或多角度时可用二级标题(`##`)区分;严禁把所有内容挤在一段内。"""; |
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue