哪些网站是.net开发的,李沧网站建设谁家好,南宁市网站,中国舆情在线一、整体流程介绍
PostMapping(value /choice) 定义一个 POST 接口#xff0c;接收一个 JSON 格式的 AnalysisRequest 请求体#xff0c;返回一个 MapString, Object 类型的响应#xff08;包含分析结果或错误信息#xff09;。
核心处理流程#…一、整体流程介绍
PostMapping(value /choice) 定义一个 POST 接口接收一个 JSON 格式的 AnalysisRequest 请求体返回一个 MapString, Object 类型的响应包含分析结果或错误信息。
核心处理流程 日志记录 参数校验 构造 AI 请求消息System User Prompt 调用 AI 接口分析错题 解析 AI 的 JSON 响应 封装为结构化数据对象 AnalysisResponse 记录日志、返回响应 二、接口入口解析
接口入口analyzeChoiceQuestions()
核心流程
构造提示词Prompt
String systemPrompt buildSystemPrompt(request);
String userMessage buildUserMessage(request);调用 AI 接口分析错题
String aiResponse analyzeWithAISync(systemPrompt, userMessage, request);解析 AI 返回结果
AnalysisResponse analysisResponse parseAIResponse(analysisId, request, aiResponse);构造返回数据结构
result.put(data, analysisResponse);
result.put(analysis, analysisResponse.getOverallAnalysis());三、核心方法细讲
1.AI 调用analyzeWithAISync()
方法签名
private String analyzeWithAISync(String systemPrompt, String userMessage, AnalysisRequest request)throws IOException, InterruptedException入参 systemPrompt系统指令告诉 AI 它的角色、职责 userMessage用户输入具体要分析的内容 request分析请求体虽然这里没有直接使用但可能用于日志、回溯等
返回值AI 回复的正文 content 字符串
构造消息结构
ListMapString, String messages new ArrayList();创建一个用于存储对话的消息列表每条消息是一个 Map角色内容。 使用 OkHttp 客户端发起 HTTP 请求
OkHttpClient client new OkHttpClient.Builder().build();发送 POST 请求模型使用的是
params.put(model, deepseek-chat);携带两种类型的 Prompt
System Prompt指导 AI 扮演教学分析师
MapString, String systemMessage new HashMap();
systemMessage.put(role, system);
systemMessage.put(content, systemPrompt);
messages.add(systemMessage);User Prompt具体的错题信息、题干、选项、用户作答等
MapString, String userMsg new HashMap();
userMsg.put(role, user);
userMsg.put(content, userMessage);
messages.add(userMsg);最终效果
[{role: system, content: 你是一个老师...},{role: user, content: 以下是我的答题... }
]构造请求参数组装 API 的 payload
MapString, Object params new HashMap();
params.put(model, deepseek-chat);
params.put(stream, false);
params.put(messages, messages);
params.put(temperature, 0.7);model指定使用的模型比如 deepseek-chat
stream是否启用流式返回false 表示同步一次性拿到结果
messages传入的对话历史包括 system 和 user
temperature控制 AI 输出的“随机程度”数值越高越发散。 String jsonParams JsonUtils.convertObj2Json(params);使用工具类将 Map 转换为 JSON 字符串便于发送。 构建 HTTP 请求
Request.Builder builder new Request.Builder().url(AI_URL);
builder.addHeader(Authorization, Bearer apiPassword);
builder.addHeader(Content-Type, application/json);指定 URLAI 的接口地址
添加鉴权Bearer Token 设置请求头为 JSON 格式
okhttp3.RequestBody body okhttp3.RequestBody.create(okhttp3.MediaType.parse(application/json; charsetutf-8),jsonParams
);
Request httpRequest builder.post(body).build();设置请求体为 JSON
构造 POST 请求
创建 OkHttp 客户端并发起同步请求
OkHttpClient client new OkHttpClient.Builder().connectTimeout(timeout, TimeUnit.SECONDS).writeTimeout(timeout, TimeUnit.SECONDS).readTimeout(timeout, TimeUnit.SECONDS).build();配置超时时间连接、写入、读取 从 AI 响应中提取 content
MapString, Object responseMap JsonUtils.convertJson2Obj(responseBody, Map.class);将 JSON 字符串反序列化为 Map 结构
if (responseMap ! null responseMap.containsKey(choices)) {ListMapString, Object choices (ListMapString, Object) responseMap.get(choices);if (!choices.isEmpty()) {MapString, Object firstChoice choices.get(0);if (firstChoice.containsKey(message)) {MapString, Object message (MapString, Object) firstChoice.get(message);if (message.containsKey(content)) {return (String) message.get(content);}}}
}DeepSeek 通用响应结构如下
{choices: [{message: {role: assistant,content: 分析结果内容...}}]
}上述逻辑层层检查字段是否存在最终提取 message.content 字段作为 AI 的回答文本。
2.解析AI返回parseAIResponse()
方法定义
private AnalysisResponse parseAIResponse(Long analysisId, AnalysisRequest request, String aiResponse)analysisId本次分析的唯一 ID。
request用户发起请求时的详细信息包含题目、正确率、难度等。
aiResponseAI 模型返回的原始字符串预期为 JSON 格式。
返回值为构建好的 AnalysisResponse 对象。 流程
创建返回对象并设置分析ID
AnalysisResponse response new AnalysisResponse();
response.setAnalysisId(analysisId);这里创建一个空的响应对象 response并先设置分析 ID。 清理 AI 响应内容
String cleanedResponse cleanAIResponse(aiResponse);
logger.debug(清理后的AI响应: {}, cleanedResponse);AI 可能返回带有 Markdown 代码块标记如 json ... 或者格式不规范因此调用 cleanAIResponse 做预处理。
这一步是为了解决 AI 返回不是纯净 JSON 的问题提高解析成功率。 解析 JSON 内容
MapString, Object parsedResponse JsonUtils.convertJson2Obj(cleanedResponse, Map.class);将清理后的字符串解析成 MapString, Object 结构然后使用工具类 JsonUtils 将 JSON 转换为 Java Map 便于访问字段。 成功解析 JSON 的情况 如果 parsedResponse 不为 null则逐个提取字段
提取整体分析总结
response.setOverallAnalysis((String) parsedResponse.get(overallAnalysis));
response.setLearningPlan((String) parsedResponse.get(learningPlan));提取每道题的分析信息
if (parsedResponse.containsKey(questionAnalyses)) {ListMapString, Object questionAnalyses (ListMapString, Object) parsedResponse.get(questionAnalyses);ListQuestionAnalysis analyses new ArrayList();for (MapString, Object qa : questionAnalyses) {QuestionAnalysis analysis new QuestionAnalysis();analysis.setQuestion((String) qa.get(question));analysis.setErrorReason((String) qa.get(errorReason));analysis.setCorrectAnswerExplanation((String) qa.get(correctAnswerExplanation));analysis.setImprovementSuggestion((String) qa.get(improvementSuggestion));analyses.add(analysis);}response.setQuestionAnalyses(analyses);
}道错题的信息被封装在 questionAnalyses 数组中每条记录被解析为 QuestionAnalysis 对象添加到结果中。
提取薄弱知识点
if (parsedResponse.containsKey(weaknessPoints)) {ListString weaknessPoints (ListString) parsedResponse.get(weaknessPoints);response.setWeaknessPoints(weaknessPoints ! null ? weaknessPoints : new ArrayList());
}以这个解析为例进行详细分析逻辑过程 if (parsedResponse.containsKey(weaknessPoints)) { 作用判断 AI 返回的 JSON 数据中是否包含 weaknessPoints 这个字段。 parsedResponse 是一个 MapString, Object 类型的数据结构。 weaknessPoints 是 AI 分析输出中标记“知识薄弱点”的字段。 如果不包含就什么都不做如果包含就进入下一步。 ListString weaknessPoints (ListString) parsedResponse.get(weaknessPoints); 从 Map 中取出 weaknessPoints 对应的值并尝试将其强制转换为 ListString 类型。 假设 AI 返回的结构是类似下面这种 JSON
{weaknessPoints: [函数定义与调用,循环结构的控制,语法错误识别]
}那么这里 parsedResponse.get(weaknessPoints) 的结果应该是一个 List其中每个元素是一个 String。强制转换是必要的因为从 MapString, Object 拿出来的是 Object 类型。 response.setWeaknessPoints(weaknessPoints ! null ? weaknessPoints : new ArrayList()); 目的设置最终的结果对象 response 的 weaknessPoints 字段。
这个三目运算符是一个空值保护机制 如果 AI 的 JSON 中 weaknessPoints 字段存在但为 null就不会直接传 null 进去 而是使用一个新的空 ListString防止后续出现 NullPointerException。
换句话说无论 AI 有没有真正提供内容最终结果中的 weaknessPoints 字段一定不会是 null而是一个 List可能为空。 示例
假设输入为
{overallAnalysis: ...,weaknessPoints: [集合运算, 图形几何, 函数表达式]
}执行完这一段后
response.getWeaknessPoints()返回值为
[集合运算, 图形几何, 函数表达式]提取学习建议
if (parsedResponse.containsKey(studySuggestions)) {ListString studySuggestions (ListString) parsedResponse.get(studySuggestions);response.setStudySuggestions(studySuggestions ! null ? studySuggestions : new ArrayList());
}如果 JSON 解析失败则降级为文本处理
parseTextResponse(response, aiResponse, request);这是一个降级策略保证系统即使遇到错误数据也能返回“最起码的结果”。