You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
7.9 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: "第一章ChatModel 与 MessageConsole"
---
## Eino 框架简介
**Eino 是什么?**
Eino 是一个 Go 语言实现的 AI 应用开发框架Agent Development Kit旨在帮助开发者快速构建可扩展、可维护的 AI 应用。
**Eino 解决什么问题?**
1. **模型抽象**:统一不同 LLM 提供商的接口OpenAI、Ark、Claude 等),切换模型无需修改业务代码
2. **能力组合**:通过 Component 接口实现可替换、可组合的能力单元(对话、工具、检索等)
3. **编排框架**:提供 Agent、Graph、Chain 等编排抽象,支持复杂的多步骤 AI 工作流
4. **运行时支持**内置流式输出、中断与恢复、状态管理、Callback 可观测性等能力
**Eino 的主要仓库:**
- **eino**(本仓库):核心库,定义接口、编排抽象和 ADK
- **eino-ext**:扩展库,提供各类 Component 的具体实现OpenAI、Ark、Milvus 等)
- **eino-examples**:示例代码库,包含本 quickstart 系列
---
## ChatWithEino与 Eino 文档对话的智能助手
**ChatWithEino 是什么?**
ChatWithEino 是一个基于 Eino 框架构建的智能助手,能够帮助开发者学习 Eino 框架并编写 Eino 代码。它通过访问 Eino 仓库的源码、注释和示例,为用户提供最准确、最及时的技术支持。
**核心能力:**
- **对话交互**:理解用户关于 Eino 的问题,提供清晰的解答
- **代码访问**:直接读取 Eino 源码、注释和示例,基于真实实现回答问题
- **持久化会话**:支持多轮对话,记住上下文,可跨进程恢复会话
- **工具调用**:能够执行文件读取、代码搜索等操作
**技术架构:**
- **ChatModel**与大语言模型通信OpenAI、Ark、Claude 等)
- **Tool**:文件系统访问、代码搜索等能力扩展
- **Memory**:对话历史持久化存储
- **Agent**:统一的执行框架,协调各组件协同工作
## Quickstart 文档系列:从零构建 ChatWithEino
本系列文档通过循序渐进的方式,带你从最基础的 ChatModel 调用开始,逐步构建一个功能完整的 ChatWithEino Agent。
**学习路径:**
| 章节 | 主题 | 核心内容 | 能力提升 |
|------|------|----------|----------|
| **第一章** | ChatModel 与 Message | 理解 Component 抽象,实现单次对话 | 基础对话能力 |
| **第二章** | Agent 与 Runner | 引入执行抽象,实现多轮对话 | 会话管理能力 |
| **第三章** | Memory 与 Session | 持久化对话历史,支持会话恢复 | 持久化能力 |
| **第四章** | Tool 与文件系统 | 添加文件访问能力,读取源码 | 工具调用能力 |
| **第五章** | Middleware | 中间件机制,统一处理横切关注点 | 扩展性增强 |
| **第六章** | Callback | 回调机制,监控 Agent 执行过程 | 可观测性 |
| **第七章** | Interrupt 与 Resume | 中断与恢复,支持长时间任务 | 可靠性增强 |
| **第八章** | Graph 与 Tool | 使用 Graph 编排复杂工作流 | 复杂编排能力 |
| **第九章** | A2UI | Agent 到 UI 的集成方案 | 生产级应用 |
**为什么这样设计?**
每一章都在前一章的基础上增加一个核心能力,让你:
1. **理解每个组件的作用**:不是一次性展示所有功能,而是逐步引入
2. **看到架构演进过程**:从简单到复杂,理解为什么需要每个抽象
3. **掌握实际开发技能**:每章都有可运行的代码,可以动手实践
---
本章目标:理解 Eino 的 Component 抽象,用最小代码调用一次 ChatModel支持流式输出并掌握 `schema.Message` 的基本用法。
## 代码位置
- 入口代码:[cmd/ch01/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch01/main.go)
## 为什么需要 Component 接口
Eino 定义了一组 Component 接口(`ChatModel`、`Tool`、`Retriever`、`Loader` 等),每个接口描述一类可替换的能力:
```go
type BaseChatModel interface {
Generate(ctx context.Context, input []*schema.Message, opts ...Option) (*schema.Message, error)
Stream(ctx context.Context, input []*schema.Message, opts ...Option) (
*schema.StreamReader[*schema.Message], error)
}
```
**接口带来的好处:**
1. **实现可替换**`eino-ext` 提供了 OpenAI、Ark、Claude、Ollama 等多种实现,业务代码只依赖接口,切换模型只需改构造逻辑。
2. **编排可组合**Agent、Graph、Chain 等编排层只依赖 Component 接口,不关心具体实现。你可以把 OpenAI 换成 Ark编排代码无需改动。
3. **测试可 Mock**:接口天然支持 mock单元测试不需要真实调用模型。
本章只涉及 `ChatModel`,后续章节会逐步引入 `Tool`、`Retriever` 等 Component。
## schema.Message对话的基本单位
`Message` 是 Eino 里对话数据的基本结构:
```go
type Message struct {
Role RoleType // system / user / assistant / tool
Content string // 文本内容
ToolCalls []ToolCall // 仅 assistant 消息可能有
// ...
}
```
常用构造函数:
```go
schema.SystemMessage("You are a helpful assistant.")
schema.UserMessage("What is the weather today?")
schema.AssistantMessage("I don't know.", nil) // 第二个参数是 ToolCalls
schema.ToolMessage("tool result", "call_id")
```
**角色语义:**
- `system`:系统指令,通常放在 messages 最前面
- `user`:用户输入
- `assistant`:模型回复
- `tool`:工具调用结果(后续章节涉及)
## 前置条件
### 获取代码
```bash
git clone https://github.com/cloudwego/eino-examples.git
cd eino-examples/quickstart/chatwitheino
```
- Go 版本Go 1.21+(见 `go.mod`
- 一个可调用的 ChatModel默认使用 OpenAI也支持 Ark
### 方式 AOpenAI默认
```bash
export OPENAI_API_KEY="..."
export OPENAI_MODEL="gpt-4.1-mini" # OpenAI 2025 年新模型,也可用 gpt-4o、gpt-4o-mini 等
# 可选:
# OPENAI_BASE_URL代理或兼容服务
# OPENAI_BY_AZURE=true使用 Azure OpenAI
```
### 方式 BArk
```bash
export MODEL_TYPE="ark"
export ARK_API_KEY="..."
export ARK_MODEL="..."
# 可选ARK_BASE_URL
```
## 运行
`examples/quickstart/chatwitheino` 目录下执行:
```bash
go run ./cmd/ch01 -- "用一句话解释 Eino 的 Component 设计解决了什么问题?"
```
输出示例(流式逐步打印):
```text
[assistant] Eino 的 Component 设计通过定义统一接口...
```
## 入口代码做了什么
按执行顺序:
1. **创建 ChatModel**:根据 `MODEL_TYPE` 环境变量选择 OpenAI 或 Ark 实现
2. **构造输入 messages**`SystemMessage(instruction)` + `UserMessage(query)`
3. **调用 Stream**:所有 ChatModel 实现都必须支持 `Stream()`,返回 `StreamReader[*Message]`
4. **打印结果**:迭代 `StreamReader` 逐帧打印 assistant 回复
关键代码片段(**注意:这是简化后的代码片段,不能直接运行,完整代码请参考** [cmd/ch01/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch01/main.go)
```go
// 构造输入
messages := []*schema.Message{
schema.SystemMessage(instruction),
schema.UserMessage(query),
}
// 调用 Stream所有 ChatModel 都必须实现)
stream, err := cm.Stream(ctx, messages)
if err != nil {
log.Fatal(err)
}
defer stream.Close()
for {
chunk, err := stream.Recv()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Print(chunk.Content)
}
```
## 本章小结
- **Component 接口**:定义可替换、可组合、可测试的能力边界
- **Message**:对话数据的基本单位,通过角色区分语义
- **ChatModel**:最基础的 Component提供 `Generate``Stream` 两个核心方法
- **实现选择**:通过环境变量或配置切换 OpenAI/Ark 等不同实现,业务代码无需改动