原始输入
-${item.content}
+${safeContent}
生成结果
-${item.result}
+${safeResult}
{{ msg }}
+ + """, + msg=msg + ), 500 + return app \ No newline at end of file diff --git a/src/flask_prompt_master/__pycache__/__init__.cpython-312.pyc b/src/flask_prompt_master/__pycache__/__init__.cpython-312.pyc index 76e0ddf..d4b41ac 100644 Binary files a/src/flask_prompt_master/__pycache__/__init__.cpython-312.pyc and b/src/flask_prompt_master/__pycache__/__init__.cpython-312.pyc differ diff --git a/src/flask_prompt_master/models/__pycache__/models.cpython-312.pyc b/src/flask_prompt_master/models/__pycache__/models.cpython-312.pyc index a5e6c3b..ff1ca86 100644 Binary files a/src/flask_prompt_master/models/__pycache__/models.cpython-312.pyc and b/src/flask_prompt_master/models/__pycache__/models.cpython-312.pyc differ diff --git a/src/flask_prompt_master/models/models.py b/src/flask_prompt_master/models/models.py index 3ba59a3..3427eea 100644 --- a/src/flask_prompt_master/models/models.py +++ b/src/flask_prompt_master/models/models.py @@ -109,4 +109,60 @@ class MealPlan(db.Model): # 关联关系 user = db.relationship('User', backref='meal_plans') - wx_user = db.relationship('WxUser', backref='meal_plans') \ No newline at end of file + wx_user = db.relationship('WxUser', backref='meal_plans') + + +class WeeklyReport(db.Model): + """智能周报/日报保存表""" + __tablename__ = 'weekly_report' + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('user.uid'), nullable=True) + report_type = db.Column(db.String(20), nullable=False) # weekly | daily + content_input = db.Column(db.Text) # 用户输入的工作要点 + report_content = db.Column(db.Text, nullable=False) # 生成的报告内容(Markdown) + created_at = db.Column(db.DateTime, default=datetime.utcnow) + updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + user = db.relationship('User', backref='weekly_reports') + + +class TravelPlan(db.Model): + """旅行攻略保存表""" + __tablename__ = 'travel_plan' + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('user.uid'), nullable=True) + destination = db.Column(db.String(200), nullable=False) + days = db.Column(db.String(20), default='3') + people = db.Column(db.String(20), default='2') + preferences = db.Column(db.Text) + budget = db.Column(db.String(50), default='中等') + plan_content = db.Column(db.Text, nullable=False) # 生成的攻略内容(Markdown) + created_at = db.Column(db.DateTime, default=datetime.utcnow) + updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + user = db.relationship('User', backref='travel_plans') + + +class MeetingMinutes(db.Model): + """会议纪要保存表""" + __tablename__ = 'meeting_minutes' + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('user.uid'), nullable=True) + title = db.Column(db.String(200)) # 会议主题/标题 + raw_content = db.Column(db.Text, nullable=False) # 用户输入的原始内容(转写或要点) + summary_content = db.Column(db.Text, nullable=False) # 生成的纪要内容(Markdown) + created_at = db.Column(db.DateTime, default=datetime.utcnow) + updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + user = db.relationship('User', backref='meeting_minutes') + + +class ResumeOptimization(db.Model): + """简历/求职信优化保存表""" + __tablename__ = 'resume_optimization' + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('user.uid'), nullable=True) + opt_type = db.Column(db.String(20), nullable=False) # resume | cover_letter + original_content = db.Column(db.Text, nullable=False) # 原始简历或求职信内容 + job_description = db.Column(db.Text) # 岗位描述(可选,用于针对性优化) + optimized_content = db.Column(db.Text, nullable=False) # 优化后内容(Markdown) + created_at = db.Column(db.DateTime, default=datetime.utcnow) + updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + user = db.relationship('User', backref='resume_optimizations') \ No newline at end of file diff --git a/src/flask_prompt_master/routes/__pycache__/android_tools.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/android_tools.cpython-312.pyc new file mode 100644 index 0000000..3131791 Binary files /dev/null and b/src/flask_prompt_master/routes/__pycache__/android_tools.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/expert_generate_2.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/expert_generate_2.cpython-312.pyc new file mode 100644 index 0000000..a32b0ac Binary files /dev/null and b/src/flask_prompt_master/routes/__pycache__/expert_generate_2.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/meeting_minutes.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/meeting_minutes.cpython-312.pyc new file mode 100644 index 0000000..5d27117 Binary files /dev/null and b/src/flask_prompt_master/routes/__pycache__/meeting_minutes.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/placeholder_apps.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/placeholder_apps.cpython-312.pyc new file mode 100644 index 0000000..171b81d Binary files /dev/null and b/src/flask_prompt_master/routes/__pycache__/placeholder_apps.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/prompt_optimization.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/prompt_optimization.cpython-312.pyc new file mode 100644 index 0000000..09cddd3 Binary files /dev/null and b/src/flask_prompt_master/routes/__pycache__/prompt_optimization.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/resume_optimization.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/resume_optimization.cpython-312.pyc new file mode 100644 index 0000000..a8770b6 Binary files /dev/null and b/src/flask_prompt_master/routes/__pycache__/resume_optimization.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/routes.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/routes.cpython-312.pyc index e27f57c..cfb41e5 100644 Binary files a/src/flask_prompt_master/routes/__pycache__/routes.cpython-312.pyc and b/src/flask_prompt_master/routes/__pycache__/routes.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/smart_prompt_optimization.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/smart_prompt_optimization.cpython-312.pyc new file mode 100644 index 0000000..9bcbfab Binary files /dev/null and b/src/flask_prompt_master/routes/__pycache__/smart_prompt_optimization.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/travel_planning.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/travel_planning.cpython-312.pyc index d67b2a8..1c66248 100644 Binary files a/src/flask_prompt_master/routes/__pycache__/travel_planning.cpython-312.pyc and b/src/flask_prompt_master/routes/__pycache__/travel_planning.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/__pycache__/weekly_report.cpython-312.pyc b/src/flask_prompt_master/routes/__pycache__/weekly_report.cpython-312.pyc index d65d3c2..70898c5 100644 Binary files a/src/flask_prompt_master/routes/__pycache__/weekly_report.cpython-312.pyc and b/src/flask_prompt_master/routes/__pycache__/weekly_report.cpython-312.pyc differ diff --git a/src/flask_prompt_master/routes/android_tools.py b/src/flask_prompt_master/routes/android_tools.py new file mode 100644 index 0000000..06a64c5 --- /dev/null +++ b/src/flask_prompt_master/routes/android_tools.py @@ -0,0 +1,243 @@ +# -*- coding: utf-8 -*- +""" +Android 工程师专区:Crash/异常日志解读、依赖冲突分析 等 +""" +from flask import Blueprint, render_template, request, jsonify +from openai import OpenAI +import logging +import os +from src.flask_prompt_master import db +from src.flask_prompt_master.models.models import User +from src.flask_prompt_master.models.history_models import PromptHistory, UserStatistics + +logger = logging.getLogger(__name__) +android_tools_bp = Blueprint('android_tools', __name__) + +client = OpenAI( + api_key=os.environ.get('LLM_API_KEY') or 'sk-fdf7cc1c73504e628ec0119b7e11b8cc', + base_url=os.environ.get('LLM_API_URL') or 'https://api.deepseek.com/v1' +) + +# Crash/异常日志解读 系统提示词 +CRASH_ANALYST_SYSTEM = """你是一位资深的 Android 开发专家,擅长分析崩溃堆栈和 Logcat 日志。 + +用户会粘贴一段 Android 崩溃堆栈(Stack Trace)或 Logcat 异常输出。请: +1. 用简洁的中文说明「发生了什么」(异常类型、发生位置、直接原因) +2. 分析可能的根本原因(如空指针、线程、权限、版本兼容等) +3. 给出 3~5 条具体可操作的排查或修复建议,按优先级排序 +4. 若涉及第三方库或系统 API,可简要说明版本或替代方案 + +输出格式清晰,使用小标题和分点,便于开发者快速定位问题。不要编造不存在的类名或行号。""" + +# 依赖冲突分析 系统提示词 +GRADLE_CONFLICT_SYSTEM = """你是一位资深的 Android/Gradle 构建专家,擅长解决依赖冲突与构建错误。 + +用户会粘贴 Gradle 同步失败的错误信息、依赖冲突报错、或 `./gradlew :app:dependencies` 相关输出。请: +1. 用简洁的中文说明「错误类型」与「冲突/失败的直接原因」 +2. 指出涉及冲突的依赖或模块(group:artifact:version) +3. 给出 3~5 条具体可操作的解决思路,例如:排除传递依赖、统一版本、使用 resolutionStrategy、替换库等,并给出示例代码片段(build.gradle) when 有用 +4. 若涉及 Android Gradle Plugin 或 Kotlin 版本,可提醒兼容性矩阵 + +输出格式清晰,代码块用 markdown 标注,便于开发者直接复制修改。""" + +# 性能优化建议 系统提示词 +PERF_OPTIMIZE_SYSTEM = """你是一位资深的 Android 性能优化专家,熟悉启动、内存、卡顿、包体、电量等优化场景。 + +用户会描述当前遇到的性能问题或优化目标(如:启动慢、内存占用高、列表卡顿、APK 体积大、耗电等),或只给出场景关键词。请: +1. 简要确认用户关注的优化方向 +2. 给出该场景下的优化思路框架(分大类,如:启动可拆为 Application、首屏、多线程等) +3. 列出 5~10 条具体可执行的 Checklist(每条一句话,便于逐项排查或落地) +4. 视情况推荐工具(如 Profiler、LeakCanary、Baseline Profile)或官方文档要点 + +输出格式清晰,使用小标题和分点,便于开发者按清单执行。""" + +# 技术方案评审要点 系统提示词 +TECH_REVIEW_SYSTEM = """你是一位资深的 Android 架构师,擅长技术方案评审与风险识别。 + +用户会粘贴或描述一段技术方案(如:选型说明、架构设计、改造方案、技术调研结论等)。请: +1. 提炼该方案的核心目标与关键决策 +2. 从「可行性、可维护性、性能、兼容性、安全、工期/成本」等维度列出评审要点(每维度 2~5 条具体问题或检查项) +3. 指出该方案下 Android 开发中常见的坑点或易遗漏项(如版本适配、进程/线程、依赖关系、测试覆盖等) +4. 给出 2~4 条改进或补充建议(可选) + +输出格式清晰,使用小标题和分点,便于评审会议或自检。""" + +# Code Review 清单 系统提示词 +CODE_REVIEW_SYSTEM = """你是一位资深的 Android 开发专家,擅长代码规范与 Code Review。 + +用户会说明当前要审查的模块或代码类型(如:Activity/Fragment、网络层、数据库、自定义 View、Jetpack 使用、多线程等),或粘贴一段代码片段。请: +1. 针对该模块/类型,列出 8~15 条 Code Review 检查要点(每条一句话,涵盖:规范、安全、性能、可读性、可测试性、Android 特有问题等) +2. 若用户粘贴了代码,则针对该代码逐条对照检查并给出具体修改建议;若未粘贴代码,则输出通用清单便于 Reviewer 使用 +3. 适当区分「必须项」与「建议项」 + +输出格式清晰,使用小标题和分点,便于 Reviewer 逐项打勾或评论。""" + + +def _get_user_id(): + try: + from flask_login import current_user + if current_user.is_authenticated: + return getattr(current_user, 'id', None) or getattr(current_user, 'uid', None) + except Exception: + pass + from flask import session + uid = session.get('user_id') + if uid is not None: + return uid + try: + u = User.query.filter_by(login_name='admin').first() + return u.uid if u else 1 + except Exception as e: + logger.warning("获取默认用户失败: %s", e) + return 1 + + +def _call_llm(system_prompt: str, user_content: str, max_tokens: int = 1200) -> str: + try: + resp = client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_content} + ], + temperature=0.3, + max_tokens=max_tokens, + timeout=60 + ) + return (resp.choices[0].message.content or "").strip() + except Exception as e: + logger.exception("LLM 调用失败: %s", e) + return "" + + +def _save_to_history(user_id: int, original_input: str, generated_prompt: str, template_name: str): + try: + PromptHistory.add_history( + user_id=user_id, + original_input=original_input, + generated_prompt=generated_prompt, + template_name=template_name + ) + UserStatistics.update_statistics(user_id) + except Exception as e: + logger.warning("保存到历史失败: %s", e) + + +# ---------- Crash/异常日志解读 ---------- +@android_tools_bp.route('/android/crash-log', methods=['GET']) +def crash_log_page(): + return render_template('android_crash_log.html') + + +@android_tools_bp.route('/api/android/crash-log/analyze', methods=['POST']) +def crash_log_analyze_api(): + try: + data = request.get_json() or {} + raw_log = (data.get('input_text') or data.get('raw_log') or '').strip() + if not raw_log: + return jsonify({'success': False, 'message': '请粘贴崩溃堆栈或 Logcat 日志'}) + result = _call_llm(CRASH_ANALYST_SYSTEM, raw_log) + if not result: + return jsonify({'success': False, 'message': '分析失败,请重试'}) + user_id = _get_user_id() + _save_to_history(user_id, raw_log, result, 'Crash/异常日志解读') + return jsonify({'success': True, 'data': {'result': result}}) + except Exception as e: + logger.exception("Crash 解读失败") + return jsonify({'success': False, 'message': str(e) or '分析失败,请重试'}) + + +# ---------- 依赖冲突分析 ---------- +@android_tools_bp.route('/android/gradle-conflict', methods=['GET']) +def gradle_conflict_page(): + return render_template('android_gradle_conflict.html') + + +@android_tools_bp.route('/api/android/gradle-conflict/analyze', methods=['POST']) +def gradle_conflict_analyze_api(): + try: + data = request.get_json() or {} + raw_error = (data.get('input_text') or data.get('raw_error') or '').strip() + if not raw_error: + return jsonify({'success': False, 'message': '请粘贴 Gradle 报错或依赖树片段'}) + result = _call_llm(GRADLE_CONFLICT_SYSTEM, raw_error) + if not result: + return jsonify({'success': False, 'message': '分析失败,请重试'}) + user_id = _get_user_id() + _save_to_history(user_id, raw_error, result, '依赖冲突分析') + return jsonify({'success': True, 'data': {'result': result}}) + except Exception as e: + logger.exception("依赖冲突分析失败") + return jsonify({'success': False, 'message': str(e) or '分析失败,请重试'}) + + +# ---------- 性能优化建议 ---------- +@android_tools_bp.route('/android/perf-optimize', methods=['GET']) +def perf_optimize_page(): + return render_template('android_perf_optimize.html') + + +@android_tools_bp.route('/api/android/perf-optimize/generate', methods=['POST']) +def perf_optimize_api(): + try: + data = request.get_json() or {} + user_input = (data.get('input_text') or '').strip() + if not user_input: + return jsonify({'success': False, 'message': '请描述性能问题或优化场景'}) + result = _call_llm(PERF_OPTIMIZE_SYSTEM, user_input, max_tokens=1400) + if not result: + return jsonify({'success': False, 'message': '生成失败,请重试'}) + user_id = _get_user_id() + _save_to_history(user_id, user_input, result, '性能优化建议') + return jsonify({'success': True, 'data': {'result': result}}) + except Exception as e: + logger.exception("性能优化建议失败") + return jsonify({'success': False, 'message': str(e) or '生成失败,请重试'}) + + +# ---------- 技术方案评审要点 ---------- +@android_tools_bp.route('/android/tech-review', methods=['GET']) +def tech_review_page(): + return render_template('android_tech_review.html') + + +@android_tools_bp.route('/api/android/tech-review/generate', methods=['POST']) +def tech_review_api(): + try: + data = request.get_json() or {} + user_input = (data.get('input_text') or '').strip() + if not user_input: + return jsonify({'success': False, 'message': '请粘贴或描述技术方案内容'}) + result = _call_llm(TECH_REVIEW_SYSTEM, user_input, max_tokens=1400) + if not result: + return jsonify({'success': False, 'message': '生成失败,请重试'}) + user_id = _get_user_id() + _save_to_history(user_id, user_input, result, '技术方案评审要点') + return jsonify({'success': True, 'data': {'result': result}}) + except Exception as e: + logger.exception("技术方案评审失败") + return jsonify({'success': False, 'message': str(e) or '生成失败,请重试'}) + + +# ---------- Code Review 清单 ---------- +@android_tools_bp.route('/android/code-review', methods=['GET']) +def code_review_page(): + return render_template('android_code_review.html') + + +@android_tools_bp.route('/api/android/code-review/generate', methods=['POST']) +def code_review_api(): + try: + data = request.get_json() or {} + user_input = (data.get('input_text') or '').strip() + if not user_input: + return jsonify({'success': False, 'message': '请说明待审查的模块/类型或粘贴代码片段'}) + result = _call_llm(CODE_REVIEW_SYSTEM, user_input, max_tokens=1400) + if not result: + return jsonify({'success': False, 'message': '生成失败,请重试'}) + user_id = _get_user_id() + _save_to_history(user_id, user_input, result, 'Code Review 清单') + return jsonify({'success': True, 'data': {'result': result}}) + except Exception as e: + logger.exception("Code Review 清单失败") + return jsonify({'success': False, 'message': str(e) or '生成失败,请重试'}) diff --git a/src/flask_prompt_master/routes/expert_generate_2.py b/src/flask_prompt_master/routes/expert_generate_2.py new file mode 100644 index 0000000..3543b01 --- /dev/null +++ b/src/flask_prompt_master/routes/expert_generate_2.py @@ -0,0 +1,238 @@ +# -*- coding: utf-8 -*- +""" +智能提示词优化2号专家 - 独立实现,与专家模式功能一致但代码完全分离。 +便于后续与专家模式做对比优化,不复用任何专家模式代码。 +""" +from flask import Blueprint, render_template, request, jsonify +from openai import OpenAI +import json +import logging +import os +from src.flask_prompt_master import db +from src.flask_prompt_master.models.models import User, Prompt +from src.flask_prompt_master.models.history_models import PromptHistory, UserStatistics + +logger = logging.getLogger(__name__) +expert_generate_2_bp = Blueprint('expert_generate_2', __name__) + +client = OpenAI( + api_key=os.environ.get('LLM_API_KEY') or 'sk-fdf7cc1c73504e628ec0119b7e11b8cc', + base_url=os.environ.get('LLM_API_URL') or 'https://api.deepseek.com/v1' +) + +# 第一阶段:意图分析提示词(独立写一份) +INTENT_ANALYST_PROMPT = """你是一位资深的意图分析专家,请分析用户输入的意图和需求。 + +你必须严格按照以下JSON格式返回,不要添加任何其他内容: +{ + "core_intent": "技术", + "domain": "具体专业领域", + "key_requirements": ["需求1", "需求2"], + "expected_output": "期望输出的具体形式", + "constraints": ["约束1", "约束2"], + "keywords": ["关键词1", "关键词2"] +} + +注意: +1. 严格遵守JSON格式 +2. core_intent必须是以下之一:技术、创意、分析、咨询 +3. 数组至少包含1个元素 +4. 所有字段都必须存在 +5. 不要包含注释 +6. 不要添加任何额外的文本""" + +# 第二阶段:领域专家模板(独立写一份) +DOMAIN_EXPERT_TEMPLATES = { + "技术": """你是一位专业的技术领域提示工程师。基于以下意图分析,生成一个专业的技术任务提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 明确的技术背景和上下文 +2. 具体的技术要求和规范 +3. 性能和质量标准 +4. 技术约束条件 +5. 预期交付成果 +6. 评估标准 + +使用专业技术术语,确保提示词的可执行性和可验证性。""", + "创意": """你是一位专业的创意领域提示工程师。基于以下意图分析,生成一个创意设计提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 创意方向和灵感来源 +2. 风格和氛围要求 +3. 目标受众定义 +4. 设计元素规范 +5. 创意表现形式 +6. 评估标准 + +使用专业创意术语,确保提示词的创新性和可执行性。""", + "分析": """你是一位专业的数据分析提示工程师。基于以下意图分析,生成一个数据分析提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 分析目标和范围 +2. 数据要求和规范 +3. 分析方法和工具 +4. 输出格式要求 +5. 关键指标定义 +6. 质量控制标准 + +使用专业分析术语,确保提示词的科学性和可操作性。""", + "咨询": """你是一位专业的咨询领域提示工程师。基于以下意图分析,生成一个咨询服务提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 咨询问题界定 +2. 背景信息要求 +3. 分析框架设定 +4. 建议输出格式 +5. 实施考虑因素 +6. 效果评估标准 + +使用专业咨询术语,确保提示词的专业性和实用性。""" +} + +DEFAULT_EXPERT_TEMPLATE = """你是一位专业的通用领域提示工程师。基于以下意图分析,生成一个专业的提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 明确的目标定义 +2. 具体要求和规范 +3. 质量标准 +4. 约束条件 +5. 预期输出 +6. 评估标准 + +确保提示词的清晰性和可执行性。""" + + +def _get_user_id(): + try: + from flask_login import current_user + if current_user.is_authenticated: + return getattr(current_user, 'id', None) or getattr(current_user, 'uid', None) + except Exception: + pass + from flask import session + uid = session.get('user_id') + if uid is not None: + return uid + try: + u = User.query.filter_by(login_name='admin').first() + return u.uid if u else 1 + except Exception as e: + logger.warning("获取默认用户失败: %s", e) + return 1 + + +@expert_generate_2_bp.route('/expert-generate-2', methods=['GET']) +def expert_generate_2_page(): + """智能提示词优化2号专家 - 页面""" + return render_template('expert_generate_2.html') + + +@expert_generate_2_bp.route('/api/expert-generate-2/generate', methods=['POST']) +def expert_generate_2_api(): + """智能提示词优化2号专家 - 两阶段生成 API(独立实现,不复用专家模式)""" + try: + if not request.is_json: + return jsonify({'code': 400, 'message': '请求必须是JSON格式', 'data': None}) + + data = request.get_json() or {} + user_input = (data.get('input_text') or '').strip() + if not user_input: + return jsonify({'code': 400, 'message': '请输入您的需求', 'data': None}) + + # 第一阶段:意图分析 + intent_response = client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "system", "content": INTENT_ANALYST_PROMPT}, + {"role": "user", "content": user_input} + ], + temperature=0.1, + timeout=60 + ) + intent_analysis_text = intent_response.choices[0].message.content.strip() + intent_analysis_text = intent_analysis_text.replace('```json', '').replace('```', '').strip() + + try: + intent_analysis = json.loads(intent_analysis_text) + required_fields = ['core_intent', 'domain', 'key_requirements', 'expected_output', 'constraints', 'keywords'] + for f in required_fields: + if f not in intent_analysis: + raise ValueError(f"缺少字段: {f}") + if intent_analysis['core_intent'] not in ('技术', '创意', '分析', '咨询'): + intent_analysis['core_intent'] = '技术' + for f in ['key_requirements', 'constraints', 'keywords']: + if not isinstance(intent_analysis.get(f), list) or len(intent_analysis[f]) == 0: + intent_analysis[f] = ['未指定'] + except json.JSONDecodeError as e: + logger.error("2号专家 JSON解析失败: %s", e) + return jsonify({'code': 500, 'message': '意图分析格式有误,请重试', 'data': None}) + except ValueError as e: + logger.error("2号专家 数据验证失败: %s", e) + return jsonify({'code': 500, 'message': str(e), 'data': None}) + + # 第二阶段:领域专家提示生成 + expert_prompt = DOMAIN_EXPERT_TEMPLATES.get( + intent_analysis['core_intent'], + DEFAULT_EXPERT_TEMPLATE + ) + final_response = client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "system", "content": expert_prompt.format( + analysis=json.dumps(intent_analysis, ensure_ascii=False, indent=2) + )}, + {"role": "user", "content": user_input} + ], + temperature=0.7, + max_tokens=1000, + timeout=60 + ) + generated_prompt = (final_response.choices[0].message.content or "").strip() + if not generated_prompt: + return jsonify({'code': 500, 'message': '生成失败,请重试', 'data': None}) + + user_id = _get_user_id() + try: + p = Prompt(input_text=user_input, generated_text=generated_prompt, user_id=user_id) + db.session.add(p) + db.session.commit() + except Exception as e: + db.session.rollback() + logger.warning("2号专家 保存 Prompt 失败: %s", e) + try: + PromptHistory.add_history( + user_id=user_id, + original_input=user_input, + generated_prompt=generated_prompt, + template_name='智能提示词优化2号专家' + ) + UserStatistics.update_statistics(user_id) + except Exception as e: + logger.warning("2号专家 保存历史失败: %s", e) + + return jsonify({ + 'code': 200, + 'message': 'success', + 'data': { + 'intent_analysis': intent_analysis, + 'generated_prompt': generated_prompt + } + }) + except Exception as e: + logger.exception("智能提示词优化2号专家失败") + return jsonify({'code': 500, 'message': str(e) or '生成失败,请重试', 'data': None}) diff --git a/src/flask_prompt_master/routes/expert_generate_3.py b/src/flask_prompt_master/routes/expert_generate_3.py new file mode 100644 index 0000000..cf5b662 --- /dev/null +++ b/src/flask_prompt_master/routes/expert_generate_3.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +""" +智能提示词优化3号专家 - 独立实现,与专家模式/2号专家功能一致但代码完全分离。 +便于后续对比优化,不复用任何其他专家代码。 +含提示词生成历史记录功能。 +""" +from flask import Blueprint, render_template, request, jsonify +from openai import OpenAI +import json +import logging +import os +from src.flask_prompt_master import db +from src.flask_prompt_master.models.models import User, Prompt +from src.flask_prompt_master.models.history_models import PromptHistory, UserStatistics + +logger = logging.getLogger(__name__) +expert_generate_3_bp = Blueprint('expert_generate_3', __name__) + +_llm_client = OpenAI( + api_key=os.environ.get('LLM_API_KEY') or 'sk-fdf7cc1c73504e628ec0119b7e11b8cc', + base_url=os.environ.get('LLM_API_URL') or 'https://api.deepseek.com/v1' +) + +INTENT_PROMPT_3 = """你是一位资深的意图分析专家,请分析用户输入的意图和需求。 + +你必须严格按照以下JSON格式返回,不要添加任何其他内容: +{ + "core_intent": "技术", + "domain": "具体专业领域", + "key_requirements": ["需求1", "需求2"], + "expected_output": "期望输出的具体形式", + "constraints": ["约束1", "约束2"], + "keywords": ["关键词1", "关键词2"] +} + +注意: +1. 严格遵守JSON格式 +2. core_intent必须是以下之一:技术、创意、分析、咨询 +3. 数组至少包含1个元素 +4. 所有字段都必须存在 +5. 不要包含注释 +6. 不要添加任何额外的文本""" + +EXPERT_TEMPLATES_3 = { + "技术": """你是一位专业的技术领域提示工程师。基于以下意图分析,生成一个专业的技术任务提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 明确的技术背景和上下文 +2. 具体的技术要求和规范 +3. 性能和质量标准 +4. 技术约束条件 +5. 预期交付成果 +6. 评估标准 + +使用专业技术术语,确保提示词的可执行性和可验证性。""", + "创意": """你是一位专业的创意领域提示工程师。基于以下意图分析,生成一个创意设计提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 创意方向和灵感来源 +2. 风格和氛围要求 +3. 目标受众定义 +4. 设计元素规范 +5. 创意表现形式 +6. 评估标准 + +使用专业创意术语,确保提示词的创新性和可执行性。""", + "分析": """你是一位专业的数据分析提示工程师。基于以下意图分析,生成一个数据分析提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 分析目标和范围 +2. 数据要求和规范 +3. 分析方法和工具 +4. 输出格式要求 +5. 关键指标定义 +6. 质量控制标准 + +使用专业分析术语,确保提示词的科学性和可操作性。""", + "咨询": """你是一位专业的咨询领域提示工程师。基于以下意图分析,生成一个咨询服务提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 咨询问题界定 +2. 背景信息要求 +3. 分析框架设定 +4. 建议输出格式 +5. 实施考虑因素 +6. 效果评估标准 + +使用专业咨询术语,确保提示词的专业性和实用性。""" +} + +FALLBACK_TEMPLATE_3 = """你是一位专业的通用领域提示工程师。基于以下意图分析,生成一个专业的提示词: + +意图分析: +{analysis} + +请生成的提示词包含: +1. 明确的目标定义 +2. 具体要求和规范 +3. 质量标准 +4. 约束条件 +5. 预期输出 +6. 评估标准 + +确保提示词的清晰性和可执行性。""" + +TEMPLATE_NAME_3 = '智能提示词优化3号专家' + + +def _resolve_user_id(): + try: + from flask_login import current_user + if current_user.is_authenticated: + return getattr(current_user, 'id', None) or getattr(current_user, 'uid', None) + except Exception: + pass + from flask import session + sid = session.get('user_id') + if sid is not None: + return sid + try: + u = User.query.filter_by(login_name='admin').first() + return u.uid if u else 1 + except Exception as ex: + logger.warning("3号专家 获取默认用户失败: %s", ex) + return 1 + + +@expert_generate_3_bp.route('/expert-generate-3', methods=['GET']) +def expert_generate_3_page(): + """智能提示词优化3号专家 - 页面""" + return render_template('expert_generate_3.html') + + +@expert_generate_3_bp.route('/api/expert-generate-3/generate', methods=['POST']) +def expert_generate_3_api(): + """智能提示词优化3号专家 - 两阶段生成 API,含历史记录""" + try: + if not request.is_json: + return jsonify({'code': 400, 'message': '请求必须是JSON格式', 'data': None}) + payload = request.get_json() or {} + raw_input = (payload.get('input_text') or '').strip() + if not raw_input: + return jsonify({'code': 400, 'message': '请输入您的需求', 'data': None}) + resp1 = _llm_client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "system", "content": INTENT_PROMPT_3}, + {"role": "user", "content": raw_input} + ], + temperature=0.1, + timeout=60 + ) + intent_raw = (resp1.choices[0].message.content or "").strip() + intent_raw = intent_raw.replace('```json', '').replace('```', '').strip() + try: + intent_data = json.loads(intent_raw) + for field in ['core_intent', 'domain', 'key_requirements', 'expected_output', 'constraints', 'keywords']: + if field not in intent_data: + raise ValueError("缺少字段: " + field) + if intent_data['core_intent'] not in ('技术', '创意', '分析', '咨询'): + intent_data['core_intent'] = '技术' + for arr_field in ['key_requirements', 'constraints', 'keywords']: + v = intent_data.get(arr_field) + if not isinstance(v, list) or len(v) == 0: + intent_data[arr_field] = ['未指定'] + except json.JSONDecodeError as e: + logger.error("3号专家 JSON解析失败: %s", e) + return jsonify({'code': 500, 'message': '意图分析格式有误,请重试', 'data': None}) + except ValueError as e: + logger.error("3号专家 数据验证失败: %s", e) + return jsonify({'code': 500, 'message': str(e), 'data': None}) + tpl = EXPERT_TEMPLATES_3.get(intent_data['core_intent'], FALLBACK_TEMPLATE_3) + analysis_str = json.dumps(intent_data, ensure_ascii=False, indent=2) + resp2 = _llm_client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "system", "content": tpl.format(analysis=analysis_str)}, + {"role": "user", "content": raw_input} + ], + temperature=0.7, + max_tokens=1000, + timeout=60 + ) + result_prompt = (resp2.choices[0].message.content or "").strip() + if not result_prompt: + return jsonify({'code': 500, 'message': '生成失败,请重试', 'data': None}) + uid = _resolve_user_id() + try: + db.session.add(Prompt(input_text=raw_input, generated_text=result_prompt, user_id=uid)) + db.session.commit() + except Exception as e: + db.session.rollback() + logger.warning("3号专家 保存 Prompt 失败: %s", e) + try: + PromptHistory.add_history( + user_id=uid, + original_input=raw_input, + generated_prompt=result_prompt, + template_name=TEMPLATE_NAME_3 + ) + UserStatistics.update_statistics(uid) + except Exception as e: + logger.warning("3号专家 保存历史失败: %s", e) + return jsonify({ + 'code': 200, + 'message': 'success', + 'data': {'intent_analysis': intent_data, 'generated_prompt': result_prompt} + }) + except Exception as e: + logger.exception("智能提示词优化3号专家失败") + return jsonify({'code': 500, 'message': str(e) or '生成失败,请重试', 'data': None}) diff --git a/src/flask_prompt_master/routes/meeting_minutes.py b/src/flask_prompt_master/routes/meeting_minutes.py new file mode 100644 index 0000000..b21d91c --- /dev/null +++ b/src/flask_prompt_master/routes/meeting_minutes.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +""" +会议纪要整理功能路由 +""" +from flask import Blueprint, render_template, request, jsonify, session +from openai import OpenAI +import logging +import os +from src.flask_prompt_master import db +from src.flask_prompt_master.models.models import User, MeetingMinutes + +logger = logging.getLogger(__name__) +meeting_minutes_bp = Blueprint('meeting_minutes', __name__) + +client = OpenAI( + api_key=os.environ.get('LLM_API_KEY') or 'sk-fdf7cc1c73504e628ec0119b7e11b8cc', + base_url=os.environ.get('LLM_API_URL') or 'https://api.deepseek.com/v1' +) + + +def _generate_minutes(raw_content: str, title: str) -> str: + """调用 LLM 生成会议纪要。""" + system_prompt = """你是一位专业的会议记录助手,擅长将零散的会议转写或要点整理成结构清晰的会议纪要。 + +要求: +1. 从用户输入中提炼:会议主题、时间/参与人(如有)、讨论要点、结论与决议、待办事项(含责任人/截止时间若可推断)。 +2. 使用 Markdown 格式:一级标题为「一、会议概要」「二、讨论要点」「三、结论与决议」「四、待办事项」等,二级标题和列表项简明扼要。 +3. 语气正式、条理清楚,便于归档和分享。若信息不足可合理归纳,不要编造具体人名与数据。""" + user_prompt = f"""请将以下会议内容整理成会议纪要:\n\n{f'会议主题:{title}\n\n' if title else ''}{raw_content}""" + messages = [ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_prompt} + ] + response = client.chat.completions.create( + model="deepseek-chat", + messages=messages, + temperature=0.4, + max_tokens=2000, + timeout=50 + ) + return response.choices[0].message.content + + +def _get_meeting_user_id(): + user_id = session.get('user_id') + if user_id is not None: + return user_id + try: + u = User.query.filter_by(login_name='admin').first() + return u.uid if u else 1 + except Exception as e: + logger.warning(f"获取默认用户失败: {e}") + return 1 + + +@meeting_minutes_bp.route('/meeting-minutes', methods=['GET']) +def minutes_page(): + return render_template('meeting_minutes.html') + + +@meeting_minutes_bp.route('/meeting-minutes/history', methods=['GET']) +def minutes_history_page(): + return render_template('meeting_minutes_history.html') + + +@meeting_minutes_bp.route('/api/meeting-minutes/generate', methods=['POST']) +def generate_minutes_api(): + try: + data = request.get_json() or {} + raw_content = (data.get('raw_content') or '').strip() + title = (data.get('title') or '').strip() + if not raw_content: + return jsonify({'success': False, 'message': '请粘贴或输入会议内容'}) + result = _generate_minutes(raw_content, title) + return jsonify({'success': True, 'data': {'summary': result, 'title': title}}) + except Exception as e: + logger.exception('会议纪要生成失败') + return jsonify({'success': False, 'message': str(e) or '生成失败,请重试'}) + + +@meeting_minutes_bp.route('/api/meeting-minutes/save', methods=['POST']) +def save_minutes_api(): + try: + data = request.get_json() or {} + title = (data.get('title') or '').strip() + raw_content = (data.get('raw_content') or '').strip() + summary_content = (data.get('summary_content') or '').strip() + if not summary_content: + return jsonify({'success': False, 'message': '纪要内容不能为空'}) + user_id = _get_meeting_user_id() + m = MeetingMinutes(user_id=user_id, title=title or None, raw_content=raw_content or '', summary_content=summary_content) + db.session.add(m) + db.session.commit() + return jsonify({'success': True, 'message': '保存成功', 'data': {'id': m.id, 'created_at': m.created_at.isoformat()}}) + except Exception as e: + db.session.rollback() + logger.exception('保存会议纪要失败') + return jsonify({'success': False, 'message': str(e) or '保存失败'}) + + +@meeting_minutes_bp.route('/api/meeting-minutes/list', methods=['GET']) +def list_minutes_api(): + try: + user_id = _get_meeting_user_id() + page = request.args.get('page', 1, type=int) + per_page = request.args.get('per_page', 10, type=int) + pag = MeetingMinutes.query.filter_by(user_id=user_id).order_by(MeetingMinutes.created_at.desc()).paginate(page=page, per_page=per_page, error_out=False) + items = [{'id': x.id, 'title': x.title or '未命名', 'raw_content': (x.raw_content or '')[:200], 'summary_content': x.summary_content, 'created_at': x.created_at.isoformat()} for x in pag.items] + return jsonify({'success': True, 'data': {'plans': items, 'pagination': {'page': pag.page, 'pages': pag.pages, 'per_page': pag.per_page, 'total': pag.total, 'has_next': pag.has_next, 'has_prev': pag.has_prev}}}) + except Exception as e: + logger.exception('列表会议纪要失败') + return jsonify({'success': False, 'message': str(e) or '获取失败'}) + + +@meeting_minutes_bp.route('/api/meeting-minutes/按模块类型或粘贴代码,生成审查要点与建议
+说明模块类型或粘贴代码后,点击「生成清单」
+结果将自动保存到历史记录
+粘贴堆栈或 Logcat,获取通俗解释与排查建议
+粘贴崩溃堆栈或 Logcat 后,点击「分析解读」
+结果将自动保存到历史记录
+粘贴 Gradle 报错或依赖树,获取解决思路与示例
+粘贴 Gradle 报错或依赖树后,点击「分析解读」
+结果将自动保存到历史记录
+描述性能问题或场景,获取优化思路与 Checklist
+描述性能问题或优化场景后,点击「生成建议」
+结果将自动保存到历史记录
+粘贴或描述技术方案,生成评审维度与常见坑点
+粘贴或描述技术方案后,点击「生成评审要点」
+结果将自动保存到历史记录
+正在分析需求并生成专业提示词...
+核心意图:
+专业领域:
+预期输出:
+关键需求:
+约束条件:
+正在分析需求并生成专业提示词...
+核心意图:
+专业领域:
+预期输出:
+关键需求:
+约束条件:
+粘贴会议转写或要点,一键生成结构化会议纪要
+ 办公 +润色简历或根据岗位生成针对性求职信
+ 求职 +使用通用模板,将普通描述转换为专业 AI 提示词
+ 通用 +根据需求描述生成优化模板,再按模板优化您的提示词
+ 智能 +与专家模式一致:需求分析 + 领域专家生成高质量提示词
+ 专家 +与专家模式一致:需求分析 + 领域专家生成,含历史记录
+ 专家 +生成摘要、金句、思维导图式大纲或读后感
+ 文化 +育儿建议、睡前故事、简单科普或习题讲解
+ 教育 +根据目标与场地生成一周训练计划与动作要点
+ 健康 +人话版要点、风险提示与建议关注条款
+ 法律 +生成标题、分镜文案、口播稿
+ 创作 +按岗位类型出题并给参考答案与点评
+ 求职 +祝福语、贺卡文案、红包配文
+ 生活 +结构化复盘与下周重点
+ 成长 +零散待办生成按优先级与日期的日程清单
效率草稿或要点生成得体邮件回复
办公根据主题与场合生成演讲稿或汇报大纲
办公公司名、产品名或宝宝取名建议
创意根据食材或菜名生成详细做法
生活生成学习计划与复习建议
教育结构化记录或轻疏导建议
成长润色、改错与学习建议
教育生成注释或通俗解释
技术根据要点生成 PRD 或需求描述
办公根据场景生成短文案、配文
生活根据题材生成梗概或分集大纲
创作数据或结论生成通俗解读与建议
办公生成竞品分析维度与模板
办公长文生成摘要与要点
效率中英互译并润色
办公根据类型生成合同模板或条款建议
法律策划框架与执行清单
办公年度大事与数据生成总结报告
成长根据主题生成问答式学习卡片
教育根据议题生成议程与时间分配
办公待办转为日历事件描述
效率常用场景邮件模板与改写
办公按岗位生成周报结构模板
办公按岗位生成日报结构模板
办公流水记录转结构化工作日志
办公根据项目经过生成复盘框架
办公根据方向生成 OKR 草案
办公生成会议邀请与议程摘要
办公生成请假条或报销说明文案
办公错题分类与复习建议
教育按章节或主题生成知识点总结
教育作文批改与修改建议
教育题目生成解题步骤与思路
教育根据词书或目标生成记忆计划
教育根据文章生成阅读题
教育生成口语话题与参考表达
教育根据题目生成论文大纲
教育零散笔记整理成结构化笔记
教育根据考纲生成复习与押题建议
教育根据正文生成多组标题建议
创作根据问题生成回答大纲或草稿
创作根据视频内容生成文案与话题
创作生成视频简介与标签建议
创作根据主题生成播客大纲与话题
创作根据设定生成开篇段落或大纲
创作根据主题或风格生成短诗
创作根据上联或主题生成对联
文化根据场景生成轻松段子
生活根据产品卖点生成广告语
创意生成搬家待办与打包清单
生活根据目的地与天数生成清单
生活生成婚礼筹备事项与时间线
生活根据户型生成预算分类表
生活根据宠物类型生成喂养与护理建议
生活根据植物品种生成养护要点
生活根据需求生成选购维度与建议
生活条款对比与人话解读
生活根据目标生成理财建议框架
生活流水描述生成分类与标签
生活根据体质或目标生成饮食建议
健康根据情况生成睡眠改善建议
健康生成拉伸动作与提醒话术
健康指标解读与随访建议
健康药品说明转简明提醒与注意
健康症状描述生成就医与自查建议
健康生成自测题与解读框架
健康生成阶段性计划与替代建议
健康合同要点提炼与风险提示
法律租房合同要点与注意项
法律根据金额与关系生成借条模板
法律根据场景生成免责声明文案
法律根据需求描述生成或优化 SQL
技术根据接口信息生成文档草稿
技术根据描述生成正则表达式
技术命令或报错生成使用说明
技术报错信息转通俗解释与解决思路
技术根据变更生成 commit message
技术根据主题生成技术文章大纲
技术需求描述转用户故事与验收点
技术粘贴堆栈或 Logcat,生成解释与排查建议
Android启动/内存/卡顿等场景的优化思路与 Checklist
Android生成评审维度与常见坑点
Android按模块类型生成 Android 代码审查要点
Android根据 commit 或需求生成 Release Notes
AndroidGradle 报错或依赖树生成解决思路
Android根据需求推荐组件与迁移建议
Android面试题与参考答案
Android项目描述生成架构思路与模块划分
Android官方文档或邮件翻译、润色
Android查看和管理已保存的周报/日报历史
+ 历史 +查看和管理已保存的旅行攻略
+ 历史 +${item.content}
+${safeContent}
${item.result}
+${safeResult}
AI驱动的个性化饭菜清单规划师
加载中...
使用「通用提示词优化」模板,将普通描述转换为专业的 AI 提示词
+输入您的需求描述,点击「生成优化提示词」开始
+生成结果将自动保存到历史记录
+润色简历或根据岗位生成针对性求职信
+填写简历内容或要点,可选填岗位描述,点击「生成」开始
+加载中...
正在分析需求并生成专业提示词...
+核心意图:
+专业领域:
+预期输出:
+关键需求:
+约束条件:
+根据目的地与天数,AI 生成行程与实用建议
查看和管理已保存的旅行攻略
+加载中...
输入工作要点,一键生成规范周报/日报
查看和管理已保存的周报/日报
+加载中...