SpringAi中使用MySQL作为聊天消息持久化产生的问题

255 阅读3分钟

项目环境:JDK17,springboot 版本:3.4.5,springai版本:1.0.0-RC1,mysql版本:8.0 ##问题描述:在使用基于mysql 的JdbcChatMemoryRepository作为持久化存储库的时候,与大模型对话会触发下面的异常: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT content, type FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ? ORDER BYtimestamp` DESC LIMIT ?] .....

Caused by: java.sql.SQLException: No value specified for parameter 2 ###ChatClient配置: @Configuration public class AIClientConfig { /** * 配置并创建一个ChatMemoryRepository bean实例 * * @param jdbcTemplate JDBC模板对象,用于与数据库进行交互 * @return ChatMemoryRepository实例,用于存储聊天记录 */ @Bean public ChatMemoryRepository getChatMemoryRepository(JdbcTemplate jdbcTemplate) { return JdbcChatMemoryRepository.builder() .jdbcTemplate(jdbcTemplate) //这里添加的是MySQL实现的聊天记忆仓库 .dialect(new MysqlChatMemoryRepositoryDialect()) .build(); }

/**
 * 配置并创建一个ChatMemory bean实例
 * 该实例用于管理聊天消息的记忆,确保对话的连贯性
 *
 * @return ChatMemory实例,用于消息记忆管理
 */
@Bean
public ChatMemory getChatMemory(ChatMemoryRepository jdbcChatMemoryRepository) {
    // 创建一个MessageWindowChatMemory实例,最多保存100条消息
    return MessageWindowChatMemory.builder()
            .chatMemoryRepository(jdbcChatMemoryRepository)
            .maxMessages(100).build();
}

/**
 * 配置并创建一个ChatClient实例
 *
 * @param model      用于聊天客户端的模型,决定了客户端的响应行为和风格
 * @param chatMemory 聊天记忆对象,使得客户端能够根据之前的对话内容进行有上下文的响应
 * @return ChatClient实例,用于与用户进行个性化和有记忆的对话
 */
@Bean
public ChatClient gptChatClient(OpenAiChatModel model, ChatMemory chatMemory) {
    // 创建ChatClient实例,使用指定的模型和系统默认设置
    return ChatClient
            .builder(model)
            .defaultSystem("你的名字叫小周,用可爱的语句回答问题")
            .defaultAdvisors(new SimpleLoggerAdvisor(), MessageChatMemoryAdvisor.builder(chatMemory).build())
            .build();
}

} ` ###问题产生的原因: springai官方提供的MySQL聊天消息仓库实现的getSelectMessagesSql()方法返回的SQL语句需要的参数有2个,一个是conversation_id,一个是获取消息的条数,即limit关键字后面的部分。 file 但在JdbcChatMemoryRepository 、JdbcTemplate里面调用的时候只给了一个参数 JdbcChatMemoryRepository: file JdbcTemplate: file

由于参数不匹配,就会抛出 BadSqlGrammarException 异常:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT content, type FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ? ORDER BY timestamp` DESC LIMIT ?] 。。。。

Caused by: java.sql.SQLException: No value specified for parameter 2 ` ###官方回应:目前springai官方仓库已经发现该问题,可能在后续的版本中修复: file

补充,如果自定义 ChatMemoryRepositoryDialect,然后在ChatClient指定数据库的方言,还是会抛出同样的异常,原因在于通过配置文件使用 JDBC URL 时,springai会从JDBC URL 中自动选择对应的数据库,然后选择对应的 ChatMemoryRepository,官方文档描述如下:

使用 JdbcChatMemoryRepositoryDialect.from(DataSource) 时,可以从 JDBC URL 自动检测正确的方言。您可以通过实现 JdbcChatMemoryRepositoryDialect 接口来扩展对其他数据库的支持。

###自定义ChatMemoryRepository过程:

` public class CustomChatMemoryRepositoryDialect implements JdbcChatMemoryRepositoryDialect { private static final int DEFAULT_MAX_MESSAGES = 50;

@Override
public String getSelectMessagesSql() {
    return "SELECT message_text, message_type FROM chat_memory WHERE conversation_id = ? ORDER BY timestamp DESC LIMIT " + DEFAULT_MAX_MESSAGES;
}

@Override
public String getInsertMessageSql() {
    return "INSERT INTO chat_memory (id, conversation_id, message_text, message_type, timestamp) VALUES (?, ?, ?, ?, ?)";
}

@Override
public String getDeleteMessagesSql() {
    return "DELETE FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ?";
}

@Override
public String getSelectConversationIdsSql() {
    return "SELECT DISTINCT conversation_id FROM SPRING_AI_CHAT_MEMORY";
}

}

/** * 配置并创建一个ChatMemoryRepository bean实例 * * @param jdbcTemplate JDBC模板对象,用于与数据库进行交互 * @return ChatMemoryRepository实例,用于存储聊天记录 */ @Bean public ChatMemoryRepository getChatMemoryRepository(JdbcTemplate jdbcTemplate) { return JdbcChatMemoryRepository.builder() .jdbcTemplate(jdbcTemplate) //此处使用自定义数据库 .dialect(new CustomChatMemoryRepositoryDialect()) .build(); } `

结语:以上就是使用springai中MySQL作为消息持久化仓库有可能产生的问题,如果大家在使用springai的过程中遇到了其他问题,欢迎在评论区补充!

本文由博客一文多发平台 OpenWrite 发布!