Skip to content
鼓励作者:欢迎打赏犒劳

eino实现Agent

eino 是字节官方出来的Agent框架,类似spring-ai

初体验-对话

对接deepseek

go
package main

import (
	"context"
	"fmt"

	"github.com/cloudwego/eino-ext/components/model/deepseek"
	"github.com/cloudwego/eino/schema"
)

func main() {
	// 创建模型
	cm, err := deepseek.NewChatModel(context.Background(), &deepseek.ChatModelConfig{
		Model:  "deepseek-chat",
		APIKey: "sk-xxxxxxxxxxxxxxxxx",
	})
	if err != nil {
		fmt.Printf("创建模型失败: %v\n", err)
		return
	}

	// 直接调用Generate  是一次性返回全部
	resp, err := cm.Generate(context.Background(), []*schema.Message{
		schema.SystemMessage("你是一个有用的助手"),
		schema.UserMessage("Go 语言适合做 AI 开发吗?"),
	})
	if err != nil {
		fmt.Printf("调用模型失败: %v\n", err)
		return
	}

	fmt.Println(resp.Content)
}

对接本地Ollama

go
package main

import (
	"context"
	"fmt"

	"github.com/cloudwego/eino-ext/components/model/ollama"
	"github.com/cloudwego/eino/schema"
)

func main() {
	// 创建模型
	cm, err := ollama.NewChatModel(context.Background(), &ollama.ChatModelConfig{
		BaseURL: "http://localhost:11434", // Ollama 默认地址
		Model:   "qwen2.5:3b",             // 你本地已下载的模型名称
	})
	if err != nil {
		fmt.Printf("创建模型失败: %v\n", err)
		return
	}

	// 直接调用
	resp, err := cm.Generate(context.Background(), []*schema.Message{
		schema.SystemMessage("你是一个有用的助手"),
		schema.UserMessage("你是谁?"),
	})
	if err != nil {
		fmt.Printf("调用模型失败: %v\n", err)
		return
	}

	fmt.Println(resp.Content)
}

连续对话

go
package main

import (
	"bufio"
	"context"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/cloudwego/eino-ext/components/model/ollama"
	"github.com/cloudwego/eino/schema"
)

func main() {
	ctx := context.Background()
	// 创建模型
	cm, err := ollama.NewChatModel(context.Background(), &ollama.ChatModelConfig{
		BaseURL: "http://localhost:11434", // Ollama 默认地址
		Model:   "qwen2.5:3b",             // 你本地已下载的模型名称
	})
	if err != nil {
		fmt.Printf("创建模型失败: %v\n", err)
		return
	}
	// 对话历史
	messages := []*schema.Message{
		schema.SystemMessage("你是一个友好的 AI 助手"),
	}

	scanner := bufio.NewScanner(os.Stdin)
	fmt.Println("开始对话(输入 'exit' 退出):")

	for {
		fmt.Print("\n你: ")
		if !scanner.Scan() {
			break
		}

		userInput := strings.TrimSpace(scanner.Text())
		if userInput == "exit" {
			fmt.Println("再见!")
			break
		}

		if userInput == "" {
			continue
		}

		// 添加用户消息
		messages = append(messages, schema.UserMessage(userInput))

		// 生成 AI 响应
		response, err := cm.Generate(ctx, messages)
		if err != nil {
			log.Printf("生成失败: %v", err)
			continue
		}

		// 添加 AI 响应到历史
		messages = append(messages, response)

		fmt.Printf("\\nAI: %s\\n", response.Content)
	}
}

流式对话

go
package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log"
	"strings"

	"github.com/cloudwego/eino-ext/components/model/ollama"
	"github.com/cloudwego/eino/schema"
)

func main() {
	ctx := context.Background()
	// 创建模型
	chatModel, err := ollama.NewChatModel(context.Background(), &ollama.ChatModelConfig{
		BaseURL: "http://localhost:11434", // Ollama 默认地址
		Model:   "qwen2.5:3b",             // 你本地已下载的模型名称
	})
	if err != nil {
		fmt.Printf("创建模型失败: %v\n", err)
		return
	}

	messages := []*schema.Message{
		schema.UserMessage("请列举 5 个 Go 语言的特点"),
	}

	stream, err := chatModel.Stream(ctx, messages)
	if err != nil {
		log.Fatalf("流式生成失败: %v", err)
	}
	defer stream.Close()

	var fullContent strings.Builder
	fmt.Print("AI 回复: ")

	for {
		chunk, err := stream.Recv()
		if err != nil {
			if errors.Is(err, io.EOF) {
				break
			}
			log.Fatalf("接收失败: %v", err)
		}

		// 实时打印
		fmt.Print(chunk.Content)

		// 同时收集完整内容
		fullContent.WriteString(chunk.Content)
	}

	fmt.Println("\\n\\n======== 完整响应 ========")
	fmt.Println(fullContent.String())
}

Token 使用统计

go
package main

import (
	"context"
	"fmt"

	"github.com/cloudwego/eino-ext/components/model/ollama"
	"github.com/cloudwego/eino/schema"
)

func main() {
	// 创建模型
	chatModel, err := ollama.NewChatModel(context.Background(), &ollama.ChatModelConfig{
		BaseURL: "http://localhost:11434", // Ollama 默认地址
		Model:   "qwen2.5:3b",             // 你本地已下载的模型名称
	})
	if err != nil {
		fmt.Printf("创建模型失败: %v\n", err)
		return
	}
	// 直接调用
	resp, err := chatModel.Generate(context.Background(), []*schema.Message{
		schema.SystemMessage("你是一个有用的助手"),
		schema.UserMessage("你是谁?"),
	})
	if err != nil {
		fmt.Printf("调用模型失败: %v\n", err)
		return
	}

	fmt.Println(resp.Content)

	printTokenUsage(resp)
}

// 打印 Token 使用情况
func printTokenUsage(response *schema.Message) {
	if response.ResponseMeta != nil && response.ResponseMeta.Usage != nil {
		fmt.Printf("\nToken 使用统计:\n")
		fmt.Printf("  输入 Token: %d\n", response.ResponseMeta.Usage.PromptTokens)
		fmt.Printf("  输出 Token: %d\n", response.ResponseMeta.Usage.CompletionTokens)
		fmt.Printf("  总计 Token: %d\n", response.ResponseMeta.Usage.TotalTokens)
		if response.ResponseMeta.Usage.PromptTokenDetails.CachedTokens > 0 {
			fmt.Printf("  缓存 Token: %d\n", response.ResponseMeta.Usage.PromptTokenDetails.CachedTokens)
		}
	}
}

流式统计

go
package main

import (
	"context"
	"fmt"

	"github.com/cloudwego/eino-ext/components/model/ollama"
	"github.com/cloudwego/eino/schema"
)

func main() {
	ctx := context.Background()

	chatModel, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
		BaseURL: "http://localhost:11434",
		Model:   "qwen2.5:3b",
	})
	if err != nil {
		fmt.Printf("创建模型失败: %v\n", err)
		return
	}

	// 准备消息
	messages := []*schema.Message{
		schema.SystemMessage("你是一个有用的助手"),
		schema.UserMessage("讲一个100字左右的小故事"),
	}

	// 流式调用
	streamResult, err := chatModel.Stream(ctx, messages)
	if err != nil {
		fmt.Printf("流式调用失败: %v\n", err)
		return
	}

	// 收集所有响应
	var fullContent string
	var finalUsage *schema.TokenUsage

	for {
		msg, err := streamResult.Recv()
		if err != nil {
			// 注意:EOF 表示流结束
			if err.Error() == "EOF" {
				break
			}
			fmt.Printf("接收流数据出错: %v\n", err)
			return
		}

		// 累积内容
		fullContent += msg.Content

		// 检查是否有 Usage 信息(通常在最后一个包中)
		if msg.ResponseMeta != nil && msg.ResponseMeta.Usage != nil {
			finalUsage = msg.ResponseMeta.Usage
		}
	}

	// 输出结果
	fmt.Println(fullContent)

	// 打印 Token 统计
	if finalUsage != nil {
		fmt.Printf("\nToken 使用统计:\n")
		fmt.Printf("  输入 Token: %d\n", finalUsage.PromptTokens)
		fmt.Printf("  输出 Token: %d\n", finalUsage.CompletionTokens)
		fmt.Printf("  总计 Token: %d\n", finalUsage.TotalTokens)
		if finalUsage.PromptTokenDetails.CachedTokens > 0 {
			fmt.Printf("  缓存 Token: %d\n", finalUsage.PromptTokenDetails.CachedTokens)
		}
	} else {
		fmt.Println("\n未获取到 Token 使用信息")
	}
}

ChatTemplate模版

简单对话

go
package main

import (
	"context"
	"fmt"

	"github.com/cloudwego/eino-ext/components/model/ollama"
	"github.com/cloudwego/eino/components/prompt"
	"github.com/cloudwego/eino/schema"
)

func main() {
	ctx := context.Background()

	// 1. 创建 ChatTemplate
	template := prompt.FromMessages(schema.FString,
		&schema.Message{
			Role:    schema.System,
			Content: "你是一个{role}助手,擅长{skill}领域",
		},
		&schema.Message{
			Role:    schema.User,
			Content: "请解释一下:{question}",
		},
	)

	// 2. 准备模板变量
	variables := map[string]any{
		"role":     "专业的 AI",
		"skill":    "Go 语言编程",
		"question": "什么是 ChatTemplate?",
	}

	// 3. 格式化模板生成消息列表
	messages, err := template.Format(context.Background(), variables)
	if err != nil {
		fmt.Printf("格式化模板失败: %v\n", err)
		return
	}

	//4.查看生成的消息
	fmt.Println("生成的消息:")
	for i, msg := range messages {
		fmt.Printf("%d. [%s] : %s \n", i+1, msg.Role, msg.Content)
	}

	// 4. 创建 ChatModel
	chatModel, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
		BaseURL: "http://localhost:11434",
		Model:   "qwen2.5:3b",
	})
	if err != nil {
		fmt.Printf("创建模型失败: %v\n", err)
		return
	}

	// 5. 使用格式化的消息调用模型
	resp, err := chatModel.Generate(ctx, messages)
	if err != nil {
		fmt.Printf("调用模型失败: %v\n", err)
		return
	}

	fmt.Println(resp.Content)
}

历史对话

go
package main

import (
	"context"
	"fmt"

	"github.com/cloudwego/eino-ext/components/model/ollama"
	"github.com/cloudwego/eino/components/prompt"
	"github.com/cloudwego/eino/schema"
)

func main() {
	ctx := context.Background()

	// ✅ 正确方式:使用 prompt.FromMessages 创建 ChatTemplate
	template := prompt.FromMessages(
		schema.FString, // 模板格式:FString 支持 {variable} 占位符

		// 系统消息模板
		schema.SystemMessage("你是一个{personality}助手,用{language}语言回答"),

		// 消息占位符:插入历史消息(true 表示可选)
		schema.MessagesPlaceholder("history", true),

		// 用户消息模板
		schema.UserMessage("{question}"),
	)

	// 初始化模型
	chatModel, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
		BaseURL: "http://localhost:11434",
		Model:   "qwen2.5:3b",
	})
	if err != nil {
		fmt.Printf("创建模型失败: %v\n", err)
		return
	}

	// 准备输入变量
	input := map[string]any{
		"personality": "友好且专业",
		"language":    "简洁",
		"history": []*schema.Message{
			schema.UserMessage("你好"),
			schema.AssistantMessage("你好!有什么可以帮你的?", nil),
		},
		"question": "eino 框架的 ChatTemplate 有什么用?",
	}

	// 格式化消息
	messages, err := template.Format(ctx, input)
	if err != nil {
		fmt.Printf("格式化失败: %v\n", err)
		return
	}
	//查看生成的消息
	fmt.Println("生成的消息:")
	for i, msg := range messages {
		fmt.Printf("%d. [%s] : %s \n", i+1, msg.Role, msg.Content)
	}

	// 调用模型
	resp, err := chatModel.Generate(ctx, messages)
	if err != nil {
		fmt.Printf("调用失败: %v\n", err)
		return
	}

	fmt.Println("AI 回复:", resp.Content)
}

如有转载或 CV 的请标注本站原文地址