AI下调用redis并调用deepseek

1.redis 可以作为内部资源的缓存数据库,把有效的数据放到redis时,当用户来调用,先优先从redis中进行匹配,来丰富请求内容。

2.然后把拼装好的内容,再发给LLM,这里使用deepseek。

redis的下载. 安装

准备好redis的环境。

第一步:读取文件,加载到redis中

java 复制代码
package com.example.LLm03;


import com.fasterxml.jackson.databind.ObjectMapper;
import redis.clients.jedis.Jedis;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class FaqService {

    private static final String REDIS_KEY_PREFIX = "faq:";
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private final Jedis jedis;

    public FaqService(Jedis jedis) {
        this.jedis = jedis;
    }

    /**
     *  把文件加载放到redis中
     *  前缀:faq: 后缀拼接行数,
     *  结果为 faq:0, faq:1 格式 
     * @throws IOException
     */
    public void loadFaqDataToRedis() throws IOException {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("train_zh.txt");
        if (inputStream == null) {
            throw new FileNotFoundException("File not found in resources: data.json");
        }

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {

            String line;
            int index = 0;
            while ((line = reader.readLine()) != null) {
                if (line.trim().isEmpty()) continue;
                FaqItem item = objectMapper.readValue(line, FaqItem.class);
                String key = REDIS_KEY_PREFIX + index++;
                jedis.set(key, line); // 存储原始字符串,方便后续读取
            }
        }



    }

    public  void loadFaqDataToRedis2() {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("train_zh.txt");
        // JSON文件路径(替换为你的实际文件路径)
        String jsonFilePath = "train_zh.txt";
        // Jackson核心对象,用于反序列化
        ObjectMapper objectMapper = new ObjectMapper();

        // try-with-resources自动关闭流,避免资源泄漏
        try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            String line;
            int lineNum = 1;
            // 循环读取每一行
            while ((line = br.readLine()) != null) {
                System.out.println("第" + lineNum + "行读取内容:" + line);
                // 将每行内容拼接到StringBuilder中
                lineNum++;

            // 1. 获取完整的JSON字符串


            // 2. 将JSON字符串反序列化为Java对象
            FaqItem rdmConfig = objectMapper.readValue(line, FaqItem.class);

            String key = REDIS_KEY_PREFIX + lineNum++;
            jedis.set(key, line); // 存储原始字符串,方便后续读取

            // 3. 打印转换后的对象信息
            System.out.println("\nJSON转换为Java对象结果:");
            System.out.println(rdmConfig);
            }

        } catch (IOException e) {
            System.err.println("读取JSON文件或反序列化失败:" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 用户查询时,先从redis进行精确匹配,
     * @param keyword 用户输入关键字
     * @param topNum 返回行数
     * @return
     * @throws IOException
     */
    public List<FaqItem> searchInstructionByKeyword(String keyword,int topNum) throws IOException {
        Set<String> keys = jedis.keys(REDIS_KEY_PREFIX + "*");
        List<FaqItem> result = new ArrayList<>();

        for (String key : keys) {
            String json = jedis.get(key);
            FaqItem item = objectMapper.readValue(json, FaqItem.class);
            if (item.getInstruction().contains(keyword)) {
                result.add(item);
            }
            if(result.size() >= topNum) {
                break;
            }
        }

        return result;
    }


}

加载的对象结构体:

java 复制代码
package com.example.LLm03;

public class FaqItem {
    private String instruction;
    private String input;
    private String output;

    // Getters and Setters
    public String getInstruction() {
        return instruction;
    }

    public void setInstruction(String instruction) {
        this.instruction = instruction;
    }

    public String getInput() {
        return input;
    }

    public void setInput(String input) {
        this.input = input;
    }

    public String getOutput() {
        return output;
    }

    public void setOutput(String output) {
        this.output = output;
    }

    @Override
    public String toString() {
        return "FaqItem{" +
                "instruction='" + instruction + '\'' +
                ", input='" + input + '\'' +
                ", output='" + output + '\'' +
                '}';
    }
}
java 复制代码
package com.example.LLm03;

import com.example.llm01.LLMUtils;
import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 加载数据并存在到Redis中
 * @throws Exception
 */

public class loadRedisFileData{


    /**
     * 加载数据并存在到Redis中
     * @throws Exception
     */
    @Test
    public void loadRedisFileData() throws Exception{
        Jedis jedis = new Jedis("localhost", 6379);
        jedis.auth("000000");

        FaqService faqService = new FaqService(jedis);
        faqService.loadFaqDataToRedis();
//        faqService.loadFaqDataToRedis2();
    }

    /**
     * 1.从redis中取到关键字
     * 2.拼接成有效的上下文,请求LLM
     * @throws Exception
     */
    @Test
    public void rag1() throws Exception{
        String prompt = "甲状腺囊肿如何治疗";
        // 检索相关的内容
        Jedis jedis = new Jedis("localhost", 6379);
        jedis.auth("000000");
        FaqService faqService = new FaqService(jedis);
        List<FaqItem> list = faqService.searchInstructionByKeyword(prompt, 1);
        // 把这个集合拼接为一个字符串
        String result = list.stream()
                .map(item -> "Q: " + item.getInstruction() + "\nA: " + item.getOutput())
                .collect(Collectors.joining("\n"));
        System.out.println(result);
        String role="你是一个问答机器人。" +
                "你的任务是根据下述给定的已知信息回答用户问题。" +
                "根据已知信息的内容推理给出用户问题的解决方案。" +
                "确保你的回复完全依据下述已知信息。不要编造答案。" +
                "如果下述已知信息不足以回答用户的问题,请直接回复我无法回答您的问题。";
        // 构建 Prompt
        prompt = String.format("""
                已知信息:
                %s
                
                用户问题:
                %s
                
                请用中文回答用户问题。
                """, result, prompt);
        // 然后把新的Prompt提交给大模型。看看对应的输出结果是怎么样的?
       // String completion = LLMUtils.completion2("医生","感冒", "deepseek-chat");
                //LLMUtils.completion2(role,prompt, "deepseek-chat");
        String completion =  LLMUtils.chatCompletion(role,prompt);
        System.out.println(completion);
    }


}

Redis 存储数据结果

调用 LLM 代码:

java 复制代码
    public static String chatCompletion(String systemPrompt, String userPrompt) throws Exception {
        // 会话记忆
        OkHttpClient client = new OkHttpClient().newBuilder(). build();
        ObjectMapper mapper = new ObjectMapper();

        // 使用ObjectNode构建请求体
        ObjectNode requestBody = mapper.createObjectNode();
        requestBody.put("model", "deepseek-chat");

        ArrayNode messages = mapper.createArrayNode();
        messages.addObject().put("role", "system").put("content", systemPrompt);
        messages.addObject().put("role", "user").put("content", userPrompt);
        requestBody.set("messages", messages);

        String jsonBody = mapper.writeValueAsString(requestBody);

        RequestBody body = RequestBody.create( MediaType.parse("application/json"),jsonBody);
        Request request = new Request.Builder()
                .url("https://api.deepseek.com/chat/completions")
                .post(body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", "Bearer " +  API_KEY) // 从环境变量读取
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response + ", body: " + response.body().string());
            }
            String json= response.body().string(); // 返回原始JSON响应
            // 解析返回的内容
            JsonNode root = mapper.readTree(json);
            JsonNode choices = root.get("choices");
            if (choices != null && choices.isArray() && choices.size() > 0) {
                return choices.get(0).get("message").get("content").asText();
            }
            return "No response content found.";
        }
    }

文件位置:

html 复制代码
{"instruction": "1前几天体检时医生说我有甲状腺囊肿,我也没有什么感觉啊,为什么会长这个东西啊", "input": "","output": "1甲状腺囊肿是甲状腺疾病的一种,它是指甲状腺内出现的一个或多个液体囊肿。甲状腺囊肿的形成原因比较复杂,可能是由于甲状腺内的一些细胞发生异常增生,导致甲状腺组织在某些部位形成了囊肿,也可能是由于甲状腺内的一些细胞因为某种原因死亡,导致甲状腺组织在某些部位形成了囊肿。\n\n甲状腺囊肿一般不会有特别明显的症状,有的患者可能会出现颈部肿块或者轻微的不适感,但大部分患者是没有任何症状的。如果甲状腺囊肿较大或者压迫周围的组织或器官,可能会引起一些症状,如吞咽困难、呼吸困难、声音嘶哑等。\n\n如果您被诊断出有甲状腺囊肿,建议您定期复查,如果囊肿增大或引起症状,可能需要进行手术治疗。同时,保持良好的生活习惯,均衡饮食,避免过度疲劳和过度紧张,也有助于预防和治疗甲状腺囊肿。"}
{"instruction": "2前几天体检时医生说我有甲状腺囊肿,我也没有什么感觉啊,为什么会长这个东西啊", "input": "","output": "2甲状腺囊肿是甲状腺疾病的一种,它是指甲状腺内出现的一个或多个液体囊肿。甲状腺囊肿的形成原因比较复杂,可能是由于甲状腺内的一些细胞发生异常增生,导致甲状腺组织在某些部位形成了囊肿,也可能是由于甲状腺内的一些细胞因为某种原因死亡,导致甲状腺组织在某些部位形成了囊肿。\n\n甲状腺囊肿一般不会有特别明显的症状,有的患者可能会出现颈部肿块或者轻微的不适感,但大部分患者是没有任何症状的。如果甲状腺囊肿较大或者压迫周围的组织或器官,可能会引起一些症状,如吞咽困难、呼吸困难、声音嘶哑等。\n\n如果您被诊断出有甲状腺囊肿,建议您定期复查,如果囊肿增大或引起症状,可能需要进行手术治疗。同时,保持良好的生活习惯,均衡饮食,避免过度疲劳和过度紧张,也有助于预防和治疗甲状腺囊肿。"}
相关推荐
遇见火星2 小时前
Redis主从复制深度解析:数据高可用与负载均衡的核心方案
数据库·redis·缓存·负载均衡
酸菜牛肉汤面2 小时前
22、数据库的乐观锁和悲观锁是什么?怎么实现的?
数据库
陌路202 小时前
MYSQL事务篇--事务隔离机制
数据库·mysql
清风6666663 小时前
基于单片机的PID调节脉动真空灭菌器上位机远程监控设计
数据库·单片机·毕业设计·nosql·课程设计·期末大作业
酩酊仙人3 小时前
ABP将ExtraProperties作为查询条件
数据库·postgresql·asp.net
在风中的意志3 小时前
[数据库SQL] [leetcode] 614. 二级关注者
数据库·sql
·云扬·3 小时前
MySQL Group Replication(MGR)核心特性全解析:从事务流程到一致性配置
数据库·mysql
陌路203 小时前
MYSQL事务篇--事务隔离机制的实现
数据库·mysql
oMcLin3 小时前
CentOS 7.9 高负载导致 MySQL 数据库性能下降:内存泄漏与配置优化
数据库·mysql·centos