本文用的是ChatGPT为示例,如果你无法注册也可以应用 文心一言 作为示例,langchainGo也支持
1. AIGC
自从ChatGPT的横空出世开始,点燃了各大行业对于AI的探讨和研究,而其中AIGC是其中的核心话题之一,现如今很多的网站系统均有应用AIGC的示例,比如掘金就应用了AIGC辅助我们对于文章的阅读。
然对于该话题暂且就到这,我们的核心问题是go语言如何进行AIGC的开发。
2. 应用程序与ChatGPT的开发基本方式
2.1 AIGC使用
在我们平常的使用中主要是基于现有的Chat界面,然后向其输入提示词让AI根据提示词完成对应事项。
在这个过程中输入是:字符串【提示词】、输出:字符串【提示词】
2.2 应用程序与ChatGPT开发
应用程序只是将我们向ChatGPT提问的过程用程序处理,因此在输入和输出上仍然是以字符串进行交互。
但如果是无序的字符串则对于程序而言则无疑增加开发难点,在传统的API接口开发中均会约定最基础的数据结构比如
要求传递:
{
"id": xxx
}
确定输出
{
"id": xxx,
"name": "langchainGo"
}
AI是智能的,我们可以在发送的提示词中要求AI给我们返回以json格式的数据,这样我们就可以从中解析出自己所需要的数据。
比如如下示例:
2.3 总结
因此在应用程序与ChatGPT进行对接开发中
- 输入:字符串
- 输出:字符串
- 要求:我们需要自己指定输出的数据格式,最好可以被程序以特定格式解析如json格式
在与ChatGPT的开发中,我们需要自己定义目标的输出数据格式,此项依据自己的项目定义。
3. openai - sdk
对于大模型的调用我们以ChatGPT为示例,下载如下的sdk即可开发
func Test_OpenAIText(t *testing.T) {
// 配置
gptCfg := openai.DefaultConfig(apiKey)
gptCfg.BaseURL = url
// 客户端
client := openai.NewClientWithConfig(gptCfg)
// 请求
res, err := client.CreateCompletion(context.Background(), openai.CompletionRequest{
Model: openai.GPT3Dot5TurboInstruct,
MaxTokens: 5,
Prompt: "hello world",
})
if err != nil {
t.Fatal(err)
}
t.Log(res)
}
4. langchainGo
langchain我们可以将其理解为是一款框架也可以理解为是一个组件,它是一种方案用于解决应用程序与AI的应用开发交互过程中的问题。
它总共有如下几个核心模块
- Agents(代理):主要的事项是以LLM作为驱动,期望让大模型自己可以调用内部或者外部的工具
- Chains(链):可以认我们将多个组件组合在一起使用,以应对特殊场景的功能
- Indexes(索引 -):许多LLM应用中特定数据并不在模型训练集中,Langchain提供了加载、转化、存储和查询数据的构建块【可以理解为是本地知识库】 DocumentLoaders、VectorStores、Retrievers
- Memory(记忆存储): 用于在链直接存储和传递信息,实现对话上下文感知能力
- Models(模型):包含各大语言模型的 LangChain 接口和调用细节,以及输出解析机制。
- Prompts(提示工程):理论上可以划分与Models中,提示模板的目标是使跨不同模型重用提示变得容易。它们允许将提示工程与模型调用分开。借助对自定义模板的支持,您可以根据用例的需要灵活地参数化和格式化提示。
- Callback:LangChain提供了一个回调系统,允许开发者在LLM应用的各个阶段对状态进行干预。有点类似于事件。
4.1 使用
你只需要下载langchainGo的依赖包即可
go get github.com/tmc/langchaingo
简单案例
import (
"context"
"testing"
"github.com/tmc/langchaingo/llms"
"github.com/tmc/langchaingo/llms/openai"
)
func TestLLM_text(t *testing.T) {
url:= "" // 可以不提,如果用代理则需要填写
apiKey := "" // key
ctx := context.Background()
//llm, err := ernie.New(ernie.WithAKSK("", ""))
llm, err := openai.New(openai.WithBaseURL(url), openai.WithToken(apiKey))
if err != nil {
t.Fatal(err)
}
prompt := "我很帅气对吗"
text, err := llms.GenerateFromSinglePrompt(ctx, llm, prompt)
NoError(t, err)
t.Log(text)
}
我们以前面具的例子用langchainGo实现
package main
import (
"context"
"fmt"
"github.com/tmc/langchaingo/callbacks"
"github.com/tmc/langchaingo/chains"
"github.com/tmc/langchaingo/llms/openai"
"github.com/tmc/langchaingo/outputparser"
"github.com/tmc/langchaingo/prompts"
)
func main() {
url := "https://api.aiproxy.io/v1"
apiKey := ""
ctx := context.Background()
llm, err := openai.New(openai.WithBaseURL(url), openai.WithToken(apiKey))
if err != nil {
panic(err)
}
// 定义要求大模型返回的数据格式
output := outputparser.NewStructured([]outputparser.ResponseSchema{
{
Name: "city",
Description: "城市",
}, {
Name: "temperature",
Description: "气温",
}, {
Name: "weather",
Description: "天气",
},
})
// output会根据指定的内容生成要求大模型根据指定格式返回的提示词,与基础提示词拼接就是最终提示词
template := "请问今天{{.input}}天气怎么样" + output.GetFormatInstructions()
fmt.Println("提示词:", template)
// 这是组成用户问题的基础提示词,其中city则是可代替的内容
prompt := prompts.NewPromptTemplate(template, []string{"input"})
// callback是langchain中的事件,可以打印出其中交互的提示词
callback := callbacks.LogHandler{}
chain := chains.NewLLMChain(llm, prompt, chains.WithCallback(callback))
// 运行
res, err := chains.Call(ctx, chain, map[string]any{
"input": "长沙",
})
if err != nil {
panic(err)
}
fmt.Println("结果: ", res)
}
运行结果
D:\01.project\01.go\src\gitee.com\dn-jinmin\scenario\07.langchain>go run .
提示词: 请问今天{{.input}}天气怎么样The output should be a markdown code snippet formatted in the following schema:
```json
{
"city": string // 城市
"temperature": string // 气温
"weather": string // 天气
}
Entering chain with inputs: “input” : “长沙”,
Exiting chain with outputs: “text” : “json { "city": "长沙", "temperature": "28°C", "weather": "多云" }
”,
结果: map[text:```json
{
“city”: “长沙”,
“temperature”: “28°C”,
“weather”: “多云”
}
D:\01.project\01.go\src\gitee.com\dn-jinmin\scenario\07.langchain>