feat(coordinator): 在贴身业务参谋决策锦囊中注入相似标杆案例自推荐

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WeiCHEN
2026-09-08 13:43:08 +08:00
co-authored by Cursor
parent 0f1f0c6713
commit f111fb19ae
4 changed files with 170 additions and 18 deletions
+6 -2
View File
@@ -36,6 +36,8 @@ type ChatResponse struct {
// Session 多轮对话与协同会话管理器
type Session struct {
ID string `json:"id"`
UserID int64 `json:"user_id"`
ProjectID int64 `json:"project_id"`
UserCtx *coordinator.UserProjectContext `json:"user_ctx"`
Recognizer intent.Recognizer `json:"-"`
Coordinator *coordinator.CoordinatorEngine `json:"-"`
@@ -59,6 +61,8 @@ func NewSession(id string, userCtx *coordinator.UserProjectContext, rec intent.R
return &Session{
ID: id,
UserID: 1,
ProjectID: 1,
UserCtx: userCtx,
Recognizer: rec,
Coordinator: coord,
@@ -94,7 +98,7 @@ func (s *Session) sendMessageInternal(ctx context.Context, userInput string, str
s.Messages = append(s.Messages, userMsg)
if s.CtxMgr != nil {
_ = s.CtxMgr.RecordUserMessage(ctx, s.ID, 1, "user", userInput, "", "", nil)
_ = s.CtxMgr.RecordUserMessage(ctx, s.ID, s.UserID, "user", userInput, "", "", nil)
}
// 1. 意图识别 (L1 对话层,带非阻塞桌角备忘快照)
@@ -155,7 +159,7 @@ func (s *Session) sendMessageInternal(ctx context.Context, userInput string, str
s.Messages = append(s.Messages, asstMsg)
if s.CtxMgr != nil {
_ = s.CtxMgr.RecordUserMessage(ctx, s.ID, 1, "assistant", coordRes.NaturalReply, string(coordRes.Intent), string(recRes.Branch), nil)
_ = s.CtxMgr.RecordUserMessage(ctx, s.ID, 0, "assistant", coordRes.NaturalReply, string(coordRes.Intent), string(recRes.Branch), nil)
}
// 4. 流式推送参谋自然语言回复与决策锦囊
+73
View File
@@ -7,7 +7,9 @@ import (
"chat-agent-system/internal/bizdev"
"chat-agent-system/internal/chat"
"chat-agent-system/internal/config"
"chat-agent-system/internal/coordinator"
"chat-agent-system/internal/docgov"
"chat-agent-system/internal/intent"
"chat-agent-system/internal/squad"
)
@@ -239,3 +241,74 @@ func TestChatSession_Branch3_AmbiguousConsult(t *testing.T) {
t.Errorf("expected NextExpectation to be populated for user choice")
}
}
// 用例 6: 贴身参谋决策锦囊中自推荐往期标杆案例
func TestChatSession_AdvisorCaseRecommendation(t *testing.T) {
cfg := &config.Config{DataDir: t.TempDir()}
svc := bizdev.NewService(cfg)
ctx := context.Background()
// 1. 预置一个已终审批准的往期标杆案例
doc := &docgov.DocumentRecord{
DocID: "doc_history_ultrasonic_01",
ProjectID: 201,
TaskKey: "feasibility_reg",
Title: "超声软组织切割止血手术设备注册评估",
Stage: "V0.5_feasibility",
CurrentState: docgov.StateApproved,
IsLocked: true,
AuthorName: "李工",
}
body := `# 超声软组织切割止血手术设备注册评估
## 概述与器械分类
主要用于外科微创手术中软组织切割与止血闭合,按三类医疗器械申报。
## 关键性能与型检预估
重点满足 GB 9706.1-2020 及 YY 0644 专用安全规范,型检周期约 5 个月。`
_, err := svc.ContextManager().IndexApprovedDocument(ctx, doc, body)
if err != nil {
t.Fatalf("IndexApprovedDocument failed: %v", err)
}
// 2. 发起新会话咨询
rec := intent.NewRecognizer()
engine := coordinator.NewCoordinatorEngine(svc)
userCtx := &coordinator.UserProjectContext{
Project: coordinator.ProjectInfo{
Name: "超声软组织刀研发咨询",
DeviceType: "超声手术设备",
IntendedUse: "软组织切割闭合",
CurrentStage: bizdev.StageV01_Triage,
},
LatestAdvisorBrief: &squad.AdvisorBriefing{
MaturityScore: 60,
MaturityLevel: "V0.1",
MaturityHeadline: "需求初步梳理中",
},
}
session := chat.NewSession("sess_case_recommend", userCtx, rec, engine)
session.CtxMgr = svc.ContextManager()
resp, err := session.SendMessage(ctx, "我们之前做过类似的超声手术设备吗?注册和型检要注意什么?")
if err != nil {
t.Fatalf("SendMessage failed: %v", err)
}
if resp.AdvisorBrief == nil {
t.Fatalf("expected AdvisorBrief in response")
}
if len(resp.AdvisorBrief.RecommendedCases) == 0 {
t.Fatalf("expected RecommendedCases to be populated, got 0")
}
recCase := resp.AdvisorBrief.RecommendedCases[0]
t.Logf("✓ 贴身参谋锦囊成功自推荐标杆案例: 文档=%s, 标题=%s, 章节=%s, 相似度=%.2f",
recCase.DocID, recCase.ArtifactTitle, recCase.SectionTitle, recCase.SimilarityScore)
if recCase.DocID != "doc_history_ultrasonic_01" {
t.Errorf("unexpected doc ID: %s", recCase.DocID)
}
}
+70 -9
View File
@@ -9,6 +9,7 @@ import (
"strings"
"chat-agent-system/internal/bizdev"
"chat-agent-system/internal/ctxmgr"
"chat-agent-system/internal/intent"
"chat-agent-system/internal/squad"
"chat-agent-system/internal/stream"
@@ -79,7 +80,11 @@ func (e *CoordinatorEngine) ProcessIntent(
// 1. 若为分支 3 (模糊/分忧引导),触发参谋主动分析与建议
if recRes.Branch == intent.BranchAmbiguousFallback {
return e.handleAmbiguousConsult(top, userCtx)
res, err := e.handleAmbiguousConsult(top, userCtx)
if err == nil && res != nil {
e.enrichAdvisorBriefWithCases(ctx, res.AdvisorBrief, userCtx, top.FilledSlots)
}
return res, err
}
// 2. 若缺少核心槽位且需澄清
@@ -95,35 +100,91 @@ func (e *CoordinatorEngine) ProcessIntent(
}
// 3. 根据候选意图执行分支
var coordRes *CoordinationResult
var coordErr error
switch top.Intent {
case intent.IntentDeclineExpectation:
return e.handleDeclineExpectation(userCtx)
coordRes, coordErr = e.handleDeclineExpectation(userCtx)
case intent.IntentQueryProgress:
return e.handleQueryProgress(top, userCtx)
coordRes, coordErr = e.handleQueryProgress(top, userCtx)
case intent.IntentSupplementInfo:
return e.handleSupplementInfo(top, userCtx)
coordRes, coordErr = e.handleSupplementInfo(top, userCtx)
case intent.IntentAdvanceStage:
return e.handleAdvanceStage(ctx, top, userCtx)
coordRes, coordErr = e.handleAdvanceStage(ctx, top, userCtx)
case intent.IntentTriggerTask:
return e.handleTriggerTask(ctx, top, userCtx)
coordRes, coordErr = e.handleTriggerTask(ctx, top, userCtx)
case intent.IntentCasualChat:
return e.handleCasualChat(userCtx)
coordRes, coordErr = e.handleCasualChat(userCtx)
default:
nextExp := BuildNextExpectation(userCtx.Project.CurrentStage, userCtx.Project.Name)
return &CoordinationResult{
coordRes = &CoordinationResult{
Status: StatusAccepted,
Intent: top.Intent,
Branch: recRes.Branch,
NaturalReply: "我已收到您的指示。针对当前项目,请问需要我为您查询进展、补充技术事实,还是推进方案论证?随时吩咐我。",
UpdatedContext: userCtx,
NextExpectation: nextExp,
}, nil
}
}
if coordErr == nil && coordRes != nil {
e.enrichAdvisorBriefWithCases(ctx, coordRes.AdvisorBrief, userCtx, top.FilledSlots)
}
return coordRes, coordErr
}
// enrichAdvisorBriefWithCases 结合上下文与意图槽位检索相似标杆案例并注入参谋锦囊
func (e *CoordinatorEngine) enrichAdvisorBriefWithCases(ctx context.Context, brief *squad.AdvisorBriefing, userCtx *UserProjectContext, slots map[string]string) {
if brief == nil || e.bizdevSvc == nil {
return
}
ctxMgr := e.bizdevSvc.ContextManager()
if ctxMgr == nil {
return
}
// 构造搜索语句
queryParts := []string{userCtx.Project.DeviceType, userCtx.Project.IntendedUse}
if topic, ok := slots[intent.SlotQueryTopic]; ok && topic != "" {
queryParts = append(queryParts, topic)
}
query := strings.TrimSpace(strings.Join(queryParts, " "))
if query == "" {
query = userCtx.Project.Name
}
if query == "" {
return
}
cases, err := ctxMgr.SearchSimilarCases(ctx, ctxmgr.CaseSearchOptions{
Query: query,
Limit: 2,
MinScore: 0.50,
})
if err != nil || len(cases) == 0 {
return
}
for _, c := range cases {
brief.RecommendedCases = append(brief.RecommendedCases, squad.AdvisorCaseRecommendation{
DocID: c.DocID,
ProjectName: c.ProjectName,
TaskKey: c.TaskKey,
ArtifactTitle: c.ArtifactTitle,
SectionTitle: c.SectionTitle,
SummarySnippet: c.SummarySnippet,
KeyRegulations: c.KeyRegulations,
SimilarityScore: c.SimilarityScore,
ApprovedAt: c.ApprovedAt,
})
}
}
+21 -7
View File
@@ -217,13 +217,27 @@ type Manifest struct {
DurationMs int64 `json:"duration_ms"`
}
// AdvisorCaseRecommendation 参谋决策锦囊推荐的往期标杆案例
type AdvisorCaseRecommendation struct {
DocID string `json:"doc_id"`
ProjectName string `json:"project_name"`
TaskKey string `json:"task_key"`
ArtifactTitle string `json:"artifact_title"`
SectionTitle string `json:"section_title"`
SummarySnippet string `json:"summary_snippet"`
KeyRegulations []string `json:"key_regulations,omitempty"`
SimilarityScore float64 `json:"similarity_score"`
ApprovedAt string `json:"approved_at"`
}
// AdvisorBriefing B轨业务参谋决策锦囊
type AdvisorBriefing struct {
MaturityScore int `json:"maturity_score"` // 成熟度评分 (0-100)
MaturityLevel string `json:"maturity_level"` // 成熟度等级 (如 V0.1, V0.5, V1.0)
MaturityHeadline string `json:"maturity_headline"` // 总体进展研判(一句话核心诊断)
BaselineAssumptions []string `json:"baseline_assumptions"` // 基准假设清单(替代填空,为用户预设)
PreemptiveRisks []string `json:"preemptive_risks"` // 预见性风险雷达(替用户提前看两步)
NextBestActions []string `json:"next_best_actions"` // 建议下一步行动选项
CommunicationKit string `json:"communication_kit"` // 建议对外沟通话术(微信/邮件模板)
MaturityScore int `json:"maturity_score"` // 成熟度评分 (0-100)
MaturityLevel string `json:"maturity_level"` // 成熟度等级 (如 V0.1, V0.5, V1.0)
MaturityHeadline string `json:"maturity_headline"` // 总体进展研判(一句话核心诊断)
BaselineAssumptions []string `json:"baseline_assumptions"` // 基准假设清单(替代填空,为用户预设)
PreemptiveRisks []string `json:"preemptive_risks"` // 预见性风险雷达(替用户提前看两步)
NextBestActions []string `json:"next_best_actions"` // 建议下一步行动选项
CommunicationKit string `json:"communication_kit"` // 建议对外沟通话术(微信/邮件模板)
RecommendedCases []AdvisorCaseRecommendation `json:"recommended_cases,omitempty"` // 💡 往期标杆案例与历史报价经验自推荐
}