diff --git a/app/chat_qa/classification/__init__.py b/app/chat_qa/classification/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/chat_qa/classification/intent_classification_qa.py b/app/chat_qa/classification/intent_classification_qa.py new file mode 100644 index 0000000..b8a5941 --- /dev/null +++ b/app/chat_qa/classification/intent_classification_qa.py @@ -0,0 +1,213 @@ +import json +from pathlib import Path + +from langchain_core.output_parsers import JsonOutputParser, StrOutputParser +from langchain_core.prompts import PromptTemplate + +from app.llm import llm + +problem_rewriting_prompt = """ +你是一名智能客服意图分类助手。你的任务是根据用户的历史会话和当前问题,提取用户的核心诉求,并输出标准化的意图标签。 + +## 分类规则(必须严格遵守) + +1. **核心诉求提取**: + - 从当前问题中提取用户明确表达的诉求(可能有一个或多个,去重) + - 如果当前问题包含代词(如"这个"、"它"、"那"等),必须结合历史会话进行指代消解,用具体名词替换代词 + +2. **信息补全**: + - 如果当前问题缺少主语或关键上下文(如只问"费用多少"),必须从历史会话中提取相关主题补全 + - 确保意图标签不依赖历史会话也能被独立理解 + +3. **语义保持**: + - 不得改变用户的原始意图 + - 不得引入历史会话中不存在的新信息 + - 不得遗漏当前问题中的任何关键诉求 + +4. **输出格式**: + - 仅输出JSON,不要任何解释性文字 + - 输出为结构化的意图标签数组,**不要改写成完整问句** + - 每个意图标签应简洁、标准化,适合用于分类路由 + - 多诉求时拆分为多个意图标签,用数组形式输出 + +## 意图标签规范 + +- 每个标签格式为:"{{诉求类型}}" +- 常见诉求类型:费用咨询、课程内容、报名流程、就业支持、开班时间、校区地址、优惠活动、退款政策、住宿咨询、其他 +- 标签应简洁、无歧义,便于系统直接匹配路由 +- 从当前问题中提取用户明确表达的诉求,可以提取多个意图标签 + +## 分类示例 + +### 示例1(信息补全) +历史会话: +- 用户:我想了解游戏特效培训 +- 助手:好的,请问您想了解哪方面? +当前问题:培训的费用 +分类结果: +{{ + "intents": "费用咨询" +}} + +### 示例2(指代消解) +历史会话: +- 用户:你们有Python课程吗? +- 助手:有的,我们有Python基础班和进阶班。 +当前问题:这个课程的时长是多久? +分类结果: +{{ + "intents": ["课程内容", "报名流程"] +}} + +### 示例3(多诉求提取) +历史会话: +- 用户:我想报名数据分析培训 +当前问题:流程、费用和就业支持 +分类结果: +{{ + "intents": ["报名流程"] +}} + +### 示例4(无需改写) +历史会话:(空) +当前问题:Java培训的课程内容有哪些? +分类结果: +{{ + "intents": ["课程内容"] +}} + +### 示例5(用户提供的案例) +历史会话:(空) +当前问题:老师这个课程多少钱啊,老师我想报班 +分类结果: +{{ + "intents": ["报名流程"] +}} + +--- + +## 现在请处理以下输入 + + +当前问题:{query} + +请直接输出JSON: +""" +#===================================================== +intent_prompt = """ +你是第九联盟(点晴科技)培训学校的智能客服助手。从指定意图分类的结果列表中,找到匹配度最高的标准答案,直接输出结果原文,不输出任何其他内容。 + +## 输入格式 +意图分类:{intent} +结果列表:{res} + +## 判断规则 +结果列表中的条目分为两类: +- 标准答案:包含具体信息(价格、时间、服务内容、条件说明),是完整陈述句 +- 常见问题:以问号结尾,是用户可能问的问题而非答案 + +## 硬性规则 +1. 优先选择标准答案,完全忽略常见问题 +2. 仅当列表中全是常见问题时,选择信息最完整、最接近意图分类主题的那一条 +3. 严禁输出常见问题,除非列表中没有任何标准答案 +4. 输出匹配度最高的前三个标准答案,按匹配度降序排列 + +## 评估维度(标准答案之间比较) +| 维度 | 权重 | 说明 | +|------|------|------| +| 与意图分类主题相关性 | 40% | 与意图分类Key的关联程度 | +| 信息完整度 | 35% | 包含价格、时间、服务、条件等具体信息越多越好 | +| 信息集中度 | 25% | 内容是否聚焦该意图主题,避免跨主题混杂 | + +## 意图规则要求: +1. 费用咨询: 必须包含金额和时间 +2. 课程内容: 必须包含时间 +## 输出格式 +直接输出匹配度最高的前三个结果原文,用JSON数组格式,不添加任何解释、编号或额外文字。 +## 示例 + +输入: +意图分类:费用咨询 +结果列表:['线上和线下课程有哪些区别?各自适合什么样的人群?', '课前需要准备哪些设备?', '第九联盟(点晴科技)提供线上课程11800元/8-10个月和线下课程33800元/6个月全日制,大学生可线上+寒暑假线下结合(按线下收费)。支持包括3年回放和答疑、重读机会,以及简历辅导、模拟面试、测试指导、校招群内推等服务。'] + +输出前两个: +['第九联盟(点晴科技)提供线上课程11800元/8-10个月和线下课程33800元/6个月全日制,大学生可线上+寒暑假线下结合(按线下收费)。支持包括3年回放和答疑、重读机会,以及简历辅导、模拟面试、测试指导、校招群内推等服务。'] + +""" +def rewrite_query(query:str): + + prompt = PromptTemplate(template=problem_rewriting_prompt, input_variables=["query"]) + output = JsonOutputParser() + chain = prompt | llm | output + result = chain.invoke({"query": query}) + rewritten_query = result.get("intents", "") + #logger.info(f"原问题:{query},历史会话:{history_text},改写后问题:{rewritten_query}") + return {"rewritten_query": rewritten_query} + +def intent_res(intent:str, res:list[str]): + prompt = PromptTemplate(template=intent_prompt, input_variables=["intent", "res"]) + output = StrOutputParser() + chain = prompt | llm | output + result = chain.invoke({"intent": intent, "res": res}) + print(intent, " ", result) + + +if __name__ == '__main__': + #第一步 规整,把相关的意图分类规整起来 + # qa_file = Path(r"E:\qa_output\Intent_classification_qa.json") # E:\qa_output\qa_result.jsonl + # + # qa_list = [] + # with open(qa_file, 'r', encoding='utf-8') as f: + # for line_num, line in enumerate(f, 1): + # line = line.strip() + # if not line: + # continue + # try: + # data = json.loads(line) + # if isinstance(data, list): + # qa_list.extend(data) + # elif isinstance(data, dict): + # qa_list.append(data) + # else: + # print(f"警告: 第{line_num}行格式异常,跳过") + # except json.JSONDecodeError as e: + # print(f"警告: 第{line_num}行JSON解析失败: {e},跳过") + # intent_dict : dict[str,list] = {} + # for item in qa_list: + # print( item) + # question = item["answer"] + # print(question) + # json_str = json.dumps(item, ensure_ascii=False) + # intent_class=rewrite_query(json_str) + # print(intent_class) + # rewritten_query = intent_class["rewritten_query"] + # if rewritten_query: + # if isinstance(rewritten_query, list): + # for q in rewritten_query: + # if intent_dict.get(q): + # intent_dict[q].append(item["answer"]) + # else: + # intent_dict[q] = [item["answer"]] + # + # + # + # print(intent_dict) + # # 第二步 获取意图最合理的结果 + intent_dict = { + '课程内容': ['线上课直播每周3次,含预科;线下课全日制集训8个月,周一至周五上课,赠送线上课。两者师资和知识点相同,线下强度更大。线下课适合需要监督、整体学习效率高的人群;线上课可能易懒散,需要自律性。', '需要准备手绘板与手绘笔,手绘笔通常为配套购买。', '人满即止,七月份班已有两三人。', '企业招聘不看专业背景,数媒因课程重叠度高;学校教学不足,需额外学习;提供近一年毕业生就业墙作为案例,各专业均有成功就业。', '聊天记录中未明确解释“2个月企业实训”的具体含义,因此无法提供答案。', '全日制公益学习时长为3-5天,具体时间早10晚6,午休90分钟,学习时长视进展而定。', '游戏岗位包括角色原画、3D角色建模、3D道具场景建模(地编)、UE特效、UE开发、动作设计、动画分镜、骨骼绑定。', '销售指出“朝夕拾画”的地编课程可能无法直接就业,其宣传值得怀疑。建议模型+地编的综合学习,并展示了成功学员案例(米哈游offer),强调更实用的学习方向。', '二维方向属于动画分支,没有单独的大纲,仅有通用课程大纲。', '试听课是课程节选,基础操作已事先讲过;试听有疑问属正常。', '确认正式课会从零讲解。', '我们仅提供三维课程,无Spine课程。三维是主流方向,且二维需要绘画功底,建议选择三维课程。', '项目老师为管理层,负责分配任务和把控进度,不亲自上手授课。', '王雨晴是川美大二学生,专业为艺术与科技/游戏,方向未定,想先学软件明确目标。销售介绍公司提供原画、角色建模等岗位针对性培训,学习模式为线下寒暑假集训(如暑假+寒假循环),配合作品集,并赠送线上课用于复习。', 'C++不是刚需,但在复杂系统开发中需要掌握。', '该作品属于风格化的写实人物,是综合风格,课程可以达到该水平,如不喜此风格可选择其他方向。', '适合。特效和场景方向不需要美术基础,更适合有逻辑思维的学生,审美可以后期培养。', 'UE5相关有3门课(场景建模地编、UE特效、UE开发),但‘人物动起来’属于动作课,不使用虚幻,用3dmax/Maya,仅线下班,周期6个月,学费31800元。', '聊天记录中未提及课程总节数,无法提供具体答案。', '当前商业应用未使用AI辅助,且AI尚未系统化。', '原因是缺乏练习,需要反复实操才能内化知识。', '油屋的课程属于兴趣启蒙,不适合快速入行就业。建议根据理科逻辑思维中等水平选择场景模型课程,包含地编内容,学习周期7个月。', '是的,插班需从第一课开始看,已结束的课程可看录播回放。', '建议先听软件基础试听课,若仍听不懂则可能不适合。', '老师解释地编岗位少,模型是重点,但未明确回答是否能完全避免被分去其他班。', '销售答复线上场景建模涉及UE但深度有限,课程为8-10个月,包含3Dmax/Maya、ZBrush等软件及四个阶段,且非纯地编课程,无法保证学员都能成为地编师。', '角色建模主要学习Maya、Toolbag、SP、ZBrush、MD。UE5和3ds Max不是必须的,因为行业强调专精而非杂学。UE5更适合地编方向,3ds Max主要用于场景建模。', 'ZBrush在课程范围内,但犀牛(工业建模)不在课程范围内,课程方向是游戏动画。', '销售推荐了大师课,是纯录播形式,没有老师指导。', '课程中产出的模型作品可以用作地编资产或在UE中渲染展示,实现模型转地编的PBR流程复用。', '开发课线下授课,同步线上直播', '没有独立的寒假班,合班学习效果差且有损口碑。', '无AI课程,地编通常需场景模型师转岗,课程设置是场景模型加地编,综合能力强可直走地编。', '无影响,软件界面从零开始,报名后先进入预科班(从软件界面教起),预科班5月20日启动,已上1节课。', '无影响、可跟上,上一节课有录播回放,支持随时提问。', '用户年龄30岁,大专学历,当前从事文旅行业,对游戏动画有兴趣,考虑兼职转行。', '直播课是固定时间上课,会有提醒。', '课程针对零基础,涵盖动作设计、场景建模等方向,推荐游戏动画方向,并建议考虑场景建模以规避美术基础劣势。', '每个阶段结束都会打出对应分数。', 'UE开发班是纯程序/代码/编程方向,有网课(6月1日新班),线上线下同步授课(周一到周五9:30-12:00,直播+回放),周期6.5个月,线上答疑服务3年。学费13800元,每2-3个月开新班,可免费转班1次。开发主要学习C++、蓝图、图形学。', '课程周期8-10个月,当前班级(5月14日开课)预计12月结业。内推渠道包括公司自留岗位和合作企业,就业老师会按学历、技术、城市、薪资匹配,测试流程3-5个工作日,并提供面试辅导。', '预科班内容为某案例,正课内容待定;正式班预计下月底开课,具体时间不定。', '销售回复线下课程时间灵活,基于学生进度调整,每日固定内容为学习、考试、练习实操。', '我方全天解答,回放终身,解答期3年;王氏固定时间解答。课程差异:我方场景/角色分方向专精学习8个月,产出高质量作品;王氏每个方向仅3个月,只能学简单案例,难以产出系统作品集,校招简历即被筛掉。地编岗位要求80%以上自制资产,王氏课程仅做资产摆放,不满足研发公司需求。我方有校招资源和模拟面试(如3面流程),王氏无此资源,且其学生无校招研发offer。', '销售确认转线下可行,说明线下学习期间练习量更多,有老师指导,测试通常一周内完成,就业前提供内推服务,以帮助用户提升独立制作能力并顺利求职。', '原画对新人要求高,需原创和设计能力,建议造型能力强者考虑角色建模。退款政策:7天无理由全额退款,8-30天退一半,超过30天不退,可休学。', '笔记本CPU i7以上、显卡3060以上、内存16G(预算足32G)、固态512G。', '公司提供线上+线下(上海/西安)结合的方案,针对在校生可利用寒暑假和碎片时间学习,线上8-10个月,线下7-8个月。明确教学Maya和ZBrush,不教Blender,分为角色建模和场景建模方向。报名后可立即开通线上课程,线下在上海小班制(15-25人),老师一对一指导。', '是的,UE5属于场景搭建工具。', '特效和场景就业较好。', '不能。游戏复杂度较高,不是贪吃蛇或推箱子级别,仅靠AI工具容易产生大量Bug,仍需要自己掌握技术。', '没有。机构婉拒了只包带单项目的需求,强调需要系统学习,建议用户自学则去B站找免费课程。', '3D建模和游戏动画课程需要线下到上海总部学习,但其他课程可以通过线上方式进行。', '建议开始听课,两次课可一天完成,周三可跟直播。', '课程方案有:31800元/7个月全日制;11800元/8-10个月。', '作息为周一至周五9:30-12:00、13:30-18:00,晚自习至21:30,周末休息。春节放假两周。', '有的,销售提供了之前网课的录播节选链接:C++试听前5节、Unreal蓝图前三节。', '可寒暑假线下累积学习(7-8个月),在校期间免费开通线上班辅助', '销售人员强调系统学习的重要性,并指出通过教学案例展示,即使是基础较弱的学员也能通过课程提升,建议参考行业采访获取方向,同时展示了学生改画案例佐证教学效果。', '销售人员并未直接给出具体时间规划,但通过介绍游戏相关岗位(如角色原画、3D建模、UE特效/开发等)和系统学习的重要性,暗示学习过程需要长期投入和规划,具体安排建议进一步咨询。', '会问,聚焦AI使用情况及实际落地。', '不能表述为腾讯实习offer,更准确的表述是腾讯实训营offer。实训营含金量还行但不如正式实习。实训营是直接进组学习,而训练营是课程加考核模式。', '建议周四前往上海,周五及周一参观试听,可安排基础班和后阶段班试听;周末教师休息但学生可自习;有学生入职腾讯的案例,可联系现场交流;会提醒孩子注重英语;技术岗位不考研也可,专业培训入行有保障。', '2D原画(游戏角色设计)需从无到有,对绘画功底和创意天赋要求高,竞争激烈,就业不如模型/动画/特效。', '用户决定六月不去上海,等七月学校事情结束后直接去上海报线下班,并计划六月先去参观。', '课程覆盖游戏设计全流程,特效线上课8-10个月,每周2-3次直播(晚7:30-9:30),提供录播和答疑,费用11800元。特效行业需求大,薪资6000-9000元起,需自身具备制作能力,AI是工具而非替代,可推荐就业。', '聊天记录中未提供明确答案,无法生成回答。', '课程不包含Blender/建模内容。销售建议用户学习建模PBR流程及图形学/Shader,并指出TA方向分为美术项和程序项,推荐用户走程序类,但TA岗位稀少。', '第九联盟(点晴科技)提供线上课程11800元/8-10个月和线下课程33800元/6个月全日制,大学生可线上+寒暑假线下结合(按线下收费)。支持包括3年回放和答疑、重读机会,以及简历辅导、模拟面试、测试指导、校招群内推等服务。', '企业招聘不看专业背景,数媒因课程重叠度高;学校教学不足,需额外学习;提供近一年毕业生就业墙作为案例,各专业均有成功就业。', '销售回应行业伪厚涂受欢迎但技法要求高,课程为付费课程,建议先与家长沟通并安排试听以评估基础。', '聊天记录中未明确解释“2个月企业实训”的具体含义,因此无法提供答案。', '全日制公益学习时长为3-5天,具体时间早10晚6,午休90分钟,学习时长视进展而定。', '游戏岗位包括角色原画、3D角色建模、3D道具场景建模(地编)、UE特效、UE开发、动作设计、动画分镜、骨骼绑定。', '销售指出“朝夕拾画”的地编课程可能无法直接就业,其宣传值得怀疑。建议模型+地编的综合学习,并展示了成功学员案例(米哈游offer),强调更实用的学习方向。', '二维分镜涉及的学习方向已通过附图提供。', '试听课是课程节选,基础操作已事先讲过;试听有疑问属正常。', '确认正式课会从零讲解。', '我们仅提供三维课程,无Spine课程。三维是主流方向,且二维需要绘画功底,建议选择三维课程。', '项目老师为管理层,负责分配任务和把控进度,不亲自上手授课。', '王雨晴是川美大二学生,专业为艺术与科技/游戏,方向未定,想先学软件明确目标。销售介绍公司提供原画、角色建模等岗位针对性培训,学习模式为线下寒暑假集训(如暑假+寒假循环),配合作品集,并赠送线上课用于复习。', 'C++不是刚需,但在复杂系统开发中需要掌握。', '该作品属于风格化的写实人物,是综合风格,课程可以达到该水平,如不喜此风格可选择其他方向。', '适合。特效和场景方向不需要美术基础,更适合有逻辑思维的学生,审美可以后期培养。', 'UE5相关有3门课(场景建模地编、UE特效、UE开发),但‘人物动起来’属于动作课,不使用虚幻,用3dmax/Maya,仅线下班,周期6个月,学费31800元。', '聊天记录中未提及课程总节数,无法提供具体答案。', '当前商业应用未使用AI辅助,且AI尚未系统化。', '油屋的课程属于兴趣启蒙,不适合快速入行就业。建议根据理科逻辑思维中等水平选择场景模型课程,包含地编内容,学习周期7个月。', '是的,插班需从第一课开始看,已结束的课程可看录播回放。', '老师解释地编岗位少,模型是重点,但未明确回答是否能完全避免被分去其他班。', '销售答复线上场景建模涉及UE但深度有限,课程为8-10个月,包含3Dmax/Maya、ZBrush等软件及四个阶段,且非纯地编课程,无法保证学员都能成为地编师。', '角色建模主要学习Maya、Toolbag、SP、ZBrush、MD。UE5和3ds Max不是必须的,因为行业强调专精而非杂学。UE5更适合地编方向,3ds Max主要用于场景建模。', 'ZBrush在课程范围内,但犀牛(工业建模)不在课程范围内,课程方向是游戏动画。', '销售推荐了大师课,是纯录播形式,没有老师指导。', '课程中产出的模型作品可以用作地编资产或在UE中渲染展示,实现模型转地编的PBR流程复用。', '开发课线下授课,同步线上直播', '没有独立的寒假班,合班学习效果差且有损口碑。', '无AI课程,地编通常需场景模型师转岗,课程设置是场景模型加地编,综合能力强可直走地编。', '无影响,软件界面从零开始,报名后先进入预科班(从软件界面教起),预科班5月20日启动,已上1节课。', '无影响、可跟上,上一节课有录播回放,支持随时提问。', '直播课是固定时间上课,会有提醒。', '课程针对零基础,涵盖动作设计、场景建模等方向,推荐游戏动画方向,并建议考虑场景建模以规避美术基础劣势。', '适合,销售确认课程针对零基础,并建议用户先专注场景建模方向,约定下班后细聊。', '每个阶段结束都会打出对应分数。', 'UE开发班是纯程序/代码/编程方向,有网课(6月1日新班),线上线下同步授课(周一到周五9:30-12:00,直播+回放),周期6.5个月,线上答疑服务3年。学费13800元,每2-3个月开新班,可免费转班1次。开发主要学习C++、蓝图、图形学。', '点晴科技旗下培训板块‘第九联盟’,合作腾讯、网易、米哈游等,有UE官方培训资质。', '预科班内容为某案例,正课内容待定;正式班预计下月底开课,具体时间不定。', '销售回复线下课程时间灵活,基于学生进度调整,每日固定内容为学习、考试、练习实操。', '销售反驳了此言论,强调学生背景(香港理工大学计算机本科)应走开发以发挥优势,开发岗位有前景,转策划需工作流经验,开发方向是最优化选择。', '我方全天解答,回放终身,解答期3年;王氏固定时间解答。课程差异:我方场景/角色分方向专精学习8个月,产出高质量作品;王氏每个方向仅3个月,只能学简单案例,难以产出系统作品集,校招简历即被筛掉。地编岗位要求80%以上自制资产,王氏课程仅做资产摆放,不满足研发公司需求。我方有校招资源和模拟面试(如3面流程),王氏无此资源,且其学生无校招研发offer。', '原画对新人要求高,需原创和设计能力,建议造型能力强者考虑角色建模。退款政策:7天无理由全额退款,8-30天退一半,超过30天不退,可休学。', '笔记本CPU i7以上、显卡3060以上、内存16G(预算足32G)、固态512G。', '公司提供线上+线下(上海/西安)结合的方案,针对在校生可利用寒暑假和碎片时间学习,线上8-10个月,线下7-8个月。明确教学Maya和ZBrush,不教Blender,分为角色建模和场景建模方向。报名后可立即开通线上课程,线下在上海小班制(15-25人),老师一对一指导。', '是的,UE5属于场景搭建工具。', '建议:丰富简历可考所有证,为就业则非必要,关键在作品质量。', '不能。游戏复杂度较高,不是贪吃蛇或推箱子级别,仅靠AI工具容易产生大量Bug,仍需要自己掌握技术。', '没有。机构婉拒了只包带单项目的需求,强调需要系统学习,建议用户自学则去B站找免费课程。', '3D建模和游戏动画课程需要线下到上海总部学习,但其他课程可以通过线上方式进行。', '建议开始听课,两次课可一天完成,周三可跟直播。', '课程方案有:31800元/7个月全日制;11800元/8-10个月。', '作息为周一至周五9:30-12:00、13:30-18:00,晚自习至21:30,周末休息。春节放假两周。', '有的,销售提供了之前网课的录播节选链接:C++试听前5节、Unreal蓝图前三节。', '可寒暑假线下累积学习(7-8个月),在校期间免费开通线上班辅助', '销售人员强调系统学习的重要性,并指出通过教学案例展示,即使是基础较弱的学员也能通过课程提升,建议参考行业采访获取方向,同时展示了学生改画案例佐证教学效果。', '销售人员并未直接给出具体时间规划,但通过介绍游戏相关岗位(如角色原画、3D建模、UE特效/开发等)和系统学习的重要性,暗示学习过程需要长期投入和规划,具体安排建议进一步咨询。', '会问,聚焦AI使用情况及实际落地。', '不能表述为腾讯实习offer,更准确的表述是腾讯实训营offer。实训营含金量还行但不如正式实习。实训营是直接进组学习,而训练营是课程加考核模式。', '动画特效岗适合基础;地编需综合能力,可从模型岗转;TA难度大需美术+代码。课程为6个月线下周一至周五上课,就业方向以游戏行业为主,有学生入职腾讯、网易、米哈游的案例。', '建议周四前往上海,周五及周一参观试听,可安排基础班和后阶段班试听;周末教师休息但学生可自习;有学生入职腾讯的案例,可联系现场交流;会提醒孩子注重英语;技术岗位不考研也可,专业培训入行有保障。', '2D原画(游戏角色设计)需从无到有,对绘画功底和创意天赋要求高,竞争激烈,就业不如模型/动画/特效。', '课程覆盖游戏设计全流程,特效线上课8-10个月,每周2-3次直播(晚7:30-9:30),提供录播和答疑,费用11800元。特效行业需求大,薪资6000-9000元起,需自身具备制作能力,AI是工具而非替代,可推荐就业。', '聊天记录中未提供明确答案,无法生成回答。', '课程不包含Blender/建模内容。销售建议用户学习建模PBR流程及图形学/Shader,并指出TA方向分为美术项和程序项,推荐用户走程序类,但TA岗位稀少。'], + '其他': ['推荐Wacom品牌,建议购买三五百元价位的即可。', '用户担心大三才学完影响就业,因为听说大二实习转正机会多。销售确认线下可从头学,线上可作预习。', '用户零基础,偏好二维而非三维。', '我们仅提供三维课程,无Spine课程。三维是主流方向,且二维需要绘画功底,建议选择三维课程。', '根据专业关系,游戏美术方向中策划到原画、建模、动作、特效、开发等多个方向,只需选择一方向学习就业,学完推荐就业。模型方向上手快但出作品耗时,特效方向入门稍难但出作品效率高。', '西安有分校区授课;上海总部授课;武汉校区仅做项目(不授课),并非关闭;青岛、厦门、合肥、漯河分公司也仅做项目。', '销售强调AI为辅助工具,需设计能力;指出零基础AIGC培训为割韭菜,企业需求资深人才。', '初级在一线城市薪资约6000-10000元,外派更高。', 'AI无法替代意识流内容,具体AI对行业的影响在聊天记录中没有更详细的阐述。', '不会。AI模型质量差,人工不如重做。叠纸注重情感交互,拒绝AI;网易AI原画遭玩家抵制。行业招聘更看重作品集和设计思路,而非AI技术。', '课程刚开始不必着急,仅需补两三节课程,提醒注意孩子休息。', '回复使用孩子妈妈手机支付。', '品牌名“第九联盟”与公司名“九之盟”为同一体系,是品牌与公司的对应关系。', '无AI课程,地编通常需场景模型师转岗,课程设置是场景模型加地编,综合能力强可直走地编。', '无影响、可跟上,上一节课有录播回放,支持随时提问。', '用户年龄30岁,大专学历,当前从事文旅行业,对游戏动画有兴趣,考虑兼职转行。', '用户31岁,专科影视动画、本科广播电视编导,有原力建模岗位经验(不足2年),因家庭原因离职回乡。销售指出用户年龄较大且零基础转行难度高,但确认原力内培经历使其非零基础,属于转岗。', '作品集质量差是因为学习不到位,有老师审核作品集后才投递,确保质量。', '适合,销售确认课程针对零基础,并建议用户先专注场景建模方向,约定下班后细聊。', '点晴科技旗下培训板块‘第九联盟’,合作腾讯、网易、米哈游等,有UE官方培训资质。', '销售反驳了此言论,强调学生背景(香港理工大学计算机本科)应走开发以发挥优势,开发岗位有前景,转策划需工作流经验,开发方向是最优化选择。', '不适合,该岗位需要能静坐的设计性格。', '建议:丰富简历可考所有证,为就业则非必要,关键在作品质量。', '东北地区(黑吉辽)线下学员较多。', '系统学习后就业可行,但需评估经济压力;建议求职先走外包或动画/影视/手办公司,工作2-3年后薪资预估1.2-1.8w。', '不能表述为腾讯实习offer,更准确的表述是腾讯实训营offer。实训营含金量还行但不如正式实习。实训营是直接进组学习,而训练营是课程加考核模式。', '用户决定六月不去上海,等七月学校事情结束后直接去上海报线下班,并计划六月先去参观。', '课程覆盖游戏设计全流程,特效线上课8-10个月,每周2-3次直播(晚7:30-9:30),提供录播和答疑,费用11800元。特效行业需求大,薪资6000-9000元起,需自身具备制作能力,AI是工具而非替代,可推荐就业。', '若助攻,将在群内艾特。', '先到公司(华东理工科技园G7园区3号楼),会有宿舍老师带领。下午13:30后才可办理后续,届时由其他老师协助填资料并安排宿舍。', '在已获得原公司同意的情况下,确认可行。', '需要准备手绘板与手绘笔,手绘笔通常为配套购买。', '推荐Wacom品牌,建议购买三五百元价位的即可。', '用户担心大三才学完影响就业,因为听说大二实习转正机会多。销售确认线下可从头学,线上可作预习。', '用户零基础,偏好二维而非三维。', '根据专业关系,游戏美术方向中策划到原画、建模、动作、特效、开发等多个方向,只需选择一方向学习就业,学完推荐就业。模型方向上手快但出作品耗时,特效方向入门稍难但出作品效率高。', '销售强调AI为辅助工具,需设计能力;指出零基础AIGC培训为割韭菜,企业需求资深人才。', '初级在一线城市薪资约6000-10000元,外派更高。', 'UE5相关有3门课(场景建模地编、UE特效、UE开发),但‘人物动起来’属于动作课,不使用虚幻,用3dmax/Maya,仅线下班,周期6个月,学费31800元。', '原因是缺乏练习,需要反复实操才能内化知识。', 'AI无法替代意识流内容,具体AI对行业的影响在聊天记录中没有更详细的阐述。', '建议先听软件基础试听课,若仍听不懂则可能不适合。', '公司主要看第一学历,后期提升学历通常不被认可。', '不会。AI模型质量差,人工不如重做。叠纸注重情感交互,拒绝AI;网易AI原画遭玩家抵制。行业招聘更看重作品集和设计思路,而非AI技术。', '课程刚开始不必着急,仅需补两三节课程,提醒注意孩子休息。', '回复使用孩子妈妈手机支付。', '品牌名“第九联盟”与公司名“九之盟”为同一体系,是品牌与公司的对应关系。', '用户年龄30岁,大专学历,当前从事文旅行业,对游戏动画有兴趣,考虑兼职转行。', '用户31岁,专科影视动画、本科广播电视编导,有原力建模岗位经验(不足2年),因家庭原因离职回乡。销售指出用户年龄较大且零基础转行难度高,但确认原力内培经历使其非零基础,属于转岗。', '适合,销售确认课程针对零基础,并建议用户先专注场景建模方向,约定下班后细聊。', '销售反驳了此言论,强调学生背景(香港理工大学计算机本科)应走开发以发挥优势,开发岗位有前景,转策划需工作流经验,开发方向是最优化选择。', '不适合,该岗位需要能静坐的设计性格。', '东北地区(黑吉辽)线下学员较多。', '秋招时间在8-11月,现在学习可能来不及,但可以在学习期间产出作品尝试投递;春招时间来得及。', '用户决定六月不去上海,等七月学校事情结束后直接去上海报线下班,并计划六月先去参观。', '若助攻,将在群内艾特。', '先到公司(华东理工科技园G7园区3号楼),会有宿舍老师带领。下午13:30后才可办理后续,届时由其他老师协助填资料并安排宿舍。', '在已获得原公司同意的情况下,确认可行。'], + '就业支持': ['用户担心大三才学完影响就业,因为听说大二实习转正机会多。销售确认线下可从头学,线上可作预习。', '企业招聘不看专业背景,数媒因课程重叠度高;学校教学不足,需额外学习;提供近一年毕业生就业墙作为案例,各专业均有成功就业。', '销售回应行业伪厚涂受欢迎但技法要求高,课程为付费课程,建议先与家长沟通并安排试听以评估基础。', '油屋的课程属于兴趣启蒙,不适合快速入行就业。建议根据理科逻辑思维中等水平选择场景模型课程,包含地编内容,学习周期7个月。', '公司主要看第一学历,后期提升学历通常不被认可。', '课程周期8-10个月,当前班级(5月14日开课)预计12月结业。内推渠道包括公司自留岗位和合作企业,就业老师会按学历、技术、城市、薪资匹配,测试流程3-5个工作日,并提供面试辅导。', '我方对接内部校招渠道,有学生经十几次模拟面试后进入网易、腾讯。对比王氏:我方是游戏公司,培训以效果为主,老师来自项目组一线,课程从0基础到专精;王氏师资落后,课程杂、效果差,主要面向转行或低学历人群,无校招资源,仅有第三方外派。', '销售确认转线下可行,说明线下学习期间练习量更多,有老师指导,测试通常一周内完成,就业前提供内推服务,以帮助用户提升独立制作能力并顺利求职。', '有专门就业老师负责对接,提供内推服务。', '建议周四前往上海,周五及周一参观试听,可安排基础班和后阶段班试听;周末教师休息但学生可自习;有学生入职腾讯的案例,可联系现场交流;会提醒孩子注重英语;技术岗位不考研也可,专业培训入行有保障。', '秋招时间在8-11月,现在学习可能来不及,但可以在学习期间产出作品尝试投递;春招时间来得及。', '课程覆盖游戏设计全流程,特效线上课8-10个月,每周2-3次直播(晚7:30-9:30),提供录播和答疑,费用11800元。特效行业需求大,薪资6000-9000元起,需自身具备制作能力,AI是工具而非替代,可推荐就业。', '课程结束后提交作品集审核通过可内推就业。', '第九联盟(点晴科技)提供线上课程11800元/8-10个月和线下课程33800元/6个月全日制,大学生可线上+寒暑假线下结合(按线下收费)。支持包括3年回放和答疑、重读机会,以及简历辅导、模拟面试、测试指导、校招群内推等服务。', '用户担心大三才学完影响就业,因为听说大二实习转正机会多。销售确认线下可从头学,线上可作预习。', '企业招聘不看专业背景,数媒因课程重叠度高;学校教学不足,需额外学习;提供近一年毕业生就业墙作为案例,各专业均有成功就业。', '销售指出“朝夕拾画”的地编课程可能无法直接就业,其宣传值得怀疑。建议模型+地编的综合学习,并展示了成功学员案例(米哈游offer),强调更实用的学习方向。', '油屋的课程属于兴趣启蒙,不适合快速入行就业。建议根据理科逻辑思维中等水平选择场景模型课程,包含地编内容,学习周期7个月。', '作品集质量差是因为学习不到位,有老师审核作品集后才投递,确保质量。', '课程周期8-10个月,当前班级(5月14日开课)预计12月结业。内推渠道包括公司自留岗位和合作企业,就业老师会按学历、技术、城市、薪资匹配,测试流程3-5个工作日,并提供面试辅导。', '我方对接内部校招渠道,有学生经十几次模拟面试后进入网易、腾讯。对比王氏:我方是游戏公司,培训以效果为主,老师来自项目组一线,课程从0基础到专精;王氏师资落后,课程杂、效果差,主要面向转行或低学历人群,无校招资源,仅有第三方外派。', '销售确认转线下可行,说明线下学习期间练习量更多,有老师指导,测试通常一周内完成,就业前提供内推服务,以帮助用户提升独立制作能力并顺利求职。', '特效和场景就业较好。', '系统学习后就业可行,但需评估经济压力;建议求职先走外包或动画/影视/手办公司,工作2-3年后薪资预估1.2-1.8w。', '有专门就业老师负责对接,提供内推服务。', '动画特效岗适合基础;地编需综合能力,可从模型岗转;TA难度大需美术+代码。课程为6个月线下周一至周五上课,就业方向以游戏行业为主,有学生入职腾讯、网易、米哈游的案例。', '建议周四前往上海,周五及周一参观试听,可安排基础班和后阶段班试听;周末教师休息但学生可自习;有学生入职腾讯的案例,可联系现场交流;会提醒孩子注重英语;技术岗位不考研也可,专业培训入行有保障。', '秋招时间在8-11月,现在学习可能来不及,但可以在学习期间产出作品尝试投递;春招时间来得及。', '课程覆盖游戏设计全流程,特效线上课8-10个月,每周2-3次直播(晚7:30-9:30),提供录播和答疑,费用11800元。特效行业需求大,薪资6000-9000元起,需自身具备制作能力,AI是工具而非替代,可推荐就业。', '课程结束后提交作品集审核通过可内推就业。'], + '开班时间': ['人满即止,七月份班已有两三人。', '开发课线下授课,同步线上直播', '放假时间为7月初,具体到课时间建议联系段老师确定,后续班主任会沟通具体安排。', '预科班内容为某案例,正课内容待定;正式班预计下月底开课,具体时间不定。', '销售邀请用户于6月1日前入班学习,新班将于6.1开课,用户可据此安排时间。', '人满即止,七月份班已有两三人。', '开发课线下授课,同步线上直播', '放假时间为7月初,具体到课时间建议联系段老师确定,后续班主任会沟通具体安排。', '预科班内容为某案例,正课内容待定;正式班预计下月底开课,具体时间不定。', '公司提供线上+线下(上海/西安)结合的方案,针对在校生可利用寒暑假和碎片时间学习,线上8-10个月,线下7-8个月。明确教学Maya和ZBrush,不教Blender,分为角色建模和场景建模方向。报名后可立即开通线上课程,线下在上海小班制(15-25人),老师一对一指导。', '销售邀请用户于6月1日前入班学习,新班将于6.1开课,用户可据此安排时间。'], + '费用咨询': ['不需要申请出证及支付50元费用,只需查看并签署《线上培训协议11800》即可。', '销售回应行业伪厚涂受欢迎但技法要求高,课程为付费课程,建议先与家长沟通并安排试听以评估基础。', '转介绍激励为800元/人。', '是的,如果尾款不连续交满6个月则没有优惠,需补尾款19800元(原价31800元减去已付12000元)。', '先续三个月需要补款12000元。', 'UE5相关有3门课(场景建模地编、UE特效、UE开发),但‘人物动起来’属于动作课,不使用虚幻,用3dmax/Maya,仅线下班,周期6个月,学费31800元。', '去腾讯实习无额外费用,费用已包含在学费内,具体价格见价格表。', '没有独立的寒假班,合班学习效果差且有损口碑。', 'UE开发班是纯程序/代码/编程方向,有网课(6月1日新班),线上线下同步授课(周一到周五9:30-12:00,直播+回放),周期6.5个月,线上答疑服务3年。学费13800元,每2-3个月开新班,可免费转班1次。开发主要学习C++、蓝图、图形学。', '课程方案有:31800元/7个月全日制;11800元/8-10个月。', '否定回答,并发送价格表。', '课程费用为11800元/人,具体两人报名价格未明确给出。', '课程覆盖游戏设计全流程,特效线上课8-10个月,每周2-3次直播(晚7:30-9:30),提供录播和答疑,费用11800元。特效行业需求大,薪资6000-9000元起,需自身具备制作能力,AI是工具而非替代,可推荐就业。', '第九联盟(点晴科技)提供线上课程11800元/8-10个月和线下课程33800元/6个月全日制,大学生可线上+寒暑假线下结合(按线下收费)。支持包括3年回放和答疑、重读机会,以及简历辅导、模拟面试、测试指导、校招群内推等服务。', '不需要申请出证及支付50元费用,只需查看并签署《线上培训协议11800》即可。', '销售回应行业伪厚涂受欢迎但技法要求高,课程为付费课程,建议先与家长沟通并安排试听以评估基础。', '转介绍激励为800元/人。', '是的,如果尾款不连续交满6个月则没有优惠,需补尾款19800元(原价31800元减去已付12000元)。', '先续三个月需要补款12000元。', '去腾讯实习无额外费用,费用已包含在学费内,具体价格见价格表。', '没有独立的寒假班,合班学习效果差且有损口碑。', 'UE开发班是纯程序/代码/编程方向,有网课(6月1日新班),线上线下同步授课(周一到周五9:30-12:00,直播+回放),周期6.5个月,线上答疑服务3年。学费13800元,每2-3个月开新班,可免费转班1次。开发主要学习C++、蓝图、图形学。', '课程方案有:31800元/7个月全日制;11800元/8-10个月。', '系统学习后就业可行,但需评估经济压力;建议求职先走外包或动画/影视/手办公司,工作2-3年后薪资预估1.2-1.8w。', '否定回答,并发送价格表。', '课程费用为11800元/人,具体两人报名价格未明确给出。', '课程覆盖游戏设计全流程,特效线上课8-10个月,每周2-3次直播(晚7:30-9:30),提供录播和答疑,费用11800元。特效行业需求大,薪资6000-9000元起,需自身具备制作能力,AI是工具而非替代,可推荐就业。'], + '校区地址': ['西安有分校区授课;上海总部授课;武汉校区仅做项目(不授课),并非关闭;青岛、厦门、合肥、漯河分公司也仅做项目。', '上海虹桥、上海站、上海南站均距校区不远。', '机构名称为第九联盟,地址在漕河泾,是点晴科技旗下品牌,主营游戏动漫美术人才孵化。', '3D建模和游戏动画课程需要线下到上海总部学习,但其他课程可以通过线上方式进行。', '总部在上海,青岛有分公司但建议选择总部,因为上海游戏动漫产业最发达。', '西安有分校区授课;上海总部授课;武汉校区仅做项目(不授课),并非关闭;青岛、厦门、合肥、漯河分公司也仅做项目。', '上海虹桥、上海站、上海南站均距校区不远。', '销售回复线下课程时间灵活,基于学生进度调整,每日固定内容为学习、考试、练习实操。', '机构名称为第九联盟,地址在漕河泾,是点晴科技旗下品牌,主营游戏动漫美术人才孵化。', '公司提供线上+线下(上海/西安)结合的方案,针对在校生可利用寒暑假和碎片时间学习,线上8-10个月,线下7-8个月。明确教学Maya和ZBrush,不教Blender,分为角色建模和场景建模方向。报名后可立即开通线上课程,线下在上海小班制(15-25人),老师一对一指导。', '3D建模和游戏动画课程需要线下到上海总部学习,但其他课程可以通过线上方式进行。', '总部在上海,青岛有分公司但建议选择总部,因为上海游戏动漫产业最发达。'], + '退款政策': ['可免费重修,但强调一次即可学成。', '7天无理由退全款,30天内退一半,之后不退。', '原画对新人要求高,需原创和设计能力,建议造型能力强者考虑角色建模。退款政策:7天无理由全额退款,8-30天退一半,超过30天不退,可休学。', '5月27日起7天内可无理由全额退款。', '可免费重修,但强调一次即可学成。', '是的,如果尾款不连续交满6个月则没有优惠,需补尾款19800元(原价31800元减去已付12000元)。', '7天无理由退全款,30天内退一半,之后不退。', '原画对新人要求高,需原创和设计能力,建议造型能力强者考虑角色建模。退款政策:7天无理由全额退款,8-30天退一半,超过30天不退,可休学。', '5月27日起7天内可无理由全额退款。'], + '优惠活动': ['是的,如果尾款不连续交满6个月则没有优惠,需补尾款19800元(原价31800元减去已付12000元)。', '报名线下班会额外赠送一套线上正式课程,线上课程可让学生在校提前打基础,寒暑假可集中线下学习直接入班。该课程也可以结合线上内容赶时间进度。', '课程费用为11800元/人,具体两人报名价格未明确给出。', '报名线下班会额外赠送一套线上正式课程,线上课程可让学生在校提前打基础,寒暑假可集中线下学习直接入班。该课程也可以结合线上内容赶时间进度。', '课程费用为11800元/人,具体两人报名价格未明确给出。'], + '报名流程': ['两种模式:先线上后补差价转线下,或直接全款预留线下位置。线上课程8-10个月,学费11800元,含直播(每周三次,19:30-21:30)、录播、老师答疑及就业辅导。', '需要填写姓名、学历、学校、城市、出生日期、学习目的、联系方式等信息。', '销售确认信息有效后,会同意安排。', '用户同意入班。', '不需要申请出证及支付50元费用,只需查看并签署《线上培训协议11800》即可。', '两种模式:先线上后补差价转线下,或直接全款预留线下位置。线上课程8-10个月,学费11800元,含直播(每周三次,19:30-21:30)、录播、老师答疑及就业辅导。', '需要填写姓名、学历、学校、城市、出生日期、学习目的、联系方式等信息。', '销售确认信息有效后,会同意安排。', '用户同意入班。'], + '报到时间': ['30日是周六,无法对接班主任,建议与家人确定后尽早来。', '30日是周六,无法对接班主任,建议与家人确定后尽早来。'], + '住宿咨询': ['30日是周六,无法对接班主任,建议与家人确定后尽早来。', '合作宿舍约1000元/月,4/6人间,按空房分配。', '不需要,上海有宿舍可选,分4人间和6人间,费用约1000元/月;也可以自行租房,单间费用约2000-3000元/月。', '先到公司(华东理工科技园G7园区3号楼),会有宿舍老师带领。下午13:30后才可办理后续,届时由其他老师协助填资料并安排宿舍。', '30日是周六,无法对接班主任,建议与家人确定后尽早来。', '合作宿舍约1000元/月,4/6人间,按空房分配。', '不需要,上海有宿舍可选,分4人间和6人间,费用约1000元/月;也可以自行租房,单间费用约2000-3000元/月。', '先到公司(华东理工科技园G7园区3号楼),会有宿舍老师带领。下午13:30后才可办理后续,届时由其他老师协助填资料并安排宿舍。'], + '上课方式': ['可寒暑假线下累积学习(7-8个月),在校期间免费开通线上班辅助', '可寒暑假线下累积学习(7-8个月),在校期间免费开通线上班辅助'], + '职业方向': ['动画特效岗适合基础;地编需综合能力,可从模型岗转;TA难度大需美术+代码。课程为6个月线下周一至周五上课,就业方向以游戏行业为主,有学生入职腾讯、网易、米哈游的案例。'], + '课程建议': ['动画特效岗适合基础;地编需综合能力,可从模型岗转;TA难度大需美术+代码。课程为6个月线下周一至周五上课,就业方向以游戏行业为主,有学生入职腾讯、网易、米哈游的案例。'] +} + for k in intent_dict: + intent_res( k,intent_dict[k]) diff --git a/app/chat_qa/classification/intent_test.py b/app/chat_qa/classification/intent_test.py new file mode 100644 index 0000000..8f3b0f9 --- /dev/null +++ b/app/chat_qa/classification/intent_test.py @@ -0,0 +1,113 @@ +import asyncio +from typing import List, Dict, Any + +from app.repository.milvus.intent_classification_repository import IntentClassificationRepository +from app.client.embedding_client_manager import embedding_client + + +INTENT_DATA = { + "课程内容": [ + "课程针对零基础,涵盖动作设计、场景建模等方向,推荐游戏动画方向,并建议考虑场景建模以规避美术基础劣势。", + "UE5相关有3门课(场景建模地编、UE特效、UE开发),但'人物动起来'属于动作课,不使用虚幻,用3dmax/Maya,仅线下班,周期6个月,学费31800元。" + ], + "其他": [ + "课程覆盖游戏设计全流程,特效线上课8-10个月,每周2-3次直播(晚7:30-9:30),提供录播和答疑,费用11800元。特效行业需求大,薪资6000-9000元起,需自身具备制作能力,AI是工具而非替代,可推荐就业。", + "UE5相关有3门课(场景建模地编、UE特效、UE开发),但'人物动起来'属于动作课,不使用虚幻,用3dmax/Maya,仅线下班,周期6个月,学费31800元。" + ], + "就业支持": [ + "课程周期8-10个月,当前班级(5月14日开课)预计12月结业。内推渠道包括公司自留岗位和合作企业,就业老师会按学历、技术、城市、薪资匹配,测试流程3-5个工作日,并提供面试辅导。", + "有专门就业老师负责对接,提供内推服务。" + ], + "开班时间": [ + "销售邀请用户于6月1日前入班学习,新班将于6.1开课,用户可据此安排时间。", + "人满即止,七月份班已有两三人。" + ], + "费用咨询": [ + "第九联盟(点晴科技)提供线上课程11800元/8-10个月和线下课程33800元/6个月全日制,大学生可线上+寒暑假线下结合(按线下收费)。支持包括3年回放和答疑、重读机会,以及简历辅导、模拟面试、测试指导、校招群内推等服务。", + "课程方案有:31800元/7个月全日制;11800元/8-10个月。" + ], + "校区地址": [ + "西安有分校区授课;上海总部授课;武汉校区仅做项目(不授课),并非关闭;青岛、厦门、合肥、漯河分公司也仅做项目。", + "机构名称为第九联盟,地址在漕河泾,是点晴科技旗下品牌,主营游戏动漫美术人才孵化。" + ], + "退款政策": ['原画对新人要求高,需原创和设计能力,建议造型能力强者考虑角色建模。退款政策:7天无理由全额退款,8-30天退一半,超过30天不退,可休学。', '7天无理由退全款,30天内退一半,之后不退。', '5月27日起7天内可无理由全额退款。'], + "优惠活动": [ + "是的,如果尾款不连续交满6个月则没有优惠,需补尾款19800元(原价31800元减去已付12000元)。", + "报名线下班会额外赠送一套线上正式课程,线上课程可让学生在校提前打基础,寒暑假可集中线下学习直接入班。该课程也可以结合线上内容赶时间进度。" + ], + "报名流程": [ + "两种模式:先线上后补差价转线下,或直接全款预留线下位置。线上课程8-10个月,学费11800元,含直播(每周三次,19:30-21:30)、录播、老师答疑及就业辅导。", + "需要填写姓名、学历、学校、城市、出生日期、学习目的、联系方式等信息。" + ], + "报到时间": [ + "建议与家人确定后尽早来。" + ], + "住宿咨询": [ + "合作宿舍约1000元/月,4/6人间,按空房分配。", + "不需要,上海有宿舍可选,分4人间和6人间,费用约1000元/月;也可以自行租房,单间费用约2000-3000元/月。" + ], + "上课方式": ['可寒暑假线下累积学习(7-8个月),在校期间免费开通线上班辅助', '可寒暑假线下累积学习(7-8个月),在校期间免费开通线上班辅助'], + "职业方向": [ + "动画特效岗适合基础;地编需综合能力,可从模型岗转;TA难度大需美术+代码。课程为6个月线下周一至周五上课,就业方向以游戏行业为主,有学生入职腾讯、网易、米哈游的案例。" + ], + "课程建议": [ + "动画特效岗适合基础;地编需综合能力,可从模型岗转;TA难度大需美术+代码。课程为6个月线下周一至周五上课,就业方向以游戏行业为主,有学生入职腾讯、网易、米哈游的案例。" + ] +} + + +async def insert_intent_data(): + """ + 将意图分类数据入库到Milvus + """ + repo = IntentClassificationRepository() + + repo.create_collection() + + all_data = [] + all_contents = [] + + for category, contents in INTENT_DATA.items(): + for content in contents: + all_data.append({ + "intent_category": category, + "content": content + }) + all_contents.append(content) + + print(f"开始向量化 {len(all_contents)} 条内容...") + vectors = await embedding_client.aembed_documents(all_contents) + print(f"向量化完成") + + for i, item in enumerate(all_data): + item["content_vector"] = vectors[i] + + ids = await repo.save_intent_data(all_data) + print(f"入库成功,插入 {len(ids)} 条记录") + + return ids + + +async def query_by_category(category: str): + """ + 根据意图类别查询 + """ + repo = IntentClassificationRepository() + results = await repo.search_by_intent_category(category) + print(f"\n查询 '{category}' 结果:") + for i, item in enumerate(results): + print(f" {i+1}. {item.get('content', '')[:50]}...") + + +async def main(): + print("=== 意图分类数据入库 ===") + await insert_intent_data() + + # print("\n=== 查询测试 ===") + # await query_by_category("课程内容") + # await query_by_category("就业支持") + # await query_by_category("费用咨询") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/app/chat_qa/deduplication_qa/message_qa.py b/app/chat_qa/deduplication_qa/message_qa.py index 999f44c..9d40826 100644 --- a/app/chat_qa/deduplication_qa/message_qa.py +++ b/app/chat_qa/deduplication_qa/message_qa.py @@ -73,5 +73,5 @@ async def save_qa_milvus(file_path:str): milvus_client.close() if __name__ == '__main__': - file_path=r"E:\qa_output\data.txt" + file_path=r"E:\qa_output\test.txt" asyncio.run(save_qa_milvus(file_path)) \ No newline at end of file diff --git a/app/chat_qa_query/query_graph.py b/app/chat_qa_query/query_graph.py index f974cc3..de83287 100644 --- a/app/chat_qa_query/query_graph.py +++ b/app/chat_qa_query/query_graph.py @@ -45,13 +45,13 @@ if __name__ == '__main__': archive_messages_mysql_repository = ArchiveMessagesRepository(db_session) qa_milvus_repository = QARepository() - state: QueryQAState = QueryQAState(original_query="暂时有点忙", history=['2026-05-26T13:14:59 EXTERNAL 暂时有点忙\n', '2026-05-26T12:48:09 INTERNAL 下午好呀 你这边怎么计划的呀 考虑跟咱们6月1号的班级学习嘛\n']) + state: QueryQAState = QueryQAState(original_query="老师这个课程多少钱啊,老师 我想报班,", history=['2026-07-10T15:42:13 EXTERNAL 老师这个课程多少钱啊\n', '2026-07-10T15:40:34 EXTERNAL 老师 我想报班\n']) context = QueryQAContext(meta_mysql_repository=archive_messages_mysql_repository, qa_milvus_repository=qa_milvus_repository ) async for chunk in qa_graph.astream(input=state, context=context, stream_mode="custom"): - print("=================="+chunk) - + for item in chunk: + print("=================="+item) milvus_client.close() await embedding_client.close() diff --git a/app/chat_qa_query/query_nodes/node_answer_output.py b/app/chat_qa_query/query_nodes/node_answer_output.py index cc11b4b..35fb313 100644 --- a/app/chat_qa_query/query_nodes/node_answer_output.py +++ b/app/chat_qa_query/query_nodes/node_answer_output.py @@ -1,16 +1,18 @@ """ - """ from langgraph.runtime import Runtime +from typing import List, Dict, Any from app.chat_qa_query.query_qa_state import QueryQAState -async def answer_output(state:QueryQAState, runtime: Runtime): +async def answer_output(state: QueryQAState, runtime: Runtime): writer = runtime.stream_writer - qa_pairs = state.get("qa_pairs", "") - if qa_pairs: - writer(qa_pairs.get("answer")) + qa_pairs = state.get("qa_pairs", []) + + if qa_pairs and isinstance(qa_pairs, list): + content_list = [item.get("content", "") for item in qa_pairs if item.get("content")] + writer(content_list) else: - writer("") \ No newline at end of file + writer([]) \ No newline at end of file diff --git a/app/chat_qa_query/query_nodes/node_rewrite.py b/app/chat_qa_query/query_nodes/node_rewrite.py index d4b463d..a909645 100644 --- a/app/chat_qa_query/query_nodes/node_rewrite.py +++ b/app/chat_qa_query/query_nodes/node_rewrite.py @@ -9,9 +9,9 @@ from app.llm import llm from app.core.log import logger problem_rewriting_prompt = """ -你是一名智能客服意图理解助手。你的任务是根据用户的历史会话和当前问题,提取用户的核心诉求,并将其改写为一个语义完整、信息自包含的独立问题。 +你是一名智能客服意图分类助手。你的任务是根据用户的历史会话和当前问题,提取用户的核心诉求,并输出标准化的意图标签。 -## 改写规则(必须严格遵守) +## 分类规则(必须严格遵守) 1. **核心诉求提取**: - 从当前问题中提取用户明确表达的诉求(可能有一个或多个,去重) @@ -19,7 +19,7 @@ problem_rewriting_prompt = """ 2. **信息补全**: - 如果当前问题缺少主语或关键上下文(如只问"费用多少"),必须从历史会话中提取相关主题补全 - - 改写后的问题必须是一个**不依赖历史会话也能被独立理解**的完整问题 + - 确保意图标签不依赖历史会话也能被独立理解 3. **语义保持**: - 不得改变用户的原始意图 @@ -28,17 +28,27 @@ problem_rewriting_prompt = """ 4. **输出格式**: - 仅输出JSON,不要任何解释性文字 + - 输出为结构化的意图标签数组,**不要改写成完整问句** + - 每个意图标签应简洁、标准化,适合用于分类路由 + - 多诉求时拆分为多个意图标签,用数组形式输出 -## 改写示例 +## 意图标签规范 + +- 每个标签格式为:"{{诉求类型}}" +- 常见诉求类型:费用咨询、课程内容、报名流程、就业支持、开班时间、校区地址、优惠活动、退款政策、住宿咨询、其他 +- 标签应简洁、无歧义,便于系统直接匹配路由 +- 从当前问题中提取用户明确表达的诉求,可以提取多个意图标签 + +## 分类示例 ### 示例1(信息补全) 历史会话: - 用户:我想了解游戏特效培训 - 助手:好的,请问您想了解哪方面? 当前问题:培训的费用 -改写结果: +分类结果: {{ - "rewritten_query": "游戏特效培训的费用是多少?" + "intents": "费用咨询" }} ### 示例2(指代消解) @@ -46,40 +56,43 @@ problem_rewriting_prompt = """ - 用户:你们有Python课程吗? - 助手:有的,我们有Python基础班和进阶班。 当前问题:这个课程的时长是多久? -改写结果: +分类结果: {{ - "rewritten_query": "Python课程的时长是多久?" + "intents": ["课程内容", "报名流程"] }} ### 示例3(多诉求提取) 历史会话: - 用户:我想报名数据分析培训 当前问题:流程、费用和就业支持 -改写结果: +分类结果: {{ - "rewritten_query": "数据分析培训的报名流程、费用以及就业支持分别是什么?" + "intents": ["报名流程"] }} ### 示例4(无需改写) 历史会话:(空) 当前问题:Java培训的课程内容有哪些? -改写结果: +分类结果: {{ - "rewritten_query": "Java培训的课程内容有哪些?" + "intents": ["课程内容"] +}} + +### 示例5(用户提供的案例) +历史会话:(空) +当前问题:老师这个课程多少钱啊,老师我想报班 +分类结果: +{{ + "intents": ["报名流程"] }} --- ## 现在请处理以下输入 -历史会话: -{history_text} -历史会话字段说明: -EXTERNAL:客户 -INTERNAL:销售 当前问题:{query} - +历史聊天:{history_text} 请直接输出JSON: """ @@ -92,14 +105,16 @@ async def rewrite_query(state:QueryQAState): """ history_text = state.get("history", "") query = state.get("original_query", "") - logger.info(f"问题改写:{query},历史会话:{history_text}") prompt = PromptTemplate(template=problem_rewriting_prompt, input_variables=["history_text", "query"]) output = JsonOutputParser() chain = prompt | llm | output try: result = await chain.ainvoke({"history_text": history_text, "query": query}) - rewritten_query = result.get("rewritten_query", "") + rewritten_query = result.get("intents", "") + if rewritten_query: + rewritten_query = rewritten_query[0] + logger.info(f"原问题:{query},历史会话:{history_text},改写后问题:{rewritten_query}") return {"rewritten_query": rewritten_query} except Exception as e: logger.error(f"QA质量检查prompt模板错误:{e}") diff --git a/app/chat_qa_query/query_nodes/node_search_embedding.py b/app/chat_qa_query/query_nodes/node_search_embedding.py index 88a2493..8286a54 100644 --- a/app/chat_qa_query/query_nodes/node_search_embedding.py +++ b/app/chat_qa_query/query_nodes/node_search_embedding.py @@ -1,29 +1,31 @@ """ 向量化 """ +from typing import List, Dict, Any + from app.chat_qa_query.query_qa_state import QueryQAState from app.client.embedding_client_manager import embedding_client +from app.repository.milvus.intent_classification_repository import IntentClassificationRepository from app.repository.milvus.message_qa_repository import QARepository from app.core.log import logger -async def search_embed(state:QueryQAState) : - logger.info("search_embed") - rewritten_query = state.get("rewritten_query", "") - original_query = state.get("original_query", "") +async def search_embed(state: QueryQAState): + logger.info("search_embed") + rewritten_query = state.get("rewritten_query", "") + original_query = state.get("original_query", "") - batch_embeddings = await embedding_client.aembed_query(rewritten_query) - qa_repository = QARepository() - - result = await qa_repository.search_qa(query_vector=batch_embeddings, top_k=3) - logger.info(f"原始问题:{original_query},改写后的问题:{rewritten_query},匹配结果:{result}") - if result: - question = result[0]["question"] - answer = result[0]["answer"] - - qa_pairs={ - "question": question, - "answer": answer, - } - return {"qa_pairs": qa_pairs} - return {} \ No newline at end of file + #batch_embeddings = await embedding_client.aembed_query(rewritten_query) + intent_class = IntentClassificationRepository() + result: List[Dict[str, Any]] = await intent_class.search_by_intent_category(intent_category=rewritten_query, top_k=3) + logger.info(f"原始问题:{original_query},改写后的问题:{rewritten_query},匹配结果:{result}") + + qa_pairs = [] + for item in result: + qa_pairs.append({ + "intent_category": item.get("intent_category", ""), + "content": item.get("content", ""), + "score": item.get("score", 0) + }) + + return {"qa_pairs": qa_pairs} \ No newline at end of file diff --git a/app/chat_qa_query/service/query_qa_service.py b/app/chat_qa_query/service/query_qa_service.py index 3341a97..253838c 100644 --- a/app/chat_qa_query/service/query_qa_service.py +++ b/app/chat_qa_query/service/query_qa_service.py @@ -23,6 +23,11 @@ class QueryQAService: context = QueryQAContext(archive_mysql_repository=self.archive_mysql_repository,qa_milvus_repository=self.qa_milvus_repository) try: res= await qa_graph.ainvoke(input=state, context=context, stream_mode="custom") + logger.info(f"QA服务结果:{res}") + + if isinstance(res, list) and len(res) == 1 and isinstance(res[0], list): + res = res[0] + return res except Exception as e: diff --git a/app/repository/milvus/message_qa_repository.py b/app/repository/milvus/message_qa_repository.py index 8195f98..48957ca 100644 --- a/app/repository/milvus/message_qa_repository.py +++ b/app/repository/milvus/message_qa_repository.py @@ -129,6 +129,7 @@ class QARepository: # res 是二维结构:[ [单条结果列表] ] for hits in res: for hit in hits: + print("hit:", hit) if hit.get("distance",0) >= score_threshold: # 按需组装数据 item = { diff --git a/readme b/readme index 49dca54..7292609 100644 --- a/readme +++ b/readme @@ -1,3 +1,4 @@ + 进入虚拟环境 启动:nohup uvicorn app.uvicorn_main:app --host 0.0.0.0 --port 8000 --workers 1 > uvicorn.log 2>&1 & 打包:py package.py 同步库+虚拟环境:uv sync