117 lines
3.9 KiB
Markdown
117 lines
3.9 KiB
Markdown
# Design: 置信度评分与用户反馈机制
|
||
|
||
## 架构约束(来自 devflow)
|
||
|
||
- Spring Boot 3.2 + Spring AI Alibaba
|
||
- JPA ddl-auto=validate,变更走 Flyway
|
||
- 已有实体:`DiagnosisSession`(含 selfEvaluation JSON、feedback VARCHAR)、`CaseLibrary`
|
||
- **新增字段**:`DiagnosisSession.answer TEXT`,存储返回给用户的完整答案,Flyway V008 迁移
|
||
- 已有 Repository:`DiagnosisSessionRepository`、`CaseLibraryRepository`
|
||
- 当前主流程入口:`ChatService.executeChat`(非流式)、`executeChatComplex`(多 Agent)
|
||
|
||
## 模块链路
|
||
|
||
```
|
||
用户对话
|
||
↓
|
||
ChatService.executeChat / executeChatComplex
|
||
↓ SUCCESS 后异步
|
||
EvaluationService.evaluate(sessionId, answer, steps)
|
||
├─ LLM 自评 → 写 selfEvaluation(含 confidence + reasoning)
|
||
└─ 规则兜底(LLM 失败时)→ 写 selfEvaluation(含 source: "rule")
|
||
|
||
用户提交反馈
|
||
↓
|
||
POST /api/feedback { sessionId, feedback }
|
||
↓
|
||
FeedbackService.submitFeedback(sessionId, feedback)
|
||
├─ 写 DiagnosisSession.feedback
|
||
├─ feedback=useful → 写 CaseLibrary
|
||
└─ feedback=not_useful → 更新 status=BAD_CASE
|
||
```
|
||
|
||
## 数据结构定义
|
||
|
||
### DiagnosisSession.selfEvaluation(JSON 字符串)
|
||
|
||
```json
|
||
{
|
||
"evidence_score": 65,
|
||
"source": "rule",
|
||
"factors": [
|
||
{"name": "has_successful_tool_call", "delta": 30, "description": "有成功的工具调用(2次)"},
|
||
{"name": "l1_semantic_match", "delta": 20, "description": "L1 语义匹配命中"}
|
||
]
|
||
}
|
||
```
|
||
|
||
字段说明:
|
||
- `evidence_score`:0-100,衡量证据收集充分度(非答案准确性)
|
||
- `source`:评分来源,当前固定为 `"rule"`;预留 `"llm"` 供后续 LLM 观点叠加
|
||
- `factors`:命中的规则因子列表,每项含 name / delta / description,可直接用于分析
|
||
- `llm_opinion`:预留字段,LLM 观点叠加时扩展此处,不改变现有规则逻辑
|
||
|
||
### FeedbackRequest(新 DTO)
|
||
|
||
```java
|
||
public class FeedbackRequest {
|
||
String sessionId; // 必填
|
||
String feedback; // "useful" | "not_useful"
|
||
}
|
||
```
|
||
|
||
### FeedbackResponse(新 DTO)
|
||
|
||
```java
|
||
public class FeedbackResponse {
|
||
boolean success;
|
||
String message;
|
||
String caseId; // useful 时返回生成的 case_id,否则 null
|
||
}
|
||
```
|
||
|
||
### CaseLibrary 生成规则(useful 时)
|
||
|
||
| CaseLibrary 字段 | 来源 |
|
||
|---|---|
|
||
| caseId | UUID |
|
||
| diagnosisId | DiagnosisSession.sessionId |
|
||
| sourceType | SourceType.AUTO |
|
||
| faultCategory | FaultCategory.GENERAL(暂时) |
|
||
| title | DiagnosisSession.query 前 100 字符 |
|
||
| rootCause | DiagnosisSession.answer(完整答案,不截断) |
|
||
| solution | DiagnosisSession.answer(同上) |
|
||
| createdBy | "system" |
|
||
|
||
## 关键技术决策
|
||
|
||
### 决策 1:LLM 自评异步执行
|
||
|
||
置信度计算在 Agent 主流程结束后异步进行(`@Async` + Spring 线程池),不阻塞用户响应。
|
||
原因:LLM 自评耗时 1-3 秒,主流程不应等待。
|
||
|
||
### 决策 2:置信度规则兜底参数
|
||
|
||
```
|
||
基础分:60
|
||
工具调用加分:toolCallCount × 5,上限 +20
|
||
步数少加分:stepCount <= 3 → +10
|
||
status=FAILED → 直接 0
|
||
```
|
||
|
||
### 决策 3:BAD_CASE 用 status 字段而非新字段
|
||
|
||
`DiagnosisSession.status` 已有 PENDING/RUNNING/SUCCESS/FAILED,扩展为允许包含 BAD_CASE。
|
||
该字段是 VARCHAR 16,直接存字符串,无需枚举类(Java 端用常量控制)。
|
||
|
||
### 决策 4:案例内容提取策略
|
||
|
||
useful 时,`rootCause` 和 `solution` 从 `AgentStepRepository.findBySessionIdOrderByStepIndex` 的最后一步 `thought` 字段提取。
|
||
如果 thought 为空,则用 DiagnosisSession.query + "(自动提取失败,请人工补充)" 占位。
|
||
|
||
## 接口影响等级
|
||
|
||
- `POST /api/feedback`:新增接口,L2(内部,前端新消费)
|
||
- `ChatService.executeChat`:新增异步后置调用,不改返回值,L1
|
||
- `DiagnosisSession.status` 增加 BAD_CASE 值:原调用方只读不写此字段,L2
|