travel项目——ai流程

image

role为system就是只用说一次,全局都遵守
user "用户角色"的消息,可长可短,可多条,有效在这一轮
max_token最大token数
stream是流模式,一般我们都开着.模型调模型,设置为false
temperature值越小越严谨
top_p核采样概率阈值

参数 作用 功能
n 生成多少条回答 ✓ 返回多少条记录
top_p 核采样概率阈值 控制输出严谨度
max_tokens 每条回答最大长度 限制单条长度
temperature 采样温度 控制发散程度

我们用的是open ai的模式
返回的应答数据,我们要的是content
image

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

image
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)
image

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
image

 		//私库数据
        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
image


		//拼接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 私库数据 + 大模型回答) │
└──────────────────────────────────────────────────┘

posted @ 2026-08-24 22:14  Jennifer_F  阅读(7)  评论(0)    收藏  举报