Eino ChatModel 组件指南摘要
🤖 Eino ChatModel 组件完全指南
📖 基本介绍
ChatModel
组件是一个用于与大语言模型交互的核心组件。它的主要作用是将用户的输入消息发送给语言模型,并获取模型的响应。这个组件在 AI 应用开发中扮演着**“大脑”**的角色。
🎯 核心价值
在传统的应用开发中,我们只能处理结构化数据和预定义逻辑。而 ChatModel 组件让我们能够:
传统应用:固定逻辑 + 结构化数据 ❌
AI 应用:智能推理 + 自然语言理解 ✅
🚀 主要应用场景
- 💬 自然语言对话: 构建智能聊天机器人和对话系统
- 📝 文本生成和补全: 自动生成文章、代码、创意内容等
- 🛠️ 工具调用的参数生成: 智能分析用户需求并调用相应工具
- 🎭 多模态交互: 处理文本、图片、音频等多种输入形式
- 🤖 智能Agent系统: 作为Agent的推理引擎,驱动复杂决策
- 📊 内容分析和理解: 文本分类、情感分析、信息提取等
🔧 核心接口
ChatModel
组件提供了简洁而强大的接口设计:
基础接口
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)
}
工具调用接口
type ToolCallingChatModel interface {BaseChatModel// WithTools 返回绑定了指定工具的新实例// 此方法不会修改当前实例,使并发使用更安全WithTools(tools []*schema.ToolInfo) (ToolCallingChatModel, error)
}
接口详解
📤 Generate 方法
- 功能: 生成完整的模型响应
- 输入:
ctx
: 上下文对象,用于传递请求级别信息和 Callback Managerinput
: 输入消息列表 ([]*schema.Message
)opts
: 可选参数,用于配置模型行为
- 输出:
*schema.Message
: 模型生成的响应消息error
: 生成过程中的错误信息
🌊 Stream 方法
- 功能: 以流式方式生成模型响应
- 参数: 与 Generate 方法相同
- 输出:
*schema.StreamReader[*schema.Message]
: 模型响应的流式读取器error
: 生成过程中的错误信息
🛠️ WithTools 方法
- 功能: 为模型绑定可用的工具
- 输入:
tools
- 工具信息列表 - 输出:
ToolCallingChatModel
: 绑定了工具后的新实例error
: 绑定过程中的错误信息
📨 Message 结构体
Message
是模型交互的基本数据结构,支持丰富的消息类型:
type Message struct {// Role 表示消息的角色(system/user/assistant/tool)Role RoleType// Content 是消息的文本内容Content string// MultiContent 是多模态内容,支持文本、图片、音频等MultiContent []ChatMessagePart// Name 是消息的发送者名称Name string// ToolCalls 是 assistant 消息中的工具调用信息ToolCalls []ToolCall// ToolCallID 是 tool 消息的工具调用 IDToolCallID string// ResponseMeta 包含响应的元信息ResponseMeta *ResponseMeta// Extra 用于存储额外信息Extra map[string]any
}
🎭 消息角色类型
- 🔧 system: 系统消息,用于设定AI的行为和角色
- 👤 user: 用户消息,来自用户的输入
- 🤖 assistant: AI助手消息,模型的回复
- 🛠️ tool: 工具消息,工具执行的结果
🎨 多模态支持
Message
结构体支持多种内容类型:
- 📝 文本内容: 通过
Content
字段 - 🖼️ 图片内容: 通过
MultiContent
支持图像输入 - 🎵 音频内容: 支持音频文件处理
- 📹 视频内容: 支持视频文件分析
- 📎 文件内容: 支持各种文档格式
⚙️ 配置选项 (Options)
ChatModel
组件提供了丰富的配置选项来控制模型行为:
通用选项
type Options struct {// Temperature 控制输出的随机性 (0.0-2.0)Temperature *float32// MaxTokens 控制生成的最大 token 数量MaxTokens *int// Model 指定使用的模型名称Model *string// TopP 控制输出的多样性 (0.0-1.0)TopP *float32// Stop 指定停止生成的条件Stop []string
}
选项设置方法
// 设置温度 - 控制创造性
model.WithTemperature(0.7) // 0.0=确定性, 1.0=平衡, 2.0=高创造性// 设置最大 token 数 - 控制响应长度
model.WithMaxTokens(2000)// 设置模型名称 - 选择特定模型
model.WithModel("gpt-4")// 设置 top_p 值 - 控制词汇选择范围
model.WithTopP(0.9)// 设置停止词 - 定义生成结束条件
model.WithStop([]string{"\n\n", "结束"})
参数调优指南
参数 | 推荐值 | 适用场景 |
---|---|---|
Temperature | 0.1-0.3 | 事实性回答、代码生成 |
Temperature | 0.7-0.9 | 创意写作、头脑风暴 |
MaxTokens | 500-1000 | 简短回答 |
MaxTokens | 2000-4000 | 详细分析、长文生成 |
TopP | 0.9-0.95 | 平衡质量和多样性 |
🛠️ 使用方式
1. 单独使用
这是最直接的使用方式,适合简单的对话和文本生成场景:
import ("context""fmt""io""github.com/cloudwego/eino-ext/components/model/ark""github.com/cloudwego/eino/components/model""github.com/cloudwego/eino/schema"
)func basicChatModelExample() {ctx := context.Background()// 1. 初始化模型 (以ARK为例)cm, err := ark.NewChatModel(ctx, &ark.ChatModelConfig{APIKey: "YOUR_API_KEY",Model: "doubao-pro-4k",Timeout: 30 * time.Second,})if err != nil {log.Fatal("初始化模型失败:", err)}// 2. 准备输入消息messages := []*schema.Message{{Role: schema.System,Content: "你是一个有帮助的AI助手,请用简洁明了的方式回答问题。",},{Role: schema.User,Content: "请解释什么是机器学习?",},}// 3. 生成响应response, err := cm.Generate(ctx, messages, model.WithTemperature(0.7),model.WithMaxTokens(1000),)if err != nil {log.Fatal("生成响应失败:", err)}// 4. 处理响应fmt.Printf("AI回复: %s\n", response.Content)// 5. 流式生成示例fmt.Println("\n=== 流式生成 ===")streamResult, err := cm.Stream(ctx, messages)if err != nil {log.Fatal("流式生成失败:", err)}defer streamResult.Close()for {chunk, err := streamResult.Recv()if err == io.EOF {break}if err != nil {log.Printf("接收流式数据出错: %v", err)break}// 实时输出响应片段fmt.Print(chunk.Content)}fmt.Println()
}
2. 在编排中使用 (推荐)
与其他 Eino 组件结合使用,构建复杂的 AI 工作流:
import ("github.com/cloudwego/eino/schema""github.com/cloudwego/eino/compose"
)func orchestrationExample() {ctx := context.Background()// 1. 初始化 ChatModelcm, err := ark.NewChatModel(ctx, &ark.ChatModelConfig{APIKey: "YOUR_API_KEY",Model: "doubao-pro-4k",})if err != nil {log.Fatal("初始化模型失败:", err)}// 2. 在 Chain 中使用chain := compose.NewChain[[]*schema.Message, *schema.Message]()chain.AppendChatModel(cm)// 编译并运行runnable, err := chain.Compile(ctx)if err != nil {log.Fatal("编译链失败:", err)}messages := []*schema.Message{{Role: schema.User, Content: "你好!"},}result, err := runnable.Invoke(ctx, messages)if err != nil {log.Fatal("执行链失败:", err)}fmt.Printf("链式处理结果: %s\n", result.Content)// 3. 在 Graph 中使用graph := compose.NewGraph[[]*schema.Message, *schema.Message]()graph.AddChatModelNode("chat_model", cm)// 设置图的流程graph.AddEdge(compose.START, "chat_model")graph.AddEdge("chat_model", compose.END)graphRunnable, err := graph.Compile(ctx)if err != nil {log.Fatal("编译图失败:", err)}graphResult, err := graphRunnable.Invoke(ctx, messages)if err != nil {log.Fatal("执行图失败:", err)}fmt.Printf("图式处理结果: %s\n", graphResult.Content)
}
3. 工具调用集成
展示如何将 ChatModel 与工具系统集成:
func toolCallingExample() {ctx := context.Background()// 1. 创建工具tools := []tool.InvokableTool{// 假设已经实现了计算器工具NewCalculatorTool(),NewWeatherTool(),}// 2. 初始化支持工具调用的模型cm, err := ark.NewChatModel(ctx, &ark.ChatModelConfig{APIKey: "YOUR_API_KEY",Model: "doubao-pro-4k",})if err != nil {log.Fatal("初始化模型失败:", err)}// 3. 绑定工具到模型toolInfos := make([]*schema.ToolInfo, 0, len(tools))for _, tool := range tools {info, err := tool.Info(ctx)if err != nil {log.Printf("获取工具信息失败: %v", err)continue}toolInfos = append(toolInfos, info)}// 使用 BindTools 方法绑定工具cm.BindTools(toolInfos)// 4. 发送需要工具调用的消息messages := []*schema.Message{{Role: schema.System,Content: "你是一个智能助手,可以使用工具来帮助用户解决问题。",},{Role: schema.User,Content: "请帮我计算 123 * 456 的结果,然后查询北京今天的天气。",},}// 5. 生成响应(可能包含工具调用)response, err := cm.Generate(ctx, messages)if err != nil {log.Fatal("生成响应失败:", err)}// 6. 处理工具调用if len(response.ToolCalls) > 0 {fmt.Printf("模型请求调用 %d 个工具:\n", len(response.ToolCalls))for _, toolCall := range response.ToolCalls {fmt.Printf("- 工具: %s, 参数: %s\n", toolCall.Function.Name, toolCall.Function.Arguments)// 这里可以执行实际的工具调用// result := executeTool(toolCall)}} else {fmt.Printf("直接回复: %s\n", response.Content)}
}
📊 回调机制 (Callbacks)
回调机制允许开发者在 ChatModel
的生命周期关键点注入自定义逻辑,用于监控、日志记录和性能分析。
回调事件
OnStart
: 在模型开始生成时触发OnEnd
: 在模型成功生成响应后触发OnError
: 在发生错误时触发OnStream
: 在流式生成过程中触发(每个chunk)
使用示例
import "github.com/cloudwego/eino/callbacks"func callbackExample() {ctx := context.Background()// 1. 创建回调处理器handler := &callbacks.ChatModelCallbackHandler{OnStart: func(ctx context.Context, info *callbacks.ChatModelStartInfo) {fmt.Printf("[回调] 开始生成,模型: %s, 消息数: %d\n", info.Model, len(info.Messages))},OnEnd: func(ctx context.Context, info *callbacks.ChatModelEndInfo) {fmt.Printf("[回调] 生成完成,耗时: %v, Token使用: %d\n", info.Duration, info.TokenUsage.TotalTokens)},OnError: func(ctx context.Context, info *callbacks.ChatModelErrorInfo) {fmt.Printf("[回调] 生成失败: %v\n", info.Error)},OnStream: func(ctx context.Context, info *callbacks.ChatModelStreamInfo) {fmt.Printf("[回调] 流式数据: %s\n", info.Chunk.Content)},}callbackHandler := callbacks.NewHandlerHelper().ChatModel(handler).Handler()// 2. 在编排中使用回调chain := compose.NewChain[[]*schema.Message, *schema.Message]()chain.AppendChatModel(cm)runnable, _ := chain.Compile(ctx)messages := []*schema.Message{{Role: schema.User, Content: "你好!"},}// 3. 带回调执行result, err := runnable.Invoke(ctx, messages,compose.WithCallbacks(callbackHandler),)if err != nil {log.Printf("执行失败: %v", err)return}fmt.Printf("最终结果: %s\n", result.Content)
}
高级回调应用
// 性能监控回调
type PerformanceMonitor struct {startTime time.Timemetrics map[string]interface{}
}func (p *PerformanceMonitor) CreateHandler() *callbacks.ChatModelCallbackHandler {return &callbacks.ChatModelCallbackHandler{OnStart: func(ctx context.Context, info *callbacks.ChatModelStartInfo) {p.startTime = time.Now()p.metrics = make(map[string]interface{})p.metrics["model"] = info.Modelp.metrics["input_messages"] = len(info.Messages)},OnEnd: func(ctx context.Context, info *callbacks.ChatModelEndInfo) {duration := time.Since(p.startTime)p.metrics["duration_ms"] = duration.Milliseconds()p.metrics["total_tokens"] = info.TokenUsage.TotalTokensp.metrics["tokens_per_second"] = float64(info.TokenUsage.TotalTokens) / duration.Seconds()// 发送到监控系统p.sendMetrics()},OnError: func(ctx context.Context, info *callbacks.ChatModelErrorInfo) {p.metrics["error"] = info.Error.Error()p.metrics["status"] = "failed"p.sendMetrics()},}
}func (p *PerformanceMonitor) sendMetrics() {// 发送指标到监控系统(如 Prometheus、DataDog 等)fmt.Printf("性能指标: %+v\n", p.metrics)
}
🎯 实际应用示例
1. 智能客服系统
type CustomerServiceBot struct {chatModel model.BaseChatModelknowledge []string // 知识库
}func NewCustomerServiceBot(cm model.BaseChatModel) *CustomerServiceBot {return &CustomerServiceBot{chatModel: cm,knowledge: []string{"我们的营业时间是周一到周五 9:00-18:00","退货政策:7天无理由退货","配送时间:1-3个工作日",},}
}func (bot *CustomerServiceBot) HandleCustomerQuery(ctx context.Context, query string) (string, error) {// 构建系统提示systemPrompt := fmt.Sprintf(`你是一个专业的客服助手。
知识库信息:
%s请根据知识库信息回答用户问题,如果知识库中没有相关信息,请礼貌地告知用户联系人工客服。`,strings.Join(bot.knowledge, "\n"))messages := []*schema.Message{{Role: schema.System, Content: systemPrompt},{Role: schema.User, Content: query},}response, err := bot.chatModel.Generate(ctx, messages,model.WithTemperature(0.3), // 较低温度确保回答准确model.WithMaxTokens(500),)if err != nil {return "", err}return response.Content, nil
}
2. 代码生成助手
type CodeGenerator struct {chatModel model.BaseChatModel
}func NewCodeGenerator(cm model.BaseChatModel) *CodeGenerator {return &CodeGenerator{chatModel: cm}
}func (cg *CodeGenerator) GenerateCode(ctx context.Context, requirement string, language string) (string, error) {systemPrompt := fmt.Sprintf(`你是一个专业的%s程序员。
请根据用户需求生成高质量的代码,要求:
1. 代码结构清晰,注释完整
2. 遵循最佳实践和编码规范
3. 包含必要的错误处理
4. 提供使用示例`, language)messages := []*schema.Message{{Role: schema.System, Content: systemPrompt},{Role: schema.User, Content: fmt.Sprintf("请用%s实现:%s", language, requirement)},}response, err := cg.chatModel.Generate(ctx, messages,model.WithTemperature(0.2), // 低温度确保代码准确性model.WithMaxTokens(2000),)if err != nil {return "", err}return response.Content, nil
}// 使用示例
func codeGeneratorExample() {ctx := context.Background()cm, _ := ark.NewChatModel(ctx, &ark.ChatModelConfig{APIKey: "YOUR_API_KEY",Model: "doubao-pro-4k",})generator := NewCodeGenerator(cm)code, err := generator.GenerateCode(ctx, "实现一个线程安全的计数器", "Go")if err != nil {log.Fatal(err)}fmt.Println("生成的代码:")fmt.Println(code)
}
3. 多轮对话管理
type ConversationManager struct {chatModel model.BaseChatModelhistory []*schema.MessagemaxHistory int
}func NewConversationManager(cm model.BaseChatModel) *ConversationManager {return &ConversationManager{chatModel: cm,history: make([]*schema.Message, 0),maxHistory: 10, // 保持最近10轮对话}
}func (cm *ConversationManager) Chat(ctx context.Context, userInput string) (string, error) {// 添加用户消息到历史userMessage := &schema.Message{Role: schema.User,Content: userInput,}cm.history = append(cm.history, userMessage)// 构建完整的对话历史messages := make([]*schema.Message, 0, len(cm.history)+1)// 添加系统提示systemMessage := &schema.Message{Role: schema.System,Content: "你是一个友好的AI助手,能够记住对话历史并提供连贯的回复。",}messages = append(messages, systemMessage)// 添加历史对话(限制长度)startIdx := 0if len(cm.history) > cm.maxHistory {startIdx = len(cm.history) - cm.maxHistory}messages = append(messages, cm.history[startIdx:]...)// 生成回复response, err := cm.chatModel.Generate(ctx, messages,model.WithTemperature(0.7),model.WithMaxTokens(1000),)if err != nil {return "", err}// 添加AI回复到历史cm.history = append(cm.history, response)// 清理过长的历史if len(cm.history) > cm.maxHistory*2 {cm.history = cm.history[len(cm.history)-cm.maxHistory:]}return response.Content, nil
}func (cm *ConversationManager) ClearHistory() {cm.history = make([]*schema.Message, 0)
}func (cm *ConversationManager) GetHistoryLength() int {return len(cm.history)
}
🔧 最佳实践
1. 性能优化
连接池管理
type ChatModelPool struct {models chan model.BaseChatModelconfig *ark.ChatModelConfig
}func NewChatModelPool(size int, config *ark.ChatModelConfig) *ChatModelPool {pool := &ChatModelPool{models: make(chan model.BaseChatModel, size),config: config,}// 预创建模型实例for i := 0; i < size; i++ {cm, err := ark.NewChatModel(context.Background(), config)if err != nil {log.Printf("创建模型实例失败: %v", err)continue}pool.models <- cm}return pool
}func (p *ChatModelPool) Get() model.BaseChatModel {return <-p.models
}func (p *ChatModelPool) Put(cm model.BaseChatModel) {select {case p.models <- cm:default:// 池已满,丢弃实例}
}
请求批处理
type BatchProcessor struct {chatModel model.BaseChatModelbatchSize inttimeout time.Duration
}func (bp *BatchProcessor) ProcessBatch(ctx context.Context, requests []ChatRequest) ([]ChatResponse, error) {responses := make([]ChatResponse, len(requests))// 并发处理批次var wg sync.WaitGroupsemaphore := make(chan struct{}, bp.batchSize)for i, req := range requests {wg.Add(1)go func(index int, request ChatRequest) {defer wg.Done()semaphore <- struct{}{} // 获取信号量defer func() { <-semaphore }() // 释放信号量ctx, cancel := context.WithTimeout(ctx, bp.timeout)defer cancel()response, err := bp.chatModel.Generate(ctx, request.Messages)responses[index] = ChatResponse{Response: response,Error: err,}}(i, req)}wg.Wait()return responses, nil
}
2. 错误处理和重试
type ResilientChatModel struct {chatModel model.BaseChatModelmaxRetries intretryDelay time.DurationbackoffRate float64
}func NewResilientChatModel(cm model.BaseChatModel) *ResilientChatModel {return &ResilientChatModel{chatModel: cm,maxRetries: 3,retryDelay: time.Second,backoffRate: 2.0,}
}func (rcm *ResilientChatModel) Generate(ctx context.Context, messages []*schema.Message, opts ...model.Option) (*schema.Message, error) {var lastErr errordelay := rcm.retryDelayfor attempt := 0; attempt <= rcm.maxRetries; attempt++ {if attempt > 0 {select {case <-ctx.Done():return nil, ctx.Err()case <-time.After(delay):delay = time.Duration(float64(delay) * rcm.backoffRate)}}response, err := rcm.chatModel.Generate(ctx, messages, opts...)if err == nil {return response, nil}lastErr = err// 判断是否应该重试if !shouldRetry(err) {break}log.Printf("第 %d 次尝试失败: %v", attempt+1, err)}return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", rcm.maxRetries, lastErr)
}func shouldRetry(err error) bool {// 根据错误类型判断是否应该重试if strings.Contains(err.Error(), "timeout") {return true}if strings.Contains(err.Error(), "rate limit") {return true}if strings.Contains(err.Error(), "server error") {return true}return false
}
3. 监控和日志
type MonitoredChatModel struct {chatModel model.BaseChatModelmetrics *Metricslogger *log.Logger
}type Metrics struct {TotalRequests int64SuccessRequests int64FailedRequests int64TotalTokens int64AverageLatency time.Durationmu sync.RWMutex
}func (mcm *MonitoredChatModel) Generate(ctx context.Context, messages []*schema.Message, opts ...model.Option) (*schema.Message, error) {startTime := time.Now()// 记录请求开始mcm.metrics.mu.Lock()mcm.metrics.TotalRequests++mcm.metrics.mu.Unlock()mcm.logger.Printf("[ChatModel] 开始处理请求,消息数: %d", len(messages))// 执行实际请求response, err := mcm.chatModel.Generate(ctx, messages, opts...)// 记录结果duration := time.Since(startTime)mcm.metrics.mu.Lock()if err != nil {mcm.metrics.FailedRequests++mcm.logger.Printf("[ChatModel] 请求失败,耗时: %v, 错误: %v", duration, err)} else {mcm.metrics.SuccessRequests++if response.ResponseMeta != nil && response.ResponseMeta.Usage != nil {mcm.metrics.TotalTokens += int64(response.ResponseMeta.Usage.TotalTokens)}mcm.logger.Printf("[ChatModel] 请求成功,耗时: %v", duration)}// 更新平均延迟mcm.updateAverageLatency(duration)mcm.metrics.mu.Unlock()return response, err
}func (mcm *MonitoredChatModel) updateAverageLatency(newLatency time.Duration) {// 简单的移动平均if mcm.metrics.AverageLatency == 0 {mcm.metrics.AverageLatency = newLatency} else {mcm.metrics.AverageLatency = (mcm.metrics.AverageLatency + newLatency) / 2}
}func (mcm *MonitoredChatModel) GetMetrics() Metrics {mcm.metrics.mu.RLock()defer mcm.metrics.mu.RUnlock()return *mcm.metrics
}
4. 配置管理
type ChatModelConfig struct {Provider string `yaml:"provider"` // ark, openai, etc.Model string `yaml:"model"` // 模型名称APIKey string `yaml:"api_key"` // API密钥BaseURL string `yaml:"base_url"` // 基础URLTemperature float32 `yaml:"temperature"` // 温度MaxTokens int `yaml:"max_tokens"` // 最大token数Timeout time.Duration `yaml:"timeout"` // 超时时间Retries int `yaml:"retries"` // 重试次数
}type ChatModelFactory struct {configs map[string]*ChatModelConfig
}func NewChatModelFactory(configFile string) (*ChatModelFactory, error) {data, err := ioutil.ReadFile(configFile)if err != nil {return nil, err}var configs map[string]*ChatModelConfigif err := yaml.Unmarshal(data, &configs); err != nil {return nil, err}return &ChatModelFactory{configs: configs}, nil
}func (factory *ChatModelFactory) CreateChatModel(ctx context.Context, name string) (model.BaseChatModel, error) {config, exists := factory.configs[name]if !exists {return nil, fmt.Errorf("配置 %s 不存在", name)}switch config.Provider {case "ark":return ark.NewChatModel(ctx, &ark.ChatModelConfig{APIKey: config.APIKey,Model: config.Model,BaseURL: config.BaseURL,Temperature: config.Temperature,MaxTokens: config.MaxTokens,Timeout: config.Timeout,})case "openai":// 实现 OpenAI 模型创建return nil, fmt.Errorf("OpenAI 提供商暂未实现")default:return nil, fmt.Errorf("不支持的提供商: %s", config.Provider)}
}
🚨 常见问题和解决方案
1. Token 限制问题
问题: 输入或输出超过模型的 token 限制
解决方案:
func truncateMessages(messages []*schema.Message, maxTokens int) []*schema.Message {// 简单的截断策略:保留系统消息和最近的用户消息if len(messages) <= 2 {return messages}result := make([]*schema.Message, 0)// 保留系统消息for _, msg := range messages {if msg.Role == schema.System {result = append(result, msg)break}}// 从后往前添加消息,直到接近 token 限制estimatedTokens := 0for i := len(messages) - 1; i >= 0; i-- {msg := messages[i]if msg.Role == schema.System {continue}// 粗略估算 token 数(1 token ≈ 4 字符)msgTokens := len(msg.Content) / 4if estimatedTokens+msgTokens > maxTokens {break}result = append([]*schema.Message{msg}, result...)estimatedTokens += msgTokens}return result
}
2. 速率限制处理
问题: API 调用频率过高导致限流
解决方案:
type RateLimiter struct {limiter *rate.Limiter
}func NewRateLimiter(requestsPerSecond float64) *RateLimiter {return &RateLimiter{limiter: rate.NewLimiter(rate.Limit(requestsPerSecond), 1),}
}func (rl *RateLimiter) Wait(ctx context.Context) error {return rl.limiter.Wait(ctx)
}type RateLimitedChatModel struct {chatModel model.BaseChatModelrateLimiter *RateLimiter
}func (rlcm *RateLimitedChatModel) Generate(ctx context.Context, messages []*schema.Message, opts ...model.Option) (*schema.Message, error) {// 等待速率限制if err := rlcm.rateLimiter.Wait(ctx); err != nil {return nil, err}return rlcm.chatModel.Generate(ctx, messages, opts...)
}
3. 内存泄漏预防
问题: 长时间运行导致内存泄漏
解决方案:
type ManagedChatModel struct {chatModel model.BaseChatModelcleanup func()
}func NewManagedChatModel(ctx context.Context, config *ark.ChatModelConfig) (*ManagedChatModel, error) {cm, err := ark.NewChatModel(ctx, config)if err != nil {return nil, err}managed := &ManagedChatModel{chatModel: cm,}// 设置清理函数managed.cleanup = func() {// 清理资源if closer, ok := cm.(io.Closer); ok {closer.Close()}}// 注册清理函数runtime.SetFinalizer(managed, (*ManagedChatModel).finalize)return managed, nil
}func (mcm *ManagedChatModel) finalize() {if mcm.cleanup != nil {mcm.cleanup()}
}func (mcm *ManagedChatModel) Close() {mcm.finalize()runtime.SetFinalizer(mcm, nil)
}
📚 相关资源
- 官方文档: Eino ChatModel 使用说明
- GitHub 仓库: cloudwego/eino