
是由字节开发的Go的大模型应用框架,为go开发者提供类似LangChain的能力。
go
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/cloudwego/eino-ext/components/model/deepseek"
"github.com/cloudwego/eino/schema"
)
func main() {
ctx := context.Background()
//创建模型
model, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("API_KEY"),
Model: os.Getenv("deepseek-chat"),
BaseURL: "https://api.deepseek.com",
})
if err != nil {
log.Fatalf("create model failed: %v", err)
}
//开始对话
messages := []*schema.Message{
schema.SystemMessage("你是一个很好的ai助手"),
schema.UserMessage("你好,请介绍一下Eino框架"),
}
response, err := model.Generate(ctx, messages)
if err != nil {
log.Fatalf("generate failed: %v", err)
}
content := response.Content
//输出结果
fmt.Println(content)
if response.ResponseMeta != nil && response.ResponseMeta.Usage != nil {
fmt.Println(response.ResponseMeta.Usage)
fmt.Printf("input token;%d\n",response.ResponseMeta.Usage.PromptTokens)
fmt.Printf("output token;%d\n",response.ResponseMeta.Usage.CompletionTokens)
fmt.Printf("total token:%d\n",response.ResponseMeta.Usage.TotalTokens)
}
}
go
func multiChatModel() {
ctx := context.Background()
//创建模型
model, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("API_KEY"),
Model: os.Getenv("deepseek-chat"),
BaseURL: "https://api.deepseek.com",
})
if err != nil {
log.Fatalf("create model failed: %v", err)
}
//开始对话
messages := []*schema.Message{
schema.SystemMessage("你是一个很好的ai助手"),
}
scanner := bufio.NewScanner(os.Stdin)
fmt.Printf("开始对话(输入exit退出)")
for {
fmt.Printf("\n你:")
if !scanner.Scan() {
break
}
input := strings.TrimSpace(scanner.Text())
if input == "exit" {
fmt.Println("bye")
break
}
if input == "" {
continue
}
//添加到message中
messages = append(messages, schema.UserMessage(input))
response, err := model.Generate(ctx, messages)
if err != nil {
log.Fatalf("generate failed: %v", err)
}
//添加AI响应到历史
messages = append(messages, response)
fmt.Printf("\nAI: %s\n", response.Content)
}
}
go
func streamInput() {
ctx := context.Background()
model, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("API_KEY"),
Model: os.Getenv("deepseek-chat"),
BaseURL: "https://api.deepseek.com",
})
if err != nil {
log.Fatalf("create model failed: %v", err)
}
messages := []*schema.Message{
schema.SystemMessage("你是一个程序员"),
schema.UserMessage("请列举5个GO的特点"),
}
stream, err := model.Stream(ctx, messages)
if err != nil {
log.Fatalf("stream input failed: %v", err)
}
defer stream.Close()
var fullContent strings.Builder
for {
chunk, err := stream.Recv()
if err != nil {
if err == io.EOF {
break
}
log.Fatalf("receive failed: %v", err)
}
fmt.Printf(chunk.Content)
fullContent.WriteString(chunk.Content)
}
fmt.Println(fullContent.String())
}
go
func chatTemplate() {
ctx := context.Background()
template := prompt.FromMessages(
schema.FString,
schema.SystemMessage("你是一个{role}"),
schema.UserMessage("{question}"),
)
//准备变量
variables := map[string]any{
"role": "专业的Go程序猿",
"question": "请详解一下interface",
}
messages, err := template.Format(ctx, variables)
if err != nil {
log.Fatalf("format failed: %v", err)
}
for _, message := range messages {
fmt.Println(message.Role, message.Content)
}
model, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("API_KEY"),
Model: os.Getenv("deepseek-chat"),
BaseURL: "https://api.deepseek.com",
})
if err != nil {
log.Fatalf("create model failed: %v", err)
}
generateAndInput(ctx, model, messages)
}
func generateAndInput(ctx context.Context, model *deepseek.ChatModel, messages []*schema.Message) {
resp, err := model.Generate(ctx, messages)
if err != nil {
log.Fatalf("generate failed: %v", err)
}
content := resp.Content
fmt.Println(content)
}
go
func simpleChain() {
ctx := context.Background()
template := prompt.FromMessages(
schema.FString,
schema.SystemMessage("你是一个{role}"),
schema.UserMessage("{question}"),
)
// 创建model
model, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("API_KEY"),
Model: os.Getenv("deepseek-chat"),
BaseURL: "https://api.deepseek.com",
})
if err != nil {
log.Fatalf("create model failed: %v", err)
}
//创建chain
chain := compose.NewChain[map[string]any, *schema.Message]()
chain.AppendChatTemplate(template) //格式化模版
chain.AppendChatModel(model) //调用模型
//编译chain
runnable, err := chain.Compile(ctx)
if err != nil {
log.Fatalf("compile failed: %v", err)
}
//执行chain
input := map[string]any{
"role": "专业的Go程序猿",
"question": "请详解一下interface",
}
output, err := runnable.Invoke(ctx, input)
if err != nil {
log.Fatalf("execute failed: %v", err)
}
fmt.Println(output.Content)
}
go
func simpleLambda() {
ctx := context.Background()
//创建一个简单chain:输入字符串-转大写字母-天假前缀-输出
chain := compose.NewChain[string, string]()
chain.AppendLambda(
compose.InvokableLambda(func(ctx context.Context, input string) (output string, err error) {
fmt.Printf("步骤1:输入=%s\n", input)
result := strings.ToUpper(input)
fmt.Printf("步骤1:输出=%s\n", result)
return result, nil
})).
AppendLambda(
compose.InvokableLambda(func(ctx context.Context, input string) (output string, err error) {
fmt.Printf("步骤2输入=%s\n", input)
result := "prefix" + input
fmt.Printf("步骤2输出=%s\n", result)
return result, nil
}),
)
compile, err := chain.Compile(ctx)
if err != nil {
log.Fatalf("compile failed: %v", err)
}
output, err := compile.Invoke(ctx, "Hello Eino")
if err != nil {
log.Fatalf("execute failed: %v", err)
}
fmt.Println(output)
}
go
func complicateChain() {
ctx := context.Background()
// 数据清洗-分析-总结
// 创建model
model, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("API_KEY"),
Model: os.Getenv("deepseek-chat"),
BaseURL: "https://api.deepseek.com",
})
if err != nil {
log.Fatalf("create model failed: %v", err)
}
// 创建chain
chain := compose.NewChain[string, string]()
chain.AppendLambda(compose.InvokableLambda(func(ctx context.Context, input string) (output string, err error) {
// 对字符串去空格换行等
cleaned := strings.TrimSpace(input)
strings.ReplaceAll(cleaned, "\n\n", "\n")
return cleaned, nil
})).
AppendLambda(compose.InvokableLambda(func(ctx context.Context, input string) (map[string]any, error) {
fmt.Println(input)
return map[string]any{
"text": input,
}, nil
})).
AppendGraph(func() *compose.Chain[map[string]any, *schema.Message] {
analysisChain := compose.NewChain[map[string]any, *schema.Message]()
template := prompt.FromMessages(
schema.FString,
schema.SystemMessage("你是一个文本分析专家,请分析一下文本的关键信息,主题和情感"),
schema.UserMessage("{text}"),
)
analysisChain.AppendChatTemplate(template)
analysisChain.AppendChatModel(model)
return analysisChain
}()).
AppendLambda(compose.InvokableLambda(func(ctx context.Context, msg *schema.Message) (output string, err error) {
fmt.Printf("步骤3提取结果")
return msg.Content, nil
}))
compile, err := chain.Compile(ctx)
if err != nil {
log.Fatalf("compile failed: %v", err)
}
output, err := compile.Invoke(ctx, "Hello Eino")
if err != nil {
log.Fatalf("execute failed: %v", err)
}
fmt.Println(output)
}
javascript
func parallelChain() {
ctx := context.Background()
// 创建model
model, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("API_KEY"),
Model: os.Getenv("deepseek-chat"),
BaseURL: "https://api.deepseek.com",
})
if err != nil {
log.Fatalf("create model failed: %v", err)
}
//创建并行节点
parallel := compose.NewParallel()
// 任务1:提取关键字
parallel.AddLambda("keywords", compose.InvokableLambda(func(ctx context.Context, input map[string]any) (output string, err error) {
fmt.Println("并行任务1:提取关键字")
template := prompt.FromMessages(
schema.FString,
schema.SystemMessage("请提取文本中的关键字,用逗号分隔"),
schema.UserMessage("{text}"),
)
messages, err := template.Format(ctx, input)
if err != nil {
log.Fatalf("format failed: %v", err)
}
resp, err := model.Generate(ctx, messages)
if err != nil {
log.Fatalf("generate failed: %v", err)
}
return resp.Content, nil
}))
//并行任务2 情感分析
parallel.AddLambda("sentiment", compose.InvokableLambda(func(ctx context.Context, input map[string]any) (output string, err error) {
fmt.Println("并行任务2:情感分析")
template := prompt.FromMessages(
schema.FString,
schema.SystemMessage("请分析文本的情感倾向(正面/负面/中性"),
schema.UserMessage("{text}"),
)
messages, err := template.Format(ctx, input)
if err != nil {
log.Fatalf("format failed: %v", err)
}
resp, err := model.Generate(ctx, messages)
if err != nil {
log.Fatalf("generate failed: %v", err)
}
return resp.Content, nil
}))
//以上生成了两个并行任务集合
//现在创建chain
chain := compose.NewChain[string, map[string]any]()
chain.AppendLambda(compose.InvokableLambda(func(ctx context.Context, input string) (output map[string]any, err error) {
return map[string]any{"text": input}, nil
})).
AppendParallel(parallel).
AppendLambda(compose.InvokableLambda(func(ctx context.Context, input map[string]any) (output map[string]any, err error) {
fmt.Println("所有任务完成")
return input, nil
}))
compile, err := chain.Compile(ctx)
if err != nil {
log.Fatalf("compile failed: %v", err)
}
text:= "Eino是一个优秀的开发框架"
output, err := compile.Invoke(ctx, text)
if err != nil {
log.Fatalf("execute failed: %v", err)
}
fmt.Println("任务1",output["keywords"])
fmt.Println("任务2",output["sentiment"])
}
go
func branchChain() {
ctx := context.Background()
// 定义分支条件
branchCondition := func(ctx context.Context, input map[string]any) (string, error) {
language := input["language"].(string)
language = strings.ToLower(language)
if language == "go" {
return "go_branch", nil
}
if language == "python" {
return "py_branch", nil
}
return "other_branch", nil
}
// 定义go分支处理
goBranch := compose.InvokableLambda(func(ctx context.Context, input map[string]any) (output map[string]any, err error) {
fmt.Println("执行go分支")
input["advice"] = "推荐使用Eino框架开发"
input["features"] = []string{"高性能", "并发支持", "类型安全"}
return input, nil
})
// python分支处理
pyBranch := compose.InvokableLambda(func(ctx context.Context, input map[string]any) (output map[string]any, err error) {
fmt.Println("执行py分支")
input["advice"] = "推荐使用LangChain框架开发"
input["features"] = []string{"生态好", "易上手", "社区活跃"}
return input, nil
})
// 其他分支
otherBranch := compose.InvokableLambda(func(ctx context.Context, input map[string]any) (output map[string]any, err error) {
fmt.Println("执行other分支")
input["advice"] = "不推荐"
input["features"] = []string{"生态好", "易上手", "社区活跃"}
return input, nil
})
chain := compose.NewChain[map[string]any, map[string]any]()
chain.AppendLambda(compose.InvokableLambda(func(ctx context.Context, input map[string]any) (output map[string]any, err error) {
fmt.Println("开始处理")
return input, nil
})).
AppendBranch(
compose.NewChainBranch(branchCondition).
AddLambda("go_branch", goBranch).
AddLambda("py_branch", pyBranch).
AddLambda("other_branch", otherBranch),
).
AppendLambda(compose.InvokableLambda(func(ctx context.Context, input map[string]any) (map[string]any, error) {
fmt.Println("处理完成")
return input, nil
}))
compile, err := chain.Compile(ctx)
if err != nil {
log.Fatalf("compile failed: %v", err)
}
testCase := []map[string]any{
{"language": "go"},
{"language": "java"},
{"language": "python"},
}
for _, test := range testCase {
fmt.Println("测试")
output, err := compile.Invoke(ctx, test)
if err != nil {
log.Fatalf("execute failed: %v", err)
}
fmt.Println(output["advice"])
fmt.Println(output["features"])
}
}
javascript
// BaseTool get tool info for ChatModel intent recognition.
type BaseTool interface {
Info(ctx context.Context) (*schema.ToolInfo, error)
}
// InvokableTool the tool for ChatModel intent recognition and ToolsNode execution.
type InvokableTool interface {
BaseTool
// InvokableRun call function with arguments in JSON format
InvokableRun(ctx context.Context, argumentsInJSON string, opts ...Option) (string, error)
}
go
package tool
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/cloudwego/eino/components/tool/utils"
"github.com/cloudwego/eino/schema"
)
// 通过使用NewTool创建
type TimeParams struct {
Format string `json:"format"`
}
type TimeResult struct {
CurrentTime string `json:"current_time"`
}
func GetCurrentTime(ctx context.Context, params *TimeParams) (*TimeResult, error) {
now := time.Now()
var result string
switch params.Format {
case "date":
result = now.Format("2006-01-02")
case "time":
result = now.Format("15:04:05")
default:
result = now.Format("2006-01-02 15:04:05")
}
return &TimeResult{CurrentTime: result}, nil
}
func run() {
ctx := context.Background()
// 使用util.NewTool将函数封装成工具
timeTool := utils.NewTool(&schema.ToolInfo{
Name: "get_current_time",//这个工具的名称
Desc: "获取当前时间",//工具的描述
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"format": {
Type: schema.String,
Desc: "时间格式:date(日期),time(时间),datetime(日期时间)",
Required: false,
},//info接口中需要知道传参的字段名,以及这个字段名的定义格式和相关描述等。这个是个map,所以可以将需要的参数全部告诉info接口
}),
}, GetCurrentTime)
testCase := []string{"date", "time", "datetime"}
for _, format := range testCase {
params := TimeParams{Format: format}
marshal, err := json.Marshal(params)
if err != nil {
fmt.Println(err)
}
outPutJson, err := timeTool.InvokableRun(ctx, string(marshal))
if err != nil {
fmt.Println(err)
}
fmt.Printf("格式=%s,结果=%s\n", format, outPutJson)
}
}
go
package tool
import (
"context"
"fmt"
"os"
"github.com/cloudwego/eino-ext/components/model/deepseek"
"github.com/cloudwego/eino/components/model"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/components/tool/utils"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/schema"
)
func ToolsNodeCase() {
ctx := context.Background()
currentTime := utils.NewTool(&schema.ToolInfo{
Name: "get_cuurent_time",
Desc: "获取当前时间",
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"format": {
Type: schema.String,
Desc: "输出格式",
Required: true,
},
}),
}, GetCurrentTime)
calculator := utils.NewTool(&schema.ToolInfo{
Name: "加法计算器",
Desc: "加法计算器",
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"input": {
Type: "string",
Desc: "输入",
Required: false,
},
}),
}, func(ctx context.Context, params map[string]any) (string, error) {
return "30", nil
})
chatModel, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("CHAT_MODEL_API_KEY"),
Model: os.Getenv("CHAT_MODEL_MODEL"),
BaseURL: os.Getenv("CHAT_MODEL_BASE_URL"),
})
if err != nil {
fmt.Println(err)
}
//创建toolsNOde
toolNode, err := compose.NewToolNode(ctx, &compose.ToolsNodeConfig{
Tools: []tool.BaseTool{calculator, currentTime},
})
if err != nil {
fmt.Println(err)
}
//获取工具列表信息
calInfo, err := calculator.Info(ctx)
if err != nil {
fmt.Println(err)
}
timeInfo, err := currentTime.Info(ctx)
if err != nil {
fmt.Println(err)
}
toolinfos := []*schema.ToolInfo{calInfo, timeInfo}
testCases := []string{
"现在几点了?",
"帮我计算一下10+20等于多少?",
"你好,请介绍一下自己",
}
for _, testCase := range testCases {
messages := []*schema.Message{
schema.UserMessage(testCase),
}
resp, err := chatModel.Generate(ctx, messages, model.WithTools(toolinfos))
if err != nil {
fmt.Println(err)
}
if len(resp.ToolCalls) > 0 {
for _, toolCall := range resp.ToolCalls {
fmt.Println("使用工具", toolCall.Function.Name)
toolResult, err := toolNode.Invoke(ctx, resp)
if err != nil {
fmt.Println(err)
continue
}
fmt.Println("工具调用结果", toolResult)
}
} else {
fmt.Println("直接回答", resp.Content)
}
}
}
go
package tool
import (
"context"
"fmt"
"os"
"github.com/cloudwego/eino-ext/components/model/deepseek"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/components/tool/utils"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/flow/agent/react"
"github.com/cloudwego/eino/schema"
)
func ReactAgentCase() {
ctx := context.Background()
currentTime := utils.NewTool(&schema.ToolInfo{
Name: "get_cuurent_time",
Desc: "获取当前时间",
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"format": {
Type: schema.String,
Desc: "输出格式",
Required: true,
},
}),
}, GetCurrentTime)
calculator := utils.NewTool(&schema.ToolInfo{
Name: "加法计算器",
Desc: "加法计算器",
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"input": {
Type: "string",
Desc: "输入",
Required: false,
},
}),
}, func(ctx context.Context, params map[string]any) (string, error) {
return "30", nil
})
chatModel, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: os.Getenv("CHAT_MODEL_API_KEY"),
Model: os.Getenv("CHAT_MODEL_MODEL"),
BaseURL: os.Getenv("CHAT_MODEL_BASE_URL"),
})
if err != nil {
fmt.Println(err)
}
agent, err := react.NewAgent(ctx, &react.AgentConfig{
ToolCallingModel: chatModel,
ToolsConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{calculator, currentTime},
},
})
if err != nil {
fmt.Println(err)
}
testCases := []string{
"现在几点了?",
"帮我计算一下10+20等于多少?",
"你好,请介绍一下自己",
}
for _, testCase := range testCases {
messages := []*schema.Message{
schema.UserMessage(testCase),
}
resp, err := agent.Generate(ctx, messages)
if err != nil {
fmt.Println(err)
}
fmt.Println("agent回答:", resp.Content)
}
}