用 LangChain Go 实现 Google AI Gemini 流式输出:googleai-streaming-example 全解析
用 LangChain Go 实现 Google AI Gemini 流式输出googleai-streaming-example 全解析【免费下载链接】langchaingoLangChain for Go, the easiest way to write LLM-based programs in Go项目地址: https://gitcode.com/GitHub_Trending/la/langchaingo导读本文以 googleai-streaming-example 为线索完整讲解如何在 LangChain Golangchaingo中调用 Google AI 的 Gemini 系列模型并通过WithStreamingFunc以流式方式实时接收与打印模型输出。读完本文你将掌握 Gemini 客户端的初始化、多角色消息构造、流式回调的底层实现原理以及如何替换模型与个性化 Prompt直接上手构建自己的流式 LLM 程序。示例程序在做什么该示例是一个不到 40 行的 Go 小程序完整演示了「Google AI 鉴权 → Gemini 模型接入 → 多消息对话 → 流式输出」的完整链路通过GOOGLE_API_KEY环境变量完成对 Google AI 服务的认证建立到 Gemini 1.5 Pro 模型的连接构造一个「公司品牌设计魔法师」company branding design wizard的角色场景向模型提问为一个生产 Go 技术栈 LLM 工具的公司起个好名字以流式方式接收 AI 回复每个文本块到达后立即打印到控制台。从源码看其主程序位于 googleai-stremaing-example.go对应的模块文件 go.mod 声明module github.com/tmc/langchaingo/examples/googleai-streaming-example要求 Go 1.24.3 及以上版本并依赖github.com/tmc/langchaingo示例锁定在v0.1.14-pre.4。环境准备与运行方式前置条件已安装 Go示例要求go 1.24.3见 go.mod一个可用的 Google AI API Key可从 ai.google.dev 获取。设置环境变量在终端中导出你的 API Keyexport GOOGLE_API_KEYyour_api_key_here值得一提的是即使不显式传入 KeyLangChain Go 的 Google AI 客户端也会在构造时自动回退到该环境变量Options.EnsureAuthPresent()会在未配置任何认证选项时读取GOOGLE_API_KEY并注入客户端见 option.go。因此「设置环境变量」这一步几乎是所有 Google AI 程序的最低配置门槛。运行示例go run googleai-streaming-example.go注意示例程序不包含自己的go.mod独立执行路径之外的额外依赖说明建议在仓库的examples/googleai-streaming-example目录下运行或将该目录作为独立模块用go run .执行。运行效果程序启动后模型回复会以「打字机」式的节奏实时滚动输出到控制台而不是等整段文本生成完毕后再一次性返回。这种体验在问答、聊天机器人、流式摘要等对「首字延迟」敏感的场景中至关重要。核心代码逐段解析1. 初始化 Gemini 客户端ctx : context.Background() apiKey : os.Getenv(GOOGLE_API_KEY) llm, err : googleai.New(ctx, googleai.WithAPIKey(apiKey), googleai.WithDefaultModel(gemini-1.5-pro)) if err ! nil { log.Fatal(err) }googleai.New是 Google AI provider 的入口构造函数位于 new.go。它先合并DefaultOptions()再依次应用传入的Option最后调用genai.NewClient创建底层客户端googleai.WithAPIKey将 API Key 写入客户端的认证选项见 option.gogoogleai.WithDefaultModel(gemini-1.5-pro)指定默认模型名该值会存入Options.DefaultModel后续未显式指定模型的调用都会使用它。可供选用的 Gemini 模型清单参见 ai.google.dev 的 Gemini API 模型文档。提示若不设置WithDefaultModel默认模型为gemini-2.0-flash见 option.go 的DefaultOptions。2. 构造多角色对话消息content : []llms.MessageContent{ llms.TextParts(llms.ChatMessageTypeSystem, You are a company branding design wizard.), llms.TextParts(llms.ChatMessageTypeHuman, What would be a good company name for a comapny that produces Go-backed LLM tools?), }llms.MessageContent是 langchaingo 统一的消息结构由Role角色与Parts内容片段列表组成见 generatecontent.gollms.TextParts(role, parts...)是快捷构造器以指定角色包装若干文本片段见 generatecontent.go消息角色在 chat_messages.go 中定义ChatMessageTypeSystemsystem系统指令、ChatMessageTypeHumanhuman用户输入、ChatMessageTypeAIai模型回复。3. 流式生成并逐块打印completion, err : llm.GenerateContent(ctx, content, llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error { fmt.Print(string(chunk)) return nil })) if err ! nil { log.Fatal(err) } _ completionllm.GenerateContent是llms.Model接口的核心方法Google AI 实现位于 googleai.gollms.WithStreamingFunc来自 options.go它会设置CallOptions.StreamingFunc。一旦设置了该回调生成过程便切换为流式模式回调函数签名是func(ctx context.Context, chunk []byte) error每个chunk是模型产出的一个文本片段这里直接fmt.Print到标准输出completion变量保存最终聚合的完整响应含Choices与GenerationInfo示例中未使用故用_忽略。流式输出背后的源码实现理解GenerateContent内部的分支逻辑就能明白「设置一个回调函数」为何能改变整个请求模式在 googleai.go 的generateFromSingleMessage中if opts.StreamingFunc nil { // 非流式一次性调用 GenerateContent 并返回完整候选 resp, err : model.GenerateContent(ctx, convertedParts...) ... } iter : model.GenerateContentStream(ctx, convertedParts...) return convertAndStreamFromIterator(ctx, iter, opts)即未提供StreamingFunc时走model.GenerateContent一次性返回提供了则调用底层的GenerateContentStream拿到一个响应迭代器再交给convertAndStreamFromIterator消费。convertAndStreamFromIterator见 googleai.go是流式处理的核心循环不断调用iter.Next()拉取下一个响应块遇到iterator.Done时结束循环将每个块的genai.Text片段通过opts.StreamingFunc(ctx, []byte(text))实时推送给调用方同时把各块拼接到一个聚合的candidate上最后通过convertCandidates产出完整的llms.ContentResponse。需要留意的是流式模式下该实现目前假设只有单个候选len(resp.Candidates) ! 1会返回错误这对常规问答场景完全够用。客户端配置参数全览Google AI provider 默认配置DefaultOptions()见 option.go给出如下出厂默认值未显式覆盖时生效配置项默认值说明DefaultModelgemini-2.0-flash默认内容生成模型DefaultEmbeddingModelembedding-001默认 Embedding 模型DefaultCandidateCount1返回候选数DefaultMaxTokens2048单次生成最大 Token 数DefaultTemperature0.5采样温度随机性DefaultTopK3Top-K 采样DefaultTopP0.95Top-P 采样HarmThresholdHarmBlockOnlyHigh安全过滤阈值常用构造选项googleai.Option全部选项定义见 option.go常用包括WithAPIKey(apiKey)API Key 认证WithDefaultModel(model)指定默认模型示例即用它切换到gemini-1.5-proWithDefaultMaxTokens/WithDefaultTemperature/WithDefaultTopK/WithDefaultTopP/WithDefaultCandidateCount覆盖上述默认采样参数WithHarmThreshold(ht)设置安全阈值枚举HarmBlockUnspecified、HarmBlockLowAndAbove、HarmBlockMediumAndAbove、HarmBlockOnlyHigh、HarmBlockNoneWithCredentialsJSON/WithCredentialsFile使用服务账号 JSON 凭证认证适合 Vertex AI 场景WithRest()强制走 REST API 而非默认的 gRPC测试与排查时有用WithHTTPClient/WithGRPCConn注入自定义 HTTP 客户端或 gRPC 连接WithCloudProject/WithCloudLocation面向 Vertex AI 的项目与区域配置。调用级选项llms.CallOption流式回调只是其中之一GenerateContent还支持按调用覆盖模型与采样参数例如llms.WithModel、llms.WithTemperature、llms.WithMaxTokens、llms.WithTopP、llms.WithStopWords等见 options.go。它们与构造选项的区别在于前者作用于单次调用后者作用于整个客户端。自定义与进阶玩法原示例 README 建议你自由探索以下两个方向1. 修改角色设定与提问替换ChatMessageTypeSystem的系统提示词即可切换角色例如改成「你是一位资深的产品经理」再配合调整 Human 消息内容就能快速验证不同场景下的流式回复效果。2. 更换模型把WithDefaultModel(gemini-1.5-pro)改成其他 Gemini 模型名如gemini-2.0-flash即可。也可以不预设默认模型而在单次调用时用llms.WithModel(...)临时指定。进阶方向流式场景下保留最终结果GenerateContent返回的completion中已聚合完整文本可在流式打印的同时将其用于后续逻辑如继续交给下一个 Chain接入 Vertex AI仓库中llms/googleai/vertex目录提供了 GCP Vertex AI 的对应 provider且据 llms/googleai/README.md 说明vertex包的绝大部分代码由googleai包通过代码生成工具派生两者 API 高度一致多轮对话向content切片追加llms.TextParts(llms.ChatMessageTypeAI, ...)与新的 Human 消息即可构造带上下文的聊天历史。测试与验证流式能力有据可依仓库为 Google AI provider 提供了完善的测试覆盖其中与本文主题直接相关的是录制文件 TestGoogleAIWithStreaming.httprr记录了流式调用场景下的真实 HTTP 交互共享测试代码 shared_test.go 展示了官方测试如何组织优先使用录制的 httprr 回放通过WithRest()、WithAPIKey(test-api-key)与WithHTTPClient(rr.Client())组合注入录制客户端并会清洗请求中的真实 Key 以保证录制品安全。你可以用以下命令在本地复现 provider 级测试需在仓库根目录执行go test ./llms/googleai/...小结本文以googleai-streaming-example为起点覆盖了从环境准备、程序运行到googleai.New客户端初始化、llms.TextParts消息构造、WithStreamingFunc流式回调的完整链路并深入到GenerateContent的源码层面揭示了「是否提供流式回调」这一参数如何决定底层走GenerateContent还是GenerateContentStream两条路径。掌握这些之后你完全可以在该示例基础上快速搭建属于自己的、带实时流式输出的 Gemini 应用。【免费下载链接】langchaingoLangChain for Go, the easiest way to write LLM-based programs in Go项目地址: https://gitcode.com/GitHub_Trending/la/langchaingo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考