travel项目——ai流程

role为system就是只用说一次,全局都遵守
user "用户角色"的消息,可长可短,可多条,有效在这一轮
max_token最大token数
stream是流模式,一般我们都开着.模型调模型,设置为false
temperature值越小越严谨
top_p核采样概率阈值
| 参数 | 作用 | 功能 |
|---|---|---|
| n | 生成多少条回答 | ✓ 返回多少条记录 |
| top_p | 核采样概率阈值 | 控制输出严谨度 |
| max_tokens | 每条回答最大长度 | 限制单条长度 |
| temperature | 采样温度 | 控制发散程度 |
我们用的是open ai的模式
返回的应答数据,我们要的是content

我们要做的事,让模型去我们的私库(es)里和大模型去查,

chat接口
chatrequest是前段传回来的数据,是一个json类型的
先在controller处查私库数据
chatresponse是返回的数据,包含私库数据和大模型数据(先做了各假数据)
@RequestMapping("/chat")
public Object getAnswer(@RequestBody ChatRequest request) throws IOException {
SearchResponse<StrategyES> resp = client.search(
sh -> sh.index("strategy")
.from(0).size(request.getTopK())
.query(q -> q.multiMatch(
m -> m.query(request.getQuestion())
.fields("title", "subTitle", "summary")
.analyzer("ik_max_word")
)), StrategyES.class);
HitsMetadata<StrategyES> hits = resp.hits();
TotalHits total = hits.total();
List<Hit<StrategyES>> hits2 = hits.hits();
List<StrategyES> strategies = new ArrayList<>();
for (Hit<StrategyES> strategyES : hits2) {
strategies.add(strategyES.source());
}
//发送请求到deepseek处理
String answer = askAI(request.getQuestion(), strategies);
ChatResponse chatResponse = new ChatResponse(answer, strategies);
return chatResponse;
}
我们今天这个项目要的是请求数据messagess数组得有,model模型,thinking思考模型,temperature发散程度,top_p返回多少条数据
OpenAIMessage(messages)
OpenAIChatRequest(model,OpenAIMessage(messages),temperature,thinking,top_p)
response我只要choices里的message里的content
OpenAIChatResponse(choices,message)

yml里配了一堆配置(baseurl)
deepseek:
baseUrl: https://api.deepseek.com
model: deepseek-v4-pro
temperature: 1
thinking: enabled
top_p: 1
apiKey: sk-95597fa2fd264d96a03ae14aef775e0c
controller注入这些配置,
@Value("${deepseek.baseUrl}")
private String baseUrl;
@Value("${deepseek.model}")
private String model;
@Value("${deepseek.temperature}")
private Double temperature;
@Value("${deepseek.thinking}")
private String thinking;
@Value("${deepseek.top_p}")
private Double top_p;
@Value("${deepseek.apiKey}")
private String apiKey;
askAI方法里先带过去私库数据(ragMessage)
设定系统消息(角色定位)(sysMessage)
用户消息(userMessage)
private String askAI(String question, List<StrategyES> strategies) {
StringJoiner stringJoiner = new StringJoiner("\n\n");
//拿到es库里查回来的数据
for (StrategyES strategy : strategies) {
String jsonString = JSON.toJSONString(strategy);
stringJoiner.add(jsonString);
}
String strategiesStr = stringJoiner.toString();
}
body部分:
这三个数据构建成一个OpenAIMessage(messages)类型的message数组
拼接body数据,message和注入的那些数据,message类型的requestBody

//私库数据
OpenAIMessage ragMessage = new OpenAIMessage("system", strategiesStr);
//系统消息
OpenAIMessage sysMessage = new OpenAIMessage("system", "你是一名资深导游,请结合用户问题和私库数据,并根据互联网信息给出旅游建议。规划处路线图,必坑指南及规划条件。回答小于200字");
//用户消息(前端来的)
OpenAIMessage userMessage = new OpenAIMessage("user", question);
List<OpenAIMessage> messages = new ArrayList<>();
messages.add(ragMessage);
messages.add(sysMessage);
messages.add(userMessage);
//拼接body数据
OpenAIChatRequest requestBody = new OpenAIChatRequest();
requestBody.setMessages(messages);
requestBody.setModel(model);
requestBody.setTemperature(temperature);
Map<String, Object> map = new HashMap<>();
map.put("type", thinking);
requestBody.setThinking(map);
requestBody.setTop_p(top_p);
header部分:
拼header,设置文本类型,给一个数组类型的json数据,api key

//拼接header数据
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.APPLICATION_JSON);
headers.setAccept(mediaTypeList);
headers.setBearerAuth(apiKey);
header+body部分整合:
整合对象OpenAIChatRequest,请求的header body对象
//httpEntity等于header和body
HttpEntity<OpenAIChatRequest> httpEntity = new HttpEntity<>(requestBody, headers);
拼接请求地址
//拼接地址
String url = baseUrl + "/chat/completions";
发送请求:
发请求用restTemplate,发请求用restTemplate这里也可以设置超时
//发请求
OpenAIChatResponse response = restTemplate.postForObject(url, httpEntity, OpenAIChatResponse.class);
给restTemplate 这三个数据
url,数据和返回数据的类型OpenAIChatResponse(choices,message)
//判断大模型查回来的数据合不合规(有没有数据)
if (response == null || response.getChoices() == null ||
response.getChoices().isEmpty()){
return "AI没有返回合适的结果";
}
OpenAIChatResponse.Choice choice = response.getChoices().get(0);
if(choice==null||choice.getMessage()==null||choice.getMessage().getContent()==null){
return "AI没有返回合适的结果";
}
判断返回来的数据合规,返回数据
//返回给前端回答的content
return choice.getMessage().getContent();
前端 ChatController SearchService OpenAI API ES
│ │ │ │ │
│ POST /chat │ │ │ │
│ {question} │ │ │ │
├────────────────────▶│ │ │ │
│ │ ① search(question) │ │ │
│ ├──────────────────────▶│ │ │
│ │ │ search() │ │
│ │ ├──────────────────────────────────▶│
│ │ │ │ 返回相关文档 │
│ │ │◀──────────────────────────────────│
│ │ ragMessage │ │ │
│ │◀──────────────────────│ │ │
│ │ │ │ │
│ │ ② 组装 messages │ │
│ │ sys + rag + user │ │
│ │ │ │ │
│ │ ③ OpenAIChatRequest │ │
│ │ (model/messages/temp/top_p/thinking) │ │
│ │ │ │ │
│ │ ④ Headers + URL │ │
│ │ Authorization: Bearer xxx │ │
│ │ baseUrl/chat/completions │ │
│ │ │ │ │
│ │ ⑤ restTemplate.postForObject │ │
│ ├──────────────────────────────────────────▶│ │
│ │ │ │ 大模型推理 │
│ │ │ │ 生成 choices │
│ │◀──────────────────────────────────────────│ │
│ │ OpenAIChatResponse │ │
│ │ │ │ │
│ │ ⑥ choices[0].message.content │ │
│ │ 封装 ChatResponse │ │
│ │ (含 ES 数据 + 大模型回答) │ │
│ ChatResponse │ │ │ │
│◀────────────────────│ │ │ │
┌───────────────────────────────────────────────────────────────────────────┐
│ 前端发起 chat 请求 │
└───────────────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ChatController.chat(ChatRequest req) │
│ 接收前端 JSON,包含 question 等字段 │
└──────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ① 查私库(ES) │
│ searchService.search(req.getQuestion()) │
│ 得到 ragMessage(RAG 检索结果) │
└──────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ② 构造三条 message │
│ sysMessage (system: 角色定位,只说一次) │
│ ragMessage (user: ES 私库数据) │
│ userMessage (user: 用户原始问题) │
└──────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ③ 组装 OpenAIChatRequest │
│ model (yml 注入,如 deepseek-v3) │
│ messages (上面三条 message 的数组) │
│ temperature (yml 注入,越小越严谨) │
│ top_p (yml 注入,返回条数控制) │
│ thinking (yml 注入,思考模型开关) │
└──────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ④ 拼 Header │
│ Content-Type: application/json │
│ Authorization: Bearer ${api-key} │
└──────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ⑤ 拼请求地址 │
│ baseUrl + "/chat/completions" │
│ (baseUrl 来自 yml 注入) │
└──────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ⑥ RestTemplate 发请求 │
│ .postForObject(url, request, OpenAIChatResponse.class)│
│ 也可在此配置超时(RestTemplateBuilder) │
└──────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ⑦ 解析返回 │
│ response.getChoices().get(0).getMessage() │
│ .getContent() │
│ 只要 content 字段 │
└──────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ ⑧ 包装成 ChatResponse 返回前端 │
│ (含 ES 私库数据 + 大模型回答) │
└──────────────────────────────────────────────────┘

浙公网安备 33010602011771号