feat: 示例问题老板视角过滤+画像定向+prompt禁止清单
后端: - filter_boss_perspective(): 关键词过滤员工视角问题 覆盖:加班费/被辞退/拖欠工资/工伤认定/产假/劳动仲裁/降薪扣工资等 - /samples: prompt加禁止清单+正确视角示例,返回前过滤 画像注入加行业定向(有industry时明确要求生成行业相关问题) - /topics: prompt加禁止清单+正确视角示例,返回前过滤 - generate_daily_topics: prompt加禁止清单+正确视角示例,返回前过滤 前端: - 审查FALLBACK_SAMPLES: 三个场景兜底示例均为老板视角,无需修改 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -18,7 +18,7 @@ from bossai import (
|
||||
ExpertStore, ConsultationStore, RatingStore,
|
||||
DocumentGenerator, RegulationUpdateManager, FactFinder,
|
||||
ChatStore, redact,
|
||||
DailyTopicStore, generate_daily_topics,
|
||||
DailyTopicStore, generate_daily_topics, filter_boss_perspective,
|
||||
)
|
||||
|
||||
# ===== 日志脱敏 =====
|
||||
@@ -394,9 +394,19 @@ def generate_topics(req: TopicsRequest):
|
||||
1. 话题要覆盖该场景下不同方向,不要只集中在某一类
|
||||
2. 结合用户画像(如有)推荐个性化话题
|
||||
3. 示例问题要具体、贴近中小企业老板实际
|
||||
4. **所有问题必须从老板/雇主视角出发**(BossAi 的用户是企业老板,不是员工)。例如劳动用工应问"员工工伤后能开除吗"而非"拖欠工资怎么追讨"
|
||||
4. **所有问题必须从老板/雇主视角出发**(BossAi 的用户是企业老板,不是员工)
|
||||
5. 返回JSON数组格式:[{{"title":"话题名","desc":"简短描述","samples":["问题1","问题2","问题3","问题4"]}}]
|
||||
6. 只返回JSON,不要其他文字{existing_str}"""
|
||||
6. 只返回JSON,不要其他文字{existing_str}
|
||||
|
||||
**严禁生成员工视角问题:**
|
||||
- 加班费怎么算、被辞退怎么维权、拖欠工资怎么追讨
|
||||
- 请假被拒、工伤认定、产假怎么休、劳动仲裁怎么告公司
|
||||
- 降我薪、扣我工资、罚我款、被歧视、被骚扰
|
||||
|
||||
**正确视角示例:**
|
||||
- 老板问:员工工伤后能开除吗?(不是"工伤赔偿怎么申请")
|
||||
- 老板问:辞退员工要赔多少?(不是"被辞退怎么维权")
|
||||
- 老板问:客户拖欠货款如何催收?(不是"拖欠工资怎么追")"""
|
||||
|
||||
try:
|
||||
answer = kimi.chat([{"role": "user", "content": prompt}], temperature=0.8)
|
||||
@@ -411,15 +421,19 @@ def generate_topics(req: TopicsRequest):
|
||||
if start == -1 or end == -1:
|
||||
return {"topics": builtin_topics.get(req.scene, builtin_topics["legal"])}
|
||||
topics = json.loads(answer[start:end + 1])
|
||||
# 校验结构
|
||||
# 校验结构 + 老板视角过滤
|
||||
valid_topics = []
|
||||
for t in topics:
|
||||
if isinstance(t, dict) and t.get("title") and t.get("samples"):
|
||||
valid_topics.append({
|
||||
"title": str(t["title"])[:10],
|
||||
"desc": str(t.get("desc", ""))[:30],
|
||||
"samples": [str(s) for s in t["samples"] if isinstance(s, str) and s.strip()][:4],
|
||||
})
|
||||
boss_samples = filter_boss_perspective(
|
||||
[str(s) for s in t["samples"] if isinstance(s, str) and s.strip()]
|
||||
)[:4]
|
||||
if boss_samples:
|
||||
valid_topics.append({
|
||||
"title": str(t["title"])[:10],
|
||||
"desc": str(t.get("desc", ""))[:30],
|
||||
"samples": boss_samples,
|
||||
})
|
||||
if len(valid_topics) < 3:
|
||||
return {"topics": builtin_topics.get(req.scene, builtin_topics["legal"])}
|
||||
return {"topics": valid_topics[:8]}
|
||||
@@ -469,6 +483,17 @@ def generate_samples(req: SampleRequest):
|
||||
profile_ctx = build_profile_context(profile)
|
||||
if profile_ctx:
|
||||
prompt += f"用户画像(请结合画像生成更贴合用户自身情况的问题):\n{profile_ctx}\n\n"
|
||||
# 行业定向:如果有行业,加明确指令
|
||||
if profile.industry:
|
||||
industry_map = {
|
||||
"retail": "零售/餐饮", "manufacturing": "制造业/工厂",
|
||||
"tech": "科技/互联网", "service": "服务业",
|
||||
"construction": "建筑/工程", "logistics": "物流/运输",
|
||||
"finance": "金融/投资", "education": "教育/培训",
|
||||
"healthcare": "医疗/健康", "agriculture": "农业/农产品",
|
||||
}
|
||||
industry_label = industry_map.get(profile.industry, profile.industry)
|
||||
prompt += f"**用户行业为{industry_label},请生成与该行业密切相关的问题**\n\n"
|
||||
except Exception:
|
||||
pass
|
||||
if existing:
|
||||
@@ -482,7 +507,13 @@ def generate_samples(req: SampleRequest):
|
||||
"2. **所有问题必须从老板/雇主视角出发**(用户是企业老板,不是员工)\n"
|
||||
"3. 每个问题 15-30 字\n"
|
||||
"4. 不要重复已展示过的问题\n"
|
||||
"5. 只返回 JSON 数组,如 [\"问题1\", \"问题2\", \"问题3\", \"问题4\"]\n"
|
||||
"5. 只返回 JSON 数组,如 [\"问题1\", \"问题2\", \"问题3\", \"问题4\"]\n\n"
|
||||
"**严禁生成员工视角问题(如:加班费怎么算、被辞退怎么维权、拖欠工资怎么追讨、**\n"
|
||||
"**请假被拒、工伤认定、产假怎么休、劳动仲裁怎么告公司、降我薪扣我工资等)**\n\n"
|
||||
"**正确视角示例:**\n"
|
||||
"- 老板问:员工工伤后能开除吗?(不是"工伤赔偿怎么申请")\n"
|
||||
"- 老板问:辞退员工要赔多少?(不是"被辞退怎么维权")\n"
|
||||
"- 老板问:客户拖欠货款如何催收?(不是"拖欠工资怎么追")\n"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -507,8 +538,10 @@ def generate_samples(req: SampleRequest):
|
||||
if start == -1 or end == -1:
|
||||
return {"samples": builtin.get(req.scene, builtin["legal"])}
|
||||
samples = json.loads(answer[start:end + 1])
|
||||
# 过滤非字符串和空值
|
||||
samples = [s for s in samples if isinstance(s, str) and s.strip()][:4]
|
||||
# 过滤:老板视角 + 非字符串 + 去重
|
||||
samples = filter_boss_perspective(
|
||||
[s for s in samples if isinstance(s, str) and s.strip()]
|
||||
)[:4]
|
||||
if len(samples) < 2:
|
||||
return {"samples": builtin.get(req.scene, builtin["legal"])}
|
||||
return {"samples": samples}
|
||||
|
||||
Reference in New Issue
Block a user