
Java 25 是一个 LTS 版本,它的众多新特性中就数
JEP 506: Scoped Values能改变我们从前使用ThreadLocal时的编程范式。因其重要性,所以单列一篇来专门学习它。Scoped Values, 可用来替代ThreadLocal的使用,特别是在虚拟线程当中。Scoped Values用于在当前线程或子线程中共享不可变的数据,说到不可变的数据就会想到JEP 502: Stable Values (Preview).ThreadLocal, 甚至InheritableThreadLocal用于子线程中共享数据还是有些挑战性,特别碰到线程池的情况, 而且ThreadLocal不在乎数据可变还是不可变的,执行当中谁改了数据,不知道。Scoped Values的 JEP 说其目的不是用来完全替代ThreadLocal。下面来看看
Scoped Values如何在子线程中共享数据,它还能与虚拟线程的结构化并发配合使用。ThreadLocal/InteritableThreadLocal仍然是很多框架用来在线程中(间)共享数据的办法,在Spring框架中有大量的使用, 如XxxContextHolder之类的。目前的ThreadLocal存在一些问题- ThreadLocal 中的数据是可变的,多数应用场景只要不可变的数据
- 难以管理共享数据的生命周期,特别是在线程池中,线程被重用时,ThreadLocal 中的数据可能会被意外共享或泄露。由使用方主动清除数据,更是会造成潜在的 Bug
- 成本高昂,创建子线程,或线程切换时要对共享数据进行复制,
VirtualThread也是继承自Thread, 所以虚拟线程也能用ThreadLocal。 一旦虚拟线程的数量达到成千上万,十百万的级别时,ThreadLocal数据不停复制的代价就很高了

LangChain1.0 于 2025 年 10 月 22 日发布,这是一个里程碑式的版本,听说在 0.x 要创建一个agent很麻烦, 那时候内部是真正的链, 1.0 后虽然还叫LangChain, 实际上内部实现是图(LangGraph), 用create_agent()创建agent. 从数据结构来看,图比链表更能直观的表达Agent与模型及工具的交互场景。很庆幸在LangChain1.0 之后才开始学习这个框架,不用体验LangChain0.x 的痛苦。大概对
LangChain的 tools 有些许了解之后,现在跳到Model Context Protocol(MCP)协议这一章,本人对MCP的初步理解是相对于工具,MCP是一个远程(跨进程)的工具。为了方便的使用互联网上的各种资源,MCP在实现一个完备的Agent也是一个非常重要的工具。Model Context Protocol (MCP) 是
Anthropic推出并开放的协议,用于构建Agent与外部资源的交互,下面会与工具对照着学习它. 以前也写过一篇关于MCP的文章,今天从不同的角度再次强化对MCP的理解。在
Read MoreLangChain中要使用MCP需安装langchain-mcp-adapters依赖,然后使用它的MultiServerMCPClient, 它是无状态的。要创建自己的MCP服务,使用FastMCP库。
学习了
Agent,Models之后直接跳到Short Term Memory节,短期记忆能让我们更好的理解与模型的交互, 为什么与机器人越聊到最后它可能就 偏离主题,智商降低了。前面所用的手动拼接整个会话历史和使用InMemorySaver就是模型的短期记忆,如果会话历史过长,超过上下文件大小, 导致上下文丢失或错误,这就需要对会话进行压缩,压缩做了些什么事情呢,这就是本文要学习的内容。之前写过一篇 LangChain - 关于会话记忆, 也是关于短期记忆的,这里重新阅读官方的文档,也是加以巩固。
模型是没有记忆的,所有你和模型说过的话你都必须记住,记忆就是让 Agent 记住你与模型的会话历史,短期记忆特指单一会话的历史。短期记忆与长期记忆这两 个概念总会让人有所迷惑的,简单的可以这么理解,比如使用 ChatGPT 时
- 在同一个
Chat中的对话就是短期记忆,即便你一年后再回到那个没有删的Chat中接着聊,也是短期记忆 - 而长期记忆是跨会话的,比如在某个
Chat中说过喜欢猪头饭,再点New chat打开一个新的Chat,问今天吃什么,模型直接建议吃猪头饭,这就是长期记忆
还是那句话,大语言模型是没有记忆的, 和大语言模型对话就像和一个失忆症的人对话, 每次问话都必需把之前的对话复述一遍, 过程相当于:
Read More- 在同一个

学习了一段时间 LangChain,了解到用
create_agent()创建的 Agent 的用法,以及底层init_chat_model()与模型的交互,决定以古法的方式 亲自创建一个 AI Agent, 要实现的功能是把原来用 ApacheAirflow做的一个从猫收留网站上查看有没有新进入收容所的猫,有则发邮件通知。换成 AI Agent 的话,功能列表是
Read More- 使用 AWS Bedrock 上的一个 Claude 模型
- 用 Telegram 创建一个 Bot, 配置好 Bot Token 与 Chat ID
- 工具方面,提供读文件,写文件,和更新文件的函数,web_fetch, 还有向 Telegram 发送消息的函数
- AI Agent 从一个特定的网页上收集猫的信息,借助文件判定是否是新的
- 发现新的猫,向 Telegram Bot 发送通知, 每只新猫一个消息,消息包含猫的基本信息,图片与链接

在上一篇 LangChain 核心组件之 Agent 有介绍到模型。模型其实是一个很粗泛的概念,放到任何领域都有立身之地, 比如各种建模,经济增长模型,Covid 感染模型等。但来到 AI 时代,会不会只要有人一开口说模型便默认为大语言模型(LLM)呢?而如今的 LLM 模型又基本就是 Transformer 模型,所谓的模型开源只是开放了一堆的 Token 的权重值,不同源软件开源,拿过来能随意定制使用。
大语言模型更像是人类知识的压缩包,可用它生成多种形式的内容,比如文本、图像、音频等。模型在生成内容的过程中,还支持下面几种形式的交互
- 工具调用:可以引导模型通知 Agent 调用工具,如计算,互联网搜索,API 调用等
- 结构化输出:模型本身就支持按照约定的规则格式化输出内容
- 多模态:不仅能生成文本,还能生成图像、音视频等
- 推理:模型可以进行推理,如数学计算、逻辑推理等,就是经常看到的 Thinking 的过程
最初在 Llama3 刚发布的年代,在使用 MCP 时还要查哪个模型支不支持工具使用,现在基本上以上特性是模型的标配了。现在几大商业模型就是 OpenAI 的 GPT, Anthropic 的 Claude,Google 的 Gemini, Musk 的 Grok 在下一梯队。国外的模型选择很清晰,反而中国的大语言模型众多, 仿佛不出个自己的大语言模型就像个互联网公司。
Read More
经过了一番
LangChain的学习之后,我们开始跟随LangChain的官方文档系统性的学习。首先是它的核心组件,包括Agents,Models,Messages,Tools,Short-term memory,Streaming, 和Structured output. 现在从 Agents 开始。创建 Agent
create_agent是可用于正式产品中创建 Agent 的函数, 它返回的是一个langgraph.graph.state.CompiledStateGraph对象,而非一个XxxAgent样的东西。所以它创建的是一个状态图,图吗,就有顶点和边,Agent 就是这个图中移动,比如在Model和Tools之间往复, 或在中间加入的互动的(Human-in-the-loop).
Read MoreLangGraph把与模型,工具,以及人的交互做成一个图还是很表意的,下面是来源于官方文档的表示 Agent 的状态图。
Java 24 也是一个过渡版本, 还是到下面两个链接中找相应的更新
IntelliJ IDEA 对 Java 24 Language level 描述是
- 24 - No new language features
- 24 (Preview) - Flexible constructor bodies, simple source files, etc.
把上面第二个链接中的特性列出来
- 404: Generational Shenandoah (Experimental)
- 450: Compact Object Headers (Experimental)
- 472: Prepare to Restrict the Use of JNI
- 475: Late Barrier Expansion for G1
- 478: Key Derivation Function API (Preview)
- 479: Remove the Windows 32-bit x86 Port
- 483: Ahead-of-Time Class Loading & Linking
- 484: Class-File API *
- 485: Stream Gatherers *
- 486: Permanently Disable the Security Manager
- 487: Scoped Values (Fourth Preview)
- 488: Primitive Types in Patterns, instanceof, and switch (Second Preview)
- 489: Vector API (Ninth Incubator)
- 490: ZGC: Remove the Non-Generational Mode
- 491: Synchronize Virtual Threads without Pinning
- 492: Flexible Constructor Bodies (Third Preview)
- 493: Linking Run-Time Images without JMODs
- 494: Module Import Declarations (Second Preview)
- 495: Simple Source Files and Instance Main Methods (Fourth Preview)
- 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism
- 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm
- 498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe
- 499: Structured Concurrency (Fourth Preview)
- 501: Deprecate the 32-bit x86 Port for Removal
Java 24 中列出的特性恰如其版本一样,有 24 条,因其是一个过渡版本,多数为非正式特性,也就为什么 IntelliJ IDEA 从语言特性上把 Java 标记为 No new language features. 其实也不然,个人觉得有两个正式特性值得关注,即 Class-File API 和 Stream Gathers。
Read More
所谓大语言模型的记忆功能,就是要在说当前这句话的时候让 LLM 知道整个对话的上下文。比如说与人对话
- A: 给我讲个笑话
- B: 有一天,有人问你:“你喜欢什么?”, 你回答:“我喜欢一切……只要不叫‘考试’。” 😄 够快,够短,有没有让你会心一笑?
- A: 再来一个
- B: 问:海里面最怕什么? 答:脱水。
#3 当 A 问 "再来一个" 时候,B 因为有基于前面对话的上下文,所以能理解 "再来一个" 来一个笑话,而不是一个妞什么的,也记得曾经讲过一个笑话,而不 至于重复之前的笑话。如果突然有一天 A 对 B 突兀的说 "再来一个",B 就会有些傻眼了,AI 在没有上下文的情况也是一样。
不过人与人之间对话的上下文是互相的,两方的共同记忆,双方都是建立在你知道我问了什么,你自己回复了什么的基础之上的。而于大语言模型的对话时, 大语言模型是没有记忆的,就好像和一个失忆的人对话一样,记忆责任全在一方,你和 LLM 每一次对话时都要不停的唠叨:
我曾经问了这个,你回复过那个,问过这个,你回复过那个......,我现在问一个问题,请基于我们的会话历史作出回答
和机器对话就是这么傻傻的,当对话历史过大的时候因为上下文大小限制的原因,就必须压缩总结之前的对话内容,压缩后总会失真,这就是为什么大语言模型会 不断降智的一个原因。
Read More
前段时间 OpenClaw 确实很火,尤其是在中国,它在 2025 年 11 月上线后,最初名字是 Clawbot, 中间更名为 Molbot, 最后定名为 OpenClaw. 我在它 真正火热当中并没有产生多大兴趣去跟风,只最近一个月想看看它到底是个什么东西。弄了个虚拟机装上后,就是可以连接各个大模型, 打通与国外流行的即时通讯 软件,能自动化的就是它的 Cron Jobs.
界面上功能不少,最后发现真正有用的就是那个 Cron Jobs, 比如自己设置了一个每日两次的定时任务,实现的是从监控一个猫收容网上的列表,当发现有新的猫 就发送到指定的 Telegram Bot 上,描述很简单,但 Agent 确实很聪明,不用告诉它细节,它自己知道怎么本地文件来辅助判断是否为新猫。聪明的另一个原因是 OpenClaw 蹭了我 $20 Claude 会员的光。但到 4 月 4 日,Claude 订阅会员不让绑定到 OpenClaw 之后,试用了 Google 免费的 API Key 不怎么理想。
也不想再多折腾,如果只是要一个
Cron Job的话可以自己用LangChain实现一个。听说 OpenClaw 十分耗 Token, 于是对它的提示词有点好奇。 本文将查看一下一个新鲜的OpenClaw的提示词长什么样子。于是又新装了一个
Read MoreOpenClawv2026.4.9 版本,使用本地的Ollama模型,由于未能成功设置OpenClaw使用代理来访问OllamaAPI, 于是在Ollamaservice 前端放了一个反向代理,该反向代理也是临时用 Vibe Coding 搓出来的。让OpenClaw使用通过反向代理http://localhost:9091来访问实际的Ollamahttp://localhost:11434, 并在反向代理中记录下对OllamaAPI 完整的请求与响应数据,使用什么模型都无所谓。
上一篇 LangChain 1.2 入门学习 中使用了特定的 ChatOllama/ChatGoogleGenerativeAI, 或统一的 init_chat_model 方式创建一个与 LLM 的交互程序,并以此基础实现了一个简单的 AI Agent, 工具调用是根据响应中消息格式手工调用的, 会话处理是自己拼接全部对话历史。现在知名的 LLM 都支持推理,所以顺代也用灰色字体显示了 'thinking' 的文本内容。
本文直接学习官方 Quickstart 中的一个
AI Agent, 该 Agent 实现了以下功能- 有了上下文,会记忆会话历史
- 支持调用多个工具
- 提供结构化一致性的响应数据格式
- 能通过上下文处理用户特定的信息
- 跨交互维护会话状态