feat: 意图识别优化

This commit is contained in:
qinyong@9artedu.com 2026-07-14 16:29:59 +08:00
parent 23ec184ab0
commit 20c7d1a25f
8 changed files with 894 additions and 114 deletions

View File

@ -1,73 +1,70 @@
import asyncio import asyncio
from typing import List, Dict, Any import json
from pathlib import Path
from typing import Dict, List
from app.repository.milvus.intent_classification_repository import IntentClassificationRepository from app.repository.milvus.intent_classification_repository import IntentClassificationRepository
from app.client.embedding_client_manager import embedding_client from app.client.embedding_client_manager import embedding_client
from app.client.milvus_client_manager import milvus_client
INTENT_DATA = { QA_JSON_PATH = Path(__file__).parent / "qa.json"
"课程内容": [
"课程针对零基础,涵盖动作设计、场景建模等方向,推荐游戏动画方向,并建议考虑场景建模以规避美术基础劣势。",
"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(): def parse_qa_json(file_path: Path = None) -> Dict[str, List[str]]:
"""
解析 qa.json 文件key 对应 intent_categoryvalue 对应 content
"""
if file_path is None:
file_path = QA_JSON_PATH
print(f"读取文件: {file_path}")
if not file_path.exists():
print(f"文件不存在: {file_path}")
return {}
content = file_path.read_text(encoding="utf-8")
try:
data = json.loads(content)
except json.JSONDecodeError as e:
print(f"JSON 解析失败: {e}")
return {}
result: Dict[str, List[str]] = {}
for key, value in data.items():
if isinstance(value, str):
result[key] = [value]
elif isinstance(value, list):
result[key] = [str(item) for item in value]
else:
result[key] = [json.dumps(value, ensure_ascii=False)]
print(f"解析成功,共 {len(result)} 个类别")
return result
async def insert_intent_data(intent_data: Dict[str, List[str]] = None):
""" """
将意图分类数据入库到Milvus 将意图分类数据入库到Milvus
""" """
if intent_data is None:
intent_data = parse_qa_json()
if not intent_data:
print("没有数据可入库")
return []
repo = IntentClassificationRepository() repo = IntentClassificationRepository()
milvus_client.init()
repo.create_collection() repo.create_collection()
all_data = [] all_data = []
all_contents = [] all_contents = []
for category, contents in INTENT_DATA.items(): for category, contents in intent_data.items():
for content in contents: for content in contents:
all_data.append({ all_data.append({
"intent_category": category, "intent_category": category,
@ -75,17 +72,48 @@ async def insert_intent_data():
}) })
all_contents.append(content) all_contents.append(content)
print(f"开始向量化 {len(all_contents)} 条内容...") total = len(all_contents)
vectors = await embedding_client.aembed_documents(all_contents) print(f"开始向量化 {total} 条内容...")
print(f"向量化完成")
batch_size = 5
all_vectors = []
for start in range(0, total, batch_size):
end = min(start + batch_size, total)
batch = all_contents[start:end]
batch_num = start // batch_size + 1
total_batches = (total + batch_size - 1) // batch_size
print(f" 向量化批次 {batch_num}/{total_batches}: {len(batch)}")
vectors = await embedding_client.aembed_documents(batch)
print(f" 返回 {len(vectors)} 个向量")
if len(vectors) != len(batch):
print(f" 警告: 向量数量不匹配 (期望 {len(batch)}, 实际 {len(vectors)}),尝试逐条向量化")
for single_text in batch:
single_vector = await embedding_client.aembed_documents([single_text])
if single_vector:
all_vectors.append(single_vector[0])
print(f" 单条成功: {single_text[:30]}...")
else:
print(f" 单条失败,跳过: {single_text[:30]}...")
else:
all_vectors.extend(vectors)
print(f"向量化完成,共 {len(all_vectors)} 个向量")
if len(all_vectors) != len(all_data):
print(f"警告: 向量数量({len(all_vectors)})与数据数量({len(all_data)})不匹配,仅入库成功的数据")
all_data = all_data[:len(all_vectors)]
for i, item in enumerate(all_data): for i, item in enumerate(all_data):
item["content_vector"] = vectors[i] item["content_vector"] = all_vectors[i]
try:
ids = await repo.save_intent_data(all_data) ids = await repo.save_intent_data(all_data)
print(f"入库成功,插入 {len(ids)} 条记录") print(f"入库成功,插入 {len(ids)} 条记录")
return ids return ids
finally:
await embedding_client.close()
async def query_by_category(category: str): async def query_by_category(category: str):
@ -96,17 +124,22 @@ async def query_by_category(category: str):
results = await repo.search_by_intent_category(category) results = await repo.search_by_intent_category(category)
print(f"\n查询 '{category}' 结果:") print(f"\n查询 '{category}' 结果:")
for i, item in enumerate(results): for i, item in enumerate(results):
print(f" {i+1}. {item.get('content', '')[:50]}...") print(f" {i+1}. {item.get('content', '')[:80]}...")
async def main(): async def main():
print("=== 意图分类数据入库 ===") print("=== 读取 qa.json 并入库 ===")
await insert_intent_data()
# print("\n=== 查询测试 ===") intent_data = parse_qa_json()
# await query_by_category("课程内容")
# await query_by_category("就业支持") if intent_data:
# await query_by_category("费用咨询") print(f"\n解析到的类别 ({len(intent_data)} 个):")
for category, contents in intent_data.items():
print(f" {category}: {len(contents)} 条内容")
for content in contents:
print(f" -> {content[:80]}...")
await insert_intent_data(intent_data)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -0,0 +1,31 @@
{
"公司介绍": "[\"母公司点睛科技成立于2013年是一家专业的数字艺术教育机构。旗下品牌第九联盟和GGAC专注于CG游戏、动漫、影视等数字艺术教育提供原画、3D建模、动画、特效等核心课程与腾讯、网易、米哈游、盛趣、莉莉丝等数百家游戏企业有人才合作校区分布有上海、西安、青岛、厦门等校区地址相关网站https://www.alchemyart.com.cn/ 、https://9artedu.com/ 、https://www.ggac.com/home\"]",
"课程咨询": "[\"3D建模、2D原画、动作/分镜、游戏特效、开发、3D大师课、GGAC绘啦课程、兴趣/提升班等课程体系,课程不同相关的价格和内容也有所不同,如果需要了解某一个课程,请告诉我课程名称\"]",
"3D建模": "{\"3D场景建模\": {\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"7个月\", \"价格\": \"31800元\"}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"8-10个月\", \"价格\": \"11800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校开通线上服务\", \"价格\": \"31800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"回校开通线上直播与答疑学习服务\"]}], \"课程介绍链接\": \"https://www.9artedu.com/3d/\"}, \"3D角色建模\": {\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"8个月\", \"价格\": \"33800元\"}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"8-10个月\", \"价格\": \"11800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校开通线上服务\", \"价格\": \"33800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"回校开通线上直播与答疑学习服务\"]}], \"课程介绍链接\": \"https://www.9artedu.com/3d-role/\"}}",
"3D场景建模": "{\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"7个月\", \"价格\": \"31800元\"}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"8-10个月\", \"价格\": \"11800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校开通线上服务\", \"价格\": \"31800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"回校开通线上直播与答疑学习服务\"]}], \"课程介绍链接\": \"https://www.9artedu.com/3d/\"}",
"3D角色建模": "{\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"8个月\", \"价格\": \"33800元\"}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"8-10个月\", \"价格\": \"11800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校开通线上服务\", \"价格\": \"33800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"回校开通线上直播与答疑学习服务\"]}], \"课程介绍链接\": \"https://www.9artedu.com/3d-role/\"}",
"2D原画": "{\"2D角色原画\": {\"二次元风格\": {\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"6个月\", \"价格\": \"31800元\"}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"8-10个月\", \"价格\": \"11800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校开通线上服务\", \"价格\": \"31800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"以线下学习时间为主,回校开通线上直播与答疑学习服务\"]}]}, \"写实风格\": {\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"6个月\", \"价格\": \"31800元\", \"备注\": [\"项目组实训教学\"]}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"8-10个月\", \"价格\": \"11800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校开通线上服务\", \"价格\": \"31800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"以线下学习时间为主,回校开通线上直播与答疑学习服务\"]}]}, \"介绍链接\": \"https://www.9artedu.com/2d\"}}",
"二次元风格": "{\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"6个月\", \"价格\": \"31800元\"}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"8-10个月\", \"价格\": \"11800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校开通线上服务\", \"价格\": \"31800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"以线下学习时间为主,回校开通线上直播与答疑学习服务\"]}]}",
"写实风格": "{\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"6个月\", \"价格\": \"31800元\", \"备注\": [\"项目组实训教学\"]}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"8-10个月\", \"价格\": \"11800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校开通线上服务\", \"价格\": \"31800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"以线下学习时间为主,回校开通线上直播与答疑学习服务\"]}]}",
"动作/分镜": "{\"游戏动作/分镜\": {\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"6个月\", \"价格\": \"33800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校提供线上答疑指导\", \"价格\": \"31800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"以线下学习时间为主,回校做练习提供线上答疑指导服务\"]}], \"介绍链接\": \"https://www.9artedu.com/animation/\"}}",
"游戏动作/分镜": "{\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"6个月\", \"价格\": \"33800元\"}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校提供线上答疑指导\", \"价格\": \"31800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"以线下学习时间为主,回校做练习提供线上答疑指导服务\"]}], \"介绍链接\": \"https://www.9artedu.com/animation/\"}",
"开发": "{\"UE引擎开发\": {\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"6个月\", \"价格\": \"33800元\", \"备注\": [\"以线下学习时间为主,回校开通线上直播与答疑学习服务\"]}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校提供线上答疑指导\", \"价格\": \"33800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"以线下学习时间为主,回校做练习提供线上答疑指导服务\"]}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"6-8个月\", \"价格\": \"13800元\", \"备注\": [\"白天线上授课及答疑\"]}], \"介绍链接\": \"https://www.9artedu.com/ue/\"}}",
"UE引擎开发": "{\"课程列表\": [{\"课程类型\": \"线下就业班\", \"学习时长\": \"6个月\", \"价格\": \"33800元\", \"备注\": [\"以线下学习时间为主,回校开通线上直播与答疑学习服务\"]}, {\"课程类型\": \"线上线下结合就业班\", \"学习时长\": \"线下寒暑假学习,回校提供线上答疑指导\", \"价格\": \"33800元\", \"备注\": [\"限大一大二大三在校生\", \"线下寒暑假学习送线上\", \"以线下学习时间为主,回校做练习提供线上答疑指导服务\"]}, {\"课程类型\": \"线上就业班\", \"学习时长\": \"6-8个月\", \"价格\": \"13800元\", \"备注\": [\"白天线上授课及答疑\"]}], \"介绍链接\": \"https://www.9artedu.com/ue/\"}",
"3D大师课": "{\"介绍\": \"第九联盟联合十余位3D美术大咖针对紧缺技术方向设课。涵盖场景、角色、Blender动画全流程16位老师精讲11大主题直播可回放赠入门课总课时超300小时。\", \"课程形式\": \"直播教学、同步录播\", \"课程链接\": {\"第三期\": \"https://www.huilahujila.com/3ddsk3.0/pc/\", \"第二期\": \"https://www.ggac.com/v2/edu/dsk\", \"第一期\": \"http://m.9artedu.com/\"}, \"合适人群\": [\"在校大学生\", \"在职从业者\", \"兴趣爱好\", \"预算较少\"], \"课程设置\": {\"基础课\": [\"软件基础教学\", \"结合案例、物件制作\"], \"进阶课\": [\"深度系统教学,直播+录播+答疑,性价比高非常适合小白\", \"多个流行技术点\"], \"就业课\": \"邀请行业大厂hr和制作负责人进行就业分享\"}, \"优势\": [\"价格实惠 - 1500-2500\", \"性价比高\", \"顶尖师资\", \"系统化全流程教学\"], \"费用\": \"1580-2500\"}",
"GGAC绘殓课程": "{\"造型力\": {\"课程详细链接\": \"https://www.9artedu.com/xinqi/\", \"适合人群\": [\"从业者提升\", \"美院学生\"], \"费用\": {\"旁听席(不单独改作业)\": \"4500元\", \"vip\": \"6800元\"}}, \"大学生扶持计划\": {\"课程亮点\": [\"一线大厂亲授,全流程实战,直播可回放,作业答疑超值。\"], \"适合人群\": [\"预算少\", \"在校生\", \"兴趣学生\", \"作品集\"], \"优势\": [\"费用低\", \"师资强\", \"服务号\", \"系统教学\"], \"费用\": \"2500元\", \"链接\": \"\"}}",
"造型力": "{\"课程详细链接\": \"https://www.9artedu.com/xinqi/\", \"适合人群\": [\"从业者提升\", \"美院学生\"], \"费用\": {\"旁听席(不单独改作业)\": \"4500元\", \"vip\": \"6800元\"}}",
"大学生扶持计划": "{\"课程亮点\": [\"一线大厂亲授,全流程实战,直播可回放,作业答疑超值。\"], \"适合人群\": [\"预算少\", \"在校生\", \"兴趣学生\", \"作品集\"], \"优势\": [\"费用低\", \"师资强\", \"服务号\", \"系统教学\"], \"费用\": \"2500元\", \"链接\": \"\"}",
"兴趣/提升班": "{\"线下面授\": [{\"时长\": \"2个月\", \"价格\": \"13800元\"}, {\"时长\": \"3个月\", \"价格\": \"19800元\"}], \"备注\": \"无推荐就业服务\"}",
"学习模式": "{\"线下面授教学\": {\"上课时间\": {\"时段\": \"9:30-18:00\", \"日期\": \"周一到周五\"}, \"自习时间\": {\"时段\": \"18:00-22:30\", \"安排\": \"周末自行安排\", \"备注\": \"入学录入指纹,学员可随时自行出入\"}}, \"线上直播教学\": {\"上课时间\": {\"课次\": \"135或245晚\", \"时段\": \"19:30-21:30\"}, \"直播教学\": \"最多跟两期\", \"同步录播\": \"反复回放,永久有效\"}, \"寒暑假\": {\"上课形式\": {\"假期安排\": \"寒暑假线下面授教学\", \"回校安排\": \"回校开通线上直播、录播课程持续学习,线上答疑与指导\", \"上课时间\": \"同线上模式\"}, \"课时统计\": \"以线下实际授课市场为准,线上赠送\"}}",
"线下面授教学": "{\"上课时间\": {\"时段\": \"9:30-18:00\", \"日期\": \"周一到周五\"}, \"自习时间\": {\"时段\": \"18:00-22:30\", \"安排\": \"周末自行安排\", \"备注\": \"入学录入指纹,学员可随时自行出入\"}}",
"线上直播教学": "{\"上课时间\": {\"课次\": \"135或245晚\", \"时段\": \"19:30-21:30\"}, \"直播教学\": \"最多跟两期\", \"同步录播\": \"反复回放,永久有效\"}",
"寒暑假教学": "{\"上课形式\": {\"假期安排\": \"寒暑假线下面授教学\", \"回校安排\": \"回校开通线上直播、录播课程持续学习,线上答疑与指导\", \"上课时间\": \"同线上模式\"}, \"课时统计\": \"以线下实际授课市场为准,线上赠送\"}",
"提供服务": "{\"基础服务\": [\"住宿推荐与对接\", \"保险\", \"职业规划建议\"], \"多对一教学服务\": {\"服务角色\": [\"教学老师\", \"班主任\", \"就业老师\"]}, \"就业相关服务\": [\"就业推荐\", \"项目化作品实训\", \"游戏公司氛围\", {\"实习章\": \"学习2个月以后\"}]}",
"优势/竞争力": "{\"公司\": {\"规模\": [\"公司成立12年\", \"700多人\", \"全国6家分公司\", \"公司整体规模比所有纯培训机构都大,靠谱,不像刚成立不久的小公司可能经营不好随时跑路倒闭\"], \"资质\": [\"坐拥多项市级权威资质,规模实力远非同行可比。\"], \"专业\": [\"游戏公司背景,大厂合作认证,深耕行业,品质实力保障。\"], \"口碑\": [\"公司特别注重口碑,每一个业务和品牌再行业内都有非常好的口碑,可以网上了解一下或者找行业内懂的人打听一下\"]}, \"就业资源\": [\"合作数百家游戏企业,就业资源丰富,毕业渠道更广。\"], \"氛围\": {\"上课\": [\"游戏公司环境,上课氛围完全区别于传统培训机构\"], \"游戏公司氛围\": [\"年轻,活力,轻松,开放\"]}}",
"校区分布": "{\"上海\": {\"地址\": \"上海市徐汇区桂箐路7号3号楼3楼\", \"课程\": [\"原画角色设计\", \"3d场景建模\", \"3d角色建模\", \"游戏动画/分镜\", \"游戏特效\", \"引擎开发\"]}, \"西安\": {\"地址\": \"西安市浐灞生态区兴泰南路1555号发展大厦16层\", \"课程\": [\"场景建模\", \"角色建模\", \"特效\", \"动画\", \"角色原画\"]}, \"青岛\": {\"地址\": \"青岛市长江中路519号建国大厦1604室\", \"课程\": [\"场景建模\"]}, \"厦门\": {\"地址\": \"厦门市思明区前埔东路1733号万科创想中心A座\", \"课程\": [\"场景建模\"], \"备注\": \"仅寒暑假\"}}",
"退费咨询": "{\"标准\": {\"计算方式\": \"缴费日起计算\", \"规则\": [\"不含缴费但未进班\", \"不含缴费但线上课程为学习超5课时\", \"7天无理由退费\", \"7-30日 退50%\", \"超过30天 不退\"]}, \"特殊情况\": \"如因自身原因无法学习,可休学,保留学习权限\"}",
"住宿咨询": "{\"对接说明\": \"为了学生方便我们合作的公寓,尽可能协调,但可太挑;学生也可以自己找住宿\", \"环境\": \"4-6人间上下铺多数为4人间\", \"费用\": {\"房租\": \"800-1200之间\", \"水电网\": \"未标注\"}, \"优势\": {\"方便(省心)\": [\"可随时拎包入住\", \"毕业或返校按天计算,不扣押金,不为住满月费用\"], \"安全便捷(安心)\": [\"离学校1-2公里以内5-10分钟到达\", \"室友都是第九联盟学生,无社会人同住\", \"大多为在校生或应届毕业生,素质层次相同\", \"有问题第九联盟老师可以协助沟通协调\"], \"实惠(放心)\": [\"价格便宜\", \"按照公寓原价给学生分摊没有中间商赚差价\", \"没住满或空房,第九联盟为学员补贴\"]}}",
"学不会怎么办": "{\"就业情况说明\": \"多年办学学员认真学基本都能就业。学得好进大厂月薪1-2万一般4-8千差的先入行积累经验再跳槽。能力决定薪资我们与学员共成长。\", \"前提\": [\"不经常逃课\", \"不做练习和作品\"], \"方案\": [\"只要认真学习按照老师的节奏来真没学会我们认为是我们自己的问题可以免费重修个别同学基础差点接受能力慢点一般跟着老师继续多学1-2个月都能就业再不济也可以免费重修一期\", \"合同里面有关于不就业和重修的承诺来保证学员学习效果和权益\"], \"工资多少\": [\"平均工资4-8千之间\", \"部分学得好的进大厂的1-2万之间\"]}",
"就业咨询": "{\"核心说明\": \"不包就业,我们推荐就业\"}",
"学历咨询": "{\"大厂态度\": \"大厂会看学历,技术优先,如果技术足够强可以降低学历要求\", \"学历优势\": \"当然你学历好技术也好的话有优势的\"}"
}

View File

@ -0,0 +1,574 @@
{
"公司介绍": [
"母公司点睛科技成立于2013年是一家专业的数字艺术教育机构。旗下品牌第九联盟和GGAC专注于CG游戏、动漫、影视等数字艺术教育提供原画、3D建模、动画、特效等核心课程与腾讯、网易、米哈游、盛趣、莉莉丝等数百家游戏企业有人才合作校区分布有上海、西安、青岛、厦门等校区地址相关网站https://www.alchemyart.com.cn/ 、https://9artedu.com/ 、https://www.ggac.com/home"
],
"课程咨询": [
"3D建模、2D原画、动作/分镜、游戏特效、开发、3D大师课、GGAC绘啦课程、兴趣/提升班等课程体系,课程不同相关的价格和内容也有所不同,如果需要了解某一个课程,请告诉我课程名称"
],
"3D建模": {
"3D场景建模": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "7个月",
"价格": "31800元"
},
{
"课程类型": "线上就业班",
"学习时长": "8-10个月",
"价格": "11800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校开通线上服务",
"价格": "31800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"回校开通线上直播与答疑学习服务"
]
}
],
"课程介绍链接": "https://www.9artedu.com/3d/"
},
"3D角色建模": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "8个月",
"价格": "33800元"
},
{
"课程类型": "线上就业班",
"学习时长": "8-10个月",
"价格": "11800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校开通线上服务",
"价格": "33800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"回校开通线上直播与答疑学习服务"
]
}
],
"课程介绍链接": "https://www.9artedu.com/3d-role/"
}
},
"3D场景建模": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "7个月",
"价格": "31800元"
},
{
"课程类型": "线上就业班",
"学习时长": "8-10个月",
"价格": "11800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校开通线上服务",
"价格": "31800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"回校开通线上直播与答疑学习服务"
]
}
],
"课程介绍链接": "https://www.9artedu.com/3d/"
},
"3D角色建模": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "8个月",
"价格": "33800元"
},
{
"课程类型": "线上就业班",
"学习时长": "8-10个月",
"价格": "11800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校开通线上服务",
"价格": "33800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"回校开通线上直播与答疑学习服务"
]
}
],
"课程介绍链接": "https://www.9artedu.com/3d-role/"
},
"2D原画": {
"2D角色原画": {
"二次元风格": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "6个月",
"价格": "31800元"
},
{
"课程类型": "线上就业班",
"学习时长": "8-10个月",
"价格": "11800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校开通线上服务",
"价格": "31800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"以线下学习时间为主,回校开通线上直播与答疑学习服务"
]
}
]
},
"写实风格": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "6个月",
"价格": "31800元",
"备注": [
"项目组实训教学"
]
},
{
"课程类型": "线上就业班",
"学习时长": "8-10个月",
"价格": "11800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校开通线上服务",
"价格": "31800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"以线下学习时间为主,回校开通线上直播与答疑学习服务"
]
}
]
},
"介绍链接": "https://www.9artedu.com/2d"
}
},
"二次元风格": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "6个月",
"价格": "31800元"
},
{
"课程类型": "线上就业班",
"学习时长": "8-10个月",
"价格": "11800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校开通线上服务",
"价格": "31800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"以线下学习时间为主,回校开通线上直播与答疑学习服务"
]
}
]
},
"写实风格": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "6个月",
"价格": "31800元",
"备注": [
"项目组实训教学"
]
},
{
"课程类型": "线上就业班",
"学习时长": "8-10个月",
"价格": "11800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校开通线上服务",
"价格": "31800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"以线下学习时间为主,回校开通线上直播与答疑学习服务"
]
}
]
},
"动作/分镜": {
"游戏动作/分镜": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "6个月",
"价格": "33800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校提供线上答疑指导",
"价格": "31800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"以线下学习时间为主,回校做练习提供线上答疑指导服务"
]
}
],
"介绍链接": "https://www.9artedu.com/animation/"
}
},
"游戏动作/分镜": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "6个月",
"价格": "33800元"
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校提供线上答疑指导",
"价格": "31800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"以线下学习时间为主,回校做练习提供线上答疑指导服务"
]
}
],
"介绍链接": "https://www.9artedu.com/animation/"
},
"开发": {
"UE引擎开发": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "6个月",
"价格": "33800元",
"备注": [
"以线下学习时间为主,回校开通线上直播与答疑学习服务"
]
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校提供线上答疑指导",
"价格": "33800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"以线下学习时间为主,回校做练习提供线上答疑指导服务"
]
},
{
"课程类型": "线上就业班",
"学习时长": "6-8个月",
"价格": "13800元",
"备注": [
"白天线上授课及答疑"
]
}
],
"介绍链接": "https://www.9artedu.com/ue/"
}
},
"UE引擎开发": {
"课程列表": [
{
"课程类型": "线下就业班",
"学习时长": "6个月",
"价格": "33800元",
"备注": [
"以线下学习时间为主,回校开通线上直播与答疑学习服务"
]
},
{
"课程类型": "线上线下结合就业班",
"学习时长": "线下寒暑假学习,回校提供线上答疑指导",
"价格": "33800元",
"备注": [
"限大一大二大三在校生",
"线下寒暑假学习送线上",
"以线下学习时间为主,回校做练习提供线上答疑指导服务"
]
},
{
"课程类型": "线上就业班",
"学习时长": "6-8个月",
"价格": "13800元",
"备注": [
"白天线上授课及答疑"
]
}
],
"介绍链接": "https://www.9artedu.com/ue/"
},
"3D大师课": {
"介绍": "第九联盟联合十余位3D美术大咖针对紧缺技术方向设课。涵盖场景、角色、Blender动画全流程16位老师精讲11大主题直播可回放赠入门课总课时超300小时。",
"课程形式": "直播教学、同步录播",
"课程链接": {
"第三期": "https://www.huilahujila.com/3ddsk3.0/pc/",
"第二期": "https://www.ggac.com/v2/edu/dsk",
"第一期": "http://m.9artedu.com/"
},
"合适人群": ["在校大学生", "在职从业者", "兴趣爱好", "预算较少"],
"课程设置": {
"基础课": ["软件基础教学", "结合案例、物件制作"],
"进阶课": ["深度系统教学,直播+录播+答疑,性价比高非常适合小白", "多个流行技术点"],
"就业课": "邀请行业大厂hr和制作负责人进行就业分享"
},
"优势": ["价格实惠 - 1500-2500", "性价比高", "顶尖师资", "系统化全流程教学"],
"费用": "1580-2500"
},
"GGAC绘殓课程": {
"造型力": {
"课程详细链接": "https://www.9artedu.com/xinqi/",
"适合人群": ["从业者提升", "美院学生"]
"费用": {
"旁听席(不单独改作业)": "4500元",
"vip": "6800元"
}
},
"大学生扶持计划": {
"课程亮点": [
"一线大厂亲授,全流程实战,直播可回放,作业答疑超值。"
],
"适合人群": ["预算少", "在校生", "兴趣学生", "作品集"],
"优势": ["费用低", "师资强", "服务号", "系统教学"],
"费用": "2500元",
"链接": ""
}
},
"造型力": {
"课程详细链接": "https://www.9artedu.com/xinqi/",
"适合人群": ["从业者提升", "美院学生"],
"费用": {
"旁听席(不单独改作业)": "4500元",
"vip": "6800元"
}
},
"大学生扶持计划": {
"课程亮点": [
"一线大厂亲授,全流程实战,直播可回放,作业答疑超值。"
],
"适合人群": ["预算少", "在校生", "兴趣学生", "作品集"],
"优势": ["费用低", "师资强", "服务号", "系统教学"],
"费用": "2500元",
"链接": ""
},
"兴趣/提升班": {
"线下面授": [
{
"时长": "2个月",
"价格": "13800元"
},
{
"时长": "3个月",
"价格": "19800元"
}
],
"备注": "无推荐就业服务"
},
"学习模式": {
"线下面授教学": {
"上课时间": {
"时段": "9:30-18:00",
"日期": "周一到周五"
},
"自习时间": {
"时段": "18:00-22:30",
"安排": "周末自行安排",
"备注": "入学录入指纹,学员可随时自行出入"
}
},
"线上直播教学": {
"上课时间": {
"课次": "135或245晚",
"时段": "19:30-21:30"
},
"直播教学": "最多跟两期",
"同步录播": "反复回放,永久有效"
},
"寒暑假": {
"上课形式": {
"假期安排": "寒暑假线下面授教学",
"回校安排": "回校开通线上直播、录播课程持续学习,线上答疑与指导",
"上课时间": "同线上模式"
},
"课时统计": "以线下实际授课市场为准,线上赠送"
}
},
"线下面授教学": {
"上课时间": {
"时段": "9:30-18:00",
"日期": "周一到周五"
},
"自习时间": {
"时段": "18:00-22:30",
"安排": "周末自行安排",
"备注": "入学录入指纹,学员可随时自行出入"
}
},
"线上直播教学": {
"上课时间": {
"课次": "135或245晚",
"时段": "19:30-21:30"
},
"直播教学": "最多跟两期",
"同步录播": "反复回放,永久有效"
},
"寒暑假教学": {
"上课形式": {
"假期安排": "寒暑假线下面授教学",
"回校安排": "回校开通线上直播、录播课程持续学习,线上答疑与指导",
"上课时间": "同线上模式"
},
"课时统计": "以线下实际授课市场为准,线上赠送"
},
"提供服务": {
"基础服务": [
"住宿推荐与对接",
"保险",
"职业规划建议"
],
"多对一教学服务": {
"服务角色": [
"教学老师",
"班主任",
"就业老师"
]
},
"就业相关服务": [
"就业推荐",
"项目化作品实训",
"游戏公司氛围",
{
"实习章": "学习2个月以后"
}
]
},
"优势/竞争力": {
"公司": {
"规模": [
"公司成立12年",
"700多人",
"全国6家分公司",
"公司整体规模比所有纯培训机构都大,靠谱,不像刚成立不久的小公司可能经营不好随时跑路倒闭"
],
"资质": [
"坐拥多项市级权威资质,规模实力远非同行可比。"
],
"专业": [
"游戏公司背景,大厂合作认证,深耕行业,品质实力保障。"
],
"口碑": [
"公司特别注重口碑,每一个业务和品牌再行业内都有非常好的口碑,可以网上了解一下或者找行业内懂的人打听一下"
]
}
"就业资源": [
"合作数百家游戏企业,就业资源丰富,毕业渠道更广。"
]
"氛围": {
"上课": [
"游戏公司环境,上课氛围完全区别于传统培训机构"
],
"游戏公司氛围": [
"年轻,活力,轻松,开放"
]
}
},
"校区分布": {
"上海": {
"地址": "上海市徐汇区桂箐路7号3号楼3楼",
"课程": ["原画角色设计", "3d场景建模", "3d角色建模", "游戏动画/分镜", "游戏特效", "引擎开发"]
},
"西安": {
"地址": "西安市浐灞生态区兴泰南路1555号发展大厦16层",
"课程": ["场景建模", "角色建模", "特效", "动画", "角色原画"]
},
"青岛": {
"地址": "青岛市长江中路519号建国大厦1604室",
"课程": ["场景建模"]
},
"厦门": {
"地址": "厦门市思明区前埔东路1733号万科创想中心A座",
"课程": ["场景建模"],
"备注": "仅寒暑假"
}
},
"退费咨询": {
"标准": {
"计算方式": "缴费日起计算",
"规则": [
"不含缴费但未进班",
"不含缴费但线上课程为学习超5课时",
"7天无理由退费",
"7-30日 退50%",
"超过30天 不退"
]
},
"特殊情况": "如因自身原因无法学习,可休学,保留学习权限"
},
"住宿咨询": {
"对接说明": "为了学生方便我们合作的公寓,尽可能协调,但可太挑;学生也可以自己找住宿",
"环境": "4-6人间上下铺多数为4人间",
"费用": {
"房租": "800-1200之间",
"水电网": "未标注"
},
"优势": {
"方便(省心)": ["可随时拎包入住", "毕业或返校按天计算,不扣押金,不为住满月费用"],
"安全便捷(安心)": [
"离学校1-2公里以内5-10分钟到达",
"室友都是第九联盟学生,无社会人同住",
"大多为在校生或应届毕业生,素质层次相同",
"有问题第九联盟老师可以协助沟通协调"
],
"实惠(放心)": [
"价格便宜",
"按照公寓原价给学生分摊没有中间商赚差价",
"没住满或空房,第九联盟为学员补贴"
]
}
},
"学不会怎么办": {
"就业情况说明": "多年办学学员认真学基本都能就业。学得好进大厂月薪1-2万一般4-8千差的先入行积累经验再跳槽。能力决定薪资我们与学员共成长。",
"前提": [
"不经常逃课",
"不做练习和作品"
],
"方案": [
"只要认真学习按照老师的节奏来真没学会我们认为是我们自己的问题可以免费重修个别同学基础差点接受能力慢点一般跟着老师继续多学1-2个月都能就业再不济也可以免费重修一期",
"合同里面有关于不就业和重修的承诺来保证学员学习效果和权益"
],
"工资多少": [
"平均工资4-8千之间",
"部分学得好的进大厂的1-2万之间"
]
},
"就业咨询": {
"核心说明": "不包就业,我们推荐就业"
},
"学历咨询": {
"大厂态度": "大厂会看学历,技术优先,如果技术足够强可以降低学历要求",
"学历优势": "当然你学历好技术也好的话有优势的"
}
}

View File

@ -45,7 +45,7 @@ if __name__ == '__main__':
archive_messages_mysql_repository = ArchiveMessagesRepository(db_session) archive_messages_mysql_repository = ArchiveMessagesRepository(db_session)
qa_milvus_repository = QARepository() qa_milvus_repository = QARepository()
state: QueryQAState = QueryQAState(original_query="老师这个课程多少钱啊,老师 我想报班,", history=['2026-07-10T15:42:13 EXTERNAL 老师这个课程多少钱啊\n', '2026-07-10T15:40:34 EXTERNAL 老师 我想报班\n']) state: QueryQAState = QueryQAState(original_query="老师你好我想咨询一下3d建模费用和就业情况", history=['2026-07-10T15:42:13 EXTERNAL 老师这个课程多少钱啊\n', '2026-07-10T15:40:34 EXTERNAL 老师 我想报班\n'])
context = QueryQAContext(meta_mysql_repository=archive_messages_mysql_repository, context = QueryQAContext(meta_mysql_repository=archive_messages_mysql_repository,
qa_milvus_repository=qa_milvus_repository qa_milvus_repository=qa_milvus_repository
) )

View File

@ -11,86 +11,105 @@ from app.core.log import logger
problem_rewriting_prompt = """ problem_rewriting_prompt = """
你是一名智能客服意图分类助手你的任务是根据用户的历史会话和当前问题提取用户的核心诉求并输出标准化的意图标签 你是一名智能客服意图分类助手你的任务是根据用户的历史会话和当前问题提取用户的核心诉求并输出标准化的意图标签
## 分类规则(必须严格遵守) ## 核心原则(必须严格遵守)
1. **核心诉求提取** ### 1. 双维度提取原则
- 从当前问题中提取用户明确表达的诉求可能有一个或多个去重 每个用户问题通常包含两个维度的意图必须分别识别
- 如果当前问题包含代词"这个"""""必须结合历史会话进行指代消解用具体名词替换代词 - **课程/服务主题维度**用户想咨询的具体课程类型或业务主题如3D建模2D原画UE引擎开发等
- **诉求/动作维度**用户想了解的方面如课程咨询就业咨询校区分布等
2. **信息补全** 这两个维度相互独立必须同时提取不得遗漏任何一个
- 如果当前问题缺少主语或关键上下文如只问"费用多少"必须从历史会话中提取相关主题补全
- 确保意图标签不依赖历史会话也能被独立理解
3. **语义保持** ### 2. 主题维度提取规则
- 不得改变用户的原始意图 - 如果用户明确提到了具体课程名称或类型"3D建模""2D原画""UE引擎开发"必须作为独立意图标签输出
- 不得引入历史会话中不存在的新信息 - 如果当前问题使用代词"这个"""结合历史会话进行指代消解还原具体课程名称
- 如果历史会话中也没有明确课程类型则不输出主题维度标签
### 3. 诉求维度提取规则
- 从当前问题中提取用户明确表达的动作诉求费用就业退费住宿等
- 将动作诉求映射到标准诉求类型标签
### 4. 信息补全与语义保持
- 如果当前问题缺少主语从历史会话补全
- 不得改变用户原始意图不得引入历史会话中不存在的新信息
- 不得遗漏当前问题中的任何关键诉求 - 不得遗漏当前问题中的任何关键诉求
4. **输出格式** ## 输出格式
- 仅输出JSON不要任何解释性文字 - 仅输出JSON不要任何解释性文字
- 输出为结构化的意图标签数组**不要改写成完整问句** - 多诉求时用数组形式输出每个意图标签独立
- 每个意图标签应简洁标准化适合用于分类路由 - 标签从以下列表中选择不得自创
- 多诉求时拆分为多个意图标签用数组形式输出
## 意图标签规范 **课程/服务主题标签**公司介绍3D建模3D场景建模3D角色建模2D原画二次元风格写实风格动作/分镜游戏动作/分镜开发UE引擎开发3D大师课GGAC绘殓课程造型力大学生扶持计划兴趣/提升班学习模式线下面授教学线上直播教学寒暑假教学提供服务优势/竞争力校区分布
- 每个标签格式为"{{诉求类型}}" **诉求/动作标签**课程咨询退费咨询住宿咨询学不会怎么办就业咨询学历咨询
- 常见诉求类型费用咨询课程内容报名流程就业支持开班时间校区地址优惠活动退款政策住宿咨询其他
- 标签应简洁无歧义便于系统直接匹配路由
- 从当前问题中提取用户明确表达的诉求,可以提取多个意图标签
## 分类示例 ## 分类示例
### 示例1信息补全 ### 示例1主题+诉求双维度)
历史会话
当前问题3D建模培训的课程内容有哪些
分析主题="3D建模"诉求="课程内容"课程咨询
分类结果
{{
"intents": ["3D建模", "课程咨询"]
}}
### 示例2主题+诉求双维度,信息补全)
历史会话 历史会话
- 用户我想了解游戏特效培训 - 用户我想了解游戏特效培训
- 助手好的请问您想了解哪方面 - 助手好的请问您想了解哪方面
当前问题培训的费用 当前问题培训的费用
分析主题从历史会话补全="游戏特效培训"诉求="费用"课程咨询
分类结果 分类结果
{{ {{
"intents": "费用咨询" "intents": ["课程咨询"]
}} }}
### 示例2指代消解) ### 示例3主题+诉求双维度,指代消解)
历史会话 历史会话
- 用户你们有Python课程吗 - 用户你们有Python课程吗
- 助手有的我们有Python基础班和进阶班 - 助手有的我们有Python基础班和进阶班
当前问题这个课程的时长是多久 当前问题这个课程的时长是多久
分析主题="Python课程"诉求="课程时长"课程咨询
分类结果 分类结果
{{ {{
"intents": ["课程内容", "报名流程"] "intents": ["课程咨询"]
}} }}
### 示例3(多诉求提取) ### 示例4(多诉求提取)
历史会话 历史会话
- 用户我想报名数据分析培训 - 用户我想报名数据分析培训
当前问题流程费用和就业支持 当前问题流程费用和就业支持
分析主题="数据分析培训"诉求="流程/费用"课程咨询"就业支持"就业咨询
分类结果 分类结果
{{ {{
"intents": ["报名流程"] "intents": ["课程咨询", "就业咨询"]
}} }}
### 示例4无需改写 ### 示例5主题+诉求双维度
历史会话 历史会话
当前问题Java培训的课程内容有哪些 当前问题老师3D大师课课程多少钱啊老师我想报班
分析主题="3D大师课"诉求="多少钱/报班"课程咨询
分类结果 分类结果
{{ {{
"intents": ["课程内容"] "intents": ["3D大师课", "课程咨询"]
}} }}
### 示例5用户提供的案例 ### 示例6关键示例主题必须独立提取
历史会话 历史会话
当前问题老师这个课程多少钱啊老师我想报班 - 用户老师 我想报班
- 用户老师这个课程多少钱啊
当前问题老师我想咨询3D建模费用问题
分析主题="3D建模"当前问题明确提及诉求="费用问题"课程咨询
分类结果 分类结果
{{ {{
"intents": ["报名流程"] "intents": ["3D建模", "课程咨询"]
}} }}
--- ---
## 现在请处理以下输入 ## 现在请处理以下输入
当前问题{query} 当前问题{query}
历史聊天{history_text} 历史聊天{history_text}
请直接输出JSON 请直接输出JSON
@ -112,8 +131,6 @@ async def rewrite_query(state:QueryQAState):
try: try:
result = await chain.ainvoke({"history_text": history_text, "query": query}) result = await chain.ainvoke({"history_text": history_text, "query": query})
rewritten_query = result.get("intents", "") rewritten_query = result.get("intents", "")
if rewritten_query:
rewritten_query = rewritten_query[0]
logger.info(f"原问题:{query},历史会话:{history_text},改写后问题:{rewritten_query}") logger.info(f"原问题:{query},历史会话:{history_text},改写后问题:{rewritten_query}")
return {"rewritten_query": rewritten_query} return {"rewritten_query": rewritten_query}
except Exception as e: except Exception as e:

View File

@ -12,7 +12,7 @@ from app.core.log import logger
async def search_embed(state: QueryQAState): async def search_embed(state: QueryQAState):
logger.info("search_embed") logger.info("search_embed")
rewritten_query = state.get("rewritten_query", "") rewritten_query: List[str] = state.get("rewritten_query", "")
original_query = state.get("original_query", "") original_query = state.get("original_query", "")
#batch_embeddings = await embedding_client.aembed_query(rewritten_query) #batch_embeddings = await embedding_client.aembed_query(rewritten_query)

View File

@ -3,6 +3,6 @@ from typing import TypedDict, List, Dict, Optional, Any
class QueryQAState(TypedDict): class QueryQAState(TypedDict):
original_query: str # 原始问题 original_query: str # 原始问题
rewritten_query: str # 改写后的问题 rewritten_query: List[str] # 改写后的问题
history: list # 历史对话记录 history: list # 历史对话记录
qa_pairs: Dict[str, Any] # 匹配到的QA对 qa_pairs: Dict[str, Any] # 匹配到的QA对

View File

@ -0,0 +1,125 @@
from datetime import datetime
from typing import Optional, List, Dict, Any
from pymilvus import MilvusClient, DataType
from app.client.milvus_client_manager import milvus_client
from app.conf.app_config import app_config
from app.core.log import logger
class IntentClassificationRepository:
collection_name: str = 'intent_classification'
def __init__(self):
self.dim = app_config.milvus.embedding_size
self._ensure_connection()
def _ensure_connection(self):
if milvus_client.client is None:
milvus_client.init()
def create_collection(self, dim: int = None) -> bool:
if dim is not None:
self.dim = dim
if milvus_client.has_collection(self.collection_name):
return False
schema = milvus_client.client.create_schema(
auto_id=True,
enable_dynamic_field=True,
description="意图分类向量集合"
)
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
schema.add_field(field_name="intent_category", datatype=DataType.VARCHAR, max_length=128)
schema.add_field(field_name="content", datatype=DataType.VARCHAR, max_length=65535)
schema.add_field(field_name="content_vector", datatype=DataType.FLOAT_VECTOR, dim=1024)
schema.add_field(field_name="created_at", datatype=DataType.INT64)
index_params = milvus_client.client.prepare_index_params()
index_params.add_index(
field_name="content_vector",
index_type="HNSW",
metric_type="COSINE",
params={"M": 32, "efConstruction": 300}
)
milvus_client.client.create_collection(
collection_name=self.collection_name,
schema=schema,
index_params=index_params
)
return True
async def save_intent_data(self, data: List[Dict[str, Any]]) -> List[int]:
try:
created_at = int(datetime.now().timestamp())
insert_data = []
for item in data:
insert_data.append({
"intent_category": item.get("intent_category", ""),
"content": item.get("content", ""),
"content_vector": item.get("content_vector", []),
"created_at": created_at
})
result = milvus_client.client.insert(
collection_name=self.collection_name,
data=insert_data
)
logger.info(f"意图分类数据入库成功,插入 {len(data)} 条记录")
return result.get("ids", [])
except Exception as e:
logger.error(f"意图分类数据入库失败: {str(e)}", exc_info=True)
return []
async def search_by_intent_category(self, intent_category: List[str], top_k: int = 100) -> List[Dict[str, Any]]:
if isinstance(intent_category, str):
intent_category = [intent_category]
categories_str = ", ".join(f'"{c}"' for c in intent_category)
expr = f'intent_category in [{categories_str}]'
result = milvus_client.client.query(
collection_name=self.collection_name,
filter=expr,
output_fields=["intent_category", "content", "created_at"],
limit=top_k
)
return result
async def search_by_vector(self, query_vector: List[float], top_k: int = 5) -> List[Dict[str, Any]]:
res = milvus_client.client.search(
collection_name=self.collection_name,
anns_field="content_vector",
data=[query_vector],
limit=top_k,
search_params={
"metric_type": "COSINE",
"efSearch": 300
},
output_fields=["intent_category", "content", "created_at"]
)
results = []
for hits in res:
for hit in hits:
item = {
"intent_category": hit.entity.get("intent_category"),
"content": hit.entity.get("content"),
"created_at": hit.entity.get("created_at"),
"score": hit.get("distance", 0)
}
results.append(item)
return results
async def get_all_intent_categories(self) -> List[str]:
result = milvus_client.client.query(
collection_name=self.collection_name,
output_fields=["intent_category"],
limit=1000
)
categories = list(set([item.get("intent_category", "") for item in result]))
return categories