优化RAG知识库调用功能:增强控制台日志输出和个性化分析
主要更改: 1. rag-python/app.py: - /api/rag-analyze 接口添加 similarity 字段 - 添加服务端控制台日志打印检索结果 2. PromptBuilder.java: - 增强角色设定,强调先共情后分析的风格 - 根据年龄自动添加关注点提示 - 根据职业自动添加相关压力源提示 - 增加参考资料长度限制 - 新增核心原则:个性化优先、具体化表达、共情式开头 - 建议分层:即时可行、短期调整、长期发展 3. comprehensive.vue: - 添加详细的浏览器控制台日志输出 - 显示检索到的知识库文件列表、相似度和内容预览
This commit is contained in:
parent
0f490298f3
commit
e2b270e705
|
|
@ -88,6 +88,11 @@ def search():
|
|||
|
||||
results = knowledge_service.search(query, top_k)
|
||||
|
||||
# 打印调试信息
|
||||
print(f"[Search] Query: {query[:50]}..., Results: {len(results)}")
|
||||
for i, r in enumerate(results):
|
||||
print(f" [{i+1}] filename: {r.get('filename')}, content_len: {len(r.get('content', ''))}")
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': results
|
||||
|
|
@ -131,6 +136,78 @@ def scan_folder():
|
|||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/rag-analyze', methods=['POST'])
|
||||
def rag_analyze():
|
||||
"""RAG增强的AI分析 - 结合知识库生成分析报告"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
report_content = data.get('reportContent', '')
|
||||
report_title = data.get('reportTitle', '心理测评报告')
|
||||
|
||||
if not report_content:
|
||||
return jsonify({'success': False, 'error': '报告内容不能为空'}), 400
|
||||
|
||||
# 1. 从报告中提取关键词进行知识库检索
|
||||
# 提取纯文本(去除HTML标签)
|
||||
import re
|
||||
text_content = re.sub(r'<[^>]*>', '', report_content)
|
||||
|
||||
# 提取关键信息用于检索
|
||||
query_keywords = []
|
||||
# 提取因子名称
|
||||
factor_matches = re.findall(r'([\u4e00-\u9fa5]+(?:焦虑|抑郁|压力|情绪|睡眠|躯体|认知|人格|心理)[\u4e00-\u9fa5]*)', text_content)
|
||||
query_keywords.extend(factor_matches[:5])
|
||||
# 提取等级
|
||||
level_matches = re.findall(r'(正常|轻度|中度|重度|严重)', text_content)
|
||||
query_keywords.extend(level_matches[:3])
|
||||
|
||||
query = ' '.join(set(query_keywords)) if query_keywords else '心理测评 分析 建议'
|
||||
|
||||
# 2. 检索相关知识
|
||||
search_results = knowledge_service.search(query, top_k=5)
|
||||
|
||||
# 3. 构建知识库上下文
|
||||
knowledge_context = ""
|
||||
sources = []
|
||||
if search_results and len(search_results) > 0:
|
||||
knowledge_parts = []
|
||||
for i, result in enumerate(search_results[:5]):
|
||||
content = result.get('content', '')
|
||||
filename = result.get('filename', '未知来源')
|
||||
similarity = result.get('similarity', 0)
|
||||
if content:
|
||||
knowledge_parts.append(f"【参考资料{i+1}】({filename})\n{content[:500]}")
|
||||
sources.append({
|
||||
'filename': filename,
|
||||
'content': content[:200] + '...' if len(content) > 200 else content,
|
||||
'similarity': similarity
|
||||
})
|
||||
knowledge_context = '\n\n'.join(knowledge_parts)
|
||||
|
||||
# 打印调试信息到控制台
|
||||
print("=" * 50)
|
||||
print("📚 RAG-Analyze 检索结果")
|
||||
print("=" * 50)
|
||||
print(f"查询关键词: {query}")
|
||||
print(f"检索到文档数: {len(sources)}")
|
||||
for i, s in enumerate(sources):
|
||||
print(f" [{i+1}] {s['filename']} (相似度: {s.get('similarity', 0):.4f})")
|
||||
print("=" * 50)
|
||||
|
||||
# 4. 返回检索结果,让前端调用AI
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': {
|
||||
'knowledgeContext': knowledge_context,
|
||||
'sources': sources,
|
||||
'query': query
|
||||
}
|
||||
})
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
def init_service():
|
||||
"""初始化服务"""
|
||||
print("=" * 50)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
package com.ddnai.system.rag.util;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 鎻愮ず璇嶆瀯寤哄伐鍏?
|
||||
* 鏋勫缓鍙戦€佺粰澶фā鍨嬬殑鎻愮ず璇嶏紝纭<EFBFBD>繚鍖呭惈鎵€鏈夊繀瑕佷俊鎭?
|
||||
* 提示词构建工具
|
||||
* 构建发送给大模型的提示词,确保包含所有必要信息
|
||||
*
|
||||
* @author ddnai
|
||||
*/
|
||||
|
|
@ -16,156 +17,282 @@ import java.util.Map;
|
|||
public class PromptBuilder {
|
||||
|
||||
/**
|
||||
* 鏋勫缓鎶ュ憡鐢熸垚鎻愮ず璇?
|
||||
* 构建报告生成提示词
|
||||
*
|
||||
* @param retrievedDocs 妫€绱㈠埌鐨勬枃妗?
|
||||
* @param retrievedDocs 检索到的文档
|
||||
* @param assessmentData 测评数据
|
||||
* @param userProfile 用户档案
|
||||
* @return 鎻愮ず璇?
|
||||
* @return 提示词
|
||||
*/
|
||||
public String buildReportPrompt(List<Map<String, Object>> retrievedDocs,
|
||||
Map<String, Object> assessmentData,
|
||||
Map<String, Object> userProfile) {
|
||||
StringBuilder prompt = new StringBuilder();
|
||||
|
||||
prompt.append("浣犳槸涓€浣嶄笓涓氱殑鐩戠嫳蹇冪悊瀛︿笓瀹躲€傝<EFBFBD>鍩轰簬浠ヤ笅涓撲笟鐭ヨ瘑鍜屾祴璇勬暟鎹<EFBFBD>紝鐢熸垚璇︾粏鐨勭患鍚堝績鐞嗗垎鏋愭姤鍛娿€俓n\n");
|
||||
// 增强的角色设定
|
||||
prompt.append("# 角色设定\n");
|
||||
prompt.append("你是一位资深的临床心理学专家,拥有20年以上的心理评估和咨询经验。");
|
||||
prompt.append("你的分析风格是:先共情理解,再专业分析,最后给出具体可行的建议。");
|
||||
prompt.append("你善于根据来访者的年龄、性别、职业等背景信息,提供高度个性化的解读。\n\n");
|
||||
|
||||
// 娣诲姞妫€绱㈠埌鐨勪笓涓氱煡璇?
|
||||
// 添加检索到的专业知识
|
||||
if (retrievedDocs != null && !retrievedDocs.isEmpty()) {
|
||||
prompt.append("銆愪笓涓氱煡璇嗗弬鑰冦€慭n");
|
||||
prompt.append("# 专业知识库参考\n");
|
||||
prompt.append("以下是与本次测评相关的专业知识和案例,请在分析时参考并引用:\n\n");
|
||||
for (int i = 0; i < retrievedDocs.size(); i++) {
|
||||
Map<String, Object> doc = retrievedDocs.get(i);
|
||||
String content = (String) doc.get("content");
|
||||
String filename = (String) doc.get("filename");
|
||||
Double similarity = (Double) doc.get("similarity");
|
||||
String filename = (String) doc.getOrDefault("filename", "参考资料");
|
||||
|
||||
prompt.append(String.format("%d. 鏉ユ簮锛?s锛堢浉鍏冲害锛?.2f锛塡n", i + 1, filename, similarity));
|
||||
prompt.append(content).append("\n\n");
|
||||
if (content != null && !content.isEmpty()) {
|
||||
prompt.append(String.format("## 参考资料%d(来源:%s)\n", i + 1, filename));
|
||||
// 增加参考资料长度限制
|
||||
if (content.length() > 1500) {
|
||||
content = content.substring(0, 1500) + "...";
|
||||
}
|
||||
prompt.append(content).append("\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 娣诲姞鐢ㄦ埛妗f<EFBFBD>
|
||||
// 增强的用户档案分析
|
||||
if (userProfile != null && !userProfile.isEmpty()) {
|
||||
prompt.append("銆愮敤鎴锋。妗堛€慭n");
|
||||
prompt.append(JSON.toJSONString(userProfile)).append("\n\n");
|
||||
prompt.append("# 被测评人背景信息(重要!请务必结合这些信息进行个性化分析)\n");
|
||||
|
||||
Object age = userProfile.get("age");
|
||||
Object gender = userProfile.get("gender");
|
||||
Object education = userProfile.get("education");
|
||||
Object occupation = userProfile.get("occupation");
|
||||
|
||||
if (age != null) {
|
||||
prompt.append("- 年龄:").append(age).append("岁");
|
||||
// 添加年龄段特征提示
|
||||
int ageInt = Integer.parseInt(age.toString());
|
||||
if (ageInt < 18) {
|
||||
prompt.append("(青少年期,关注学业压力、同伴关系、身份认同)");
|
||||
} else if (ageInt < 30) {
|
||||
prompt.append("(青年期,关注职业发展、亲密关系、自我实现)");
|
||||
} else if (ageInt < 50) {
|
||||
prompt.append("(中年期,关注工作压力、家庭责任、健康关注)");
|
||||
} else {
|
||||
prompt.append("(中老年期,关注退休适应、健康状况、人生意义)");
|
||||
}
|
||||
prompt.append("\n");
|
||||
}
|
||||
if (gender != null) {
|
||||
prompt.append("- 性别:").append(gender).append("\n");
|
||||
}
|
||||
if (education != null) {
|
||||
prompt.append("- 学历:").append(education).append("\n");
|
||||
}
|
||||
if (occupation != null) {
|
||||
prompt.append("- 职业:").append(occupation);
|
||||
// 添加职业相关提示
|
||||
String occStr = occupation.toString();
|
||||
if (occStr.contains("学生")) {
|
||||
prompt.append("(关注学业压力、考试焦虑、人际关系)");
|
||||
} else if (occStr.contains("教师") || occStr.contains("医") || occStr.contains("护")) {
|
||||
prompt.append("(关注职业倦怠、共情疲劳、工作压力)");
|
||||
} else if (occStr.contains("经理") || occStr.contains("主管") || occStr.contains("总")) {
|
||||
prompt.append("(关注管理压力、决策焦虑、工作生活平衡)");
|
||||
}
|
||||
prompt.append("\n");
|
||||
}
|
||||
|
||||
// 添加其他可能的背景信息
|
||||
for (Map.Entry<String, Object> entry : userProfile.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (!key.equals("age") && !key.equals("gender") && !key.equals("education") && !key.equals("occupation")) {
|
||||
prompt.append("- ").append(key).append(":").append(entry.getValue()).append("\n");
|
||||
}
|
||||
}
|
||||
prompt.append("\n");
|
||||
}
|
||||
|
||||
// 添加测评数据
|
||||
if (assessmentData != null && !assessmentData.isEmpty()) {
|
||||
prompt.append("銆愭祴璇勬暟鎹<EFBFBD>€慭n");
|
||||
prompt.append(JSON.toJSONString(assessmentData)).append("\n\n");
|
||||
prompt.append("# 测评数据详情\n");
|
||||
prompt.append("```json\n");
|
||||
prompt.append(JSON.toJSONString(assessmentData, JSONWriter.Feature.PrettyFormat)).append("\n");
|
||||
prompt.append("```\n\n");
|
||||
}
|
||||
|
||||
// 娣诲姞鐢熸垚瑕佹眰
|
||||
prompt.append("銆愮敓鎴愯<EFBFBD>姹傘€慭n");
|
||||
prompt.append("璇峰熀浜庝互涓婁俊鎭<EFBFBD>紝鐢熸垚涓€浠戒笓涓氱殑缁煎悎蹇冪悊鍒嗘瀽鎶ュ憡锛屾姤鍛婂簲鍖呮嫭锛歕n");
|
||||
prompt.append("1. 缁煎悎璇勪及锛氭暣浣撳績鐞嗙姸鎬佸垎鏋怽n");
|
||||
prompt.append("2. 椋庨櫓鍒嗘瀽锛氭綔鍦ㄥ績鐞嗛<E9909E>闄╄瘑鍒玕n");
|
||||
prompt.append("3. 鐭<>不寤鸿<E5AFA4>锛氬叿浣撶殑蹇冪悊骞查<E9AA9E>鍜岀煫娌绘柟妗圽n");
|
||||
prompt.append("4. 鍏虫敞瑕佺偣锛氶渶瑕侀噸鐐瑰叧娉ㄧ殑蹇冪悊闂<E6828A><E99782>\n\n");
|
||||
prompt.append("璇风‘淇濇姤鍛婂唴瀹逛笓涓氥€佸噯纭<EFBFBD>€佸叿鏈夊彲鎿嶄綔鎬э紝骞跺紩鐢ㄧ浉鍏崇殑蹇冪悊瀛︾悊璁烘敮鎸佷綘鐨勫垎鏋愩€俓n");
|
||||
// 增强的生成要求
|
||||
prompt.append("# 分析报告要求\n\n");
|
||||
prompt.append("请根据以上测评数据、专业知识和被测评人的背景信息,生成一份详细、专业、高度个性化的心理分析报告。\n\n");
|
||||
|
||||
prompt.append("## 核心原则\n");
|
||||
prompt.append("1. **个性化优先**:必须结合被测评人的年龄、性别、职业等信息进行分析,不能写通用内容\n");
|
||||
prompt.append("2. **具体化表达**:用具体的行为描述代替抽象术语,如\"您可能经常感到紧张,难以放松\"而非\"您有焦虑倾向\"\n");
|
||||
prompt.append("3. **共情式开头**:先表达对被测评人处境的理解,再进行分析\n");
|
||||
prompt.append("4. **可操作建议**:每条建议都要具体到可以立即执行的程度\n\n");
|
||||
|
||||
prompt.append("## 报告结构要求\n\n");
|
||||
|
||||
prompt.append("### 1. 开篇(100-150字)\n");
|
||||
prompt.append("- 以温和、支持的语气开始\n");
|
||||
prompt.append("- 结合被测评人的背景表达理解(如:\"作为一名XX岁的XX,您正面临...\")\n");
|
||||
prompt.append("- 简要概括测评结果的整体情况\n\n");
|
||||
|
||||
prompt.append("### 2. 详细分析(每个因子150-250字)\n");
|
||||
prompt.append("针对每个测评因子进行深入分析:\n");
|
||||
prompt.append("- 用通俗语言解释该因子得分的含义\n");
|
||||
prompt.append("- 描述被测评人可能正在经历的具体感受和表现\n");
|
||||
prompt.append("- 结合其年龄、职业等背景分析可能的原因\n");
|
||||
prompt.append("- 引用知识库中的专业内容支持分析\n");
|
||||
prompt.append("- 指出该因子与其他因子的关联(如有)\n\n");
|
||||
|
||||
prompt.append("### 3. 个性化建议(300-400字)\n");
|
||||
prompt.append("提供分层次的具体建议:\n");
|
||||
prompt.append("- **即时可行**(本周可以开始):3-4条简单、具体的行动\n");
|
||||
prompt.append("- **短期调整**(1-4周):需要培养的习惯或技能\n");
|
||||
prompt.append("- **长期发展**(1-3个月):持续关注的方向\n");
|
||||
prompt.append("- 每条建议都要说明具体做法,而非泛泛而谈\n");
|
||||
prompt.append("- 建议要符合被测评人的实际情况(年龄、职业等)\n\n");
|
||||
|
||||
prompt.append("### 4. 总结与鼓励(100-150字)\n");
|
||||
prompt.append("- 肯定被测评人的优势和资源\n");
|
||||
prompt.append("- 强调改变的可能性\n");
|
||||
prompt.append("- 说明何时需要寻求专业帮助\n");
|
||||
prompt.append("- 以积极、温暖的语气结束\n\n");
|
||||
|
||||
prompt.append("## 写作风格要求\n");
|
||||
prompt.append("- 使用第二人称\"您\",语气温和、专业、支持性\n");
|
||||
prompt.append("- 避免使用\"患者\"、\"症状\"等医学化标签\n");
|
||||
prompt.append("- 多用\"可能\"、\"也许\"等柔和表达,避免绝对化判断\n");
|
||||
prompt.append("- 分析要具体,避免\"注意休息\"、\"保持乐观\"等空洞建议\n");
|
||||
prompt.append("- 必须引用知识库中的专业内容来支持分析\n\n");
|
||||
|
||||
prompt.append("请开始生成报告:\n");
|
||||
|
||||
return prompt.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 鏋勫缓闂<EFBFBD>瓟鎻愮ず璇?
|
||||
* 构建问答提示词
|
||||
*
|
||||
* @param question 问题
|
||||
* @param retrievedDocs 妫€绱㈠埌鐨勬枃妗?
|
||||
* @return 鎻愮ず璇?
|
||||
* @param retrievedDocs 检索到的文档
|
||||
* @return 提示词
|
||||
*/
|
||||
public String buildQAPrompt(String question, List<Map<String, Object>> retrievedDocs) {
|
||||
StringBuilder prompt = new StringBuilder();
|
||||
|
||||
prompt.append("浣犳槸涓€浣嶄笓涓氱殑蹇冪悊瀛︿笓瀹躲€傝<EFBFBD>鍩轰簬浠ヤ笅涓撲笟鐭ヨ瘑鍥炵瓟闂<EFBFBD><EFBFBD>銆俓n\n");
|
||||
prompt.append("# 角色设定\n");
|
||||
prompt.append("你是一位专业的心理学顾问,能够基于专业知识回答心理健康相关问题。\n\n");
|
||||
|
||||
// 娣诲姞妫€绱㈠埌鐨勪笓涓氱煡璇?
|
||||
// 添加检索到的专业知识
|
||||
if (retrievedDocs != null && !retrievedDocs.isEmpty()) {
|
||||
prompt.append("銆愮浉鍏崇煡璇嗐€慭n");
|
||||
prompt.append("# 相关专业知识\n");
|
||||
prompt.append("以下是与问题相关的专业资料,请基于这些内容回答:\n\n");
|
||||
for (int i = 0; i < retrievedDocs.size(); i++) {
|
||||
Map<String, Object> doc = retrievedDocs.get(i);
|
||||
String content = (String) doc.get("content");
|
||||
String filename = (String) doc.get("filename");
|
||||
String filename = (String) doc.getOrDefault("filename", "参考资料");
|
||||
|
||||
prompt.append(String.format("%d. 鏉ユ簮锛?s\n", i + 1, filename));
|
||||
prompt.append(content).append("\n\n");
|
||||
if (content != null && !content.isEmpty()) {
|
||||
prompt.append(String.format("## 资料%d(%s)\n", i + 1, filename));
|
||||
if (content.length() > 600) {
|
||||
content = content.substring(0, 600) + "...";
|
||||
}
|
||||
prompt.append(content).append("\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加问题
|
||||
prompt.append("銆愰棶棰樸€慭n");
|
||||
prompt.append("# 用户问题\n");
|
||||
prompt.append(question).append("\n\n");
|
||||
|
||||
// 添加回答要求
|
||||
prompt.append("銆愬洖绛旇<EFBFBD>姹傘€慭n");
|
||||
prompt.append("1. 璇峰熀浜庝笂杩颁笓涓氱煡璇嗗洖绛旈棶棰榎n");
|
||||
prompt.append("2. 鍥炵瓟瑕佸噯纭<E599AF>€佷笓涓氥€佹槗鎳俓n");
|
||||
prompt.append("3. 濡傛灉鐭ヨ瘑搴撲腑娌℃湁鐩稿叧淇℃伅锛岃<E9949B>鏄庣‘璇存槑\n");
|
||||
prompt.append("4. 鍙<>互寮曠敤鍏蜂綋鐨勭悊璁烘垨鐮旂┒鏀<E29492>寔浣犵殑鍥炵瓟\n");
|
||||
prompt.append("# 回答要求\n");
|
||||
prompt.append("1. 基于上述专业知识回答,必须引用相关内容\n");
|
||||
prompt.append("2. 回答要准确、专业、易于理解\n");
|
||||
prompt.append("3. 如果知识库中没有直接相关的信息,请说明并给出一般性建议\n");
|
||||
prompt.append("4. 语气要温和、支持性\n");
|
||||
prompt.append("5. 如果问题涉及严重心理问题,建议寻求专业帮助\n\n");
|
||||
|
||||
prompt.append("请回答:\n");
|
||||
|
||||
return prompt.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 鏋勫缓寤鸿<EFBFBD>鐢熸垚鎻愮ず璇?
|
||||
* 构建建议生成提示词
|
||||
*
|
||||
* @param userProfile 用户档案
|
||||
* @param assessmentData 测评数据
|
||||
* @param retrievedDocs 妫€绱㈠埌鐨勬枃妗?
|
||||
* @return 鎻愮ず璇?
|
||||
* @param retrievedDocs 检索到的文档
|
||||
* @return 提示词
|
||||
*/
|
||||
public String buildSuggestionPrompt(Map<String, Object> userProfile,
|
||||
Map<String, Object> assessmentData,
|
||||
List<Map<String, Object>> retrievedDocs) {
|
||||
StringBuilder prompt = new StringBuilder();
|
||||
|
||||
prompt.append("浣犳槸涓€浣嶄笓涓氱殑鐩戠嫳蹇冪悊鐭<EFBFBD>不涓撳<EFBFBD>銆傝<EFBFBD>鍩轰簬浠ヤ笅淇℃伅锛屾彁渚涘叿浣撶殑蹇冪悊鐭<EFBFBD>不寤鸿<EFBFBD>銆俓n\n");
|
||||
prompt.append("# 角色设定\n");
|
||||
prompt.append("你是一位经验丰富的心理咨询师,擅长制定个性化的心理健康改善方案。\n\n");
|
||||
|
||||
// 娣诲姞妫€绱㈠埌鐨勪笓涓氱煡璇?
|
||||
// 添加检索到的专业知识
|
||||
if (retrievedDocs != null && !retrievedDocs.isEmpty()) {
|
||||
prompt.append("銆愪笓涓氱煡璇嗗弬鑰冦€慭n");
|
||||
prompt.append("# 专业知识参考\n");
|
||||
for (int i = 0; i < retrievedDocs.size(); i++) {
|
||||
Map<String, Object> doc = retrievedDocs.get(i);
|
||||
String content = (String) doc.get("content");
|
||||
String filename = (String) doc.get("filename");
|
||||
String filename = (String) doc.getOrDefault("filename", "参考资料");
|
||||
|
||||
prompt.append(String.format("%d. 鏉ユ簮锛?s\n", i + 1, filename));
|
||||
prompt.append(content).append("\n\n");
|
||||
if (content != null && !content.isEmpty()) {
|
||||
prompt.append(String.format("## %s\n", filename));
|
||||
if (content.length() > 500) {
|
||||
content = content.substring(0, 500) + "...";
|
||||
}
|
||||
prompt.append(content).append("\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加用户档案
|
||||
if (userProfile != null && !userProfile.isEmpty()) {
|
||||
prompt.append("銆愮敤鎴锋。妗堛€慭n");
|
||||
prompt.append(JSON.toJSONString(userProfile)).append("\n\n");
|
||||
prompt.append("# 用户信息\n");
|
||||
prompt.append(JSON.toJSONString(userProfile, JSONWriter.Feature.PrettyFormat)).append("\n\n");
|
||||
}
|
||||
|
||||
// 添加测评数据
|
||||
if (assessmentData != null && !assessmentData.isEmpty()) {
|
||||
prompt.append("銆愭祴璇勬暟鎹<EFBFBD>€慭n");
|
||||
prompt.append(JSON.toJSONString(assessmentData)).append("\n\n");
|
||||
prompt.append("# 测评结果\n");
|
||||
prompt.append(JSON.toJSONString(assessmentData, JSONWriter.Feature.PrettyFormat)).append("\n\n");
|
||||
}
|
||||
|
||||
// 添加生成要求
|
||||
prompt.append("銆愮敓鎴愯<EFBFBD>姹傘€慭n");
|
||||
prompt.append("璇锋彁渚涗互涓嬫柟闈㈢殑鐭<EFBFBD>不寤鸿<EFBFBD>锛歕n");
|
||||
prompt.append("1. 鐭<>湡骞查<E9AA9E>鎺<EFBFBD>柦锛?-3涓<33>湀锛塡n");
|
||||
prompt.append("2. 涓<>湡鐭<E6B9A1>不璁″垝锛?-6涓<36>湀锛塡n");
|
||||
prompt.append("3. 闀挎湡鍙戝睍鐩<E79D8D>爣锛?涓<>湀浠ヤ笂锛塡n");
|
||||
prompt.append("4. 鍏蜂綋鐨勫績鐞嗘妧鏈<E5A6A7>拰鏂规硶\n");
|
||||
prompt.append("5. 闇€瑕佹敞鎰忕殑浜嬮」鍜岄<E98D9C>闄╃偣\n\n");
|
||||
prompt.append("寤鸿<EFBFBD>搴斿叿浣撱€佸彲鎿嶄綔銆佺<EFBFBD>鍚堢洃鐙辩幆澧冪壒鐐广€俓n");
|
||||
prompt.append("# 建议方案要求\n\n");
|
||||
prompt.append("请提供一份详细的个性化改善建议方案:\n\n");
|
||||
|
||||
prompt.append("## 1. 即时可行的建议(本周可以开始)\n");
|
||||
prompt.append("- 3-5条具体、简单、可立即执行的建议\n");
|
||||
prompt.append("- 每条建议说明具体做法和预期效果\n\n");
|
||||
|
||||
prompt.append("## 2. 短期改善计划(1-4周)\n");
|
||||
prompt.append("- 需要培养的习惯或技能\n");
|
||||
prompt.append("- 具体的练习方法和频率\n");
|
||||
prompt.append("- 可能遇到的困难和应对方法\n\n");
|
||||
|
||||
prompt.append("## 3. 长期发展建议(1-3个月)\n");
|
||||
prompt.append("- 需要持续关注的方面\n");
|
||||
prompt.append("- 推荐的学习资源或活动\n");
|
||||
prompt.append("- 何时需要寻求专业帮助\n\n");
|
||||
|
||||
prompt.append("## 4. 注意事项\n");
|
||||
prompt.append("- 需要避免的行为或思维模式\n");
|
||||
prompt.append("- 可能的风险信号\n\n");
|
||||
|
||||
prompt.append("请确保建议具体、实用、符合用户的实际情况。\n");
|
||||
|
||||
return prompt.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 鏋勫缓绠€鍗曠殑鐢熸垚鎻愮ず璇?
|
||||
*
|
||||
* @param systemPrompt 绯荤粺鎻愮ず
|
||||
* @param userPrompt 鐢ㄦ埛鎻愮ず
|
||||
* @return 鎻愮ず璇?
|
||||
* 构建简单的生成提示词
|
||||
*/
|
||||
public String buildSimplePrompt(String systemPrompt, String userPrompt) {
|
||||
StringBuilder prompt = new StringBuilder();
|
||||
|
|
@ -182,11 +309,7 @@ public class PromptBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* 楠岃瘉鎻愮ず璇嶆槸鍚﹀寘鍚<EFBFBD>繀瑕佷俊鎭?
|
||||
*
|
||||
* @param prompt 鎻愮ず璇?
|
||||
* @param requiredKeywords 蹇呴渶鐨勫叧閿<EFBFBD>瘝
|
||||
* @return 鏄<EFBFBD>惁鍖呭惈鎵€鏈夊繀闇€鍏抽敭璇?
|
||||
* 验证提示词是否包含必要信息
|
||||
*/
|
||||
public boolean validatePrompt(String prompt, List<String> requiredKeywords) {
|
||||
if (prompt == null || prompt.isEmpty()) {
|
||||
|
|
@ -208,10 +331,6 @@ public class PromptBuilder {
|
|||
|
||||
/**
|
||||
* 截断过长的提示词
|
||||
*
|
||||
* @param prompt 鎻愮ず璇?
|
||||
* @param maxLength 鏈€澶ч暱搴?
|
||||
* @return 鎴<EFBFBD>柇鍚庣殑鎻愮ず璇?
|
||||
*/
|
||||
public String truncatePrompt(String prompt, int maxLength) {
|
||||
if (prompt == null || prompt.length() <= maxLength) {
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ export default {
|
|||
generating: false,
|
||||
reportDialogVisible: false,
|
||||
comprehensiveReport: '',
|
||||
ragSourcesForReport: [], // RAG知识库来源
|
||||
// ========== Kimi API配置 ==========
|
||||
API_URL: 'https://api.moonshot.cn/v1/chat/completions',
|
||||
API_KEY: 'sk-U9fdriPxwBcrpWW0Ite3N0eVtX7VxnqqqYUIBAdWd1hgEA9m',
|
||||
|
|
@ -721,10 +722,55 @@ export default {
|
|||
// Kimi API 调用方法
|
||||
async callOLLAMA(prompt) {
|
||||
try {
|
||||
// 1. 先调用RAG服务获取知识库上下文
|
||||
let knowledgeContext = '';
|
||||
let ragSources = [];
|
||||
const RAG_API_URL = 'http://localhost:5000/api/rag-analyze';
|
||||
|
||||
try {
|
||||
// 从prompt中提取关键信息用于RAG检索
|
||||
const ragResponse = await axios.post(RAG_API_URL, {
|
||||
reportContent: prompt,
|
||||
reportTitle: '综合心理评估'
|
||||
}, { timeout: 10000 });
|
||||
|
||||
if (ragResponse.data && ragResponse.data.success) {
|
||||
knowledgeContext = ragResponse.data.data.knowledgeContext || '';
|
||||
ragSources = ragResponse.data.data.sources || [];
|
||||
|
||||
// ========== 在控制台打印完整的知识库引用信息 ==========
|
||||
console.log('========================================');
|
||||
console.log('📚 RAG知识库检索结果');
|
||||
console.log('========================================');
|
||||
console.log('检索到的文档数量:', ragSources.length);
|
||||
console.log('');
|
||||
console.log('📋 引用的知识库文件列表:');
|
||||
ragSources.forEach((source, index) => {
|
||||
console.log(` ${index + 1}. 文件名: ${source.filename || '未知'}`);
|
||||
console.log(` 相似度: ${source.similarity ? (source.similarity * 100).toFixed(2) + '%' : '未知'}`);
|
||||
console.log(` 内容预览: ${source.content ? source.content.substring(0, 100) + '...' : '无内容'}`);
|
||||
console.log('');
|
||||
});
|
||||
console.log('========================================');
|
||||
console.log('📝 知识库上下文长度:', knowledgeContext.length, '字符');
|
||||
console.log('========================================');
|
||||
// ========== 打印结束 ==========
|
||||
}
|
||||
} catch (ragErr) {
|
||||
console.warn('RAG服务调用失败,将不使用知识库增强:', ragErr.message);
|
||||
}
|
||||
|
||||
// 2. 如果有知识库上下文,添加到prompt中
|
||||
let enhancedPrompt = prompt;
|
||||
if (knowledgeContext) {
|
||||
enhancedPrompt = prompt + '\n\n【专业知识库参考资料】\n' + knowledgeContext + '\n\n请结合以上专业心理学资料进行分析,使报告更加专业和有深度。';
|
||||
}
|
||||
|
||||
// 3. 调用AI API
|
||||
const { data } = await axios.post(this.API_URL, {
|
||||
model: this.MODEL,
|
||||
messages: [
|
||||
{ role: 'user', content: prompt }
|
||||
{ role: 'user', content: enhancedPrompt }
|
||||
],
|
||||
temperature: 0.3,
|
||||
max_tokens: 8000, // 增加token数量以支持3000字以上的报告
|
||||
|
|
@ -742,6 +788,11 @@ export default {
|
|||
|
||||
console.log('原始响应:', response)
|
||||
console.log('完整data:', data)
|
||||
|
||||
// 4. 如果有知识库来源,添加参考资料说明
|
||||
if (ragSources && ragSources.length > 0) {
|
||||
this.ragSourcesForReport = ragSources;
|
||||
}
|
||||
|
||||
// 清理响应内容
|
||||
response = response
|
||||
|
|
@ -854,6 +905,15 @@ export default {
|
|||
⚠️ 此结果仅供参考,不可作为临床诊断的唯一标准
|
||||
</p>
|
||||
</div>
|
||||
|
||||
${this.ragSourcesForReport && this.ragSourcesForReport.length > 0 ? `
|
||||
<div class="rag-sources" style="margin-top: 20px; padding: 15px; background: #f5f7fa; border-radius: 8px;">
|
||||
<h4 style="margin: 0 0 10px 0; color: #409EFF;"><i class="el-icon-document"></i> 参考知识库资料</h4>
|
||||
<ul style="margin: 0; padding-left: 20px; color: #666;">
|
||||
${this.ragSourcesForReport.map(source => `<li style="margin-bottom: 5px;"><strong>${source.filename}</strong></li>`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`
|
||||
return reportHtml
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user