Skip to content

Go

Obstruo exposes an OpenAI-compatible API. The official openai-go package supports custom base URLs and works with Obstruo without modification.

Prerequisites

  • An ObstruoKey and endpoint URL - see Quick Start
  • A Logical Model configured in your project
  • Go 1.21 or later

openai-go

Install the module:

go get github.com/openai/openai-go

Chat completions

package main

import (
    "context"
    "fmt"
    "os"

    "github.com/openai/openai-go"
    "github.com/openai/openai-go/option"
)

func main() {
    client := openai.NewClient(
        option.WithAPIKey(os.Getenv("OBSTRUO_API_KEY")),
        option.WithBaseURL(os.Getenv("OBSTRUO_BASE_URL")),
    )

    response, err := client.Chat.Completions.New(
        context.Background(),
        openai.ChatCompletionNewParams{
            Model: "obstruo-chat",
            Messages: []openai.ChatCompletionMessageParamUnion{
                openai.SystemMessage("You are a helpful assistant."),
                openai.UserMessage("Summarise this contract: ..."),
            },
        },
    )
    if err != nil {
        panic(err)
    }

    fmt.Println(response.Choices[0].Message.Content)
}

Streaming

stream := client.Chat.Completions.NewStreaming(
    context.Background(),
    openai.ChatCompletionNewParams{
        Model: "obstruo-chat",
        Messages: []openai.ChatCompletionMessageParamUnion{
            openai.UserMessage("Tell me a story."),
        },
    },
)

for stream.Next() {
    chunk := stream.Current()
    if len(chunk.Choices) > 0 {
        fmt.Print(chunk.Choices[0].Delta.Content)
    }
}
if err := stream.Err(); err != nil {
    panic(err)
}

Embeddings

result, err := client.Embeddings.New(
    context.Background(),
    openai.EmbeddingNewParams{
        Model: "obstruo-embedding",
        Input: openai.EmbeddingNewParamsInputArrayOfStrings([]string{"The quick brown fox"}),
    },
)
if err != nil {
    panic(err)
}

vector := result.Data[0].Embedding

Environment variables

export OBSTRUO_API_KEY="your-obstruo-key"
export OBSTRUO_BASE_URL="https://api.obstruo.ai/your-org/v1"
client := openai.NewClient(
    option.WithAPIKey(os.Getenv("OBSTRUO_API_KEY")),
    option.WithBaseURL(os.Getenv("OBSTRUO_BASE_URL")),
)

Reading gateway metadata

openai-go deserialises only known OpenAI fields. For the obstruo key, make a raw HTTP call:

import (
    "encoding/json"
    "net/http"
    "bytes"
)

type Routing struct {
    ResolvedModel string `json:"resolved_model"`
    ProviderType  string `json:"provider_type"`
    DurationMs    int    `json:"duration_ms"`
}

type Redaction struct {
    TotalEntities int            `json:"total_entities"`
    ByCategory    map[string]int `json:"by_category"`
    DurationMs    int            `json:"duration_ms"`
}

type ObstruoMeta struct {
    Routing   Routing   `json:"routing"`
    Redaction Redaction `json:"redaction"`
}

type ObstruoResponse struct {
    Choices []struct {
        Message struct {
            Content string `json:"content"`
        } `json:"message"`
    } `json:"choices"`
    Obstruo ObstruoMeta `json:"obstruo"`
}

body, _ := json.Marshal(map[string]any{
    "model":    "obstruo-chat",
    "messages": []map[string]string{{"role": "user", "content": "Hello!"}},
})

req, _ := http.NewRequest("POST",
    os.Getenv("OBSTRUO_BASE_URL")+"/chat/completions",
    bytes.NewReader(body),
)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OBSTRUO_API_KEY"))
req.Header.Set("Content-Type", "application/json")

resp, _ := http.DefaultClient.Do(req)
var parsed ObstruoResponse
json.NewDecoder(resp.Body).Decode(&parsed)

fmt.Println(parsed.Obstruo.Routing.ResolvedModel)   // "gpt-4o-mini"
fmt.Println(parsed.Obstruo.Routing.ProviderType)    // "OpenAI"
fmt.Println(parsed.Obstruo.Redaction.TotalEntities) // 0 = no PII found
fmt.Println(parsed.Obstruo.Redaction.ByCategory)    // map[EMAIL_ADDRESS:1]

Next steps