一、ChatModel 基础使用 🤖
1.1 什么是 ChatModel 🤔
ChatModel 是 Eino 框架中封装的 大模型对话核心组件,专门用于处理与大语言模型(LLM)的交互逻辑。它就像一个 “智能对话翻译官”,帮你屏蔽不同大模型(如 OpenAI、Anthropic、本地化模型等)的底层差异,提供统一、简洁的 API 来实现对话生成、流式输出、多轮上下文管理等功能。
简单说:有了 ChatModel,你不用关心不同厂商的接口格式差异,专注写业务逻辑就行啦~ ✨
1.2 ChatModel 的核心能力 🚀
Eino 的 ChatModel 内置了三大核心能力,覆盖绝大多数对话场景:
统一接口适配 🧩:一套代码兼容主流大模型,切换模型无需修改业务逻辑
灵活输出模式 ⚡:支持一次性完整输出 + 流式增量输出(打字机效果)
配置化调参 🔧:通过简单配置调整温度(temperature)、最大 tokens 等模型参数
二、基础案例:Generate 生成 📝
在开始案例前,确保你已经:
安装 Eino 框架:
go get github.com/eino-lang/eino配置大模型密钥(如 OpenAI API Key):可通过环境变量或配置文件设置
2.1 单轮对话 💬
单轮对话是最简单的场景:用户发送一个问题,模型返回一个回答,无需维护历史上下文。
package main
import (
"context"
"log"
"os"
"github.com/cloudwego/eino-ext/components/model/openai"
"github.com/cloudwego/eino/schema"
)
const DOUBAO_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
const DOUBAO_MODEL_NAME = "doubao-seed-1-6-flash-250828"
func main() {
ctx := context.Background()
key := os.Getenv("DOUBAO_API_KEY")
if key == "" {
log.Fatal("DOUBAO_API_KEY environment variable is required")
}
chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
BaseURL: DOUBAO_BASE_URL,
Model: DOUBAO_MODEL_NAME,
APIKey: key,
})
if err != nil {
log.Fatalf("创建OpenAI聊天模型失败: %v", err)
}
message := []*schema.Message{
schema.SystemMessage("你是一个专业的助手总是能够简练的总结知识点"),
schema.UserMessage("请介绍一下Go语言的特点"),
}
//调用大模型并生成响应
response, err := chatModel.Generate(ctx, message)
if err != nil {
panic(err)
}
println("model: ", response.Content)
}
2.2 多轮对话 🔄
多轮对话需要维护历史上下文,让模型能 “记住” 之前的对话内容。下面用 scan 实现交互式多轮对话,支持用户连续输入。
package main
import (
"bufio"
"context"
"log"
"os"
"github.com/cloudwego/eino-ext/components/model/openai"
"github.com/cloudwego/eino/schema"
)
const DOUBAO_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
const DOUBAO_MODEL_NAME = "doubao-seed-1-6-flash-250828"
func main() {
ctx := context.Background()
// 读取API密钥
key := os.Getenv("DOUBAO_API_KEY")
if key == "" {
log.Fatal("DOUBAO_API_KEY environment variable is required")
}
// 创建聊天模型
chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
BaseURL: DOUBAO_BASE_URL,
Model: DOUBAO_MODEL_NAME,
APIKey: key,
})
if err != nil {
log.Fatalf("创建OpenAI聊天模型失败: %v", err)
}
// 初始化聊天历史,包含系统提示(只添加一次)
chatHistory := []*schema.Message{
schema.SystemMessage("你是一个专业的助手,总是能够简练的总结知识点,回答简洁明了"),
}
// 创建Scanner读取用户输入
scanner := bufio.NewScanner(os.Stdin)
log.Println("多轮对话已启动,输入 'exit' 退出程序")
log.Println("请输入你的问题:")
// 循环处理多轮对话
for {
// 读取用户输入
print("用户:")
if !scanner.Scan() {
break // 输入结束(如Ctrl+D)
}
userInput := scanner.Text()
// 处理退出命令
if userInput == "exit" || userInput == "quit" {
log.Println("对话结束,再见!")
break
}
// 忽略空输入
if userInput == "" {
log.Println("请输入有效的问题内容")
continue
}
// 将用户输入添加到聊天历史
chatHistory = append(chatHistory, schema.UserMessage(userInput))
// 调用大模型生成响应
log.Println("正在思考...")
response, err := chatModel.Generate(ctx, chatHistory)
if err != nil {
log.Printf("调用大模型失败:%v", err)
// 移除本次失败的用户输入,避免影响后续对话
chatHistory = chatHistory[:len(chatHistory)-1]
continue
}
// 将模型响应添加到聊天历史(保持上下文)
chatHistory = append(chatHistory, schema.AssistantMessage(response.Content, nil))
// 输出结果
println("助手:", response.Content)
println("------------------------------")
}
// 检查Scanner错误
if err := scanner.Err(); err != nil {
log.Printf("读取用户输入失败:%v", err)
}
}
2.3 流式输出 ⚡
流式输出是指模型边生成边返回结果,模拟 “打字机” 效果,提升用户体验(尤其适合长文本生成)。
package main
import (
"bufio"
"context"
"log"
"os"
"github.com/cloudwego/eino-ext/components/model/openai"
"github.com/cloudwego/eino/schema"
)
const DOUBAO_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
const DOUBAO_MODEL_NAME = "doubao-seed-1-6-flash-250828"
func main() {
ctx := context.Background()
// 读取API密钥
key := os.Getenv("DOUBAO_API_KEY")
if key == "" {
log.Fatal("DOUBAO_API_KEY environment variable is required")
}
// 创建聊天模型
chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
BaseURL: DOUBAO_BASE_URL,
Model: DOUBAO_MODEL_NAME,
APIKey: key,
})
if err != nil {
log.Fatalf("创建OpenAI聊天模型失败: %v", err)
}
// 初始化聊天历史,包含系统提示(只添加一次)
chatHistory := []*schema.Message{
schema.SystemMessage("你是一个专业的助手,总是能够简练的总结知识点,回答简洁明了"),
}
// 创建Scanner读取用户输入
scanner := bufio.NewScanner(os.Stdin)
log.Println("多轮对话已启动,输入 'exit' 退出程序")
log.Println("请输入你的问题:")
// 循环处理多轮对话
for {
// 读取用户输入
print("用户:")
if !scanner.Scan() {
break // 输入结束(如Ctrl+D)
}
userInput := scanner.Text()
// 处理退出命令
if userInput == "exit" || userInput == "quit" {
log.Println("对话结束,再见!")
break
}
// 忽略空输入
if userInput == "" {
log.Println("请输入有效的问题内容")
continue
}
// 将用户输入添加到聊天历史
chatHistory = append(chatHistory, schema.UserMessage(userInput))
// 调用大模型生成响应
log.Println("正在思考...")
stream, err := chatModel.Stream(ctx, chatHistory)
if err != nil {
log.Printf("调用大模型失败:%v", err)
// 移除本次失败的用户输入,避免影响后续对话
chatHistory = chatHistory[:len(chatHistory)-1]
continue
}
defer stream.Close()
// 收集流式响应的完整内容
var fullResponse string
for {
chunk, err := stream.Recv()
if err != nil {
// EOF 是正常的流结束标志,不是错误
if err.Error() != "EOF" {
log.Printf("流式请求失败:%v", err)
}
break
}
print(chunk.Content)
fullResponse += chunk.Content
}
// 将模型响应添加到聊天历史(保持上下文)
chatHistory = append(chatHistory, schema.AssistantMessage(fullResponse, nil))
// 输出结果
println()
println("------------------------------")
}
// 检查Scanner错误
if err := scanner.Err(); err != nil {
log.Printf("读取用户输入失败:%v", err)
}
}