在Go语言中调用VertexAI生成式AI模型的鉴权问题
解决VertexAI调用中令牌有效期不足1小时的问题
方案一:使用Google官方Go客户端库(推荐)
官方客户端库会自动处理OAuth2令牌的缓存与过期刷新,无需手动管理token生命周期,同时提供更简洁的API调用方式。
- 安装依赖
go get cloud.google.com/go/aiplatform/apiv1 go get google.golang.org/api/option
- 示例代码
package main import ( "context" "fmt" "log" aiplatform "cloud.google.com/go/aiplatform/apiv1" "cloud.google.com/go/aiplatform/apiv1/aiplatformpb" "google.golang.org/api/option" "google.golang.org/protobuf/types/known/structpb" ) func main() { ctx := context.Background() projectID := "你的项目ID" location := "us-central1" modelID := "text-bison@001" // 若已通过gcloud auth application-default login配置本地凭据,可省略WithCredentialsFile参数 client, err := aiplatform.NewPredictionClient(ctx, option.WithCredentialsFile("path/to/your/service-account-key.json")) if err != nil { log.Fatalf("创建预测客户端失败: %v", err) } defer client.Close() endpoint := fmt.Sprintf("projects/%s/locations/%s/publishers/google/models/%s", projectID, location, modelID) // 构造请求实例 content := "你的输入内容" instance, err := structpb.NewStruct(map[string]interface{}{ "content": content, }) if err != nil { log.Fatalf("构造实例结构体失败: %v", err) } // 构造参数 parameters, err := structpb.NewStruct(map[string]interface{}{ "temperature": 0.2, "maxOutputTokens": 256, "topP": 0.8, "topK": 40, }) if err != nil { log.Fatalf("构造参数结构体失败: %v", err) } req := &aiplatformpb.PredictRequest{ Endpoint: endpoint, Instances: []*structpb.Value{structpb.NewStructValue(instance)}, Parameters: structpb.NewStructValue(parameters), } resp, err := client.Predict(ctx, req) if err != nil { log.Fatalf("预测请求失败: %v", err) } // 处理响应 fmt.Println("预测结果:") for _, prediction := range resp.Predictions { fmt.Println(prediction) } }
方案二:手动管理服务账号令牌(自定义HTTP请求场景)
若需要手动构造HTTP请求,可通过服务账号密钥获取token,并实现缓存与过期刷新逻辑。
- 示例代码
package main import ( "bytes" "context" "encoding/json" "fmt" "log" "net/http" "os" "time" "golang.org/x/oauth2/google" ) type TokenCache struct { Token *google.Token ExpiresAt time.Time } var tokenCache TokenCache // 获取并缓存服务账号令牌,提前5分钟刷新避免过期 func getServiceAccountToken(ctx context.Context, keyPath string) (*google.Token, error) { if tokenCache.Token != nil && time.Now().Before(tokenCache.ExpiresAt.Add(-5*time.Minute)) { return tokenCache.Token, nil } data, err := os.ReadFile(keyPath) if err != nil { return nil, fmt.Errorf("读取服务账号密钥失败: %v", err) } conf, err := google.JWTConfigFromJSON(data, "https://www.googleapis.com/auth/cloud-platform") if err != nil { return nil, fmt.Errorf("创建JWT配置失败: %v", err) } token, err := conf.TokenSource(ctx).Token() if err != nil { return nil, fmt.Errorf("获取令牌失败: %v", err) } tokenCache.Token = token tokenCache.ExpiresAt = token.Expiry return token, nil } func callVertexAI(ctx context.Context) { apiEndpoint := "你的API_ENDPOINT" projectID := "你的项目ID" modelID := "text-bison@001" keyPath := "path/to/your/service-account-key.json" token, err := getServiceAccountToken(ctx, keyPath) if err != nil { log.Fatalf("获取令牌失败: %v", err) } url := fmt.Sprintf("https://%s/v1/projects/%s/locations/us-central1/publishers/google/models/%s:predict", apiEndpoint, projectID, modelID) payload := map[string]interface{}{ "instances": []map[string]interface{}{ {"content": "你的输入内容"}, }, "parameters": map[string]interface{}{ "temperature": 0.2, "maxOutputTokens": 256, "topP": 0.8, "topK": 40, }, } payloadBytes, err := json.Marshal(payload) if err != nil { log.Fatalf("序列化请求体失败: %v", err) } req, err := http.NewRequest("POST", url, bytes.NewBuffer(payloadBytes)) if err != nil { log.Fatalf("创建请求失败: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.AccessToken)) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Fatalf("发送请求失败: %v", err) } defer resp.Body.Close() var result map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { log.Fatalf("解析响应失败: %v", err) } fmt.Println("响应结果:", result) } func main() { ctx := context.Background() callVertexAI(ctx) }
注意事项
- 服务账号需拥有Vertex AI预测权限(如
roles/aiplatform.user) - 若在Google Cloud环境(GCE、GKE、Cloud Functions等)运行,可使用默认应用凭据,无需手动指定密钥文件
内容的提问来源于stack exchange,提问作者Sumit Vishwakarma
相关产品推荐
相关产品推荐

