第6章:Spring AI 2.0 ChatClient 门面
上章思考题答案用户原话里的{orderId}若放进SystemPromptTemplate再渲染StringTemplate 会把它当成变量。缺这个键时ValidationMode.THROW抛IllegalStateException正常咨询被拒绝。用户原话应走UserMessage或ChatClient.user不要进系统模板。版本号写死在模板正文里更换或回滚都要重打镜像。作为渲染变量传入时回滚只改配置。本章之后的示例都把制度版本当变量传入。1. 项目背景1.1 业务场景邻里仓退款接口要回答「订单 LC202610060018 未发货能不能退」店规固定用户问题每次不同。店规已经能渲染成带版本号的字符串调用处却仍是new Prompt再chatModel.call。每个接口都重复这四行取模型、装系统消息、装用户消息、从ChatResponse里挖文本。退款、超时、库存三个接口各写一份系统提示词的默认句渐渐分叉。本章把这四行收成ChatClient。它和RestClient、WebClient一样是一层流式门面先建造客户端再对单次请求填system和user最后call().content()取正文。邻里仓这一周里App 退款、门店退款和超时说明三个接口都要回答同一份店规。差别只在订单号和用户原话。门面让店规有一个建造入口让订单号留在这一次请求里。控制器交给 App 的是一段中文测试和计费要看账单时再从同一次调用的ChatResponse上取Usage。这样退款接口不必再认识Generation也不会为了补一张账单把模型打第二遍。1.2 痛点继续手写Prompt时有人忘了把渲染好的店规放进SystemMessage模型只看见用户原话开始发明优惠券。另一个人每次ChatClient.create一个新实例默认店规无法集中更换。测试要断言文本还得记得getResult().getOutput().getText()写错一层就变成空指针被误判成模型没回答。没有门面时的路径每个接口自己拼Prompt→ 店规复制三份 → 取正文的代码路径不一致 → 测试断言各写各的。门店接口若仍停在上一季的字符串上App 已经换成policy-2026.10抽检会看到两种超时口径。用户拿着同一张订单在两个渠道得到相反结论客服无法解释。把门面收成共享客户端之后制度版本只从模板渲染变量进来渠道差异留在单次system()的参数里。测试断言关键短语和版本号不再逐个接口核对复制来的长文。渲染错误:Mermaid 渲染失败: Parse error on line 5: ...Model.call] call -- usage[两边都有 Usag... ----------------------^ Expecting SEMI, NEWLINE, SPACE, EOF, subgraph, end, acc_title, acc_descr, acc_descr_multiline_value, AMP, COLON, STYLE, LINKSTYLE, CLASSDEF, CLASS, CLICK, DOWN, DEFAULT, NUM, COMMA, NODE_STRING, BRKT, MINUS, MULT, UNICODE_TEXT, direction_tb, direction_bt, direction_rl, direction_lr, direction_td, got CALLBACKNAME2. 项目设计小胖把第 5 章的代码往下翻「不就是少写两个 new 吗窗口已经能喊号了再包一层塑料袋有啥用」小白问「塑料袋如果把店规和用户话装混了呢content()只给我字符串finishReason还在不在我怎么知道这句是被截断的」小胖又说「那我两个都要。门面拿来给控制器模型留给测试。」小白追问「同一道退款题走两条路token 会不会差一截差在系统提示词没带上还是差在门面多包了一层观测测试该断言两条路 token 相等还是只断言都大于 0」大师先对齐形态「ChatClient像RestClient。builder(chatModel).defaultSystem(...).build()是建造相当于给柜台贴上默认话术。prompt().system(...).user(...).call()是这一次的单据。content()只取助手正文适合控制器返回给 App。要账单和结束原因时改用call().chatResponse()里面仍是第 3 章的ChatResponse。门面不替换模型底层还是你注入的DeepSeekChatModel。」技术映射柜台默认话术是defaultSystem这一次的单据是prompt()递给用户的杯子是content()小票仍是chatResponse()上的Usage。小白问默认值和本次覆盖「建造时写了 App 渠道的短句这一次门店请求想改成完整句是再 new 一个客户端还是单次system()能盖过默认」小胖说「再 new 一个最清楚各管各的。」小白反对「两个客户端意味着两份默认顾问、两份观测。我只想换一句店规。」小白又问「DefaultChatClient把顾问和选项收进这次请求本章要不要读完它的源码」大师把范围切开「单次system(String)覆盖这一次的系统文本不需要第二个客户端。顾问列表和选项如何收进Prompt在DefaultChatClient里源码留到第 33 章。今天只建立直觉建造期放稳定的东西请求期放这一单的用户问题和偶尔的覆盖。退款接口的稳定店规用defaultSystem订单号和用户原话用user。」技术映射稳定店规放在ChatClient.Builder.defaultSystem单次覆盖用prompt().system。收集顾问的细节不在本章展开。小白又问空正文「模型若回了一个空字符串content()交给控制器App 会显示一片空白。这和调用失败一样吗我能不能从这一个字符串看出是截断、是拒绝还是真的没有生成」小胖说「空白就当失败让用户再问一次。」小白说「再问一次就是第二次计费。用户只是遇到了截断店规其实已经生成了一半。空白、截断和异常要分开记。门面如果只露出字符串这三件事会挤在同一个返回值里。」大师补上返回值的边界「content()适合已经确认要展示正文的接口。退款这种要判断是否说完的接口用chatResponse()同时看文本、finishReason和Usage。空文本不要自动重试。先看结束原因是不是LENGTH是的话调整maxTokens再决定要不要重放。异常和空文本不是同一条路径异常不会变成空字符串悄悄返回。」小胖看着两条调用「既然底层是同一个模型Usage 应该一模一样。测试写成相等就行。」小白说「门面可能多放一条默认系统消息。你没把同一份店规同时放进两条路径token 就不会相等。相等断言会把实验方法的差别误判成故障。」小白又问打印「两组 token 打在测试输出里构建日志会不会把用户的退款原因也打出来邻里仓的问题里常有手机号和地址。」小胖说「测都测了全打出来最好查。」小白说「测试用的是固定句不是真实客诉。全打出来会把后来有人换上的真实句子也带进构建日志。」大师给出对照方法「两条路径使用同一段已渲染的系统文本和同一句用户问题温度都从模型默认值来不要一边maxTokens(64)另一边不设。用户问题用固定句『这单未发货能不能退』不要用真实客诉。然后只断言两边promptTokens和completionTokens都大于 0正文都非空并且都包含关键短语『未发货可退』。不要断言 token 数值逐字相等。日志只打两组 token 数字和短语是否命中不打完整用户原文。若提示词 token 相差超过一倍先查是不是有一条路径漏了系统消息。」技术映射对照实验锁的是同一份输入和关键短语不是锁死某一次的 token 数字。完整原文不进构建日志。3. 项目实战3.1 环境准备沿用第 2 章工程。spring-ai-starter-model-deepseek已经带上spring-ai-client-chat。密钥仍是DEEPSEEK_API_KEY模型deepseek-v4-flash。店规沿用第 5 章的渲染结果本章不再复制一份 Java 字符串。把「回答中必须出现未发货可退」写进系统模板方便两条路径用同一短语断言。运行前确认三件事。第一容器里只有一个ChatModel否则注入点要改成DeepSeekChatModel避免门面和直接调用打到不同的模型。第二spring.ai.deepseek.chat.model是deepseek-v4-flash不要在对照实验里把一边改成已经废弃的deepseek-reasoner。第三测试类仍用环境变量开关没有密钥就整类跳过构建不因缺密钥失败。PowerShell 里是$env:DEEPSEEK_API_KEY你的密钥。密钥不进源码不进日志。对照实验和控制器演示共用RefundChatService。服务是单例因此建造期的defaultSystem里不要写死某一张订单。下面步骤 1 为了先跑通用了固定订单号步骤 2 立刻改成按入参渲染。阅读时把步骤 2 当成退款接口的最终形态步骤 1 只说明content()怎么取正文。3.2 分步实现步骤 1建造带默认店规的 ChatClient步骤目标退款接口不再每次new Prompt。packagecom.linlicang.aftersale;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.model.ChatModel;importorg.springframework.stereotype.Service;ServicepublicclassRefundChatService{privatefinalChatClientchatClient;privatefinalChatModelchatModel;publicRefundChatService(ChatModelchatModel){this.chatModelchatModel;StringsystemAfterSalePrompts.renderSystem(LC202610060018,App,简短,policy-2026.10);this.chatClientChatClient.builder(chatModel).defaultSystem(system\n回答中必须出现未发货可退).build();}publicStringanswer(StringuserText){returnthis.chatClient.prompt().user(userText).call().content();}}订单号若每次不同不要写进建造期的defaultSystem。建造期只放渠道和语气订单号放进单次system(rendered)。上面示例为了先跑通用了固定订单号。下一步改成单次覆盖。运行结果文字描述answer(这单未发货能不能退)返回非空中文包含「未发货可退」。没有ChatResponse变量。可能的坑content()在模型返回空文本时可能是 null。控制器要先判空再写给 App。另一个坑是把含订单号的店规放进单例ChatClient的默认系统消息下一单用户会看到上一单的订单号。这一步在业务上的含义是退款接口的调用代码不再关心Prompt和Generation。店员培训时只要记住两层。建造客户端时写入与订单无关的语气和渠道。用户按下发送时只传入这一句问题。若把LC202610060018写进单例后一个用户问自己的订单回答里仍可能出现这个号码。验收时连续用两个订单号各问一次第二段回答里不得出现第一段的订单号。这比单看某一段「像客服」更能发现串单。步骤 2单次 system 覆盖默认店规步骤目标同一客户端服务不同订单号。publicStringanswerForOrder(StringorderId,StringuserText){StringsystemAfterSalePrompts.renderSystem(orderId,App,简短,policy-2026.10);returnthis.chatClient.prompt().system(system\n回答中必须出现未发货可退).user(userText).call().content();}运行结果文字描述连续问两个订单号两段回答各自包含对应订单号。默认系统消息被这一次的system盖住。可能的坑有人以为system()是在默认店规后面追加。它是这一次的系统文本不是拼接。需要保留默认句时自己把默认句和本次句拼好再传入。覆盖不是追加这和柜台换一张今日告示一样。新告示贴上之后旧告示不应还露在旁边。若你希望「简短」和「必须出现未发货可退」同时生效把两句拼成这一次的系统文本再传入。拼好之后在测试里打印最终系统文本确认订单号只有一个制度版本只有policy-2026.10。不要靠模型的回答来反推提示词里到底有几句店规模型会省略也会复述。打印请求侧的字符串才能知道发出去的是什么。步骤 3同一问题走 ChatModel.call对照 Usage步骤目标证明门面没有换成另一个模型。publicUsagePaircompare(StringorderId,StringuserText){StringsystemAfterSalePrompts.renderSystem(orderId,App,简短,policy-2026.10)\n回答中必须出现未发货可退;varbyClientthis.chatClient.prompt().system(system).user(userText).call().chatResponse();varbyModelthis.chatModel.call(neworg.springframework.ai.chat.prompt.Prompt(java.util.List.of(neworg.springframework.ai.chat.messages.SystemMessage(system),neworg.springframework.ai.chat.messages.UserMessage(userText))));returnnewUsagePair(byClient.getMetadata().getUsage(),byModel.getMetadata().getUsage(),byClient.getResult().getOutput().getText(),byModel.getResult().getOutput().getText());}publicrecordUsagePair(org.springframework.ai.chat.metadata.UsageclientUsage,org.springframework.ai.chat.metadata.UsagemodelUsage,StringclientText,StringmodelText){}运行结果文字描述控制台打印两组promptTokens和completionTokens都大于 0。两段正文都含「未发货可退」。数字通常接近不要求相等。若客户端一侧的提示词 token 明显更大检查是否默认系统消息和单次系统消息被同时发送。以你使用的 Spring AI 2.0 行为为准在测试里打印消息条数不要凭猜测写相等断言。可能的坑call().content()之后再想拿Usage已经晚了。对照实验用chatResponse()。流式接口本章不用。对照实验要锁住输入再放开输出的措辞。两边使用同一段系统文本、同一句用户问题、同一次默认温度。然后只比较三件事正文都非空都含「未发货可退」提示词 token 和完成 token 都大于 0。把两组数字打印出来。若客户端一侧的提示词 token 比直接调用大出一倍先数系统消息的条数常见原因是默认店规和单次店规被一起送出。数字接近就可以结束本章不必改断言去追求相等。相等会把采样差异误判成故障退款接口的构建会变成偶发失败。测试部门验收时看三行输出客户端正文、模型正文、两组 token。两段正文都含短语、都不含「优惠券」token 都大于 0即算通过。不要把某一次的全文贴进断言。模型下周更换措辞时测试仍应保持绿色。开发若要排查串单再临时打开系统文本的打印查完关掉避免订单号长期留在构建日志里。验收记录写明模型名是deepseek-v4-flash并附在测试说明里。3.3 完整代码清单RefundChatService、UsagePair和下一节测试。源码对照spring-ai-client-chat/.../chat/client/ChatClient.javaspring-ai-client-chat/.../chat/client/DefaultChatClient.java只建立直觉逐行阅读放在第 33 章示例继续放在samples/linlicang-aftersale-boot。目录落地前以本章代码块为准。3.4 测试验证packagecom.linlicang.aftersale;importorg.junit.jupiter.api.Test;importorg.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importstaticorg.assertj.core.api.Assertions.assertThat;SpringBootTestEnabledIfEnvironmentVariable(namedDEEPSEEK_API_KEY,matches.)classRefundChatServiceTest{AutowiredprivateRefundChatServicerefundChatService;TestvoidcontentIsNotBlankAndContainsPhrase(){Stringtextthis.refundChatService.answerForOrder(LC202610060018,这单未发货能不能退);System.out.println(text);assertThat(text).isNotBlank();assertThat(text).contains(未发货可退);assertThat(text).doesNotContain(优惠券);}TestvoidclientAndModelBothReportUsage(){UsagePairpairthis.refundChatService.compare(LC202610060018,这单未发货能不能退);System.out.println(clientPromptpair.clientUsage().getPromptTokens());System.out.println(modelPromptpair.modelUsage().getPromptTokens());assertThat(pair.clientUsage().getPromptTokens()).isPositive();assertThat(pair.modelUsage().getPromptTokens()).isPositive();assertThat(pair.clientText()).contains(未发货可退);assertThat(pair.modelText()).contains(未发货可退);}}$env:DEEPSEEK_API_KEY你的密钥 mvn -DtestRefundChatServiceTest test无密钥时整个类跳过。预期两条测试通过控制台有正文和两组 token。4. 项目总结4.1 优点与缺点对比项每个接口手写 PromptChatClient默认店规容易复制分叉defaultSystem集中一处取正文多层 getcontent()账单总在 ChatResponse 上需要时改chatResponse()换模型改每个 new换注入的 ChatModel学习成本低要分清建造期和请求期优点退款接口的调用代码缩短店规有一个默认入口。content()让控制器不必了解Generation。底层仍是DeepSeekChatModelUsage没有丢。单次system()可以覆盖默认店规不必为每个订单 new 客户端。缺点content()把finishReason藏起来截断会被当成正常正文。建造期写入订单号会造成串单。两条路径的 token 不一定相等错误的相等断言会制造假红。门面让人以为顾问已经生效。本章还没挂顾问。4.2 适用场景适用控制器只需要一段客服正文。多个接口共享店规少量请求要覆盖语气。需要证明门面和直接调用打到同一个模型。团队已经熟悉RestClient的建造方式。测试用关键短语而不是全文做断言。不适用必须在返回前判断LENGTH。这种接口用chatResponse()不要停在content()。需要流式推到页面。那是第 7 章的stream()。4.3 注意事项建造期只放与订单无关的店规。订单号放进单次system()或用户消息。要Usage就调用chatResponse()不要调用两次call()去补账单。注入ChatModel时容器里只能有一个聊天模型否则要改回DeepSeekChatModel。不要断言两次生成的全文相同。4.4 常见踩坑第二单回答里出现第一单订单号。根因是订单号写进了defaultSystem客户端是单例。处理订单号改到单次system()。截断的半句话返回给了 App。根因是只用content()没看finishReason。处理退款接口改用chatResponse()非STOP不展示。对照测试偶发失败在 token 相等。根因是把采样差异写成了等式。处理只断言大于 0 和关键短语数字打印出来供人工看。4.5 思考题defaultSystem和单次system()同时存在时你希望请求里有几条系统消息怎样用测试把条数打印出来而不是猜控制器只拿到content()的字符串。运维要按 token 计费时账单在哪一层采集才不会把同一次调用打两次模型答案在第 7 章开头。延伸阅读与资源10倍开发者的 Dify 魔法书从零构建全栈 AI 应用后端工程师转型AI第一课-Ollama 与私有化大模型实战大型语言模型(LLM) vLLM 高性能推理落地实战Agent开发之LlamaIndex 实战修炼与源码进阶大语言模型Transformers 实战修炼与源码剖析

相关新闻

【车载定位】基于扩展卡尔曼滤波 EKF,分别利用 TDOA、AOA 以及 TDOA+AOA 融合观测,搭配近恒速 NCV / 近恒位置 NCP运动模型对车辆轨迹估计附Matlab代码

【车载定位】基于扩展卡尔曼滤波 EKF,分别利用 TDOA、AOA 以及 TDOA+AOA 融合观测,搭配近恒速 NCV / 近恒位置 NCP运动模型对车辆轨迹估计附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和数学建模资料 &…

2026/10/14 0:03:43 阅读更多 →
人工智能期末复习:用习题集构建考点地图,高效备考不挂科

人工智能期末复习:用习题集构建考点地图,高效备考不挂科

简介:这份资源汇集人工智能课程各章小结与经典习题解答,适合正在系统学习人工智能基础、准备期末考试的本科生或自学者使用。内容覆盖人工智能的概念与发展阶段、研究学派与研究领域、知识与知识表示(谓词逻辑、产生式规则、框架、语义网络&a…

2026/10/14 0:03:43 阅读更多 →
wandb-core 中的 Wire 依赖注入:从贡献指南到 go:generate 自动装配实战

wandb-core 中的 Wire 依赖注入:从贡献指南到 go:generate 自动装配实战

机器学习深度学习数据可视化可观测性 【免费下载链接】wandb The AI developer platform. Use Weights & Biases to train and fine-tune models, and manage models from experimentation to production. 项目地址: https://gitcode.com/gh_mirrors/wa/wandb 点…

2026/10/14 0:03:43 阅读更多 →

最新新闻

尖叫声音样本数据集eva:从包结构到训练基线的完整实践

尖叫声音样本数据集eva:从包结构到训练基线的完整实践

简介:EVA尖叫声音样本数据集是一份面向音乐信息检索(MIR)与音频分类研究的人声尖叫样本库,由台湾清华大学MIR课程项目整理,旨在为尖叫检测、异常声音识别、SVM分类等实验提供稀缺的领域数据。压缩包共63个文件&#xf…

2026/10/14 0:47:55 阅读更多 →
现代C++多线程编程实践与优化指南

现代C++多线程编程实践与优化指南

1. 现代C多线程编程的核心价值十年前我刚接触多线程编程时,还在用pthread这类原始接口手动管理线程生命周期。现代C11标准引入的库彻底改变了游戏规则——现在我们可以用更安全、更直观的方式构建并发程序。举个例子,过去需要几十行代码实现的线程同步&a…

2026/10/14 0:47:55 阅读更多 →
Neo4j驱动的RAG:从向量检索到知识图谱推理的工程跃迁

Neo4j驱动的RAG:从向量检索到知识图谱推理的工程跃迁

1. 这份“日报”不是资讯汇编,而是工程实践的切片快照你点开这份标题为《Agent / LLM 技术精选日报 2026-09-28(知乎版)》的文档时,大概率会下意识把它当成一份轻量级技术资讯摘要——类似科技媒体每日推送的“今日AI圈发生了什么…

2026/10/14 0:47:55 阅读更多 →
JVM元空间内存泄漏排查与防护实战指南

JVM元空间内存泄漏排查与防护实战指南

1. 面试题背后的技术深度剖析当这个面试题出现在阿里巴巴Java技术面试中时,它实际上考察的是候选人对JVM内存管理的系统化理解能力和复杂问题排查经验。元空间(Metaspace)内存泄漏不同于传统的堆内存问题,它的隐蔽性更强且往往在应用运行较长时间后才显现…

2026/10/14 0:47:55 阅读更多 →
老虎数据集2055张VOC+YOLO格式:目标检测训练与标注避坑指南

老虎数据集2055张VOC+YOLO格式:目标检测训练与标注避坑指南

简介:本资源为面向目标检测学习者的老虎数据集,采用Pascal VOC与YOLO双格式标注,适合从事单类别目标检测训练、模型验证及算法对比的研究人员与开发者使用。压缩包共约2000个文件,以1999个xml标注文件和1个说明txt为主&#xff0c…

2026/10/14 0:47:55 阅读更多 →
开题报告是研究旅程的导航图,科迅捷AI帮你把路线画清楚

开题报告是研究旅程的导航图,科迅捷AI帮你把路线画清楚

如果把博士阶段的研究比作一段长途旅行,开题报告就是出发前画好的导航图。导航图不决定你路上的每一个细节,但它决定了方向:往哪走、经过哪些站点、预计什么时候到达。没有这张图,你很容易在路上迷路,或者走很远才发现…

2026/10/14 0:46:55 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →