Go SDK
模組: github.com/vecstruct/vecstruct-sdk-go
最低版本: Go 1.25+
GitHub: vecstruct/vecstruct-sdk-go
安裝
go get github.com/vecstruct/vecstruct-sdk-go
go get github.com/joho/godotenv
初始化
package main
import (
"context"
"fmt"
"log"
"os"
vecstruct "github.com/vecstruct/vecstruct-sdk-go"
"github.com/joho/godotenv"
)
func main() {
godotenv.Load()
client, err := vecstruct.NewClient(os.Getenv("VECSTRUCT_API_KEY"))
if err != nil {
log.Fatal(err)
}
resp, err := client.CreateChatCompletion(context.Background(), vecstruct.ChatCompletionRequest{
Model: "openai/gpt-4o",
Messages: []vecstruct.ChatMessage{
{Role: "user", Content: "你好,Vecstruct!"},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Choices[0].Message.Content)
}
進階設定:
import "time"
client, err := vecstruct.NewClient(
"sk-...",
vecstruct.WithBaseURL("https://api.vecstruct.com/v1"),
vecstruct.WithTimeout(60 * time.Second),
vecstruct.WithUserAgent("my-app/1.0"),
)
| 選項 | 說明 |
|---|---|
WithBaseURL(url) | 覆蓋 API 的 Base URL |
WithTimeout(d) | HTTP 請求逾時設定 |
WithHTTPClient(c) | 注入自訂 *http.Client(proxy、mTLS 等) |
WithUserAgent(ua) | 覆蓋 User-Agent header |
Chat Completions
一般請求
resp, err := client.CreateChatCompletion(ctx, vecstruct.ChatCompletionRequest{
Model: "openai/gpt-4o",
Messages: []vecstruct.ChatMessage{
{Role: "system", Content: "你是資深工程師"},
{Role: "user", Content: "幫我 review 這段 Go 程式碼"},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Choices[0].Message.Content)
fmt.Println("Token 用量:", resp.Usage.TotalTokens)
串流回應
import (
"errors"
"io"
)
stream, err := client.StreamChatCompletion(ctx, vecstruct.ChatCompletionRequest{
Model: "openai/gpt-4o",
Messages: []vecstruct.ChatMessage{
{Role: "user", Content: "介紹向量資料庫"},
},
})
if err != nil {
log.Fatal(err)
}
defer stream.Close()
for {
chunk, err := stream.Next()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
log.Fatal(err)
}
if len(chunk.Choices) > 0 {
fmt.Print(chunk.Choices[0].Delta.Content)
}
}
// 取得串流結束後的 Vecstruct metadata
if vc := stream.Vecstruct(); vc != nil {
fmt.Printf("\nAudit ID: %s, Credits: %.4f\n", vc.AuditID, vc.CreditsConsumed)
}
啟用 RAG 與 Memory
ragOn := true
resp, err := client.CreateChatCompletion(ctx, vecstruct.ChatCompletionRequest{
Model: "openai/gpt-4o",
Messages: []vecstruct.ChatMessage{
{Role: "user", Content: "我們的退款政策是什麼?"},
},
Vecstruct: &vecstruct.VecstructParams{
RAG: &ragOn,
RAGTopK: 5,
},
})
// 取得 RAG 引用來源
for _, src := range resp.Vecstruct.RAGSources {
fmt.Printf("- %s (相似度: %.3f)\n", src.Title, src.Similarity)
}
Embeddings
emb, err := client.CreateEmbedding(ctx, vecstruct.EmbeddingRequest{
Model: "openai/text-embedding-3-small",
Input: []string{"向量搜尋的原理", "如何評估 Embedding 品質"},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("向量數量: %d, 維度: %d\n", len(emb.Data), len(emb.Data[0].Embedding))
Rerank
rr, err := client.Rerank(ctx, vecstruct.RerankRequest{
Model: "cohere/rerank-v3.5",
Query: "什麼是向量搜尋?",
Documents: []string{"A: 向量搜尋用向量距離...", "B: 今天天氣很好", "C: 向量資料庫索引..."},
TopN: 2,
})
for _, hit := range rr.Results {
fmt.Printf("Index %d -> %.3f\n", hit.Index, hit.RelevanceScore)
}
Models
// 列出所有模型
models, err := client.ListModels(ctx, nil)
// 按 provider 篩選
models, err = client.ListModels(ctx, &vecstruct.ListModelsOptions{
OwnedBy: "openai",
})
for _, m := range models {
fmt.Println(m.ModelID, "-", m.Type)
}
// 取得特定模型
m, err := client.GetModel(ctx, "openai/gpt-4o")
fmt.Println("輸入定價:", m.InputPricePer1M)
RAG 查詢(知識庫)
rag, err := client.QueryRAG(ctx, vecstruct.RAGQueryRequest{
Query: "退款政策",
TopK: 5,
MinSimilarity: 0.3,
})
if err != nil {
log.Fatal(err)
}
for _, r := range rag.Results {
fmt.Printf("[%.3f] %s\n", r.Similarity, r.Content[:80])
}
Memory(長期記憶)
// 新增記憶
importance := 0.8
mem, err := client.CreateMemory(ctx, vecstruct.CreateMemoryRequest{
Content: "使用者偏好繁體中文回覆,技術術語保留英文",
MemoryType: vecstruct.MemoryTypeRule,
Importance: &importance,
})
// 語義搜尋
results, err := client.SearchMemories(ctx, vecstruct.SearchMemoryRequest{
Query: "使用者語言偏好",
TopK: 3,
})
for _, hit := range results.Results {
fmt.Printf("[%.3f] %s\n", hit.FinalScore, hit.Memory.Content)
}
// 其他操作
client.ListMemories(ctx, &vecstruct.ListMemoriesOptions{Page: 1, PageSize: 20})
client.GetMemory(ctx, mem.ID)
client.UpdateMemory(ctx, mem.ID, vecstruct.UpdateMemoryRequest{...})
client.ExtractMemory(ctx, vecstruct.ExtractMemoryRequest{Text: "..."})
client.DeleteMemory(ctx, mem.ID)
client.BatchDeleteMemories(ctx, vecstruct.BatchDeleteMemoriesRequest{...})
Documents(文件管理)
import "os"
f, _ := os.Open("manual.pdf")
defer f.Close()
// 上傳
doc, err := client.UploadDocument(ctx, vecstruct.UploadDocumentRequest{
Filename: "manual.pdf",
Content: f,
Metadata: map[string]any{"team": "support"},
Chunking: &vecstruct.ChunkingOptions{
Strategy: vecstruct.ChunkStrategyRecursive,
Size: 800,
Overlap: 80,
},
})
// 列表 / 取得 / 刪除
list, _ := client.ListDocuments(ctx, &vecstruct.ListDocumentsOptions{Page: 1, PageSize: 20})
detail, _ := client.GetDocument(ctx, doc.ID)
_ = client.DeleteDocument(ctx, doc.ID)
// 啟用 / 停用 / 重新索引
_ = client.DeactivateDocument(ctx, doc.ID)
_ = client.ActivateDocument(ctx, doc.ID)
_ = client.ReindexDocument(ctx, doc.ID)
// 更新切分設定
_ = client.UpdateDocumentChunking(ctx, doc.ID, vecstruct.ChunkingOptions{
Strategy: vecstruct.ChunkStrategySemantic,
})
// 查看段落
chunks, _ := client.ListDocumentChunks(ctx, doc.ID, nil)
fmt.Printf("共 %d 個段落\n", len(chunks.Chunks))
稽核日誌(Audit Logs)
// 列表
logs, err := client.ListAuditLogs(ctx, &vecstruct.ListAuditLogsOptions{
StartTime: "2026-01-01",
EndTime: "2026-01-31",
Action: "gateway.chat",
Page: 1,
PageSize: 50,
})
// 詳情
detail, _ := client.GetAuditLog(ctx, logs.Logs[0].ID)
fmt.Println(detail.Action, detail.Model)
// 匯出
job, _ := client.ExportAuditLogs(ctx, vecstruct.ExportAuditLogsRequest{
StartTime: "2026-01-01",
EndTime: "2026-01-31",
Format: vecstruct.ExportFormatCSV,
})
fmt.Println("匯出 ID:", job.ExportID)
認證資訊
info, err := client.GetAuthInfo(ctx)
if err == nil {
fmt.Println("User ID:", info.UserID)
fmt.Println("Permissions:", info.Permissions)
}
Context、逾時與取消
每個方法都接受 context.Context,用它來設定 deadline 或取消請求:
// 設定 30 秒逾時
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
resp, err := client.CreateChatCompletion(ctx, req)
// 取消串流
ctx, cancel = context.WithCancel(context.Background())
go func() {
time.Sleep(5 * time.Second)
cancel() // 5 秒後取消
}()
stream, _ := client.StreamChatCompletion(ctx, req)
錯誤處理
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
if apiErr, ok := vecstruct.IsAPIError(err); ok {
switch {
case apiErr.IsCode(1100): // 未授權
log.Fatal("API Key 無效")
case apiErr.IsCode(1003): // 速率限制
log.Println("已觸發速率限制,請稍後再試")
default:
log.Fatalf("API 錯誤: code=%d %s", apiErr.Code, apiErr.Message)
}
// 回報問題時請附上 RequestID
log.Println("Request ID:", apiErr.RequestID)
}
log.Fatal(err)
}
APIError 包含:
HTTPStatus— HTTP 狀態碼Code— Vecstruct 業務錯誤碼Message— 錯誤描述RequestID— 請求 ID(回報問題時附上)Data— 後端額外資料(json.RawMessage)
Sentinel 錯誤:
vecstruct.ErrMissingAPIKeyvecstruct.ErrInvalidBaseURLvecstruct.ErrStreamClosed