Hindsight Go 客户端实战:从 Retain/Recall/Reflect 到 Nullable 字段与错误处理的完整指南
2026/9/14 9:33:10 网站建设 项目流程

Hindsight Go 客户端实战:从 Retain/Recall/Reflect 到 Nullable 字段与错误处理的完整指南

【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight

本文基于 Hindsight 仓库version-0.8文档中的 Go Client 章节与hindsight-clients/go下的实际生成代码编写,覆盖 Go 客户端的安装方式、Retain/Recall/Reflect 三大核心记忆操作的完整调用示例、结构化 API 命名空间划分、NullableString/NullableTime等可空字段类型的正确使用姿势,以及基于Execute()三元组返回值的错误处理模式。读完后你可以直接在 Go 服务中接入 Hindsight HTTP API,理解每个请求/响应模型背后的生成机制,并正确处理服务端错误。

安装

Hindsight 官方 Go 客户端由 OpenAPI 3.1 规范通过 OpenAPI Generator 自动生成,作为标准 Go 模块发布在仓库内,安装命令为:

go get github.com/vectorize-io/hindsight/hindsight-clients/go

文档要求 Go 1.23+。模块路径定义在 go.mod 中(module github.com/vectorize-io/hindsight/hindsight-clients/go),核心依赖仅有github.com/stretchr/testify(测试用)与gopkg.in/validator.v2,无重量级第三方运行时依赖。

导入时使用别名hindsight

import hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"

提示:从源码文件头(如 client.go)可以看到生成的 API 版本标记,例如API version: 0.9.2,可用于核对客户端与目标 Hindsight 服务端的版本对应关系。仓库根目录的 scripts/generate-clients.sh 与 scripts/generate-openapi.sh 用于从 OpenAPI 规范重新生成各类语言客户端,说明该目录下的代码是生成产物(文件头均带有Code generated by OpenAPI Generator; DO NOT EDIT标记),不应手工修改。

快速上手:Retain、Recall、Reflect 三步闭环

官方示例 hindsight-docs/examples/api/quickstart.go 展示了记忆系统最核心的三个操作:写入(Retain)、检索(Recall)与推理生成(Reflect)。完整示例如下:

func main() { apiURL := os.Getenv("HINDSIGHT_API_URL") if apiURL == "" { apiURL = "http://localhost:8888" } cfg := hindsight.NewConfiguration() cfg.Servers = hindsight.ServerConfigurations{ {URL: "http://localhost:8888"}, } client := hindsight.NewAPIClient(cfg) ctx := context.Background() // Retain a memory retainReq := hindsight.RetainRequest{ Items: []hindsight.MemoryItem{ {Content: hindsight.TextContent("Alice works at Google")}, }, } client.MemoryAPI.RetainMemories(ctx, "my-bank").RetainRequest(retainReq).Execute() // Recall memories recallReq := hindsight.RecallRequest{ Query: "What does Alice do?", } resp, _, _ := client.MemoryAPI.RecallMemories(ctx, "my-bank").RecallRequest(recallReq).Execute() for _, r := range resp.Results { fmt.Println(r.Text) } // Reflect - generate response reflectReq := hindsight.ReflectRequest{ Query: "Tell me about Alice", } answer, _, _ := client.MemoryAPI.Reflect(ctx, "my-bank").ReflectRequest(reflectReq).Execute() fmt.Println(answer.GetText()) }

三个操作对应的模型文件分别为 model_retain_request.go、model_recall_request.go 与 model_reflect_request.go,它们都是强类型的生成结构体,字段与服务端 Pydantic 模型一一对应。示例中有几个值得注意的 API 形态细节:

  • Builder 链式调用client.MemoryAPI.RetainMemories(ctx, "my-bank")返回一个请求构造器,.RetainRequest(retainReq)设置请求体后,.Execute()才真正发起 HTTP 请求。bank_id(此处为"my-bank")是路径参数,直接作为方法参数传入。
  • TextContent便捷类型hindsight.TextContent("...")用于构造MemoryItem.Content,它是内容联合类型(ContentAnyOfInner,见 model_content_any_of_inner.go)的文本分支;多模态场景下还可以构造图片内容块(ImageContentBlock,见 model_image_content_block.go)。
  • Execute()三元组返回值(data, httpResp, err)。示例中 Retain/Reflect 的httpResperr被忽略,属于演示简化,生产代码应按下文「错误处理」一节处理。

API 结构:结构化命名空间

Go 客户端通过结构化命名空间(API service)组织所有 Hindsight API 操作。文档列出的核心命名空间:

命名空间职责
client.MemoryAPIRetain、Recall、Reflect 操作
client.BanksAPI记忆银行(Memory Bank)管理
client.DirectivesAPIDirective 管理
client.MentalModelsAPI心智模型(Mental Model)管理
client.DocumentsAPI文档操作
client.EntitiesAPI实体操作
client.OperationsAPI异步操作监控

从 client.go 的APIClient结构体看,当前版本实际注册了 15 个 API service,除上表所列之外还包括AuditAPIBankTemplatesAPIDocumentTransferAPIFilesAPIKnowledgeBaseAPILLMTracesAPIMonitoringAPIWebhooksAPI,与 hindsight-clients/go/README.md 中生成的端点文档一一对应。其中与文档核心主题直接相关的典型端点(摘自该 README 的端点表):

  • MemoryAPI.RetainMemoriesPOST /v1/default/banks/{bank_id}/memories(写入记忆)
  • MemoryAPI.RecallMemoriesPOST /v1/default/banks/{bank_id}/memories/recall(检索记忆)
  • MemoryAPI.ReflectPOST /v1/default/banks/{bank_id}/reflect(基于记忆生成回答)
  • BanksAPI.CreateOrUpdateBank/ListBanks/DeleteBank— 银行生命周期管理
  • OperationsAPI.GetOperationStatus— 查询异步操作状态,用于轮询 Retain 等返回 operation ID 的异步任务

所有 service 共享同一个底层service结构(client.go 中NewAPIClient的初始化逻辑),即一个APIClient实例内部复用同一http.Client,官方注释也建议在大多数场景下只创建一个共享的APIClient

处理 Nullable 字段

Go 客户端使用NullableStringNullableTime等类型表示可选字段,以便区分「字段未设置」与「字段显式设为 null」。官方示例中的用法:

// Creating nullable values timestamp := time.Date(2024, 1, 15, 10, 0, 0, 0, time.UTC) retainReq2 := hindsight.RetainRequest{ Items: []hindsight.MemoryItem{ { Content: hindsight.TextContent("Alice got promoted"), Context: *hindsight.NewNullableString(hindsight.PtrString("career update")), Timestamp: *hindsight.NewNullableTimestamp(&hindsight.Timestamp{TimeTime: hindsight.PtrTime(timestamp)}), Tags: []string{"career"}, }, }, } retainResp, _, _ := client.MemoryAPI.RetainMemories(ctx, "my-bank").RetainRequest(retainReq2).Execute() // Checking if a value is set if retainResp.HasOperationId() { fmt.Println("OperationId:", retainResp.GetOperationId()) }

从 utils.go 的源码可以看到 Nullable 类型族的统一设计:每个Nullable<T>结构体内部持有value *TisSet bool两个字段,提供Get()(取指针值)、Set(val)IsSet()(判断是否显式设置过)、Unset()(重置为未设置)方法,并通过自定义MarshalJSON/UnmarshalJSON保证 JSON 序列化时只输出值本身。配合生成的模型方法HasOperationId()/GetOperationId(),可以安全地在响应字段缺失与显式 null 之间做区分——这对于RetainResponse中可能出现的异步operation_id字段尤其重要(同步写入时为空,异步写入时返回可轮询的操作 ID)。

此外,utils.go 提供了一组指针辅助函数,避免在结构体字面量中手写&var

  • PtrBoolPtrIntPtrInt32PtrInt64
  • PtrFloatPtrFloat32)、PtrFloat64
  • PtrStringPtrTime

例如hindsight.PtrString("career update")返回*string,正是NewNullableString需要的入参。时间戳字段使用的是生成的Timestamp包装模型(model_timestamp.go),其TimeTime字段为*time.Time,通过NewNullableTimestamp包装后可整体置空。

错误处理

文档给出的错误处理模式是接收并检查Execute()返回的err*http.Response

_, httpResp2, err := client.MemoryAPI.RecallMemories(ctx, "my-bank"). RecallRequest(recallReq). Execute() if err != nil { log.Fatalf("Recall failed: %v", err) } defer httpResp2.Body.Close()

这个三元组返回值的底层机制可以在 response.go 中找到:APIResponse内嵌*http.Response,并额外携带Message(错误消息)、Operation(OpenAPI 操作名)、RequestURLMethodPayload(原始响应体字节,因为底层http.Response.Body通常已被读取完毕)。也就是说,即使err为 nil,你仍然应该检查httpResp2.StatusCode

  • 4xx时,err可能为 nil 但状态码指示业务失败,此时可读取httpResp2嵌入的 body 或Payload解析服务端返回的HTTPValidationError/ValidationError(模型见 model_http_validation_error.go);
  • 传输层或反序列化错误会直接体现在err中;
  • httpResp的 Body 需要手动Close(),否则会泄漏连接。

对于需要重试或超控的场景,可以在Configuration.HTTPClient中注入自定义*http.Client(设置超时、Transport 等),NewAPIClientcfg.HTTPClient == nil时会回退到http.DefaultClient(client.go)。

服务器地址配置与多环境切换

Configuration结构体(configuration.go)提供了比简单 URL 更完整的寻址能力,默认Servers中第一项 URL 为空,因此实际使用时需要显式设置:

cfg := hindsight.NewConfiguration() cfg.Servers = hindsight.ServerConfigurations{ {URL: "http://localhost:8888"}, }

生成代码的 hindsight-clients/go/README.md 进一步说明了几种进阶配置方式:

  • 按索引选择服务器:通过 context 值hindsight.ContextServerIndexint类型):
ctx := context.WithValue(context.Background(), hindsight.ContextServerIndex, 1)
  • 模板化服务器 URL:URL 中的{var}占位符会由配置或 context 值hindsight.ContextServerVariablesmap[string]string)填充,枚举值始终会被校验,未使用的变量被静默忽略(变量替换与校验逻辑见 configuration.go 的ServerConfigurations.URL):
ctx := context.WithValue(context.Background(), hindsight.ContextServerVariables, map[string]string{ "basePath": "v2", })
  • 按操作(operation)粒度覆盖 URLConfiguration.OperationServers"{classname}Service.{nickname}"为键,可对单个操作指定不同服务器;运行期可用hindsight.ContextOperationServerIndiceshindsight.ContextOperationServerVariables覆盖索引与模板变量:
ctx = context.WithValue(context.Background(), hindsight.ContextOperationServerVariables, map[string]map[string]string{ "{classname}Service.{nickname}": { "port": "8443", }, })

这套机制对本地开发指向http://localhost:8888(本地 Hindsight 实例默认端口)、生产指向部署地址的场景特别有用:同一个ctx贯穿整个请求链,无需重建 client。另外,Configuration还支持AddDefaultHeader(key, value)添加全局默认请求头(如租户标识、追踪 ID),以及Debug开关配合http.DefaultClient做请求日志。

延伸阅读

  • Python SDK 文档 — API 概念相同
  • Node.js SDK 文档 — API 概念相同
  • Go 客户端端点与模型文档 — 由 OpenAPI Generator 生成的完整端点表与模型列表,是核对每个XxxAPI方法签名与 HTTP 路由的权威参考

【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询