feat: 初始化考培练系统项目
- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
384
backend/scripts/migrate_prompts_to_db.py
Normal file
384
backend/scripts/migrate_prompts_to_db.py
Normal file
@@ -0,0 +1,384 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
AI 提示词迁移脚本
|
||||
|
||||
功能:将代码中的 AI 提示词迁移到数据库
|
||||
|
||||
使用方法:
|
||||
python scripts/migrate_prompts_to_db.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import pymysql
|
||||
|
||||
# 添加项目根目录到路径
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
|
||||
# ============================================
|
||||
# 配置
|
||||
# ============================================
|
||||
|
||||
ADMIN_DB_CONFIG = {
|
||||
"host": os.getenv("ADMIN_DB_HOST", "120.79.247.16"),
|
||||
"port": int(os.getenv("ADMIN_DB_PORT", "3309")),
|
||||
"user": os.getenv("ADMIN_DB_USER", "root"),
|
||||
"password": os.getenv("ADMIN_DB_PASSWORD", "ProdMySQL2025!@#"),
|
||||
"db": os.getenv("ADMIN_DB_NAME", "kaopeilian_admin"),
|
||||
"charset": "utf8mb4",
|
||||
}
|
||||
|
||||
|
||||
# ============================================
|
||||
# 提示词定义
|
||||
# ============================================
|
||||
|
||||
PROMPTS = [
|
||||
{
|
||||
"code": "knowledge_analysis",
|
||||
"name": "知识点分析",
|
||||
"description": "从课程资料中提取和分析知识点,支持PDF/Word/文本等格式",
|
||||
"module": "course",
|
||||
"system_prompt": """# 角色
|
||||
你是一个文件拆解高手,擅长将用户提交的内容进行精准拆分,拆分后的内容做个简单的优化处理使其更具可读性,但要尽量使用原文的原词原句。
|
||||
|
||||
## 技能
|
||||
### 技能 1: 内容拆分
|
||||
1. 当用户提交内容后,拆分为多段。
|
||||
2. 对拆分后的内容做简单优化,使其更具可读性,比如去掉奇怪符号(如换行符、乱码),若语句不通顺,或格式原因导致错位,则重新表达。用户可能会提交录音转文字的内容,因此可能是有错字的,注意修复这些小瑕疵。
|
||||
3. 优化过程中,尽量使用原文的原词原句,特别是话术类,必须保持原有的句式、保持原词原句,而不是重构。
|
||||
4. 注意是拆分而不是重写,不需要润色,尽量不做任何处理。
|
||||
5. 输出到 content。
|
||||
|
||||
### 技能 2: 为每一个选段概括一个标题
|
||||
1. 为每个拆分出来的选段概括一个标题,并输出到 title。
|
||||
|
||||
### 技能 3: 为每一个选段说明与主题的关联
|
||||
1. 详细说明这一段与全文核心主题的关联,并输出到 topic_relation。
|
||||
|
||||
### 技能 4: 为每一个选段打上一个类型标签
|
||||
1. 用户提交的内容很有可能是一个课程、一篇讲义、一个产品的说明书,通常是用户希望他公司的员工或高管学习的知识。
|
||||
2. 用户通常是医疗美容机构或轻医美、生活美容连锁品牌。
|
||||
3. 你要为每个选段打上一个知识类型的标签,最好是这几个类型中的一个:"理论知识", "诊断设计", "操作步骤", "沟通话术", "案例分析", "注意事项", "技巧方法", "客诉处理"。当然你也可以为这个选段匹配一个更适合的。
|
||||
|
||||
## 输出要求(严格按要求输出)
|
||||
请直接输出一个纯净的 JSON 数组(Array),不要包含 Markdown 标记(如 ```json),也不要包含任何解释性文字。格式如下:
|
||||
|
||||
[
|
||||
{
|
||||
"title": "知识点标题",
|
||||
"content": "知识点内容",
|
||||
"topic_relation": "知识点与主题的关系",
|
||||
"type": "知识点类型"
|
||||
}
|
||||
]
|
||||
|
||||
## 限制
|
||||
- 仅围绕用户提交的内容进行拆分和关联标注,不涉及其他无关内容。
|
||||
- 拆分后的内容必须最大程度保持与原文一致。
|
||||
- 关联说明需清晰合理。
|
||||
- 不论如何,不要拆分超过 20 段!""",
|
||||
"user_prompt_template": """课程主题:{course_name}
|
||||
|
||||
## 用户提交的内容:
|
||||
|
||||
{content}
|
||||
|
||||
## 注意
|
||||
|
||||
- 以json的格式输出
|
||||
- 不论如何,不要拆分超过20 段!""",
|
||||
"variables": ["course_name", "content"],
|
||||
"model_recommendation": "gemini-3-flash-preview",
|
||||
"max_tokens": 8192,
|
||||
"temperature": 0.7,
|
||||
},
|
||||
{
|
||||
"code": "exam_generator",
|
||||
"name": "试题生成器",
|
||||
"description": "根据知识点自动生成考试题目,支持单选、多选、判断、填空、问答题型",
|
||||
"module": "exam",
|
||||
"system_prompt": """# 角色
|
||||
你是一个专业的试题生成器,能够根据给定的知识点内容生成高质量的考试题目。
|
||||
|
||||
## 技能
|
||||
### 技能 1: 生成单选题
|
||||
- 每道题有4个选项(A、B、C、D)
|
||||
- 只有一个正确答案
|
||||
- 选项设计要有迷惑性但不能有歧义
|
||||
|
||||
### 技能 2: 生成多选题
|
||||
- 每道题有4个选项(A、B、C、D)
|
||||
- 有2-4个正确答案
|
||||
- 考察综合理解能力
|
||||
|
||||
### 技能 3: 生成判断题
|
||||
- 陈述一个观点,判断对错
|
||||
- 答案为"对"或"错"
|
||||
|
||||
### 技能 4: 生成填空题
|
||||
- 在关键位置设置空白
|
||||
- 答案明确唯一
|
||||
|
||||
### 技能 5: 生成问答题
|
||||
- 开放性问题
|
||||
- 需要组织语言回答
|
||||
|
||||
## 输出格式
|
||||
请直接输出 JSON 数组,格式如下:
|
||||
|
||||
[
|
||||
{
|
||||
"question_type": "single_choice",
|
||||
"title": "题目内容",
|
||||
"options": ["A. 选项1", "B. 选项2", "C. 选项3", "D. 选项4"],
|
||||
"correct_answer": "A",
|
||||
"explanation": "答案解析",
|
||||
"difficulty": "easy/medium/hard"
|
||||
}
|
||||
]
|
||||
|
||||
## 限制
|
||||
- 题目必须与给定知识点相关
|
||||
- 难度要适中,兼顾基础和提升
|
||||
- 表述清晰准确,无歧义""",
|
||||
"user_prompt_template": """请根据以下知识点内容生成试题:
|
||||
|
||||
{content}
|
||||
|
||||
要求:
|
||||
- 单选题 {single_choice_count} 道
|
||||
- 多选题 {multiple_choice_count} 道
|
||||
- 判断题 {true_false_count} 道
|
||||
- 填空题 {fill_blank_count} 道
|
||||
- 问答题 {essay_count} 道
|
||||
|
||||
难度系数:{difficulty_level}(1-5,1最简单)
|
||||
|
||||
请以 JSON 格式输出题目列表。""",
|
||||
"variables": ["content", "single_choice_count", "multiple_choice_count", "true_false_count", "fill_blank_count", "essay_count", "difficulty_level"],
|
||||
"model_recommendation": "gemini-3-flash-preview",
|
||||
"max_tokens": 8192,
|
||||
"temperature": 0.7,
|
||||
},
|
||||
{
|
||||
"code": "course_chat",
|
||||
"name": "课程对话",
|
||||
"description": "与课程知识点进行智能对话,回答学员问题",
|
||||
"module": "course",
|
||||
"system_prompt": """# 角色
|
||||
你是一位专业的课程助教,负责回答学员关于课程内容的问题。
|
||||
|
||||
## 职责
|
||||
1. 准确回答与课程相关的问题
|
||||
2. 用通俗易懂的语言解释复杂概念
|
||||
3. 提供实用的学习建议
|
||||
4. 关联相关知识点帮助理解
|
||||
|
||||
## 原则
|
||||
- 回答要准确、专业
|
||||
- 语言要友好、易懂
|
||||
- 适当举例说明
|
||||
- 如果问题超出课程范围,礼貌说明
|
||||
|
||||
## 回复格式
|
||||
- 保持简洁明了
|
||||
- 可以使用列表、分点等结构化方式
|
||||
- 重要内容可以加粗强调""",
|
||||
"user_prompt_template": """课程名称:{course_name}
|
||||
|
||||
课程知识点:
|
||||
{knowledge_content}
|
||||
|
||||
学员问题:{query}
|
||||
|
||||
请根据课程知识点回答学员的问题。""",
|
||||
"variables": ["course_name", "knowledge_content", "query"],
|
||||
"model_recommendation": "gemini-3-flash-preview",
|
||||
"max_tokens": 2048,
|
||||
"temperature": 0.7,
|
||||
},
|
||||
{
|
||||
"code": "ability_analysis",
|
||||
"name": "能力分析",
|
||||
"description": "基于智能工牌对话数据分析员工能力并推荐课程",
|
||||
"module": "ability",
|
||||
"system_prompt": """# 角色
|
||||
你是一位专业的人才发展顾问,负责根据员工的对话记录分析其能力并推荐提升课程。
|
||||
|
||||
## 分析维度
|
||||
1. **专业知识**:产品知识、行业知识、技术能力
|
||||
2. **沟通能力**:表达清晰度、倾听能力、情绪管理
|
||||
3. **销售技巧**:需求挖掘、异议处理、促成能力
|
||||
4. **服务意识**:客户关怀、问题解决、满意度维护
|
||||
|
||||
## 输出格式
|
||||
请输出 JSON 格式的分析结果:
|
||||
|
||||
{
|
||||
"overall_score": 75,
|
||||
"dimensions": [
|
||||
{"name": "专业知识", "score": 80, "comment": "评价"},
|
||||
{"name": "沟通能力", "score": 70, "comment": "评价"}
|
||||
],
|
||||
"strengths": ["优势1", "优势2"],
|
||||
"weaknesses": ["待提升1", "待提升2"],
|
||||
"recommendations": [
|
||||
{"course_name": "推荐课程", "reason": "推荐理由"}
|
||||
]
|
||||
}""",
|
||||
"user_prompt_template": """员工信息:
|
||||
- 姓名:{employee_name}
|
||||
- 岗位:{position}
|
||||
|
||||
对话记录:
|
||||
{conversation_records}
|
||||
|
||||
可选课程列表:
|
||||
{available_courses}
|
||||
|
||||
请分析该员工的能力并推荐适合的课程。""",
|
||||
"variables": ["employee_name", "position", "conversation_records", "available_courses"],
|
||||
"model_recommendation": "gemini-3-flash-preview",
|
||||
"max_tokens": 4096,
|
||||
"temperature": 0.7,
|
||||
},
|
||||
{
|
||||
"code": "practice_scene",
|
||||
"name": "陪练场景生成",
|
||||
"description": "根据课程内容生成陪练场景和对话",
|
||||
"module": "practice",
|
||||
"system_prompt": """# 角色
|
||||
你是一位专业的培训场景设计师,负责为员工陪练设计模拟对话场景。
|
||||
|
||||
## 职责
|
||||
1. 根据课程内容设计真实场景
|
||||
2. 模拟客户各种可能的提问和反应
|
||||
3. 设计合理的对话流程
|
||||
4. 提供评估标准
|
||||
|
||||
## 场景类型
|
||||
- 电话销售场景
|
||||
- 面对面咨询场景
|
||||
- 客户投诉处理场景
|
||||
- 售后服务场景
|
||||
- 产品介绍场景
|
||||
|
||||
## 输出格式
|
||||
请输出 JSON 格式:
|
||||
|
||||
{
|
||||
"scene_name": "场景名称",
|
||||
"scene_type": "场景类型",
|
||||
"background": "场景背景",
|
||||
"customer_profile": "客户画像",
|
||||
"dialogue_flow": [
|
||||
{"role": "customer", "content": "客户话术"},
|
||||
{"role": "employee", "content": "员工话术"}
|
||||
],
|
||||
"evaluation_points": ["评估要点1", "评估要点2"]
|
||||
}""",
|
||||
"user_prompt_template": """课程名称:{course_name}
|
||||
|
||||
课程知识点:
|
||||
{knowledge_content}
|
||||
|
||||
请为这些知识点设计一个{scene_type}的陪练场景。
|
||||
|
||||
难度:{difficulty}
|
||||
预计时长:{duration}分钟""",
|
||||
"variables": ["course_name", "knowledge_content", "scene_type", "difficulty", "duration"],
|
||||
"model_recommendation": "gemini-3-flash-preview",
|
||||
"max_tokens": 4096,
|
||||
"temperature": 0.8,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("=" * 60)
|
||||
print("AI 提示词迁移脚本")
|
||||
print("=" * 60)
|
||||
print(f"\n目标数据库: {ADMIN_DB_CONFIG['host']}:{ADMIN_DB_CONFIG['port']}/{ADMIN_DB_CONFIG['db']}")
|
||||
print(f"待迁移提示词: {len(PROMPTS)} 个\n")
|
||||
|
||||
conn = pymysql.connect(**ADMIN_DB_CONFIG, cursorclass=pymysql.cursors.DictCursor)
|
||||
|
||||
try:
|
||||
with conn.cursor() as cursor:
|
||||
inserted = 0
|
||||
updated = 0
|
||||
|
||||
for prompt in PROMPTS:
|
||||
print(f"处理提示词: {prompt['name']} ({prompt['code']})")
|
||||
|
||||
# 检查是否已存在
|
||||
cursor.execute(
|
||||
"SELECT id, version FROM ai_prompts WHERE code = %s",
|
||||
(prompt["code"],)
|
||||
)
|
||||
existing = cursor.fetchone()
|
||||
|
||||
if existing:
|
||||
# 更新
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE ai_prompts SET
|
||||
name = %s,
|
||||
description = %s,
|
||||
module = %s,
|
||||
system_prompt = %s,
|
||||
user_prompt_template = %s,
|
||||
variables = %s,
|
||||
model_recommendation = %s,
|
||||
max_tokens = %s,
|
||||
temperature = %s,
|
||||
updated_by = 1
|
||||
WHERE id = %s
|
||||
""",
|
||||
(prompt["name"], prompt["description"], prompt["module"],
|
||||
prompt["system_prompt"], prompt["user_prompt_template"],
|
||||
json.dumps(prompt["variables"]),
|
||||
prompt["model_recommendation"], prompt["max_tokens"],
|
||||
prompt["temperature"], existing["id"])
|
||||
)
|
||||
print(f" 更新成功,ID: {existing['id']}")
|
||||
updated += 1
|
||||
else:
|
||||
# 插入
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO ai_prompts
|
||||
(code, name, description, module, system_prompt, user_prompt_template,
|
||||
variables, model_recommendation, max_tokens, temperature, is_system, created_by)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, TRUE, 1)
|
||||
""",
|
||||
(prompt["code"], prompt["name"], prompt["description"], prompt["module"],
|
||||
prompt["system_prompt"], prompt["user_prompt_template"],
|
||||
json.dumps(prompt["variables"]),
|
||||
prompt["model_recommendation"], prompt["max_tokens"], prompt["temperature"])
|
||||
)
|
||||
print(f" 插入成功,ID: {cursor.lastrowid}")
|
||||
inserted += 1
|
||||
|
||||
conn.commit()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("迁移完成!")
|
||||
print(f"新增: {inserted} 个, 更新: {updated} 个")
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f"\n错误: {e}")
|
||||
raise
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user