/* * Copyright 2024 CloudWeGo Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package model import ( "context" "github.com/cloudwego/eino/schema" ) // messageType is the sealed type constraint for message types used in BaseModel. // Only *schema.Message and *schema.AgenticMessage satisfy this constraint. type messageType interface { *schema.Message | *schema.AgenticMessage } // BaseModel is the generic base model interface parameterized by message type M. // It exposes two modes of interaction: // - [BaseModel.Generate]: blocks until the model returns a complete response. // - [BaseModel.Stream]: returns a [schema.StreamReader] that yields message // chunks incrementally as the model generates them. type BaseModel[M messageType] interface { Generate(ctx context.Context, input []M, opts ...Option) (M, error) Stream(ctx context.Context, input []M, opts ...Option) (*schema.StreamReader[M], error) } // BaseChatModel is a backward-compatible type alias for BaseModel specialized // with *schema.Message. All existing code using model.BaseChatModel continues // to work without modification. // // It exposes two modes of interaction: // - [BaseChatModel.Generate]: blocks until the model returns a complete response. // - [BaseChatModel.Stream]: returns a [schema.StreamReader] that yields message // chunks incrementally as the model generates them. // // The input is a slice of [schema.Message] representing the conversation history. // Messages carry a role (system, user, assistant, tool) and support multimodal // content (text, images, audio, video). Tool messages must include a ToolCallID // that correlates them with a prior assistant tool-call message. // // Stream usage — the caller is responsible for closing the reader: // // reader, err := m.Stream(ctx, messages) // if err != nil { ... } // defer reader.Close() // for { // chunk, err := reader.Recv() // if errors.Is(err, io.EOF) { break } // if err != nil { ... } // // handle chunk // } // // Note: a [schema.StreamReader] can only be read once. If multiple consumers // need the stream, it must be copied before reading. // //go:generate mockgen -destination ../../internal/mock/components/model/ChatModel_mock.go --package model github.com/cloudwego/eino/components/model BaseChatModel,ChatModel,ToolCallingChatModel type BaseChatModel = BaseModel[*schema.Message] // Deprecated: Use [ToolCallingChatModel] instead. // // ChatModel extends [BaseChatModel] with tool binding via [ChatModel.BindTools]. // BindTools mutates the instance in place, which causes a race condition when // the same instance is used concurrently: one goroutine's tool list can // overwrite another's. Prefer [ToolCallingChatModel.WithTools], which returns // a new immutable instance and is safe for concurrent use. type ChatModel interface { BaseChatModel // BindTools bind tools to the model. // BindTools before requesting ChatModel generally. // notice the non-atomic problem of BindTools and Generate. BindTools(tools []*schema.ToolInfo) error } // ToolCallingChatModel extends [BaseChatModel] with safe tool binding. // // Unlike the deprecated [ChatModel.BindTools], [ToolCallingChatModel.WithTools] // does not mutate the receiver — it returns a new instance with the given tools // attached. This makes it safe to share a base model instance across goroutines // and derive per-request variants with different tool sets: // // base, _ := openai.NewChatModel(ctx, cfg) // shared, no tools // withSearch, _ := base.WithTools([]*schema.ToolInfo{searchTool}) // withCalc, _ := base.WithTools([]*schema.ToolInfo{calcTool}) type ToolCallingChatModel interface { BaseChatModel WithTools(tools []*schema.ToolInfo) (ToolCallingChatModel, error) } // AgenticModel is a type alias for BaseModel specialized with // *schema.AgenticMessage. Unlike ToolCallingChatModel, agentic models do NOT // expose a WithTools method; tools are passed at request time via the // model.WithTools option, consistent with how ChatModelAgent binds tools. type AgenticModel = BaseModel[*schema.AgenticMessage]