大模型应用:LangChain-Golang核心模块使用

1.简介

LangChain是一个开源的框架,它提供了构建基于大模型的AI应用所需的模块和工具。它可以帮助开发者轻松地与大型语言模型(LLM)集成,实现文本生成、问答、翻译、对话等任务。LangChain的出现大大降低了AI应用开发的门槛,使得任何人都可以基于LLM构建自己的创意应用。本文将介绍基于Golang使用LangChain相关模块。

项目地址:https://github.com/tmc/langchaingo

2.核心模块

llm调用

go 复制代码
func demo(ctx context.Context) {
    llm, err := openai.New(
       openai.WithModel("gpt-3.5-turbo"),
       openai.WithBaseURL("https://api.openai-proxy.com/v1"),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }
    completion, err := llms.GenerateFromSinglePrompt(ctx,
       llm,
       "hello world!",
       llms.WithTemperature(0),
    )
    if err != nil {
       log.Fatal(err)
    }

    fmt.Println(completion)
}

prompt模板

  • 简单使用
go 复制代码
func promptTemplate(ctx context.Context) {
    llm, err := openai.New(
       openai.WithModel("gpt-3.5-turbo"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }
    prompt := prompts.PromptTemplate{
       Template:       "你是一个文本翻译员,请将```括起来的原始文本转化为{{.lang}}。原始文本```{{.text}}```",
       InputVariables: []string{"text"},
       PartialVariables: map[string]any{
          "lang": "英语",
       },
       TemplateFormat: prompts.TemplateFormatGoTemplate,
    }
    result, err := prompt.Format(map[string]any{
       "text": "我是中国人",
    })
    if err != nil {
       log.Fatal(err)
    }
    fmt.Println(result)
    result, err = llm.Call(ctx, result)
    if err != nil {
       log.Fatal(err)
    }
    fmt.Println(result)
}
  • 带输出格式化
go 复制代码
func promptWithRoleJSON(ctx context.Context) {
    llm, err := openai.New(
       openai.WithModel("gpt-4o"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }

    messages := []llms.MessageContent{
       llms.TextParts(llms.ChatMessageTypeSystem, "你是一个英文翻译员,需要将<>括起来的英文翻译为中文,用JSON格式输出:原始文本、翻译文本"),
       llms.TextParts(llms.ChatMessageTypeHuman, "<hello world>"),
    }
    content, err := llm.GenerateContent(ctx, messages, llms.WithJSONMode())
    if err != nil {
       log.Fatal(err)
    }
    fmt.Println(content.Choices[0].Content)
}

上下文记忆

go 复制代码
func conversationMemory(ctx context.Context) {
    llm, err := openai.New(
       openai.WithModel("gpt-4o"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }
    //memoryBuffer := memory.NewConversationBuffer()
    memoryBuffer := memory.NewConversationWindowBuffer(10)
    //memoryBuffer := memory.NewConversationTokenBuffer(llm, 1024)
    chatChain := chains.NewConversation(llm, memoryBuffer)
    messages := []string{
       "你好,我叫PBR",
       "你知道我叫什么吗?",
       "你可以解决什么问题?",
    }
    for _, message := range messages {
       completion, err := chains.Run(ctx, chatChain, message)
       for {
          if err == nil {
             break
          }
          time.Sleep(30 * time.Second)
          completion, err = chains.Run(ctx, chatChain, message)
       }
       chatMessages, _ := memoryBuffer.ChatHistory.Messages(ctx)
       fmt.Printf("上下文对话历史:%v\n", json.SafeDump(chatMessages))
       fmt.Printf("输入:%v\n输出:%v\n", message, completion)
    }
}

模型链

go 复制代码
func llmChains(ctx context.Context) {
    llm, err := openai.New(
       openai.WithModel("gpt-4o"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }
    // 单个输入
    prompt := prompts.NewPromptTemplate(
       `将"""括起来中文翻译为英文输出
              输入中文:"""{{.text}}"""
              输出结果中只需要有英文翻译,不要有其他字符`,
       []string{"text"})
    llmChain := chains.NewLLMChain(llm, prompt)
    out, err := chains.Run(ctx, llmChain, "langchain是一款不错的llm脚手架")
    if err != nil {
       log.Fatal(err)
    }
    fmt.Println(out)

    // 多个输入
    translatePrompt := prompts.NewPromptTemplate(
       "Translate the following text from {{.inputLanguage}} to {{.outputLanguage}}. {{.text}}",
       []string{"inputLanguage", "outputLanguage", "text"},
    )
    llmChain = chains.NewLLMChain(llm, translatePrompt)

    // Otherwise the call function must be used.
    outputValues, err := chains.Call(ctx, llmChain, map[string]any{
       "inputLanguage":  "English",
       "outputLanguage": "Chinese",
       "text":           "I love programming.",
    })
    if err != nil {
       log.Fatal(err)
    }

    out, ok := outputValues[llmChain.OutputKey].(string)
    if !ok {
       log.Fatal(err)
    }
    fmt.Println(out)
}

顺序链

go 复制代码
unc sequenceChains(ctx context.Context) {
    llm, err := openai.New(
       openai.WithModel("gpt-4o"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }

    // 将输入翻译为特定语言
    chain1 := chains.NewLLMChain(llm,
       prompts.NewPromptTemplate(
          "请将输入的原始文本:{{.originText}}翻译为{{.language}},直接输出翻译文本",
          []string{"originText", "language"}))
    chain1.OutputKey = "transText"

    // 总结翻译后的文本概要
    chain2 := chains.NewLLMChain(llm, prompts.NewPromptTemplate(
       "请将输入的原始文本:<{{.transText}}>总结50字以内概要文本。严格使用JSON序列化输出结果,不要带有```json序列化标识。其中originText为原始文本,summaryText为概要文本",
       []string{"transText"}))
    chain2.OutputKey = "summary_json"

    chain, err := chains.NewSequentialChain([]chains.Chain{chain1, chain2}, []string{"originText", "language"}, []string{"summary_json"})
    if err != nil {
       log.Fatal(err)
    }
    resp, err := chain.Call(ctx, map[string]any{
       "originText": "langchain is a good llm frameworks",
       "language":   "中文",
    })
    if err != nil {
       log.Fatal(err)
    }
    for key, value := range resp {
       fmt.Printf("key = %v | value = %v\n", key, value)
    }
}

向量生成

go 复制代码
func embeddingCreate(ctx context.Context) {
    // embedding生成测试
    llm, err := openai.New(
       openai.WithEmbeddingModel("text-embedding-ada-002"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }
    vectors, err := llm.CreateEmbedding(ctx, []string{"chatgpt-3.5"})
    if err != nil {
       log.Fatal(err)
    }
    fmt.Println(vectors)
}

RAG

  • RAG:检索增强生成,分为向量创建、向量存储、向量召回应用
go 复制代码
func embeddingRag(ctx context.Context) {
    // embedding生成测试
    llm, err := openai.New(
       openai.WithEmbeddingModel("text-embedding-ada-002"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }

    // 创建embedder
    openAiEmbedder, err := embeddings.NewEmbedder(llm)
    if err != nil {
       log.Fatal(err)
    }
    // 基于redis存储向量
    redisStore, err := redisvector.New(ctx,
       redisvector.WithConnectionURL(conf.LLMHubConfig.Redis.Url),
       redisvector.WithIndexName("test_vector_idx", true),
       redisvector.WithEmbedder(openAiEmbedder),
    )
    if err != nil {
       log.Fatalln(err)
    }
    // 插入测试数据
    data := []schema.Document{
       {PageContent: "狸花猫", Metadata: nil},
       {PageContent: "金渐层猫", Metadata: nil},
       {PageContent: "松狮犬", Metadata: nil},
    }

    _, err = redisStore.AddDocuments(ctx, data)
    if err != nil {
       log.Fatalln(err)
    }
    docs, err := redisStore.SimilaritySearch(ctx, "猫", 3,
       vectorstores.WithScoreThreshold(0.5),
    )
    fmt.Println(docs)

    // 将vector检索接入chains中
    result, err := chains.Run(
       ctx,
       chains.NewRetrievalQAFromLLM(
          llm,
          vectorstores.ToRetriever(redisStore, 3, vectorstores.WithScoreThreshold(0.8)),
       ),
       "有哪些猫?",
    )
    fmt.Println(result)
}

Agent

  • Agent = LLM + Memory + Tools
  • 已集成工具使用
go 复制代码
func agent_math_and_search(ctx context.Context) {
    llm, err := openai.New(
       openai.WithModel("gpt-3.5-turbo"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }
    wikiTool := wikipedia.New("test")
    agentTools := []tools.Tool{
       tools.Calculator{},
       wikiTool,
    }
    agent := agents.NewOneShotAgent(llm, agentTools)
    executor := agents.NewExecutor(
       agent,
       agentTools,
       agents.WithCallbacksHandler(callbacks.LogHandler{}),
    )
    // 计算
    result, err := chains.Run(ctx, executor, "计算1024除以2并加1024的结果")
    if err != nil {
       log.Fatal(err)
    }
    fmt.Println(result)
    // 搜索
    result, err = chains.Run(ctx, executor, "今天的日期以及中国在去年今天发生了什么大事")
    if err != nil {
       log.Fatal(err)
    }
    fmt.Println(result)
}
  • 自定义工具
go 复制代码
type randomNumberTool struct{}

func (r randomNumberTool) Name() string {
    return "随机数计算工具"
}

func (r randomNumberTool) Description() string {
    return "用于获取随机数"
}

func (r randomNumberTool) Call(ctx context.Context, input string) (string, error) {
    return "1024", nil
}

func agent_diy(ctx context.Context) {
    llm, err := openai.New(
       openai.WithModel("gpt-3.5-turbo"),
       openai.WithBaseURL(conf.LLMHubConfig.Openai.Host),
       openai.WithToken(conf.LLMHubConfig.Openai.Key),
    )
    if err != nil {
       log.Fatal(err)
    }

    agentTools := []tools.Tool{
       randomNumberTool{},
    }
    agent := agents.NewOneShotAgent(llm, agentTools)
    executor := agents.NewExecutor(
       agent,
       agentTools,
       agents.WithCallbacksHandler(callbacks.LogHandler{}),
    )
    result, err := chains.Run(ctx, executor, "告诉我一个随机数")
    if err != nil {
       log.Fatal(err)
    }
    fmt.Println(result)
}
相关推荐
云和数据.ChenGuang1 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
染指11109 小时前
162.Agent-LangGraph-检查点的作用
人工智能·python·langchain·agents
叼烟扛炮9 小时前
[LangChain] 学习笔记(02):LCEL 链式调用与动态模型配置实战
服务器·开发语言·网络·笔记·学习·langchain
YIAN11 小时前
RAG 学到最后,我真正学会的不是“检索”,而是让系统知道自己缺什么
langchain·node.js·llm
紧跟先前的步伐12 小时前
Go AI Agent 实战 22|完善 Agent 执行循环:从工具调用到最终回答
人工智能·ai·golang
lee_curry13 小时前
第十周完整学习笔记:继续升级为“检索更准、权限安全、索引可维护、失败可恢复、长期可运行”的企业级 RAG 系统
python·ai·langchain·agent·langgraph
后台模板学习14 小时前
Go Web开发中任务调度框架的源码解析与高可用实现方案
开发语言·后端·golang
FungLeo14 小时前
成为全栈·Go 后端篇·分类树与标签关系:目录变更为何需要协调
golang·go·gorm·数据库事务·分类树·成为全栈
fly-iot14 小时前
【FDE知识库】(1):AI 编程时代开发语言选型分析,云使用go,企业用java,算法python,底层c
开发语言·人工智能·golang
FungLeo14 小时前
成为全栈·Go 后端篇·文章查询与展示投影:安全分页、排序和软删除
golang·go·gorm·分页查询·成为全栈·sql安全