OpenAI 大火后有许多开发者正在活想要基于 OpenAI 做很多上层应用的开发,这方面在 Python 的生态确实比较完善,但对于 Gopher 来说要获得结构化的结果还需要额外的工作,没有既定的最佳实践。
在 golang 世界中,还没有这样的协议。但有一种非常成熟、稳定、广泛使用的协议可以实现我们想要的大部分功能:protobufs 和 protojson(用于将结构化内存中的结构转换为 JSON)。
在本文中,我们将通过代码来实现这种组合:OpenAI(包括 ollama + open weights)+ protobufs + golang。
实现
我们希望创建一个 POC,对输入和输出进行稳健的类型化验证:
输入应为国家名称,输出应为国家名称和其他统计数据。
如何在 Golang 中使用 OpenAI
这里我们使用 Sasha Baranov 开发的非官方 Golang OpenAI 客户端。
设计协议
创建 protobuf 文件:
1 | syntax = "proto3"; |
现在创建 go 对应程序(需要安装 protoc 才能使用):1
protoc --go_out=. countryinfo.proto
这将为我们在 main.go 文件中使用的内容创建一个 go 原生类型验证。我们的包含文件需要包含 protobuf,我们还需要 protojson 来解析 LLM 的输入和输出:
1 | "countryinfo/protobuf" |
system prompt
我们需要让 OpenAI 与 protobuf 对话。我们可以通过系统提示完成这项工作:
- 我们验证输出(以及输入)
- 在系统提示中包含了一份原生数据库的文本副本,显然每次重新生成原生数据库时都需要手动同步。
1
2
3
4
5
6
7
8
9
10
11
12
13
14systemPrompt := `You are a programmatic country information API used software applications.
All input messages provided MUST adhere to the CountryRequest schema: validate them and throw an error if not.
Your responses MUST adhere to the CountryResponse schema ONLY with no additional narrative or markup, backquotes or anything.
message CountryRequest {
string country = 1;
}
message CountryResponse {
string country = 1;
int32 country_population = 2;
string capital = 3;
int32 capital_population = 4;
int64 gdp_usd = 5;
}
创建类型安全请求
1 | req := openai.ChatCompletionRequest{ |
这是方法定义。看一下我们是如何使用自动生成的 protobuf 来验证内容的:
1 | func encodeCountryRequest(country string) string { |
处理 response
1 | func decodeCountryResponse(data string) (*protobuf.CountryResponse, error) { |
兼容性
上面的代码默认使用 GPT 3.5,但如果你有足够的预算,也可以重写模型使用 GPT 4,还可以重写主机网址指向 ollama(因为它与 OpenAI-API 兼容)。
下面是成功测试过的模型:
- GPT 3.5
- GPT 4
- 本地安装的 llama3-instruct
- Claude Haiku claude-3-haiku-20240307 (最便宜的型号)