feat: BossAi v2.0 UI/UX 重构 + 看板断点续接 + 多轮上下文
CI / 后端测试 (push) Has been cancelled
CI / 前端构建 (push) Has been cancelled

- 新增 web2/ 前端:任务卡看板、风险雷达、决策日志、我的团队、快捷指令
- ChatPanel 增强:风险卡置顶、案卡接入、起诉状向导、语音输入
- 事项看板:点击查看详情弹窗、断点续接(恢复历史对话+matterId)
- 保密模式恢复:密码验证后重建内存 session,保留多轮上下文
- 多轮对话:ask/ask-stream/ask-analyze 注入 session 历史,AI 有上下文
- 追问优化:紧扣用户问题,不再偏离主题(社保问社保,工伤问工伤)
- 对话区可滚动,输入区固定可见
- 状态机放宽:允许从任意非终态转到 pending_expert
- session 存活检查端点,后端重启后自动重建 session
- DB migration:风险推送表、案卡表

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
selfrelease
2026-08-31 08:38:33 +08:00
co-authored by Devin
parent 7a788bf8dc
commit 4de36547cd
88 changed files with 15237 additions and 62 deletions
+35 -17
View File
@@ -164,7 +164,7 @@ def assess_ai(question: str, kimi_client=None) -> RiskCard | None:
return None
prompt = (
"你是中国中小企业法务风险分诊专家。请判断以下问题的风险等级。\n\n"
"你是中国中小企业法务风险分诊专家,服务对象是企业老板(雇主)。请判断以下问题的风险等级。\n\n"
f"用户问题:{question}\n\n"
"风险等级定义:\n"
"- red: 重大法律风险,可能涉及刑事、行政处罚、重大诉讼、人身安全,必须人工复核\n"
@@ -2117,7 +2117,7 @@ class DocumentGenerator:
try:
return self.kimi_client.chat(
[{"role": "system", "content": "你是法律文书撰写助手,生成正式规范的文书正文。"},
[{"role": "system", "content": "你是法律文书撰写助手,服务对象是中小企业老板(原告方),生成正式规范的文书正文。"},
{"role": "user", "content": prompt}],
temperature=0.3,
timeout=30,
@@ -2483,7 +2483,7 @@ class FactFinder:
}.get(scene, "通用")
prompt = (
f"你是{scene_desc}顾问。判断已有事实是否足够给出有价值的建议。\n\n"
f"你是{scene_desc}顾问,服务对象是中小企业老板。判断已有事实是否足够给出有价值的建议。\n\n"
f"用户问题:{question}\n\n"
)
if previous_answers:
@@ -2593,7 +2593,7 @@ class FactFinder:
def generate_ai_questions(self, question: str, scene: str,
kimi_client, previous_answers: list[dict] = None,
max_questions: int = 3) -> list[dict]:
max_questions: int = 3, history: list[dict] = None) -> list[dict]:
"""用 AI 分析问题,生成针对性追问问题。
Args:
@@ -2613,25 +2613,25 @@ class FactFinder:
scene_config = {
"legal": {
"desc": "法律/法务",
"role": "你是中国执业律师",
"role": "你是中国执业律师,服务对象是中小企业老板(雇主),所有追问必须从老板/雇主视角出发",
"dim_examples": "合同、金额、时间、证据、对方态度、是否协商过",
"focus": "影响法律结论的关键事实",
},
"decision": {
"desc": "经营决策",
"role": "你是中小企业经营顾问",
"role": "你是中小企业经营顾问,服务对象是企业老板,所有追问从老板视角出发",
"dim_examples": "规模金额、现金流、市场状况、团队能力、备选方案、时间窗口",
"focus": "影响决策推演的关键事实",
},
"life": {
"desc": "生活助理",
"role": "你是生活管理顾问,擅长家庭、健康、出行等实用建议",
"role": "你是生活管理顾问,擅长家庭、健康、出行等实用建议,服务对象是企业老板",
"dim_examples": "具体状况、涉及人员、时间安排、当前困难、已有尝试",
"focus": "让建议更具体可执行的关键细节,而非泛泛的'描述情况'",
},
"emotion": {
"desc": "情绪疏导",
"role": "你是心理咨询师",
"role": "你是心理咨询师,服务对象是企业老板",
"dim_examples": "触发事件、持续时间、当前感受、已有应对、社会支持",
"focus": "理解情绪状态和触发因素的关键信息",
},
@@ -2644,6 +2644,16 @@ class FactFinder:
f"用户问题:{question}\n\n"
)
# 注入对话历史(多轮上下文),让追问能理解当前问题的背景
if history:
prompt += "之前的对话历史(用于理解当前问题的背景):\n"
for h in history[-6:]:
role_label = "用户" if h.get("role") == "user" else "AI"
content = h.get("content", "")
if content:
prompt += f"{role_label}: {content[:200]}\n"
prompt += "\n注意:当前问题是在上述对话背景下的延续,追问应结合之前的上下文,不要当成孤立问题处理。\n\n"
if previous_answers:
prompt += "已知事实:\n"
for ans in previous_answers:
@@ -2653,19 +2663,24 @@ class FactFinder:
prompt += (
f"请生成最多 {max_questions} 个最关键的追问,帮助更准确地分析这个问题。\n\n"
f"要求:\n"
f"1. 每个问题针对一个关键事实维度(如{config['dim_examples']}等)\n"
f"2. 问题必须具体、有针对性,针对用户问题中的实际情境提问\n"
f"3. 不要问'能具体描述一下情况吗'这类泛泛的问题,要问具体的细节\n"
f"4. 优先问对{config['focus']}影响最大的事实\n"
f"5. 不要问用户已经回答过的事实\n"
f"6. 如果已有足够信息,返回空列表\n\n"
f"1. **追问必须与用户问题直接相关,不要偏离主题**。"
f"例如用户问'社保未缴全',追问应该是关于社保缴纳情况、欠缴金额、是否被查等,"
f"而不是问合同违约或股东纠纷等无关问题\n"
f"2. 每个问题针对一个关键事实维度(如{config['dim_examples']}等)\n"
f"3. 问题必须具体、有针对性,针对用户问题中的实际情境提问\n"
f"4. 不要问'能具体描述一下情况吗'这类泛泛的问题,要问具体的细节\n"
f"5. 优先问对{config['focus']}影响最大的事实\n"
f"6. 不要问用户已经回答过的事实\n"
f"7. 如果已有足够信息,返回空列表\n"
f"8. **所有追问必须从老板/雇主视角出发**(用户是中小企业老板,不是员工)。"
f"例如劳动用工场景,应问'公司与该员工签的劳动合同中解除条款怎么约定的',而非'您与公司签订的劳动合同'\n\n"
f"请以 JSON 数组格式返回,每个元素包含 dim_key(维度英文标识)、dim_desc(维度中文描述)、question(追问问题):\n"
f'[{{"dim_key": "amount", "dim_desc": "涉及金额", "question": "涉及的金额大约是多少?"}}]\n'
)
try:
answer = kimi_client.chat(
[{"role": "system", "content": "你是专业顾问助手,擅长分析问题并生成精准追问。只返回 JSON 数组,不要其他内容。"},
[{"role": "system", "content": "你是专业顾问助手,服务对象是中小企业老板。所有追问必须从老板/雇主视角出发,不要用员工视角提问。只返回 JSON 数组,不要其他内容。"},
{"role": "user", "content": prompt}],
temperature=0.3,
timeout=30,
@@ -2704,7 +2719,7 @@ class FactFinder:
def build_analysis_prompt(self, question: str, scene: str,
answers: list[dict],
kimi_client=None) -> tuple[str, dict]:
kimi_client=None, history: list[dict] = None) -> tuple[str, dict]:
"""完整的追问流程:分析 → 生成追问 → 汇总事实。
优先用 AI 生成针对性追问,Kimi 不可用时降级到规则匹配。
@@ -2730,6 +2745,7 @@ class FactFinder:
if kimi_client:
questions = self.generate_ai_questions(
question, scene, kimi_client, answers, self.max_questions_per_round,
history=history,
)
# AI 不可用或返回空,降级到规则匹配
if not questions:
@@ -2841,9 +2857,11 @@ class KimiClient:
# 场景 system prompt 映射:按模块路由不同人设,前端通过 scene 参数选择
SCENE_PROMPTS: dict[str, str] = {
"legal": (
"你是中国中小企业老板的法务参谋。先给风险等级(绿色/黄色/橙色/红色),"
"你是中国中小企业老板的法务参谋,服务对象是企业老板(雇主),所有分析和建议必须从老板/雇主视角出发。"
"先给风险等级(绿色/黄色/橙色/红色),"
"再给结论、立即行动、需保存证据、禁止事项和是否需要律师复核。"
"覆盖劳动用工、合同审查、债权债务、股东纠纷、税务风险。"
"劳动用工场景中,你是帮老板处理员工问题的律师,不是帮员工维权的律师。"
"严禁编造法律依据;不确定时明确说明。"
),
"decision": (