1067 字
约 3 分钟
22
对话智能体MVP
无标签

对话智能体 MVP:一切从一个方法开始

系列:ToyAgent 智能体知识库 01/26

一句话核心:剥掉所有概念外衣,智能体的最小实现就是"把用户的话交给模型,把模型的话还给用户"——十几行代码的事。

为什么需要

网上对 Agent 的定义五花八门:自主性、规划能力、工具使用……这些描述容易让人以为智能体是什么神秘架构。工程上的起点其实极其朴素:先有一条能连通模型的通路,后面所有能力都在这条通路上叠加。从最小骨架出发的好处是——你对每一层新增能力都有清晰的 diff 视角,不会被"大而全"的框架黑盒迷惑。

核心机制

两个接口,一个实现:

// 模型抽象:智能体的"大脑",屏蔽"模型是谁"
public interface ChatModel {
    String chat(List<Message> messages);
}

public interface ChatAgent extends Agent {
    class Impl implements ChatAgent {
        private final ChatModel model;
        public Impl(ChatModel model) { this.model = model; }

        @Override
        public String chat(String input) {
            // 全部实现就这一行核心逻辑
            return model.chat(List.of(Message.user(input)));
        }
    }
}

关键在抽象分层:ChatAgent 依赖的是 ChatModel 接口,而不是某个具体厂商 SDK。它背后可能是 OpenAI 兼容端点,也可能是本地 Mock——策略代码一行不改。这正是 LangChain4j、Spring AI 都把 ChatModel 作为顶层抽象的原因。

sequenceDiagram
    participant U as 用户
    participant A as ChatAgent
    participant M as ChatModel
    participant P as 模型端点
    U->>A: chat 输入一句话
    A->>M: chat messages 列表
    M->>P: HTTP POST chat/completions
    P-->>M: 返回 choices 内容
    M-->>A: 返回字符串
    A-->>U: 返回响应

图示:对话 MVP 的完整调用链——智能体只做一次转发,模型抽象屏蔽了具体端点是谁。

模型调用到底发生了什么

"调用大模型"没有魔法,就是一次 HTTP POST:

POST {base-url}/chat/completions
{
  "model": "deepseek-chat",
  "messages": [{"role": "user", "content": "你好"}]
}
// 响应取 choices[0].message.content

理解这一点很重要:所谓 OpenAI 兼容协议,就是约定了这个请求/响应的 JSON 形状。DeepSeek、Qwen、vLLM、Ollama 都实现了同样的形状,所以换模型 = 换 base-url + model 名。

举例:为什么这是"最小"——三个"无"

用三个缺失项反推 MVP 的边界,也预埋了后续场景的方向:

用户:北京今天天气怎么样?
模型(MVP):抱歉,我无法获取实时天气。              ← 无工具:只能用参数里的知识瞎猜/拒答
用户:再问一遍,我叫什么名字?                        (之前说过"我叫小傅哥")
模型(MVP):您没有告诉过我您的名字。                  ← 无状态:每轮独立,上一轮不在本次上下文里
用户:帮我随便写点东西。                              ← 无策略:输入原样转发,没有预处理
模型(MVP):好的,我来为您写一段……(风格完全随机)

对照生产视角的同一场景(LangChain4j 风格):

// 依赖注入接口而非实现,测试时可换 MockChatModel
@ApplicationScoped
public class EchoAgent {
    private final ChatLanguageModel model;   // LangChain4j 的同名抽象

    public String chat(String input) {
        return model.generate(UserMessage.from(input)).contents().toString();
    }
}

面试考点

  • "Agent 和 Chatbot 的区别是什么?"——最小 MVP 阶段两者没有区别。区别来自后续能力:Chatbot 停在对话,Agent 在对话之上叠加了工具、记忆、循环与目标导向。
  • "为什么自己包一层 ChatModel 抽象?"——换模型供应商零成本、可插 Mock 做测试、可统一记录调用日志与 Token 计量。

生产化路径

  • 接口先行:业务代码永远依赖你自己的 ChatModel 接口(或 LangChain4j 的 ChatLanguageModel),厂商 SDK 只出现在装配层。
  • 最小骨架也要有横切关注点:这一层虽然只有一行核心逻辑,但生产上应在此处统一埋点——请求耗时、Token 用量、模型名,为后续成本治理打地基。
  • 记住三个"无"作为需求检查单:评审任何智能体需求时,先确认它需不需要工具、记忆、策略,需要哪几个再决定引入哪些后续场景。
对话智能体MVP
https://clxhxhhr.top/posts/4701/
作者
clxstart
发布于
2026-10-13
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。