大模型应用:LangChain-Golang核心模块使用
1.简介
LangChain是一个开源的框架,它提供了构建基于大模型的AI应用所需的模块和工具。它可以帮助开发者轻松地与大型语言模型(LLM)集成,实现文本生成、问答、翻译、对话等任务。LangChain的出现大大降低了AI应用开发的门槛,使得任何人都可以基于LLM构建自己的创意应用。本文将介绍基于Golang使用LangChain相关模块。
项目地址:https://github.com/tmc/langchaingo
2.核心模块
llm调用
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模板
- 简单使用
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)
}
- 带输出格式化
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)
}
上下文记忆
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)}
}
模型链
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)
}
顺序链
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)}
}
向量生成
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:检索增强生成,分为向量创建、向量存储、向量召回应用
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)}// 创建embedderopenAiEmbedder, 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
- 已集成工具使用
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)
}
- 自定义工具
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)
}
相关文章:

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

【Tkinter界面】Canvas 图形绘制(03/5)
文章目录 一、说明二、画布和画布对象2.1 画布坐标系2.2 鼠标点中画布位置2.3 画布对象显示的顺序2.4 指定画布对象 三、你应该知道的画布对象操作3.1 什么是Tag3.2 操作Tag的函数 https://www.cnblogs.com/rainbow-tan/p/14852553.html 一、说明 Canvas(画布&…...

【CS.PL】Lua 编程之道: 基础语法和数据类型 - 进度16%
2 初级阶段 —— 基础语法和数据类型 文章目录 2 初级阶段 —— 基础语法和数据类型2.0 关键字(keywords) 🔥2.1 注释与标识符2.1.1 注释2.1.2 标识符 2.2 变量与赋值2.2.1 所有变量默认是全局变量 ≠ local, 有一个例外2.2.2 local变量是局部变量, 以end作为边界2.…...
centos7 xtrabackup mysql 基本测试(3)---虚拟机环境 安装mysql
centos7 xtrabackup mysql 基本测试(3)—虚拟机环境 安装mysql centos7 安装 mysql5.7 可以在运行安装程序之前导入密钥: sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022第一步、下载MySQL 安装包: sudo w…...
Java Native Interface 使用指南
我们知道Java本身的实现,很大一部分是用C写的。实际上,Java也允许我们和原生平台的代码进行交互。 Java定义了一个接口规范,就叫做Java Native Interface,通过这个接口规范,我们就可以让Java代码运行原生平台的代码。…...
代码随想录算法训练营第三十九天 | 62.不同路径、63. 不同路径 II、343. 整数拆分、96.不同的二叉搜索树
62.不同路径 题目链接:https://leetcode.cn/problems/unique-paths/ 文档讲解:https://programmercarl.com/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE… 视频讲解:https://www.bilibili.com/video/BV1ve4y1x7Eu/ 思路 确定dp数组以及下标的含…...
C/C++函数指针、C#委托是什么?
函数指针 #include<stdio.h>//声明函数指针 typedef int(*Calc)(int a, int b); int Add(int a, int b) {return a b; } int Sub(int a, int b) {return a - b; }int main() {Calc funcPoint1 &Add;Calc funcPoint2 ⋐int x 120;int y 140;int z 0;z …...
红队攻防渗透技术实战流程:组件安全:JacksonFastJsonXStream
红队攻防渗透实战 1. 组件安全1.1 J2EE-组件Jackson-本地demo&CVE1.1.1 代码执行 (CVE-2020-8840)1.1.2 代码执行(CVE-2020-35728)1.2 J2EE-组件FastJson-本地demo&CVE1.2.1 FastJson <= 1.2.241.2.2 FastJson <= 1.2.471.2.3 FastJson <= 1.2.801.3 J2EE-组…...

Perl 语言学习进阶
一、如何深入 要深入学习Perl语言的库和框架,可以按照以下步骤进行: 了解Perl的核心模块:Perl有许多核心模块,它们提供了许多常用的功能。了解这些模块的功能和用法是深入学习Perl的第一步。一些常用的核心模块包括:S…...

LangGraph实战:从零分阶打造人工智能航空客服助手
❝ 通过本指南,你将学习构建一个专为航空公司设计的客服助手,它将协助用户查询旅行信息并规划行程。在此过程中,你将掌握如何利用LangGraph的中断机制、检查点技术以及更为复杂的状态管理功能,来优化你的助手工具,同时…...

R可视化:R语言基础图形合集
R语言基础图形合集 欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2 基础图形可视化 数据分析的图形可视化是了解数据分布、波动和相关性等属性必…...

mysql导入sql文件失败及解决措施
1.报错找不到表 1.1 原因 表格创建失败,编码问题mysql8相较于mysql5出现了新的编码集 1.2解决办法: 使用vscode打开sql文件ctrlh,批量替换,替换到你所安装mysql支持的编码集。 2.timestmp没有设置默认值 Error occured at:20…...
JS:获取鼠标点击位置
一、获取鼠标在目标元素中的点击位置 getClickPos.ts: export const getClickPos (e: MouseEvent) > {return {x: e.offsetX,y: e.offsetY,}; };二、获取鼠标在页面中的点击位置 getClickPos.ts: export const getPageClickPos (e: MouseEvent) > {return {x: e.pa…...
使用开源的zip.cpp和unzip.cpp实现压缩包的创建与解压(附源码)
目录 1、使用场景 2、压缩包的创建 3、压缩包的解压 4、CloseZipZ和CloseZipU两接口的区别...
npm 异常:peer eslint@“>=1.6.0 <7.0.0“ from eslint-loader@2.2.1
node 用16版本 npm install npm6.14.15 -g将版本降级到6...

Docker|了解容器镜像层(2)
引言 容器非常神奇。它们允许简单的进程表现得像虚拟机。在这种优雅的底层是一组模式和实践,最终使一切运作起来。在设计的根本是层。层是存储和分发容器化文件系统内容的基本方式。这种设计既出人意料地简单,同时又非常强大。在今天的帖子[1]中…...

使用Python爬取temu商品与评论信息
【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作! 【&…...

mybatis学习--自定义映射resultMap
1.1、resultMap处理字段和属性的映射关系 如果字段名和实体类中的属性名不一致的情况下,可以通过resultMap设置自定义映射。 常规写法 /***根据id查询员工信息* param empId* return*/ Emp getEmpByEmpId(Param("empId") Integer empId);<select id…...

Elasticsearch之写入原理以及调优
1、ES 的写入过程 1.1 ES支持四种对文档的数据写操作 create:如果在PUT数据的时候当前数据已经存在,则数据会被覆盖,如果在PUT的时候加上操作类型create,此时如果数据已存在则会返回失败,因为已经强制指定了操作类型…...
python中装饰器的用法
最近发现装饰器是一个非常有意思的东西,很高级! 允许你在不修改函数或类的源代码的情况下,为它们添加额外的功能或修改它们的行为。装饰器本质上是一个接受函数作为参数的可调用对象(通常是函数或类),并返…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...