<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Scar's Blog</title><link>https://cxk.me/</link><description>努力精进 | 聚焦</description><item><title>未命名</title><link>https://cxk.me/post/108.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;在Auto Research泛滥的当下，扎实地做好每一份工作，目前看来是最高效的做法。&lt;/p&gt;
&lt;/body&gt;</description><pubDate>Sun, 20 Sep 2026 10:58:35 +0800</pubDate></item><item><title>未命名</title><link>https://cxk.me/post/107.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;时间安排不合理的原因：对总任务量以及完成所需时间的错误估计。解决方案：尽可能早地去做。还有什么可以补充的吗？&lt;/p&gt;
&lt;/body&gt;</description><pubDate>Sun, 20 Sep 2026 09:16:50 +0800</pubDate></item><item><title>Casual AI 学习笔记</title><link>https://cxk.me/post/106.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;h1 id=&quot;h1-Causal20AI20u5B66u4E60u7B14u8BB0-1&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;Causal AI 学习笔记&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Causal AI 学习笔记&lt;/h1&gt;&lt;h2 id=&quot;h2-1.20u6982u5FF5-3&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 概念&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 概念&lt;/h2&gt;&lt;h3 id=&quot;h3-u56E0u679Cu63A8u65AD-5&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;因果推断&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;因果推断&lt;/h3&gt;&lt;p&gt;因果推断（Causal Inference）是 Causal AI 最核心的任务。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;关联（看到，X→Y 映射）：传统AI能做的，比如“看到冰淇淋销量高，游泳溺水人数也多”。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;干预（做）：“推断”精髓。例如，假设“如果我把冰淇淋价格提高一倍，那么溺水人数会下降吗？”——答案是不会，因为它们是温度这个“混杂因子”造成的。Causal AI通过干预计算（do-operator）来剔除虚假相关。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;反事实（想象，如果当时）：这是最高级的假设。比如“假设我当时没给这位病人开这个药，他现在会怎样？”——这是传统AI完全做不到的，也是Causal AI最厉害的地方。&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;h2-u56E0u679Cu53D1u73B0-15&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;因果发现&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;因果发现&lt;/h2&gt;&lt;p&gt;因果发现（Causal Discovery）指的是，让机器在没有任何“标准答案”的情况下，仅凭一堆历史数据，自己“画”出一张因果关系图（即 DAG 有向无环图）。&lt;/p&gt;
&lt;p&gt;如果说“因果推断”是拿着假设去考试（验证“X→Y，X是否影响Y”），那么“因果发现”就是连考卷题目都没有，直接让你从数据海洋里捞知识。它的核心任务是找出变量之间箭头指向的方向（到底是X→Y，还是Y→X）。&lt;/p&gt;
&lt;/body&gt;</description><pubDate>Sat, 11 Jul 2026 23:03:56 +0800</pubDate></item><item><title>MySQL Server MCP 真好用</title><link>https://cxk.me/post/105.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;MySQL Server MCP 真好用&lt;/p&gt;
&lt;/body&gt;</description><pubDate>Sat, 07 Mar 2026 15:36:47 +0800</pubDate></item><item><title>TRAE 的 spec 模式</title><link>https://cxk.me/post/104.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;用 spec 模式，附带详细的接口说明（任务交接文档），能显著提升 AI IDE 的长程任务能力。&lt;/p&gt;
&lt;p&gt;现在 TRAE 支持根据 Task 自动创建 Sub Coding Agent 了，总体来说还是比较好用的，偶尔会出现子任务卡死的情况。&lt;/p&gt;
&lt;p&gt;/spec 请采用 Java 开发最佳实践，完成这个任务 &lt;code&gt;d:\rightnow-core\docs\rightnow-core-接口设计交接文档.md&lt;/code&gt; &lt;code&gt;d:\rightnow-core\docs\rightnow-core-后端接口开发指南.md&lt;/code&gt;&lt;/p&gt;
&lt;/body&gt;</description><pubDate>Sat, 07 Mar 2026 15:29:40 +0800</pubDate></item><item><title>Agent Framework Philosophy: The Unbitter Lesson</title><link>https://cxk.me/post/103.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;h1 id=&quot;h1-Agent20Framework20Philosophy3A20The20Unbitter20Lesson-1&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;Agent Framework Philosophy: The Unbitter Lesson&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Agent Framework Philosophy: The Unbitter Lesson&lt;/h1&gt;&lt;h2 id=&quot;h2-1.20Introduction3A20The20Burden20of20Abstraction-3&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. Introduction: The Burden of Abstraction&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. Introduction: The Burden of Abstraction&lt;/h2&gt;&lt;p&gt;The history of software is a history of abstraction. We build layers to hide complexity, creating frameworks, patterns, and objects that promise to make our lives easier. Yet, in the nascent field of agentic AI, this instinct has led us astray. Early attempts at agent frameworks are replete with complex class hierarchies, managers for every conceivable concept (Memory, Task, Tool), and intricate state machines. They are monuments to premature abstraction.&lt;/p&gt;
&lt;p&gt;As Gregor Zunic (Cofounder &amp;amp; CEO of Browser Use) puts it, these frameworks fight the very nature of the intelligence they seek to orchestrate [1]. They fail not because the underlying Large Language Models (LLMs) are weak, but because their rigid structures impose a human-centric view of reasoning onto a non-human intelligence. They encode assumptions that are immediately invalidated by the next model breakthrough.&lt;/p&gt;
&lt;p&gt;This document outlines a different philosophy, one derived from first principles and validated by the hard-won lessons of industry pioneers like Anthropic, Manus, and OpenAI [2][3][4]. It is a philosophy of radical simplicity, where we seek not to &lt;em&gt;build&lt;/em&gt; an agent, but to &lt;em&gt;unleash&lt;/em&gt; one.&lt;/p&gt;
&lt;h2 id=&quot;h2-2.20The20First20Principle3A20An20Agent20is20a20Loop-11&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. The First Principle: An Agent is a Loop&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. The First Principle: An Agent is a Loop&lt;/h2&gt;&lt;p&gt;If we strip away all the noise, what is an agent? It is a process that perceives, thinks, and acts, in a cycle, to achieve a goal. In the context of LLMs, this translates to an almost trivial implementation:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;An agent is just a for-loop of messages. The only state an agent should have is: keep going until the model stops calling tools. You don’t need an agent framework. You don’t need anything else. It’s just a for-loop of tool calls. [1]&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;This loop is the universal constant of agentic systems. It is the engine. Everything else is just fuel and scenery.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# The irreducible core of an agent
while True:
    response = llm.invoke(context, tools)
    if not response.tool_calls:
        break
    for tool_call in response.tool_calls:
        result = execute(tool_call)
        context.append(result)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our entire architectural philosophy is built upon the foundation of protecting and empowering this simple loop. We must resist the urge to complicate it.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;max-width:100%;&quot; title=&quot;The architecture of multi-agent systems&quot; alt=&quot;null&quot; src=&quot;https://cxk.me/zb_users/upload/2026/02/202602132213581254020.png&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flowchart TD
    Sandbox --&amp;gt;|provide| Context
    Context --&amp;gt; Agent
    Agent --&amp;gt;|act| Tool
    Tool --&amp;gt;|feedback| Agent
    Agent &amp;lt;--&amp;gt;|handoff by Sandbox| Agent-2
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-3.20The20Three20Pillars20of20Simplicity-43&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. The Three Pillars of Simplicity&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. The Three Pillars of Simplicity&lt;/h2&gt;&lt;p&gt;Our design is guided by three core tenets that emerge from observing what works in practice.&lt;/p&gt;
&lt;h3 id=&quot;h3-Pillar20I3A20The20Sandbox20is20the20World-47&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;Pillar I: The Sandbox is the World&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Pillar I: The Sandbox is the World&lt;/h3&gt;&lt;p&gt;Instead of creating a multitude of objects to represent the agent’s world (&lt;code&gt;Project&lt;/code&gt;, &lt;code&gt;Task&lt;/code&gt;, &lt;code&gt;Memory&lt;/code&gt;, &lt;code&gt;Files&lt;/code&gt;), we unify them into a single, holistic concept: the &lt;strong&gt;Sandbox&lt;/strong&gt;. The Sandbox is an isolated execution environment, typically a virtual machine or container, complete with a file system and the ability to run processes. &lt;/p&gt;
&lt;p&gt;This is the most profound simplification. The Sandbox &lt;em&gt;is&lt;/em&gt; the state. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Memory is the File System&lt;/strong&gt;: An agent’s memory is not an abstract class; it is the collection of files within its sandbox. This provides an unlimited, persistent, and directly operable memory that the agent can structure and manage itself, a technique proven effective by Manus [3]. The agent learns to write notes, create logs, and manage data just as a human would.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Context is the Sandbox’s History&lt;/strong&gt;: The &lt;code&gt;context&lt;/code&gt; passed to the LLM is simply the append-only log of what has happened inside the sandbox—a stream of actions and observations.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Projects and Tasks are Implicit&lt;/strong&gt;: A project is not a database entity; it is a directory in the sandbox. A task is not an object to be managed; it is the initial prompt that kicks off the agent loop.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;By unifying the agent’s world into the sandbox, we eliminate dozens of unnecessary classes and the complex interactions between them. The agent interacts with its world not through abstract methods, but through concrete tools like &lt;code&gt;shell&lt;/code&gt; and &lt;code&gt;file&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;h3-Pillar20II3A20An20Agent20is20a20Configuration2C20Not20a20Class-59&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;Pillar II: An Agent is a Configuration, Not a Class&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Pillar II: An Agent is a Configuration, Not a Class&lt;/h3&gt;&lt;p&gt;Traditional frameworks encourage a deep inheritance model: &lt;code&gt;BaseAgent&lt;/code&gt; gives rise to &lt;code&gt;ConcreteAgent&lt;/code&gt;, which is then subclassed into &lt;code&gt;SoftwareAgent&lt;/code&gt;, &lt;code&gt;ResearchAgent&lt;/code&gt;, and so on. This is a fallacy. It conflates an agent’s &lt;em&gt;identity&lt;/em&gt; and &lt;em&gt;capabilities&lt;/em&gt; with its implementation.&lt;/p&gt;
&lt;p&gt;In our philosophy, an &lt;strong&gt;Agent is merely a configuration&lt;/strong&gt;. It is a plain-text or JSON object that defines two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Instructions&lt;/strong&gt;: The system prompt that tells the LLM its role, personality, and objectives.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Tools&lt;/strong&gt;: A list of capabilities it is allowed to use.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;The &lt;code&gt;AgentRunner&lt;/code&gt;—the engine that executes the core loop—is stateless. On each iteration, it loads the current agent’s configuration, invokes the LLM, and executes the resulting tool calls. An agent is not an &lt;em&gt;object&lt;/em&gt;; it is a &lt;em&gt;mode of operation&lt;/em&gt; for the runner.&lt;/p&gt;
&lt;p&gt;This approach has powerful implications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;: There is no &lt;code&gt;Agent&lt;/code&gt; class to maintain. Adding a new agent is as simple as writing a new configuration file.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: Agents can be composed, modified, and switched dynamically. Multi-agent collaboration becomes trivial: it is simply one agent using a &lt;code&gt;handoff&lt;/code&gt; tool to tell the runner to load a different agent’s configuration on the next loop iteration [4].&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Transparency&lt;/strong&gt;: The agent’s entire&lt;br&gt;definition is explicit and human-readable, making it easy to debug and understand.&lt;/li&gt;&lt;/ul&gt;
&lt;h3 id=&quot;h3-Pillar20III3A20Start20with20Maximum20Capability2C20Then20Restrict-77&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;Pillar III: Start with Maximum Capability, Then Restrict&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Pillar III: Start with Maximum Capability, Then Restrict&lt;/h3&gt;&lt;p&gt;Many frameworks begin by offering a small, “safe” set of tools, forcing the developer to add capabilities one by one. This leads to what has been termed the “incomplete action space” problem [1]. The agent is limited not by the model’s intelligence, but by the developer’s foresight.&lt;/p&gt;
&lt;p&gt;We invert this. We start from the assumption that the agent should be able to do &lt;em&gt;anything&lt;/em&gt; a human can do within the sandbox. We provide powerful, general-purpose tools from the outset: &lt;code&gt;shell&lt;/code&gt;, &lt;code&gt;file&lt;/code&gt;, &lt;code&gt;browser&lt;/code&gt;. The agent has maximal freedom.&lt;/p&gt;
&lt;p&gt;Restrictions are then applied as a layer of safety and guidance, not as a foundational constraint. This is the principle of “Mask, Don’t Remove” articulated by Manus [3]. We don’t take tools away; we temporarily make them unavailable based on the agent’s current state or task, guiding the LLM’s attention without crippling its potential. This ensures the action space remains complete and the KV-cache remains intact, preserving performance and adaptability.&lt;/p&gt;
&lt;h2 id=&quot;h2-4.20Conclusion3A20The20Unbitter20Lesson-85&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. Conclusion: The Unbitter Lesson&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. Conclusion: The Unbitter Lesson&lt;/h2&gt;&lt;p&gt;The bitter lesson of AI research is that general methods that leverage computation ultimately outperform systems based on hand-crafted human knowledge. Agent frameworks are at risk of repeating this mistake by encoding too many assumptions into their design.&lt;/p&gt;
&lt;p&gt;By embracing radical simplicity, we learn the &lt;em&gt;unbitter lesson&lt;/em&gt;: the most powerful agent framework is the one that gets out of the way. It is a minimal, stateless loop engine operating within a unified sandbox. It treats agents as simple configurations and trusts the LLM to be the intelligent, reasoning core.&lt;/p&gt;
&lt;p&gt;This philosophy is not about building less; it is about building &lt;em&gt;right&lt;/em&gt;. It is about creating a foundation that is not brittle but resilient, not complex but elegant, and that scales not in spite of, but &lt;em&gt;because of&lt;/em&gt;, the relentless advance of AI.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;h3-References-95&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;References&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;References&lt;/h3&gt;&lt;p&gt;[1] Zunic, G. (2026, January 16). &lt;em&gt;The Bitter Lesson of Agent Frameworks&lt;/em&gt;. Browser Use Blog. Retrieved from &lt;a href=&quot;https://browser-use.com/posts/bitter-lesson-agent-frameworks&quot;&gt;https://browser-use.com/posts/bitter-lesson-agent-frameworks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[2] Schluntz, E., &amp;amp; Zhang, B. (2024, December 19). &lt;em&gt;Building effective agents&lt;/em&gt;. Anthropic. Retrieved from &lt;a href=&quot;https://www.anthropic.com/research/building-effective-agents&quot;&gt;https://www.anthropic.com/research/building-effective-agents&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[3] Ji, Y. (2025, July 18). &lt;em&gt;Context Engineering for AI Agents: Lessons from Building Manus&lt;/em&gt;. Manus Blog. Retrieved from &lt;a href=&quot;https://manus.im/blog/Context-Engineering-for-AI-Agents-Lessons-from-Building-Manus&quot;&gt;https://manus.im/blog/Context-Engineering-for-AI-Agents-Lessons-from-Building-Manus&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[4] OpenAI. (2024). &lt;em&gt;Orchestrating Agents: Routines and Handoffs&lt;/em&gt;. OpenAI Cookbook. Retrieved from &lt;a href=&quot;https://developers.openai.com/cookbook/examples/orchestrating_agents/&quot;&gt;https://developers.openai.com/cookbook/examples/orchestrating_agents/&lt;/a&gt;&lt;/p&gt;
&lt;/body&gt;</description><pubDate>Sat, 07 Feb 2026 21:22:03 +0800</pubDate></item><item><title>Spring AI Extractor 提取器（结构化输出）</title><link>https://cxk.me/post/102.html</link><description>&lt;p&gt;Spring 官方的叫法是结构化输出，不过我更喜欢沿用 LangChain 的叫法&amp;ldquo;提取器（Extractor）&amp;rdquo;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;官方文档（Structured Output Converter）&lt;/p&gt;
&lt;p&gt;&lt;span spellcheck=&quot;false&quot;&gt;&lt;a href=&quot;https://docs.spring.io/spring-ai/reference/1.0/api/structured-output-converter.html&quot;&gt;https://docs.spring.io/spring-ai/reference/1.0/api/structured-output-converter.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;language-java&quot;&gt;&lt;code&gt;package net.heimeng.web.test;
​
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.heimeng.common.ai.extractor.ExtractorUtils;
import net.heimeng.web.Agent4jWebApplication;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.ParameterizedTypeReference;
​
import java.util.List;
​
@Slf4j
@SpringBootTest(classes = Agent4jWebApplication.class)
@DisplayName(&quot;AI 单元测试&quot;)
public class AiUnitTest {
​
    @Autowired
    private ChatModel model;
​
    @DisplayName(&quot;AI 配置项测试&quot;)
    @Test
    void propertiesTest() {
        // Given
        ChatClient client = ChatClient.builder(model).build();
​
        // Ensure the client is able to use
        log.debug(client.prompt().user(&quot;你好&quot;).call().content());
​
        // Result: 你好👋！我是人工智能助手智谱清言，可以叫我小智🤖，很高兴见到你，欢迎问我任何问题。
    }
​
    @DisplayName(&quot;Extractor 提取器测试&quot;)
    @Test
    void extractorTest() {
        // Given
        String textAboutPersons = &quot;蔡徐坤（KUN），1998年8月2日出生于浙江省温州市，&quot; +
                &quot;户籍湖南省吉首市，中国内地男歌手、演员、原创音乐制作人、MV导演。&quot; +
                &quot;朱明春的长子朱立科浙农大毕业三年后，针对温州风俗&amp;mdash;&amp;mdash;家逢喜事分红蛋的习惯，研发出了一鸣利市红蛋，&quot; +
                &quot;深受广大市民的喜爱，成为温州市民办喜事的必需品。之后，朱立科倡导的新型奶吧，&quot; +
                &quot;改变了部分温州人糯米饭加紫菜汤的早餐习惯。该模式一经推出大受温州人欢迎。&quot; +
                &quot;2002年在市区横渎开出第一家一鸣真鲜奶吧直营店，如今，一鸣真鲜奶吧直营店、加盟连锁店在温州地区已发展至近400家。&quot;;
​
        String textAboutActors = &quot;Generate the filmography of 5 movies for Tom Hanks and Bill Murray.&quot;;
​
        List&amp;lt;Person&amp;gt; persons = ExtractorUtils.extract(textAboutPersons, new ParameterizedTypeReference&amp;lt;&amp;gt;() {});
        log.debug(String.valueOf(persons));
        Assertions.assertNotNull(persons);
​
        Person person = ExtractorUtils.extract(textAboutPersons, Person.class);
        log.debug(person.toString());
        Assertions.assertNotNull(person);
​
        record ActorFilms(String actor, List&amp;lt;String&amp;gt; movies) {}
        List&amp;lt;ActorFilms&amp;gt; actorFilms = ExtractorUtils.extract(textAboutActors, new ParameterizedTypeReference&amp;lt;&amp;gt;() {});
        log.debug(actorFilms.toString());
        Assertions.assertNotNull(actorFilms);
    }
​
    @Data
    private static class Person {
        // 私有属性
        private String name;
        private int age;
        private String address;
        private List&amp;lt;String&amp;gt; occupations;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-java&quot;&gt;&lt;code&gt;package net.heimeng.common.ai.extractor;
​
import net.heimeng.common.ai.model.WithDescription;
import net.heimeng.common.core.util.SpringUtils;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.core.ParameterizedTypeReference;
​
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
​
/**
 * 提取器工具类
 *
 * @author InwardFlow
 */
public class ExtractorUtils {
​
    private static final ChatClient CLIENT = SpringUtils.getBean(ChatClient.class);
    public static &amp;lt;T extends WithDescription&amp;gt; T extractWithDescription(String text, Class&amp;lt;T&amp;gt; clazz) {
        try {
            T instance = clazz.getDeclaredConstructor().newInstance();
            return CLIENT.prompt()
                    .user(u -&amp;gt; u.text(&quot;&quot;&quot;
                                    Extract information from:
                                     {text}
                                     ---
                                     Here is the description:
                                     {description}
                                &quot;&quot;&quot;)
                            .params(Map.of(&quot;text&quot;, text, &quot;description&quot;, instance.getDescription())))
                    .call()
                    .entity(new ParameterizedTypeReference&amp;lt;&amp;gt;() {});
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(&quot;Unable to create an instance of &quot; + clazz.getName(), e);
        }
    }
​
    public static &amp;lt;T&amp;gt; T extract(String text, Class&amp;lt;T&amp;gt; clazz) {
        String className = clazz.getSimpleName();
        return CLIENT.prompt()
                .user(u -&amp;gt; u.text(&quot;&quot;&quot;
                                    Extract information about {className} from {text}
                                &quot;&quot;&quot;)
                        .params(Map.of(&quot;className&quot;, className, &quot;text&quot;, text)))
                .call()
                .entity(clazz);
    }
​
    public static &amp;lt;T&amp;gt; T extract(String text, ParameterizedTypeReference&amp;lt;T&amp;gt; typeReference) {
        return CLIENT.prompt()
                .user(u -&amp;gt; u.text(&quot;Extract information from: &quot; + text))
                .call()
                .entity(typeReference);
    }
​
}&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Fri, 16 May 2025 13:52:23 +0800</pubDate></item><item><title>Ubuntu 安装 Genius 数学工具</title><link>https://cxk.me/post/101.html</link><description>&lt;p&gt;&lt;a href=&quot;https://www.jirka.org/genius.html&quot;&gt;https://www.jirka.org/genius.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Genius 是一个通用目的的计算器程序。它既可以用作简单的计算器，也可以用作研究或教育工具。语法非常直观，旨在模仿通常的数学书写方式。&lt;/p&gt;
&lt;p&gt;GEL 是它的扩展语言名称，它代表 &lt;em&gt;Genius 扩展语言&lt;/em&gt;，真聪明，不是吗？事实上，许多标准的 genius 函数本身就是用 GEL 编写的。&lt;/p&gt;
&lt;p&gt;使用 cat /etc/issue 可以查看版本号&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cxk.me/zb_users/upload/2025/04/20250425085414174554245435958.png&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;1.&amp;nbsp;&lt;strong&gt;确保系统已启用&amp;nbsp;&lt;code&gt;universe&lt;/code&gt;&amp;nbsp;仓库&lt;/strong&gt;&lt;/h3&gt;
&lt;div&gt;Ubuntu 22.04+ 后，&lt;code&gt;universe&lt;/code&gt;&amp;nbsp;仓库默认已启用。若确认未启用（或旧版本升级后），执行：&lt;/div&gt;
&lt;div&gt;
&lt;div dir=&quot;ltr&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;apt update  # 刷新软件源
apt install genius -y&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div dir=&quot;ltr&quot;&gt;
&lt;h3&gt;2. 旧版本看这里&lt;/h3&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;# apt update &amp;amp;&amp;amp; sudo apt install software-properties-common
add-apt-repository universe
apt update
apt install genius&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><pubDate>Fri, 25 Apr 2025 08:49:59 +0800</pubDate></item><item><title>维吉尼亚 Vigenère 密码</title><link>https://cxk.me/post/100.html</link><description>&lt;p&gt;工作原理&lt;/p&gt;
&lt;p&gt;本质上，Vigen&amp;egrave;re 密码是几个凯撒密码，其移位值取决于密钥。它可以通过使用Vigen&amp;egrave;re 表格简单地手动计算。在代码中，可以使用模算术来实现。&lt;/p&gt;
&lt;p&gt;编码&lt;br /&gt;编码时，我们首先将每个字母转换为0到25之间的数字，其中A是0，Z是25。如果密钥比消息短，就将其重复直到它们长度相同，例如，如果消息是cryptography，密钥是secretkey：&lt;/p&gt;
&lt;p&gt;msg = cryptography&lt;br /&gt;key = secretkeysec&lt;br /&gt;输出O的第i个字符可以使用以下公式从消息M和密钥K计算得出：&lt;/p&gt;
&lt;p&gt;O[i] = (M[i] + K[i]) mod 26&lt;br /&gt;解码&lt;br /&gt;将输出O解码为消息M，已知密钥K，同样简单：&lt;/p&gt;
&lt;p&gt;M[i] = (O[i] - K[i]) mod 26&lt;/p&gt;</description><pubDate>Thu, 24 Apr 2025 18:44:12 +0800</pubDate></item><item><title>准确率、精确率、召回率</title><link>https://cxk.me/post/99.html</link><description>&lt;p&gt;准确率是指分类正确的样本数占总样本数的比例。&lt;/p&gt;
&lt;p&gt;精确率是针对预测结果而言的，表示预测为正例的样本中有多少是真正的正例。&lt;/p&gt;
&lt;p&gt;召回率是针对原来的样本而言的，表示样本中的正例有多少被预测正确了。&lt;/p&gt;</description><pubDate>Thu, 17 Apr 2025 10:23:57 +0800</pubDate></item></channel></rss>