|
| 1 | +# Hunyuan Model |
| 2 | + |
| 3 | +A Tencent Cloud Hunyuan model implementation for [Eino](https://github.com/cloudwego/eino) that implements the `ToolCallingChatModel` interface. This enables seamless integration with Eino's LLM capabilities for enhanced natural language processing and generation. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- Implements `github.com/cloudwego/eino/components/model.Model` |
| 8 | +- Easy integration with Eino's model system |
| 9 | +- Configurable model parameters |
| 10 | +- Support for chat completion |
| 11 | +- Support for streaming responses |
| 12 | +- Custom response parsing support |
| 13 | +- Flexible model configuration |
| 14 | +- Support for multimodal content (images, videos) |
| 15 | +- Tool calling (Function Calling) support |
| 16 | +- Reasoning content support |
| 17 | +- Complete error handling |
| 18 | +- Callback mechanism support |
| 19 | + |
| 20 | +## Installation |
| 21 | + |
| 22 | +```bash |
| 23 | +go get github.com/cloudwego/eino-ext/components/model/hunyuan@latest |
| 24 | +``` |
| 25 | + |
| 26 | +## Quick Start |
| 27 | + |
| 28 | +Here's a quick example of how to use the Hunyuan model: |
| 29 | + |
| 30 | +```go |
| 31 | +package main |
| 32 | + |
| 33 | +import ( |
| 34 | + "context" |
| 35 | + "fmt" |
| 36 | + "log" |
| 37 | + "os" |
| 38 | + "time" |
| 39 | + |
| 40 | + "github.com/cloudwego/eino-ext/components/model/hunyuan" |
| 41 | + "github.com/cloudwego/eino/schema" |
| 42 | +) |
| 43 | + |
| 44 | +func main() { |
| 45 | + ctx := context.Background() |
| 46 | + |
| 47 | + // Get authentication from environment variables |
| 48 | + secretId := os.Getenv("HUNYUAN_SECRET_ID") |
| 49 | + secretKey := os.Getenv("HUNYUAN_SECRET_KEY") |
| 50 | + |
| 51 | + if secretId == "" || secretKey == "" { |
| 52 | + log.Fatal("HUNYUAN_SECRET_ID and HUNYUAN_SECRET_KEY environment variables are required") |
| 53 | + } |
| 54 | + |
| 55 | + // Create Hunyuan chat model |
| 56 | + cm, err := hunyuan.NewChatModel(ctx, &hunyuan.ChatModelConfig{ |
| 57 | + SecretId: secretId, |
| 58 | + SecretKey: secretKey, |
| 59 | + Model: "hunyuan-lite", // Options: hunyuan-lite, hunyuan-pro, hunyuan-turbo |
| 60 | + Timeout: 30 * time.Second, |
| 61 | + }) |
| 62 | + if err != nil { |
| 63 | + log.Fatal(err) |
| 64 | + } |
| 65 | + |
| 66 | + // Build conversation messages |
| 67 | + messages := []*schema.Message{ |
| 68 | + schema.SystemMessage("You are a helpful AI assistant. Please answer user questions in Chinese."), |
| 69 | + schema.UserMessage("Please introduce the features and advantages of Tencent Cloud Hunyuan large model."), |
| 70 | + } |
| 71 | + |
| 72 | + // Call model to generate response |
| 73 | + resp, err := cm.Generate(ctx, messages) |
| 74 | + if err != nil { |
| 75 | + log.Fatal(err) |
| 76 | + } |
| 77 | + |
| 78 | + fmt.Printf("Assistant: %s\n", resp.Content) |
| 79 | + |
| 80 | + if resp.ReasoningContent != "" { |
| 81 | + fmt.Printf("\nReasoning: %s\n", resp.ReasoningContent) |
| 82 | + } |
| 83 | + |
| 84 | + if resp.ResponseMeta != nil && resp.ResponseMeta.Usage != nil { |
| 85 | + usage := resp.ResponseMeta.Usage |
| 86 | + fmt.Printf("\nToken Usage:\n") |
| 87 | + fmt.Printf(" Prompt Tokens: %d\n", usage.PromptTokens) |
| 88 | + fmt.Printf(" Completion Tokens: %d\n", usage.CompletionTokens) |
| 89 | + fmt.Printf(" Total Tokens: %d\n", usage.TotalTokens) |
| 90 | + } |
| 91 | +} |
| 92 | +``` |
| 93 | + |
| 94 | +## Configuration |
| 95 | + |
| 96 | +The model can be configured using the `hunyuan.ChatModelConfig` struct: |
| 97 | + |
| 98 | +```go |
| 99 | +type ChatModelConfig struct { |
| 100 | + // SecretId is your Tencent Cloud API Secret ID |
| 101 | + // Required |
| 102 | + SecretId string |
| 103 | + |
| 104 | + // SecretKey is your Tencent Cloud API Secret Key |
| 105 | + // Required |
| 106 | + SecretKey string |
| 107 | + |
| 108 | + // Model specifies the ID of the model to use |
| 109 | + // Required. Options: hunyuan-lite, hunyuan-pro, hunyuan-turbo |
| 110 | + Model string |
| 111 | + |
| 112 | + // Region specifies the service region |
| 113 | + // Optional. Default: ap-guangzhou |
| 114 | + Region string |
| 115 | + |
| 116 | + // Timeout specifies the maximum duration to wait for API responses |
| 117 | + // Optional. Default: 30 seconds |
| 118 | + Timeout time.Duration |
| 119 | + |
| 120 | + // Temperature controls the randomness of the output |
| 121 | + // Range: [0.0, 2.0]. Higher values make output more random |
| 122 | + // Optional. Default: 1.0 |
| 123 | + Temperature float32 |
| 124 | + |
| 125 | + // TopP controls diversity via nucleus sampling |
| 126 | + // Range: [0.0, 1.0]. Lower values make output more focused |
| 127 | + // Optional. Default: 1.0 |
| 128 | + TopP float32 |
| 129 | + |
| 130 | + // Stop sequences where the API will stop generating further tokens |
| 131 | + // Optional |
| 132 | + Stop []string |
| 133 | + |
| 134 | + // PresencePenalty prevents repetition by penalizing tokens based on presence |
| 135 | + // Range: [-2.0, 2.0]. Positive values increase likelihood of new topics |
| 136 | + // Optional. Default: 0 |
| 137 | + PresencePenalty float32 |
| 138 | + |
| 139 | + // FrequencyPenalty prevents repetition by penalizing tokens based on frequency |
| 140 | + // Range: [-2.0, 2.0]. Positive values decrease likelihood of repetition |
| 141 | + // Optional. Default: 0 |
| 142 | + FrequencyPenalty float32 |
| 143 | +} |
| 144 | +``` |
| 145 | + |
| 146 | +## Examples |
| 147 | + |
| 148 | +### Basic Text Generation |
| 149 | + |
| 150 | +Reference: [examples/generate/generate.go](./examples/generate/generate.go) |
| 151 | + |
| 152 | +```bash |
| 153 | +cd examples/generate |
| 154 | +go run generate.go |
| 155 | +``` |
| 156 | + |
| 157 | +### Streaming Response |
| 158 | + |
| 159 | +Reference: [examples/stream/stream.go](./examples/stream/stream.go) |
| 160 | + |
| 161 | +```bash |
| 162 | +cd examples/stream |
| 163 | +go run stream.go |
| 164 | +``` |
| 165 | + |
| 166 | +### Tool Calling |
| 167 | + |
| 168 | +Reference: [examples/tool_call/tool_call.go](./examples/tool_call/tool_call.go) |
| 169 | + |
| 170 | +```bash |
| 171 | +cd examples/tool_call |
| 172 | +go run tool_call.go |
| 173 | +``` |
| 174 | + |
| 175 | +### Multimodal Processing |
| 176 | + |
| 177 | +Reference: [examples/multimodal/multimodal.go](./examples/multimodal/multimodal.go) |
| 178 | + |
| 179 | +```bash |
| 180 | +cd examples/multimodal |
| 181 | +go run multimodal.go |
| 182 | +``` |
| 183 | + |
| 184 | +## Tool Calling |
| 185 | + |
| 186 | +### Defining Tools |
| 187 | + |
| 188 | +```go |
| 189 | +tools := []*schema.ToolInfo{ |
| 190 | + { |
| 191 | + Name: "get_weather", |
| 192 | + Desc: "Query city weather information", |
| 193 | + ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{ |
| 194 | + "city": { |
| 195 | + Type: schema.String, |
| 196 | + Desc: "City name", |
| 197 | + }, |
| 198 | + }), |
| 199 | + }, |
| 200 | +} |
| 201 | + |
| 202 | +cmWithTools, err := cm.WithTools(tools) |
| 203 | +``` |
| 204 | + |
| 205 | +### Handling Tool Calls |
| 206 | + |
| 207 | +```go |
| 208 | +resp, err := cmWithTools.Generate(ctx, messages) |
| 209 | +if len(resp.ToolCalls) > 0 { |
| 210 | + for _, toolCall := range resp.ToolCalls { |
| 211 | + switch toolCall.Function.Name { |
| 212 | + case "get_weather": |
| 213 | + // Execute tool call |
| 214 | + result, _ := getWeather(city) |
| 215 | + |
| 216 | + // Add result to conversation |
| 217 | + messages = append(messages, &schema.Message{ |
| 218 | + Role: schema.Tool, |
| 219 | + ToolCallID: toolCall.ID, |
| 220 | + Content: result, |
| 221 | + }) |
| 222 | + } |
| 223 | + } |
| 224 | + |
| 225 | + // Continue conversation |
| 226 | + finalResp, err := cmWithTools.Generate(ctx, messages) |
| 227 | +} |
| 228 | +``` |
| 229 | + |
| 230 | +## Multimodal Content Processing |
| 231 | + |
| 232 | +### Image Processing |
| 233 | + |
| 234 | +```go |
| 235 | +messages := []*schema.Message{ |
| 236 | + { |
| 237 | + Role: schema.User, |
| 238 | + UserInputMultiContent: []schema.MessageInputPart{ |
| 239 | + { |
| 240 | + Type: schema.ChatMessagePartTypeText, |
| 241 | + Text: "Please describe the content of this image:", |
| 242 | + }, |
| 243 | + { |
| 244 | + Type: schema.ChatMessagePartTypeImageURL, |
| 245 | + Image: &schema.MessageInputImage{ |
| 246 | + MessagePartCommon: schema.MessagePartCommon{ |
| 247 | + MIMEType: "image/jpeg", |
| 248 | + Base64Data: toPtr("base64-image-data"), |
| 249 | + }, |
| 250 | + }, |
| 251 | + }, |
| 252 | + }, |
| 253 | + }, |
| 254 | +} |
| 255 | +``` |
| 256 | + |
| 257 | +### Video Processing |
| 258 | + |
| 259 | +```go |
| 260 | +messages := []*schema.Message{ |
| 261 | + { |
| 262 | + Role: schema.User, |
| 263 | + UserInputMultiContent: []schema.MessageInputPart{ |
| 264 | + { |
| 265 | + Type: schema.ChatMessagePartTypeVideoURL, |
| 266 | + Video: &schema.MessageInputVideo{ |
| 267 | + MessagePartCommon: schema.MessagePartCommon{ |
| 268 | + MIMEType: "video/mp4", |
| 269 | + Base64Data: toPtr("base64-video-data"), |
| 270 | + }, |
| 271 | + }, |
| 272 | + }, |
| 273 | + { |
| 274 | + Type: schema.ChatMessagePartTypeText, |
| 275 | + Text: "Please analyze the main content of this video.", |
| 276 | + }, |
| 277 | + }, |
| 278 | + }, |
| 279 | +} |
| 280 | +``` |
| 281 | + |
| 282 | +## Environment Variables |
| 283 | + |
| 284 | +| Variable Name | Description | Required | |
| 285 | +|---------------|-------------|----------| |
| 286 | +| HUNYUAN_SECRET_ID | Tencent Cloud API Secret ID | Yes | |
| 287 | +| HUNYUAN_SECRET_KEY | Tencent Cloud API Secret Key | Yes | |
| 288 | + |
| 289 | +## Testing |
| 290 | + |
| 291 | +Run unit tests: |
| 292 | + |
| 293 | +```bash |
| 294 | +go test -v ./... |
| 295 | +``` |
| 296 | + |
| 297 | +## Related Links |
| 298 | + |
| 299 | +- [Tencent Cloud Hunyuan Documentation](https://cloud.tencent.com/document/product/1729) |
| 300 | +- [CloudWeGo Eino Framework](https://github.com/cloudwego/eino) |
0 commit comments