01. 基础篇:Go AI 开发范式转移
1. 为什么用 Go 做 AI 应用?
在 AI 训练(Training)领域,Python 是绝对的王者(PyTorch/TensorFlow 生态)。但在 AI 推理(Inference)与应用层开发,Go 正在迅速崛起。
| 特性 | Python | Go | 结论 |
|---|---|---|---|
| 并发模型 | GIL 锁,多线程伪并发,适合单任务 | Goroutine + Channel,原生高并发 | Go 完胜,适合处理高并发 LLM 请求 |
| 类型系统 | 动态类型,运行时报错 | 静态强类型,编译期检查 | Go 更适合大型工程和团队协作 |
| 部署运维 | 依赖地狱 (venv, conda, pip),镜像大 | 单一二进制文件,镜像极小 (Distroless) | Go 是云原生首选 |
| 生态丰富度 | 🌟🌟🌟🌟🌟 (LangChain, LlamaIndex) | 🌟🌟🌟 (LangChainGo, Eino) | Python 库多,但 Go 正在快速补齐 |
核心观点:
- 如果你的任务是洗数据、训练模型、做实验 -> 用 Python。
- 如果你的任务是构建高并发 API 网关、RAG 检索服务、企业级 Agent -> 用 Go。
2. LLM 核心概念速通
作为后端开发,你需要将 LLM 理解为一个**“概率函数”**:输入一段文本(Prompt),输出下一段文本的概率分布。
2.1 Token (词元)
模型不认识单词,只认识 Token。
- 英文:1 word ≈ 1.3 tokens。
- 中文:1 汉字 ≈ 1.5 - 2 tokens (取决于分词器)。
- Go 实战:使用
tiktoken-go计算 Token 数,用于计费和上下文窗口控制。
2.2 Context Window (上下文窗口)
模型的“内存”是有限的(如 GPT-4o 是 128k)。
- 输入 + 输出 < Context Window。
- 这意味着你不能把整本书塞进 Prompt,必须使用 RAG 技术。
2.3 Temperature (温度)
控制输出的随机性。
0.0:最确定,适合代码生成、数学题。0.7 - 1.0:有创意,适合写文章、聊天。
3. Go AI 生态选型
目前 Go 语言主流的 AI 开发方式有三种:
原生 SDK (
go-openai):- 特点: 最轻量,直接封装 OpenAI API 格式。
- 适用: 简单任务,不需要复杂编排。
- 地址:
github.com/sashabaranov/go-openai
框架流 (
langchaingo):- 特点: 模仿 Python LangChain,抽象程度高,内置大量 Tool/Loader。
- 适用: 快速原型开发,需要兼容多种 LLM。
- 地址:
github.com/tmc/langchaingo
工程流 (
eino):- 特点: 字节跳动开源,强调类型安全、图编排、中间件。
- 适用: 企业级复杂应用,强烈推荐。
- 地址:
github.com/cloudwego/eino
4. 实战:构建通用 LLM Client
下面演示如何使用 go-openai 封装一个支持 OpenAI 和兼容接口(如 DeepSeek, Ollama)的通用客户端。
4.1 安装依赖
bash
go get github.com/sashabaranov/go-openai4.2 代码实现
go
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/sashabaranov/go-openai"
)
// LLMClient 封装通用调用逻辑
type LLMClient struct {
client *openai.Client
model string
}
// NewClient 支持 OpenAI 及兼容 OpenAI 协议的模型(如 DeepSeek, Ollama, vLLM)
func NewClient(apiKey string, baseURL string, model string) *LLMClient {
config := openai.DefaultConfig(apiKey)
if baseURL != "" {
config.BaseURL = baseURL
}
return &LLMClient{
client: openai.NewClientWithConfig(config),
model: model,
}
}
// Chat 简单对话
func (c *LLMClient) Chat(ctx context.Context, prompt string) (string, error) {
resp, err := c.client.CreateChatCompletion(
ctx,
openai.ChatCompletionRequest{
Model: c.model,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: prompt,
},
},
Temperature: 0.7,
},
)
if err != nil {
return "", err
}
return resp.Choices[0].Message.Content, nil
}
func main() {
// 示例 1: 调用 OpenAI GPT-4
// client := NewClient(os.Getenv("OPENAI_API_KEY"), "", openai.GPT4)
// 示例 2: 调用本地 Ollama (Llama3)
// BaseURL 通常是 http://localhost:11434/v1
client := NewClient("ollama", "http://localhost:11434/v1", "llama3")
answer, err := client.Chat(context.Background(), "用 Go 语言写一个 Hello World HTTP Server")
if err != nil {
log.Fatalf("Chat failed: %v", err)
}
fmt.Println("AI 回答:", answer)
}5. 进阶作业
- 尝试将上述 Client 改造成支持 Stream(流式)输出,因为 LLM 生成通常较慢,流式输出能极大提升用户体验。
- 使用
tiktoken-go计算输入 Prompt 的 Token 数量,并在日志中打印。
