Java Prompt工程化:告别字符串拼接,构建可维护的LLM应用框架
1. 项目概述为什么我们需要告别字符串拼接的Prompt如果你用Java做过大语言模型LLM的应用开发下面这段代码你一定不陌生String userQuery 帮我总结一下这篇文章; String articleContent 这是一篇很长的文章内容...; String prompt 你是一个专业的文本总结助手。请根据用户的要求和提供的文章生成一个简洁的总结。\n 用户要求 userQuery \n 文章内容 articleContent \n 请开始总结; // 然后调用 LLM API String summary llmClient.complete(prompt);初看没问题功能也能跑起来。但当你需要支持多轮对话、处理复杂上下文、动态插入变量、或者为不同场景客服、编程、创作构建差异化的Prompt时噩梦就开始了。你会发现代码里充斥着各种StringBuilder、String.format或者更糟糕的直接在业务逻辑里硬编码了长长的Prompt字符串。一旦需要调整Prompt中的一个措辞或者增加一个系统指令你就得在代码库里四处搜寻、小心翼翼地修改生怕引发连锁错误。这不仅仅是代码“脏”的问题它直接导致了几个核心痛点可维护性差、难以复用、调试困难、以及无法进行系统的Prompt优化和版本管理。这正是“Prompt工程”需要被“工程化”的原因。它不再是把几句话丢给模型的玄学而是一套可设计、可测试、可迭代的软件开发实践。Java作为一门强调设计模式、类型安全和工程严谨性的语言恰恰是实践Prompt工程化的绝佳平台。本篇文章我将结合自己在一线项目中的实战经验从最基础的模板抽象开始一步步带你构建一个健壮、可扩展的Java Prompt工程框架彻底告别原始而脆弱的字符串拼接时代。2. 核心思路与架构设计构建Prompt的“领域模型”工程化的第一步是抽象。我们不能把Prompt看作一个简单的字符串而应该将其视为一个由特定组成部分构成的、有结构的“领域对象”。一个完整的、可用于对话的Prompt通常包含以下几个核心部分系统指令System Instruction定义AI助手的角色、行为边界和回答风格。例如“你是一个严谨的Java技术专家回答需准确并附上代码示例。”上下文Context提供给模型的背景信息可以是知识库片段、历史对话、用户资料等。用户输入User Input当前轮次用户的具体问题或请求。对话历史Chat History之前的多轮问答记录用于维持对话连贯性。输出格式指示Output Format明确要求模型以特定格式如JSON、列表、Markdown表格回复。基于这个认知我们可以设计一个基础的Prompt类。但更重要的是我们需要一个能够灵活组装这些部分的“构建器”Builder。直接上代码看一个初步设计// 定义Prompt的组成部分 public class Prompt { private final String systemInstruction; private final ListMessage chatHistory; private final String userInput; private final MapString, Object contextVariables; private final OutputFormat outputFormat; // 使用Builder模式构造保证复杂对象的创建安全 public static class Builder { private String systemInstruction ; private ListMessage chatHistory new ArrayList(); private String userInput; private MapString, Object contextVariables new HashMap(); private OutputFormat outputFormat OutputFormat.TEXT; public Builder systemInstruction(String instruction) { this.systemInstruction instruction; return this; } public Builder userInput(String input) { this.userInput input; return this; } public Builder addContext(String key, Object value) { this.contextVariables.put(key, value); return this; } public Builder outputFormat(OutputFormat format) { this.outputFormat format; return this; } public Prompt build() { // 可在此处添加校验逻辑例如userInput不能为空 if (userInput null || userInput.trim().isEmpty()) { throw new IllegalArgumentException(User input cannot be empty); } return new Prompt(this); } } // ... 构造函数、getter方法等 }这个Prompt对象只是一个数据容器。真正的魔法发生在“渲染器”Renderer中。渲染器的职责是将这个结构化的Prompt对象按照目标LLM API要求的格式转换成一个或多个具体的消息Message列表。例如OpenAI的ChatCompletion接口需要ListChatMessage而Anthropic的Claude可能需要另一种结构。通过引入渲染器我们将Prompt的逻辑构建与协议序列化解耦这是工程化的关键一步。实操心得在项目初期不要过度设计。这个基础的Prompt和Builder已经能解决80%简单场景的问题。先跑起来再在遇到痛点比如需要支持动态模板、复杂的上下文管理时进行迭代重构。很多团队一开始就想做一个“万能”的Prompt框架结果陷入过度设计迟迟无法落地。3. 从静态模板到动态模板引擎有了结构化的Prompt对象我们解决了组成部分的抽象问题。但systemInstruction和userInput本身可能还是静态字符串。比如客服场景的指令是“你是XX公司的客服公司主营{productName}请用{language}语言回答。”这里的{productName}和{language}就是需要运行时注入的变量。最原始的做法是继续用String.formatString instruction String.format(你是%s公司的客服公司主营%s请用%s语言回答。, companyName, productName, language);这又走回了老路。我们需要一个真正的模板引擎。Java生态中有很多强大的模板引擎如Thymeleaf、FreeMarker、Velocity。但对于Prompt这种相对简单的文本替换场景我推荐使用Apache Commons Text的StringSubstitutor它轻量且足够强大或者直接使用Java自带的MessageFormat。更好的做法是进行一层封装定义一个Template接口public interface Template { String render(MapString, Object variables); } public class StringSubstitutorTemplate implements Template { private final String templateText; public StringSubstitutorTemplate(String templateText) { this.templateText templateText; } Override public String render(MapString, Object variables) { StringSubstitutor sub new StringSubstitutor(variables, {, }); return sub.replace(templateText); } }然后在我们的Prompt.Builder中可以支持直接传入Template对象并在build阶段进行渲染public class Prompt { // ... 其他字段 private final Template systemInstructionTemplate; private final Template userInputTemplate; public static class Builder { private Template systemInstructionTemplate; private Template userInputTemplate; private MapString, Object templateVariables new HashMap(); public Builder systemInstructionTemplate(Template template) { this.systemInstructionTemplate template; return this; } public Builder userInputTemplate(Template template) { this.userInputTemplate template; return this; } public Builder addTemplateVariable(String key, Object value) { this.templateVariables.put(key, value); return this; } public Prompt build() { // 渲染模板 String systemInstruction (systemInstructionTemplate ! null) ? systemInstructionTemplate.render(templateVariables) : ; String userInput (userInputTemplate ! null) ? userInputTemplate.render(templateVariables) : ; // ... 用渲染后的字符串构造最终的Prompt对象 return new Prompt(systemInstruction, userInput, ...); } } }这样我们就可以将Prompt模板定义为外部资源如数据库、配置文件实现真正的动态配置和热更新。// 从配置中心读取模板字符串 String sysTmplStr config.get(prompt.template.customer_service.system); Template sysTmpl new StringSubstitutorTemplate(sysTmplStr); Prompt prompt new Prompt.Builder() .systemInstructionTemplate(sysTmpl) .userInputTemplate(new StringSubstitutorTemplate(用户说{query})) .addTemplateVariable(companyName, AwesomeTech) .addTemplateVariable(productName, 智能云平台) .addTemplateVariable(language, 中文) .addTemplateVariable(query, 我的服务出问题了) .build();注意事项模板变量的注入需要警惕Prompt注入攻击。如果变量内容来自不可信的用户输入必须进行严格的过滤和转义防止用户通过精心构造的输入篡改系统指令。例如如果用户输入包含了}可能会破坏模板结构。简单的办法是对变量值进行HTML转义或使用模板引擎的安全模式。4. 上下文管理与向量检索的集成复杂的应用场景中上下文Context往往不是一两个简单的变量而可能是一组从知识库中检索出来的相关文档片段。这就需要我们设计一个ContextProvider上下文提供器的抽象。假设我们有一个向量数据库存储了公司内部文档我们需要根据用户问题检索最相关的3个片段作为上下文。public interface ContextProvider { ListContextFragment provide(String userInput, int maxFragments); } public class VectorDBSemanticContextProvider implements ContextProvider { private final VectorDBClient vectorDBClient; public VectorDBSemanticContextProvider(VectorDBClient client) { this.vectorDBClient client; } Override public ListContextFragment provide(String userInput, int maxFragments) { // 1. 将用户输入转换为向量 float[] queryVector embeddingModel.embed(userInput); // 2. 在向量数据库中进行相似度搜索 ListSearchResult results vectorDBClient.similaritySearch(queryVector, maxFragments); // 3. 将结果转换为ContextFragment列表 return results.stream() .map(r - new ContextFragment(r.getContent(), r.getSource(), r.getScore())) .collect(Collectors.toList()); } }然后在构建Prompt时可以动态注入上下文public class Prompt { // ... 其他字段 private final ListContextFragment contextFragments; public static class Builder { private ListContextProvider contextProviders new ArrayList(); // ... 其他字段 public Builder addContextProvider(ContextProvider provider) { this.contextProviders.add(provider); return this; } public Prompt build() { // ... 其他构建逻辑 ListContextFragment allFragments new ArrayList(); for (ContextProvider provider : contextProviders) { allFragments.addAll(provider.provide(this.userInput, 3)); // 假设每个提供器最多返回3个片段 } // 可能需要对片段进行去重、排序、截断避免超出Token限制 allFragments processFragments(allFragments); return new Prompt(..., allFragments); } } }这样Prompt的构建过程就与复杂的知识检索逻辑解耦了。你可以轻松组合不同的上下文提供器比如一个提供产品文档一个提供最近的工单记录另一个提供用户画像信息。实操心得上下文不是越多越好。过多的、不相关的上下文会干扰模型增加Token消耗成本并可能导致模型忽略最重要的信息。一定要对检索到的上下文片段进行相关性评分过滤。例如只保留相似度分数高于0.7的片段。同时所有上下文在拼接到Prompt前需要做好格式整理比如用## 参考文档 [来源]这样的标记分隔并明确指示模型“请根据以下参考文档回答问题”。5. 对话历史的管理与优化策略对于多轮对话应用管理对话历史是Prompt工程的核心挑战之一。你不能无脑地把所有历史对话都塞进Prompt因为LLM有上下文窗口长度限制如4K、8K、16K、128K Token而且历史越长模型需要处理的信息越庞杂响应可能越慢成本也越高。我们需要一个ChatHistoryManager来负责对话历史的存储、截断和摘要。策略1固定窗口截断这是最简单的方法只保留最近的N轮对话。public class FixedWindowHistoryManager implements ChatHistoryManager { private final int maxTurns; private final LinkedListMessage history new LinkedList(); public FixedWindowHistoryManager(int maxTurns) { this.maxTurns maxTurns; } Override public void addExchange(Message userMsg, Message assistantMsg) { history.add(userMsg); history.add(assistantMsg); while (history.size() maxTurns * 2) { // 每轮包含用户和助手两条消息 history.removeFirst(); history.removeFirst(); } } Override public ListMessage getHistory() { return new ArrayList(history); } }策略2基于Token长度的智能截断更精细的策略是计算历史消息的累计Token数当接近模型上限时从最老的开始移除直到满足要求。这需要集成一个Token计算器如使用tiktoken库的Java封装或模型提供商提供的SDK。策略3历史摘要Summarization这是高级策略。当历史对话很长时可以调用LLM本身对“远古”历史生成一个简短的摘要然后在后续Prompt中用“之前的对话摘要{summary}”来代替详细的历史记录。这能极大地节省Token并保持关键信息的延续性。public class SummarizingHistoryManager implements ChatHistoryManager { private final LLMClient llmClient; private final ListMessage recentHistory new ArrayList(); private String summary ; Override public void addExchange(Message userMsg, Message assistantMsg) { recentHistory.add(userMsg); recentHistory.add(assistantMsg); // 当recentHistory达到一定长度或Token数时触发摘要生成 if (needSummarize()) { String historyText convertHistoryToText(recentHistory); String newSummary llmClient.complete(“请用一段话简要总结以下对话的核心内容\n” historyText); this.summary mergeSummary(this.summary, newSummary); // 合并新旧摘要 recentHistory.clear(); // 清空近期历史只保留摘要 } } Override public ListMessage getHistoryForPrompt() { ListMessage result new ArrayList(); if (!summary.isEmpty()) { result.add(Message.systemMessage(“历史对话摘要” summary)); } result.addAll(recentHistory); return result; } }在实际的Prompt.Builder中可以注入一个ChatHistoryManager实例由它来提供处理好的历史消息列表。常见问题用户可能会问“我刚才说了什么”如果历史被截断或摘要了模型可能无法回答。因此在实现摘要策略时需要谨慎评估摘要的保真度并在产品层面管理用户预期。一种折中方案是“混合模式”保留最近3-5轮完整对话更早的则用摘要替代。6. 输出格式约束与结构化输出解析让LLM返回结构化的数据如JSON、XML对于后续的程序化处理至关重要。这需要在Prompt中明确指定输出格式。我们可以创建一个OutputFormat枚举和对应的格式指示器。public enum OutputFormat { TEXT(请直接返回答案文本。), JSON(请将你的回答组织成一个JSON对象。), MARKDOWN_LIST(请使用Markdown无序列表格式列出要点。), // ... 其他格式 private final String instruction; OutputFormat(String instruction) { this.instruction instruction; } public String getInstruction() { return instruction; } }在构建最终Prompt时将outputFormat.getInstruction()附加到系统指令或用户输入的末尾。但仅仅给出指令还不够模型的输出可能仍然不规范。我们需要一个OutputParser来负责解析和校验。public interface OutputParserT { T parse(String llmOutput) throws ParsingException; } public class JsonOutputParserT implements OutputParserT { private final ClassT targetClass; private final ObjectMapper objectMapper; // Jackson库 public JsonOutputParser(ClassT targetClass) { this.targetClass targetClass; this.objectMapper new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } Override public T parse(String llmOutput) throws ParsingException { try { // 尝试从输出中提取JSON块模型有时会在JSON外加一些解释性文字 String jsonStr extractJsonBlock(llmOutput); return objectMapper.readValue(jsonStr, targetClass); } catch (JsonProcessingException | IllegalArgumentException e) { throw new ParsingException(Failed to parse LLM output as JSON: llmOutput, e); } } private String extractJsonBlock(String text) { // 简单的实现查找第一个{和最后一个}之间的内容 int start text.indexOf({); int end text.lastIndexOf(}); if (start ! -1 end ! -1 end start) { return text.substring(start, end 1); } return text; // 如果没有找到返回原文本让Jackson尝试解析 } }这样我们的Prompt执行流程就变成了构建Prompt - 渲染为API消息 - 调用LLM - 用OutputParser解析返回结果 - 得到类型安全的Java对象。整个流程变得非常清晰和可靠。避坑技巧即使指定了JSON格式模型偶尔也会在JSON对象前后加上“json”这样的Markdown代码块标记或额外的说明文字。因此OutputParser必须足够健壮能够处理这些情况并提取出有效的JSON字符串。一种更稳妥的方式是在Prompt中明确要求“请只输出JSON对象不要有任何额外的解释、标记或代码块符号。”7. 完整流程整合与实战示例现在让我们把以上所有模块整合到一个完整的、可执行的流程中。假设我们要构建一个“智能客服问答”场景。第一步定义领域对象和模板// 客服场景的Prompt模板可配置 public class CustomerServicePromptTemplates { public static final Template SYSTEM_TEMPLATE new StringSubstitutorTemplate( 你是{companyName}的AI客服助手。公司主营{productName}。\n 你的职责是解答用户关于产品功能、使用方法和故障排查的问题。\n 回答需专业、友好、简洁。如果遇到无法解决的问题应引导用户联系人工客服。\n 请根据以下参考文档和对话历史来回答问题。\n {outputFormatInstruction} ); public static final Template USER_INPUT_TEMPLATE new StringSubstitutorTemplate( 当前用户问题{userQuery}\n\n 相关参考文档\n{context}\n\n 请回答 ); }第二步组装Prompt构建流程public class CustomerServiceOrchestrator { private final ContextProvider contextProvider; private final ChatHistoryManager historyManager; private final LLMClient llmClient; private final OutputParserServiceResponse outputParser; public ServiceResponse handleUserQuery(String sessionId, String userQuery) { // 1. 检索上下文 ListContextFragment context contextProvider.provide(userQuery, 5); String contextText formatContext(context); // 2. 获取对话历史 ListMessage history historyManager.getHistoryForPrompt(sessionId); // 3. 构建Prompt对象 Prompt prompt new Prompt.Builder() .systemInstructionTemplate(CustomerServicePromptTemplates.SYSTEM_TEMPLATE) .userInputTemplate(CustomerServicePromptTemplates.USER_INPUT_TEMPLATE) .addTemplateVariable(companyName, TechCorp) .addTemplateVariable(productName, CloudSync Pro) .addTemplateVariable(outputFormatInstruction, OutputFormat.JSON.getInstruction()) .addTemplateVariable(userQuery, userQuery) .addTemplateVariable(context, contextText) .chatHistory(history) // 注入历史 .outputFormat(OutputFormat.JSON) .build(); // 4. 渲染并调用LLM (通过一个Renderer) PromptRenderer renderer new OpenAIChatMessageRenderer(); // 负责转换成OpenAI的消息格式 ListChatMessage messages renderer.render(prompt); String llmRawOutput llmClient.chatCompletion(messages); // 5. 解析输出 ServiceResponse response outputParser.parse(llmRawOutput); // 6. 更新对话历史 historyManager.addExchange(sessionId, Message.userMessage(userQuery), Message.assistantMessage(response.getAnswer())); return response; } private String formatContext(ListContextFragment fragments) { // 将上下文片段格式化为易读的文本 return fragments.stream() .map(f - String.format(【来自%s】%s, f.getSource(), f.getContent())) .collect(Collectors.joining(\n\n)); } }第三步定义输出结构// 期望LLM返回的JSON结构 public class ServiceResponse { private String answer; // 回答内容 private boolean needHumanAgent; // 是否需要转人工 private ListString suggestedQuestions; // 推荐问题 private String confidence; // 置信度 // getters and setters... }这个Orchestrator类成为了我们客服场景的“大脑”它协调了上下文检索、历史管理、Prompt构建、LLM调用和结果解析的完整生命周期。8. 测试、监控与持续迭代工程化的最后一步是确保系统的可靠性和可优化性。Prompt不是一次写好就一劳永逸的需要像代码一样进行测试和迭代。单元测试为Prompt构建器、Template渲染器、OutputParser等核心组件编写单元测试。Test public void testJsonOutputParser() { JsonOutputParserServiceResponse parser new JsonOutputParser(ServiceResponse.class); String llmOutput {\answer\: \重启试试\, \needHumanAgent\: false}; ServiceResponse resp parser.parse(llmOutput); assertEquals(重启试试, resp.getAnswer()); assertFalse(resp.isNeedHumanAgent()); }集成测试与A/B测试对于重要的Prompt可以设计端到端的集成测试用一批标准问题验证其回答质量。更进一步可以搭建A/B测试框架同时部署两个不同版本的Prompt如V1和V2收集用户满意度、问题解决率等指标用数据驱动Prompt的优化。监控与日志记录每一次LLM调用的详细信息至关重要。记录完整的Prompt和Completion这是调试的黄金数据。当出现错误或低质量回答时可以回放当时的输入。记录Token使用量监控成本。记录响应时间监控性能。记录解析失败率评估OutputParser的健壮性。可以将这些信息结构化后输出到日志系统如ELK Stack或发送到监控平台如Prometheus Grafana。例如每次调用后记录一条JSON日志{ sessionId: abc123, userQuery: 如何备份数据, promptVersion: cs_v1.2, totalTokens: 1250, responseTimeMs: 1250, parsingSuccess: true, confidence: high }版本管理将Prompt模板像代码一样用Git管理起来。每次对系统指令、用户模板的修改都应该有明确的版本号和提交信息。这便于回滚和追踪哪个Prompt变更导致了指标的变化。9. 进阶技巧与模式探索当基础框架搭建完毕后可以探索一些更高级的工程模式来应对复杂场景。链式调用Chain将一个复杂任务拆解成多个LLM调用步骤。例如“客服问答”链可以是1) 意图识别 - 2) 根据意图检索对应知识库 - 3) 生成回答 - 4) 安全检查。我们可以定义一个Chain接口每个Step负责一部分工作并决定下一步是什么。条件化PromptConditional Prompting根据运行时条件动态选择不同的Prompt模板或参数。例如识别到用户情绪为“愤怒”时切换到安抚性更强的系统指令和回复风格。这可以在Orchestrator中通过一个PromptSelector来实现。Few-Shot示例管理对于需要复杂推理或特定格式的任务在Prompt中提供几个示例Few-Shot非常有效。我们可以创建一个ExampleStore来管理不同任务类型的示例对输入/输出并在构建Prompt时动态选取最相关的几个示例插入到上下文中。Prompt模板的国际化如果你的应用面向多语言用户需要维护不同语言版本的Prompt模板。这可以通过将模板文本存储在外部资源文件如.properties或数据库中并根据用户语言偏好动态加载对应的模板来实现。从原始的字符串拼接到结构化的Prompt对象再到集成了模板、上下文、历史、解析的完整工程化框架这条路走下来你会发现LLM应用的开发变得前所未有的清晰和可控。它不再是黑盒魔法而是一套有设计、可测试、能迭代的标准工程实践。这不仅能提升开发效率和系统稳定性更重要的是它为持续优化AI应用的效果奠定了坚实的基础。毕竟在AI时代Prompt就是新时代的代码而写好代码从来都需要好的工程方法。

相关新闻

具身智能工程实践:从仿真到实体的技术拆解与务实路径

具身智能工程实践:从仿真到实体的技术拆解与务实路径

在实际技术领域,我们经常看到一些新兴概念在初期被过度宣传,从“元宇宙”到“大模型”,再到如今的“具身智能”。当“全球第一”、“颠覆性突破”等词汇频繁出现在技术新闻中时,从业者更需要冷静地理解其技术内核、当前的真实能力…

2026/10/27 21:45:57 阅读更多 →
叠衣服为何成为机器人技术试金石?从感知到规划的全链路解析

叠衣服为何成为机器人技术试金石?从感知到规划的全链路解析

如果你最近关注机器人领域的新闻,可能会发现一个有趣的现象:像 Figure AI、1X 这类估值动辄数十亿美元的明星机器人公司,都在不约而同地展示一个看似“简单”的技能——叠衣服。这听起来有点“大材小用”。毕竟,这些公司背后是顶尖…

2026/10/26 11:41:19 阅读更多 →
GitHub Models退役:专业模型托管平台迁移与MLOps实践指南

GitHub Models退役:专业模型托管平台迁移与MLOps实践指南

最近在开源社区和AI开发者圈子里,一个消息引起了不小的讨论:GitHub Models 正式退役了。对于很多依赖 GitHub 进行模型托管、版本管理和协作的团队来说,这无疑是一个需要认真对待的变更。无论是个人研究者在尝试复现论文模型时遇到 all mode…

2026/10/25 9:57:13 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/27 17:33:32 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/27 4:06:49 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/27 7:21:53 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/27 18:20:50 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/27 6:20:47 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/27 4:06:50 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 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/27 13:55:19 阅读更多 →
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/27 7:21:50 阅读更多 →
黑夜航拍船只数据集训练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/27 19:19:37 阅读更多 →