ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Spring AI Alibaba Chat Example 配置 TaoToken:ChatModel 与 ChatClient 接入骨架

Spring AI Alibaba Chat Example 配置 TaoToken:ChatModel 与 ChatClient 接入骨架 1. 为什么要在 Spring AI Alibaba Chat Example 里换掉默认通道Spring AI Alibaba Chat Example 是官方给出的多模型对话示例工程核心价值在于用 ChatModel / ChatClient 这层统一抽象把底层模型供应商的差异挡在业务代码之外。你写一次 Controller换模型只改 application.yml这是它最舒服的地方。但示例默认走的是各家自己的 API Key 和 endpoint一旦你要在多个模型之间来回切、或者团队里几个人共用一套额度Key 管理就会变得很碎。我这次做的事很具体保留 Chat Example 的骨架不动只把 ChatModel 的 base-url 和 api-key 指向 TaoToken 的统一通道让 ChatClient 的调用方式完全不变。这样做的直接好处是你原来写的chatClient.prompt().user(...).call().content()一行都不用改换模型只是换配置里的 model 名字。适合谁看已经在跑 Spring Boot 3.x Spring AI Alibaba 的开发者手里有 Chat Example 工程想把它接到一个统一入口上或者你正准备搭一个多模型对话服务想先跑通最小骨架再谈扩展。下面从依赖、配置、Java 配置类到本地验证一步步给全。2. TaoToken 前置Key、地址与依赖准备TaoToken 在这里扮演的角色是统一 API 通道兼容 OpenAI 风格的/v1/chat/completions接口。Spring AI 的 OpenAI starter 本身就是按这个协议实现的所以接入方式非常自然把spring.ai.openai.base-url指向 TaoToken 的 API 地址api-key填你在控制台生成的 Key模型名填通道支持的模型即可。你需要先拿到两样东西。第一是 API Key去控制台创建https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。第二是确认 API 基地址统一用 https://taotoken.net/api 注意这个地址后面不加 UTM 参数配置里保持干净。依赖方面Chat Example 里如果用的是 dashscope starter我们这次换成 OpenAI starter因为 TaoToken 走 OpenAI 兼容协议。父 POM 里统一版本子模块只声明依赖properties spring-boot.version3.3.0/spring-boot.version spring-ai.version1.0.0-M2/spring-ai.version /properties dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement子模块pom.xml里加dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId /dependency这里有个容易踩的点Spring AI 的 OpenAI starter 默认 base-url 是官方地址你不改它就会往默认地址发请求。所以下一步的 yml 配置是成败关键。3. 可复制配置application.yml 与 ChatClient Bean先给完整的application.yml这是整个接入的核心。注意base-url结尾不要多加/v1Spring AI 会自己拼路径多写一层会变成/v1/v1/chat/completions直接 404。server: port: 10000 spring: ai: openai: api-key: ${TAOTOKEN_API_KEY} base-url: https://taotoken.net/api chat: options: model: gpt-4o-mini temperature: 0.7 max-tokens: 2000api-key用环境变量注入别硬编码进仓库。本地调试时export TAOTOKEN_API_KEY你的Key然后是 Java 配置类。Chat Example 里通常直接注入 ChatModel但我们推荐再包一层 ChatClient把系统提示和默认参数固化下来Controller 里就干净了。Configuration public class ChatClientConfig { Bean public ChatClient chatClient(ChatModel chatModel) { return ChatClient.builder(chatModel) .defaultSystem(你是一个专业的技术助手用中文回答代码示例要能直接运行。) .build(); } }对应的 Controller 保持示例风格同步和流式各一个端点RestController RequestMapping(/chat) public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient chatClient) { this.chatClient chatClient; } GetMapping(/simple) public String simple(RequestParam String message) { return chatClient.prompt() .user(message) .call() .content(); } GetMapping(value /stream, produces MediaType.TEXT_EVENT_STREAM_VALUE) public FluxString stream(RequestParam String message) { return chatClient.prompt() .user(message) .stream() .content(); } }流式端点必须带produces MediaType.TEXT_EVENT_STREAM_VALUE否则浏览器拿到的是普通文本看不到逐字输出效果。这一点在 Chat Example 的原始代码里也是这么处理的。4. 验证请求本地启动与对话调用启动前确认环境变量已生效然后跑起来mvn clean package -DskipTests java -jar target/chat-example-*.jar看到Started ChatExampleApplication就说明 ChatModel Bean 装配成功。如果启动阶段就报No qualifying bean of type ChatModel八成是 starter 没引对或者 api-key 为空导致自动配置没触发。先测同步接口curl http://localhost:10000/chat/simple?message用一句话解释什么是依赖注入正常返回类似依赖注入是一种设计模式对象的依赖由外部容器创建并注入而不是对象自己 new 出来。再测流式用-N关闭 curl 缓冲才能看到逐块输出curl -N http://localhost:10000/chat/stream?message写一个Java冒泡排序你会看到data:开头的分块依次刷出来最后以data: [DONE]结束。到这一步ChatModel 到 ChatClient 的整条链路就通了。想直接在网页里对比不同模型的回答可以用模型对话入口https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。5. 本篇常见错排查报 401 UnauthorizedKey 没读到或者填错。先echo $TAOTOKEN_API_KEY确认环境变量非空再检查 yml 里是不是写成了${TAOTOKEN_API_KEY:}这种带默认空值的写法那样会静默用空字符串。报 404 Not Foundbase-url 多写了/v1。正确写法是https://taotoken.net/apiSpring AI 内部会拼/v1/chat/completions。如果你手动加了/v1路径就重复了。流式接口返回一整块而不是逐字检查produces是否漏了以及有没有经过 Nginx 之类的反向代理把响应缓冲了。本地直连一般不会有这个问题。中文乱码在流式方法里加response.setCharacterEncoding(UTF-8)或者确认请求头Accept带了text/event-stream。模型名报错spring.ai.openai.chat.options.model填的名字必须是通道支持的。先用模型对话页面确认某个模型可用再写进配置别凭记忆填。启动慢或超时检查网络到taotoken.net是否通畅可以在启动日志里看 RestClient 的请求耗时。如果是公司网络限制换一个网络环境再试。6. 下一步从骨架到长期编码跑通这个骨架之后你会发现 Chat Example 的价值不只是能对话而是它把 ChatModel / ChatClient 的边界划得很清楚。业务代码只依赖 ChatClient模型切换、参数调整、系统提示都在配置层解决。如果你打算把它用在日常编码辅助或者 Agent 场景上长期高频调用更适合走 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。接入细节和参数说明可以对照文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。Key 的创建和轮换在 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。如果你用的是 Claude Code 这类工具链Anthropic 兼容入口在这里https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite 。最后留一个实操建议把temperature和max-tokens做成可覆盖的请求参数而不是写死在 yml 里。Chat Example 的ChatClient.prompt().options(...)支持运行时覆盖这样同一个 Bean 既能处理需要确定性的代码生成也能处理需要发散的文案场景不用为每种用途各建一个 Client。
返回列表