From 4c5b3104cfcf0d7e68577864ca101b07d38b7008 Mon Sep 17 00:00:00 2001 From: ymq Date: Sat, 8 Aug 2026 15:19:18 +0800 Subject: [PATCH] agent-way: LLM resolves project aliases via project list in INTENT_PROMPT --- wwwroot/api/cockpit_chat.dspy | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/wwwroot/api/cockpit_chat.dspy b/wwwroot/api/cockpit_chat.dspy index 96db287..74b53a1 100644 --- a/wwwroot/api/cockpit_chat.dspy +++ b/wwwroot/api/cockpit_chat.dspy @@ -412,6 +412,7 @@ INTENT_PROMPT = """你是一个开发产线意图分类器。分析用户输入 - show_repos: 查看当前项目关联的仓库(如"有哪些仓库""显示仓库") 当前上下文:项目={ctx},迭代={iter} +可选项目列表(select_project时project_name必须从列表中选择):{projects} 待客户回答的问题(角色Agent执行任务中提出):{questions} 若用户消息是在回答上述问题之一,intent应为answer_question,并把回答内容填入description。 @@ -419,11 +420,18 @@ INTENT_PROMPT = """你是一个开发产线意图分类器。分析用户输入 {"intent":"...","confidence":0.8,"project_name":"...","iteration_name":"...","title":"...","description":"...","source_path":"...","role":"...","missing_info":"...","question_id":"...","repo_url":"...","repo_name":"..."}""" -async def _classify_intent(model_info, message, ctx, history_msgs, questions_text='无'): - """Classify user intent using LLM.""" +async def _classify_intent(model_info, message, ctx, history_msgs, sor, questions_text='无'): + """Classify user intent using LLM. sor is needed to load project list.""" ctx_str = ctx.get('project_name', '') or '无' iter_str = ctx.get('iteration_name', '') or '无' - prompt = INTENT_PROMPT.replace('{ctx}', ctx_str).replace('{iter}', iter_str).replace('{questions}', questions_text) + # 加载项目列表供LLM匹配 + proj_recs = await sor.sqlExe("SELECT name FROM sd_projects ORDER BY created_at DESC LIMIT 20", {}) + proj_names = ', '.join([getattr(r, 'name', '') for r in (proj_recs or [])]) or '无' + prompt = (INTENT_PROMPT + .replace('{ctx}', ctx_str) + .replace('{iter}', iter_str) + .replace('{projects}', proj_names) + .replace('{questions}', questions_text)) msgs = [{"role": "system", "content": prompt}] for h in history_msgs[-4:]: msgs.append(h) @@ -439,24 +447,12 @@ async def _classify_intent(model_info, message, ctx, history_msgs, questions_tex async def _find_project(sor, name, org_id): - """Find project by name (supports partial match).""" + """Find project by exact name (LLM should resolve aliases).""" if not name: return None - # Try exact match first recs = await sor.sqlExe( "SELECT id, name FROM sd_projects WHERE name=${name}$ AND org_id=${oid}$", {"name": name, "oid": org_id}) - if recs: - return recs[0] - # Fuzzy: load all projects for this org and match in Python - all_recs = await sor.sqlExe( - "SELECT id, name FROM sd_projects WHERE org_id=${oid}$", - {"oid": org_id}) - kw = name.lower() - for rec in (all_recs or []): - rname = (getattr(rec, 'name', '') or '').lower() - if kw in rname: - return rec - return None + return recs[0] if recs else None # ==================== 问题路由 ==================== @@ -656,7 +652,7 @@ if action == 'send_message': qlines.append(f"- [id={getattr(fq, 'id', '')}] [{getattr(fq, 'from_role', '')}] {getattr(fq, 'question', '')}") questions_text = '\n'.join(qlines) - intent = await _classify_intent(model_info, message_text, ctx, history_msgs, questions_text) + intent = await _classify_intent(model_info, message_text, ctx, history_msgs, sor, questions_text) debug(f'intent: {intent}') # 3. Route by intent