springboot整合chatgpt,并且让其可以记录上下文

整合很简单,不过需要几个小条件

1.必须要有openai官方的key

2.国内需要有代理服务器或者国外的服务器把项目部署出去也没问题

我没有使用spring的springAI,听说很方便,日后有机会去体验体验,我今天用了两种方式整合了gpt

1.Chatgpt-Java : 📖 项目简介 | Chatgpt-Java (unfbx.com)

这个巨巨巨方便,整合gpt,可以跟着官网的快速入门走,一下就解决了

先导入maven依赖

复制代码
        <dependency>
            <groupId>com.unfbx</groupId>
            <artifactId>chatgpt-java</artifactId>
            <version>1.1.5</version>
        </dependency>

然后我直接写接口

复制代码
@RestController
@RequestMapping("/ai")
@Api(tags = "ai")
public class AiController {

    @ApiOperation("ai对话")
    @PostMapping("/test")
    public ResultResponse test(String msg){

        OpenAiClient openAiClient = OpenAiClient.builder()
                .apiKey(Arrays.asList("xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"))
                .build();

        Message message = Message.builder().role(Message.Role.USER).content(msg).build();
        ChatCompletion chatCompletion = ChatCompletion.builder().messages(Arrays.asList(message)).build();
        ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
//        chatCompletionResponse.getChoices().forEach(e -> {
//            System.out.println(e.getMessage());
//        });
        return ResultResponse.success(chatCompletionResponse.getChoices());
    }
}

xxxxxxxxxxxxxxx自己替换成自己的key哈。

结束,到这里就可以直接使用gpt了,自己去postman测试一下就行。

2.直接给官网api发请求

首先3个dto类

复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatBotRequest {

    private String model;
    private List<Message> messages;
    private int n;
    private double temperature;
    private int max_tokens;
}
------------------------------------------
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatBotResponse {

    private List<Choice> choices;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Choice {
        private int index;
        private Message message;
    }
}
------------------------------------------
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Message {

    private String role;
    private String content;

}

其次配置一下config

复制代码
@Configuration
public class OpenAIChatGtpConfig {

    private final String openaiApiKey = "xxxxxxxxxxxxxxxxxxxxxxx";

    @Bean
    public RestTemplate restTemplate() {

        RestTemplate restTemplate = new RestTemplate();

        restTemplate.getInterceptors().add((request, body, execution) -> {
            request.getHeaders().add("Authorization", "Bearer " + openaiApiKey);
            return execution.execute(request, body);
        });
        
        return restTemplate;
    }
}

最后依然是直接写接口

复制代码
@Api(tags = "chat")
@RestController
@RequestMapping("/chats")
public class ChatBotController {

    @Autowired
    private RestTemplate restTemplate;

    @ApiOperation("chat")
    @PostMapping("/chat")
    public ChatBotResponse chat(@RequestParam("prompt") String prompt) {

        ChatBotRequest request = new ChatBotRequest("gpt-3.5-turbo",
                Arrays.asList(new Message("user", prompt)),
                1,
                0,
                100);

        ChatBotResponse chatBotResponse = restTemplate.postForObject("https://api.openai.com/v1/chat/completions", request, ChatBotResponse.class);
        return chatBotResponse;
    }
}

至此第二种整合方式也结束了,其实就这种阻塞式整合真的很简单,不过体验感其实比不上流式整合,回头什么时候去试试流式整合。

Cannot resolve method 'of' in 'List' 或 找不到符号of

顺带今天碰见了一点小报错,才知道Arrays.asList其实等同于List.of。不过List.of是jdk9里面新出的,jdk8没有,因此只能用自己的老东西Arrays.asList。( 参考的是【BUG】Cannot resolve method 'of' in 'List' 或 找不到符号of(非jdk8版本问题)_cannot resolve method 'of' in 'list-CSDN博客

两种整合方式都可以顺利连通,不过此时我发现gpt竟然无法联系上下文。去网上找了很久发现原来暂时没有可以直接自己联系上下文的大模型,因此得自己来做操作。感到疑惑可以看一下这个博客:手把手教会你如何通过ChatGPT API实现上下文对话 - 个人文章 - SegmentFault 思否

原理很简单,每次把之前得mes全部拼接起来,直接开始实现吧:

maven依赖:

复制代码
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>

@RestController
@RequestMapping("/ai")
@Api(tags = "ai")
public class AiController {
    public static final String token = "sk-proj-xElzheeQc3nqZrWm3J6lT3BlbkFJRCQpGjcqfdkj5jsdC1KM";

    private static final String CHAT_HISTORY_KEY = "chat_history";

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private AiService aiService;

    @ApiOperation("ai对话")
    @PostMapping("/tall")
    public ResultResponse tall(@RequestParam("msg") String msg,@RequestParam("userId") String userId) {
        String keyword = CHAT_HISTORY_KEY + "_tall" + userId;
        ListOperations<String, String> listOps = redisTemplate.opsForList();
        Message userMessage = Message.builder().role(Message.Role.USER).content(msg).build();
        List<String> history = listOps.range(keyword , 0, -1);
        List<Message> messages = new ArrayList<>();
        for (String historicalMessage : history) {
            messages.add(Message.builder().role(Message.Role.USER).content(historicalMessage).build());
        }
        messages.add(userMessage);
        OpenAiClient openAiClient = OpenAiClient.builder()
                .apiKey(Arrays.asList(token))
                .build();
        ChatCompletion chatCompletion = ChatCompletion
                .builder()
                .messages(messages)
                .model("gpt-3.5-turbo")
                .build();
        ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
        String gptResponse = chatCompletionResponse.getChoices().get(0).getMessage().getContent();
        if(redisTemplate.opsForList().size(keyword ) >= 6){
            listOps.leftPop(keyword );
        }
        listOps.rightPush(keyword, "user:"+msg); //指定role角色更有利于ai理解上下文信息
        listOps.rightPush(keyword, "assistant:"+gptResponse);
        return ResultResponse.success(gptResponse);
    }
}

很简单,就用了redis得list结构当作一个消息队列用,记录最近得6条上下文,每次拼接过去就好。

防止缓存一直占空间,可以自己弄个定时器每天或者每个月清理一次消息队列。

先再自己得application上面加个开关注解:

复制代码
@EnableScheduling
@SpringBootApplication()
public class ExamsystemApplication extends SpringBootServletInitializer 

然后直接写定时器:

复制代码
@Component
public class TimerTask {


    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Scheduled(cron = "0 0 0 1 * ?") // 每个月1号的凌晨执行
    public void TaskMethod() {
        try {
            Set<String> keys = redisTemplate.keys("chat_history*");
            redisTemplate.delete(keys);
        } catch (Exception e) {
            System.err.println("Failed to reset frequency: " + e.getMessage());
        }
    }


}

到现在ai也拥有上下文了,爽歪歪。

相关推荐
风象南9 分钟前
Claude Code这个隐藏技能,让我告别PPT焦虑
人工智能·后端
Mintopia1 小时前
OpenClaw 对软件行业产生的影响
人工智能
陈广亮1 小时前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬2 小时前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia2 小时前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区2 小时前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两5 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
前端付豪5 小时前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain
strayCat232555 小时前
Clawdbot 源码解读 7: 扩展机制
人工智能·开源