openai

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

README

openai

The wire types for an OpenAI-compatible Files + Batch API, in Go — the exact JSON shapes a base-URL-swapped OpenAI client expects to send and receive, plus a codec for the batch request/ response .jsonl files.

This is the server-side contract, not an OpenAI client. If you're building a service that a stock OpenAI SDK can talk to by just changing the base URL, these are the types your endpoints marshal — and the conformance layer that keeps you honest against the upstream spec.

  • Dependency-free. Stdlib only. It models the external contract and nothing else — no domain logic, no storage, no opinions.
  • Files + Batch surface. FileObject, Batch, RequestCounts, ListResponse[T], the batch error shapes, and the per-line BatchRequestInput / BatchRequestOutput records.
  • Batch file codec. ParseRequests reads an uploaded batch input .jsonl; WriteOutputs writes the generated output .jsonl — the two ends of the async batch flow.
  • OpenAI-shaped errors. APIError / NewInvalidRequest produce the {"error": {...}} body clients parse.

Install

go get github.com/getotium/openai

Usage

// Parse an uploaded batch input file (one BatchRequestInput per line).
reqs, lineErrs := openai.ParseRequests(inputFile, "/v1/chat/completions")

// ... run each request through your engine ...

// Write the batch output file the client will download.
err := openai.WriteOutputs(outputFile, outputs) // []openai.BatchRequestOutput

// Marshal a Batch object / a paginated list exactly as an OpenAI client expects.
body := openai.NewList([]openai.FileObject{f1, f2})

Provenance

Extracted from Otium, whose public API is OpenAI-compatible so customers integrate by pointing an existing OpenAI client at it. These are the shapes that make "just change the base URL" true; the reference server and conformance suite that exercise them are being published alongside.

License

Apache-2.0.

Documentation

Overview

Package openai holds Otium's OpenAI-compatible wire types: the JSON shapes for the Files and Batch APIs that a base-URL-swapped OpenAI client expects to see. It is the conformance layer for the public surface — the first customer (AR15.Build) integrates by pointing its existing OpenAI client at Otium, so these shapes must match OpenAI's exactly where the client depends on them.

Like pkg/huggingface, this package is deliberately dependency-free and free of Otium imports: it models the external contract only (objects + a JSONL codec for batch request/response files), returning plain wire types. The mapping between these and Otium's domain entities (pkg/batch, pkg/job) lives in the surface layer (pkg/api), not here, so this package stays lift-ready and easy to reason about against the upstream spec.

Index

Constants

View Source
const (
	ErrorTypeInvalidRequest = "invalid_request_error"
	ErrorTypeNotFound       = "invalid_request_error" // OpenAI reports 404s as invalid_request_error
	ErrorTypeServer         = "server_error"
)

Error type discriminators OpenAI uses in its error envelope.

View Source
const (
	ObjectFile  = "file"
	ObjectBatch = "batch"
	ObjectList  = "list"
)

Object-type discriminators OpenAI stamps on each resource.

View Source
const (
	BatchValidating = "validating"
	BatchFailed     = "failed"
	BatchInProgress = "in_progress"
	BatchFinalizing = "finalizing"
	BatchCompleted  = "completed"
	BatchExpired    = "expired"
	BatchCancelling = "cancelling"
	BatchCancelled  = "cancelled"
)

Batch statuses, matching OpenAI's batch lifecycle exactly. Otium's internal state machine (pkg/batch) uses the same names so the wire mapping is identity.

View Source
const (
	PurposeBatch       = "batch"
	PurposeBatchOutput = "batch_output"
)

File purposes. Otium only accepts batch input; "batch_output" is what it stamps on the files it generates (results and errors), matching OpenAI.

View Source
const CompletionWindow24h = "24h"

CompletionWindow24h is the only completion window OpenAI's Batch API documents. Otium accepts it (and maps it to an SLA tier) plus its own tier names as an extension.

View Source
const EndpointChatCompletions = "/v1/chat/completions"

EndpointChatCompletions is the only batch endpoint Otium supports today — the surface AR15.Build's enrichment pipeline uses. OpenAI also allows /v1/embeddings and /v1/completions; those are additive later.

View Source
const MaxLineBytes = 4 << 20 // 4 MiB

MaxLineBytes bounds a single JSONL line so one pathological line can't exhaust memory while parsing an input file. OpenAI's per-request body limit is well under this.

Variables

This section is empty.

Functions

func ParseRequests

func ParseRequests(r io.Reader, endpoint string) ([]ParsedRequest, []LineError)

ParseRequests reads a batch input file (JSONL) and validates each line against the constraints Otium enforces: well-formed JSON, a supported method+url, a non-empty body carrying a model, and unique custom_ids. Blank lines are skipped (trailing newlines are common). It returns the parsed requests and a slice of per-line errors; a caller treats any line error as a validation failure for the whole batch (matching OpenAI, which fails a batch whose input doesn't validate).

endpoint is the batch's declared endpoint; every line's url must match it.

func WriteOutputs

func WriteOutputs(w io.Writer, lines []BatchRequestOutput) error

WriteOutputs encodes output lines as JSONL (one compact JSON object per line). It is the inverse of ParseRequests: the result and error files are written this way.

Types

type APIError

type APIError struct {
	Error ErrorBody `json:"error"`
}

APIError is the body of an OpenAI error response: {"error": {...}}. A base-URL-swapped client unwraps the inner object, so the shape must match. Param and Code are pointers so they serialize to null when unset, as OpenAI emits them.

func NewError

func NewError(message, errType string) APIError

NewError builds an error envelope with the given message and type.

func NewInvalidRequest

func NewInvalidRequest(message string) APIError

NewInvalidRequest is the common case: a 4xx invalid-request error.

type Batch

type Batch struct {
	ID               string            `json:"id"`
	Object           string            `json:"object"` // always "batch"
	Endpoint         string            `json:"endpoint"`
	Errors           *ErrorList        `json:"errors"`
	InputFileID      string            `json:"input_file_id"`
	CompletionWindow string            `json:"completion_window"`
	Status           string            `json:"status"`
	OutputFileID     string            `json:"output_file_id,omitempty"`
	ErrorFileID      string            `json:"error_file_id,omitempty"`
	CreatedAt        int64             `json:"created_at"`
	InProgressAt     *int64            `json:"in_progress_at"`
	ExpiresAt        *int64            `json:"expires_at"`
	FinalizingAt     *int64            `json:"finalizing_at"`
	CompletedAt      *int64            `json:"completed_at"`
	FailedAt         *int64            `json:"failed_at"`
	ExpiredAt        *int64            `json:"expired_at"`
	CancellingAt     *int64            `json:"cancelling_at"`
	CancelledAt      *int64            `json:"cancelled_at"`
	RequestCounts    RequestCounts     `json:"request_counts"`
	Metadata         map[string]string `json:"metadata,omitempty"`
}

Batch is the OpenAI representation of a batch. Optional timestamps are pointers so an unset one serializes to JSON null, exactly as OpenAI emits them; Errors and Metadata likewise serialize to null/absent when empty.

type BatchError

type BatchError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
	Param   string `json:"param,omitempty"`
	Line    *int   `json:"line"`
}

BatchError is one entry in a batch's error list. Line is 1-based and points at the offending input-file line when applicable.

type BatchRequestInput

type BatchRequestInput struct {
	CustomID string          `json:"custom_id"`
	Method   string          `json:"method"`
	URL      string          `json:"url"`
	Body     json.RawMessage `json:"body"`
}

BatchRequestInput is one line of an uploaded batch input file (JSONL). Body is kept raw so the request is passed to the runtime byte-for-byte — Otium does not re-model the chat-completion request and so cannot silently drop fields the client depends on.

type BatchRequestOutput

type BatchRequestOutput struct {
	ID       string          `json:"id"`
	CustomID string          `json:"custom_id"`
	Response *OutputResponse `json:"response"`
	Error    *OutputError    `json:"error"`
}

BatchRequestOutput is one line of a generated batch output (or error) file (JSONL). Exactly one of Response / Error is set per line, matching OpenAI.

type ErrorBody

type ErrorBody struct {
	Message string  `json:"message"`
	Type    string  `json:"type"`
	Param   *string `json:"param"`
	Code    *string `json:"code"`
}

ErrorBody is the inner error object.

type ErrorList

type ErrorList struct {
	Object string       `json:"object"` // always "list"
	Data   []BatchError `json:"data"`
}

ErrorList is the non-fatal-error envelope on a batch (e.g. malformed input lines discovered during validation).

type FileObject

type FileObject struct {
	ID        string `json:"id"`
	Object    string `json:"object"` // always "file"
	Bytes     int64  `json:"bytes"`
	CreatedAt int64  `json:"created_at"`
	Filename  string `json:"filename"`
	Purpose   string `json:"purpose"`
}

FileObject is the OpenAI representation of an uploaded or generated file. Timestamps are Unix seconds, as OpenAI emits them.

type LineError

type LineError struct {
	Line    int
	Message string
}

LineError reports a malformed input line. Line is 1-based.

func (LineError) Error

func (e LineError) Error() string

type ListResponse

type ListResponse[T any] struct {
	Object  string `json:"object"` // always "list"
	Data    []T    `json:"data"`
	HasMore bool   `json:"has_more"`
}

ListResponse is the generic OpenAI list envelope used by GET /v1/files and GET /v1/batches. HasMore/cursors are omitted — Otium returns a single page for the PoC.

func NewList

func NewList[T any](data []T) ListResponse[T]

NewList wraps a slice in the OpenAI list envelope. A nil slice serializes as an empty array, not null, matching OpenAI.

type OutputError

type OutputError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

OutputError is the per-request error inside an output line (and the sole content of the error file's lines).

type OutputResponse

type OutputResponse struct {
	StatusCode int             `json:"status_code"`
	RequestID  string          `json:"request_id"`
	Body       json.RawMessage `json:"body"`
}

OutputResponse wraps the per-request HTTP result inside an output line. Body is the raw chat-completion response the runtime produced.

type ParsedRequest

type ParsedRequest struct {
	Seq      int
	CustomID string
	Model    string
	Body     json.RawMessage
}

ParsedRequest is one validated input line: the raw line plus the model pulled out of its body (the one field Otium must read to route the request to a worker). Seq is the 1-based line number, used for stable custom-id fallbacks and error reporting.

type RequestCounts

type RequestCounts struct {
	Total     int `json:"total"`
	Completed int `json:"completed"`
	Failed    int `json:"failed"`
}

RequestCounts is the per-batch progress tally OpenAI reports.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL