Documentation
¶
Overview ¶
Package typesafe is the official Go SDK for TypeSafe AI (https://typesafe.ai).
The TypeSafe AI platform evaluates deterministic classification and rating primitives through System One models. A Client sends one request that answers any number of named questions about a state, and returns every answer keyed by the name you supplied.
Primitives ¶
Three question kinds are supported:
- Noul: the probability that a statement holds, from 0 to 1.
- Choice: the best-matching criteria key, its confidence, and a probability per key.
- Score: an expected value across an ordered rubric whose levels start at 0.
Quickstart ¶
client, err := typesafe.NewClient() // reads TYPESAFE_API_KEY
if err != nil {
log.Fatal(err)
}
defer client.Close()
response, err := client.SystemOne(ctx,
map[string]any{"document": "I was charged twice. Please fix this ASAP."},
typesafe.Questions{
"billing": typesafe.NewNoul(
"Is this ticket about billing?",
typesafe.WithNoulCriteria(typesafe.NoulCriteria{
True: "Charges, refunds, or invoices",
False: "Anything else",
}),
),
"category": typesafe.NewChoice(
map[string]any{"billing": nil, "technical": nil, "other": nil},
typesafe.WithInstructions("What is this ticket about?"),
),
"urgency": typesafe.NewScore(
[]any{"can wait", "this week", "today"},
typesafe.WithInstructions("How urgent is this issue?"),
),
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("billing: %.2f\n", response.Nouls()["billing"].Noul)
fmt.Printf("category: %s (%.2f)\n", response.Choices()["category"].Choice, response.Choices()["category"].Confidence)
fmt.Printf("urgency: %.2f\n", response.Scores()["urgency"].Score)
Custom Response Models ¶
SystemOneAs decodes the payload into a caller-defined struct, so the compiler knows the shape of your answers. The struct may declare the envelope fields and one field per answer, named after the question:
type Ticket struct {
Model string `json:"model"`
Usage typesafe.Usage `json:"usage"`
Billing typesafe.NoulAnswer `json:"billing"`
Tone *typesafe.ChoiceAnswer `json:"tone"` // optional: a pointer can be absent
}
result, err := typesafe.SystemOneAs[Ticket](ctx, client, state, questions)
Alternatively, [SystemOneInto] populates an existing struct pointer in-place. A top-level field that cannot represent absence — anything but a pointer, map, slice, interface, function, or channel — is required, unless it is tagged omitempty or omitzero. A missing required field is reported as an APIResponseValidationError naming the field.
Patterns and Model Best Practices ¶
TypeSafe's Jev model is a calibrated System One engine. It excels at qualitative classification, judgment, and routing, but does not perform open-ended text generation or reliable numeric arithmetic.
1. Confidence-Gated Routing: Choice and Score answers include a statistical Confidence (0 to 1). A proven pattern is to tier actions. The bands below are an example: the boundaries are yours to choose, because they trade the cost of a wrong automatic action against the cost of a review. The docs gate at 0.5 for a high-stakes decision (https://docs.typesafe.ai/confidence) and at 0.6 for a moderation queue (https://docs.typesafe.ai/patterns/confidence-routing).
switch {
case answer.Confidence >= 0.85:
// High confidence: act automatically without human involvement
case answer.Confidence >= 0.50:
// Medium confidence: proceed with caution or ask for confirmation
default:
// Low confidence: model is unsure ("I don't know"); route to human triage
}
2. Counting & Speculative Fan-Out: Do not ask Jev to count items or compute sums. Keep arithmetic in Go: fan out atomic Noul questions across candidates in a single Client.SystemOne request, then aggregate the matching counts in Go.
3. Score Rubrics: Score questions require between 2 and 10 discrete rubric levels. The resulting ScoreAnswer.Score is an expected value suited for threshold filtering (e.g. score >= 1.5). Do not use Score as a continuous interpolator to reconstruct exact numeric quantities.
4. Choice Questions: Choice questions support up to 255 options per question.
5. What the SDK Validates: Questions are checked locally for the shape the request schema requires: a question type, criteria for a choice or a score question, at most 255 options for a choice, and between 2 and 10 levels for a score. Fields the schema makes optional — instructions above all — are sent only when the caller sets them; the HTTP reference page marks instructions required, but the request schema requires only criteria, for choice and score, so the SDK lets the API judge a question that omits them.
A success response is held to the same standard: the model, the usage with both token counts, and one answer per question must be present, or the SDK reports an APIResponseValidationError naming the missing field.
Errors ¶
Failures are typed and match with errors.As. Unsuccessful HTTP statuses map onto APIError and its status-specific subclasses (BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, UnprocessableEntityError, RateLimitError, OverloadedError, InternalServerError); each unwraps to APIError, so a single check finds both forms. OverloadedError (HTTP 529) and RateLimitError (HTTP 429) provide RetryAfter() for backoff delays. Transport failures are APIConnectionError or APITimeoutError, a malformed success body is APIResponseValidationError, and invalid configuration or input is SDKError. AsAPIError, AsRateLimitError, AsOverloadedError, AsTimeoutError, and AsValidationError are convenience extractors.
Configuration ¶
NewClient resolves configuration from its Option values first, then the environment (TYPESAFE_API_KEY, TYPESAFE_BASE_URL, TYPESAFE_DEFAULT_MODEL, TYPESAFE_LOG_LEVEL), then the SDK defaults. Client.SystemOne and ModelsService.List accept RequestOption values that override the client for a single call without mutating it: WithModel, WithCallTimeout, WithCallRetry, WithCallHeader, WithCallHeaders, and WithExtraBody.
Design ¶
The SDK is engineered for high concurrency and safety:
- Functional options: Option configures a Client, RequestOption a single call, and QuestionOption a single question.
- Resilient retries: jittered exponential backoff, honoring the retry-after-ms and Retry-After headers for up to a minute, with an optional overall budget. See RetryPolicy and DefaultRetryPolicy.
- Security by design: credential headers are redacted from logs (NewRedactingHandler extends that to your own records), credentials in URLs are stripped from error endpoints, response bodies are bounded to 16 MB, and the SDK's transport refuses TLS below 1.2. Headers the SDK owns cannot be displaced by caller-supplied ones.
- Concurrency: a Client holds no per-request state and is safe for concurrent use; every call takes a context.Context for cancellation and deadlines.
- Modern Go: for range over integers, min and max, slices and maps helpers, and generics via SystemOneAs. Standard library only, and Go 1.26 or newer.
Index ¶
- Constants
- func DefaultRetryStatuses() map[int]bool
- func NormalizeQuestions(questions any) (map[string]any, error)
- func ParseLogLevel(level string) (slog.Level, bool)
- func RuntimeString() string
- func SystemOneAs[T any](ctx context.Context, client *Client, state any, questions any, ...) (*T, error)
- type APIConnectionError
- type APIError
- type APIResponseValidationError
- type APITimeoutError
- type Answer
- type Answers
- type Asset
- type Assets
- type AuthenticationError
- type BadRequestError
- type BoxAnswer
- type BoxCoordinates
- type BoxQuestion
- type ChoiceAnswer
- type ChoiceQuestion
- type Client
- type Config
- type Image
- type InternalServerError
- type ListModelsResponse
- type ModelMetadata
- type ModelsService
- type NotFoundError
- type NoulAnswer
- type NoulCriteria
- type NoulQuestion
- type Option
- func WithAPIKey(apiKey string) Option
- func WithBaseURL(baseURL string) Option
- func WithCompression(enabled bool) Option
- func WithDefaultModel(model string) Option
- func WithHTTPClient(client *http.Client) Option
- func WithHeader(key, value string) Option
- func WithHeaders(headers map[string]string) Option
- func WithImages(enabled bool) Option
- func WithLogger(logger *slog.Logger) Option
- func WithLongContext(enabled bool) Option
- func WithRetryPolicy(policy *RetryPolicy) Option
- func WithTimeout(timeout time.Duration) Option
- func WithTransport(transport http.RoundTripper) Option
- type OverloadedError
- type PayloadTooLargeError
- type PermissionDeniedError
- type Question
- type QuestionOption
- type Questions
- type RateLimitError
- type RawQuestion
- type RedactingHandler
- type RequestOption
- func WithAssets(assets any) RequestOption
- func WithCallCompression(enabled bool) RequestOption
- func WithCallHeader(key, value string) RequestOption
- func WithCallHeaders(headers map[string]string) RequestOption
- func WithCallImages(enabled bool) RequestOption
- func WithCallLongContext(enabled bool) RequestOption
- func WithCallRetry(policy *RetryPolicy) RequestOption
- func WithCallTimeout(timeout time.Duration) RequestOption
- func WithExtraBody(extra map[string]any) RequestOption
- func WithModel(model string) RequestOption
- type RetryPolicy
- type SDKError
- type ScoreAnswer
- type ScoreError
- type ScoreQuestion
- type SystemOneResponse
- func (r *SystemOneResponse) Boxes() map[string]*BoxAnswer
- func (r *SystemOneResponse) Choices() map[string]*ChoiceAnswer
- func (r *SystemOneResponse) MarshalJSON() ([]byte, error)
- func (r *SystemOneResponse) Nouls() map[string]*NoulAnswer
- func (r *SystemOneResponse) RawBody() []byte
- func (r *SystemOneResponse) RawHTTPResponse() (*http.Response, error)
- func (r *SystemOneResponse) RawRequestID() string
- func (r *SystemOneResponse) RequestID() (string, error)
- func (r *SystemOneResponse) Scores() map[string]*ScoreAnswer
- func (r *SystemOneResponse) String() string
- type TypeSafeError
- type UnprocessableEntityError
- type UnsupportedMediaTypeError
- type Usage
Examples ¶
Constants ¶
const ( // APIKeyEnv is the environment variable for the TypeSafe API key. APIKeyEnv = "TYPESAFE_API_KEY" // BaseURLEnv is the environment variable for the API base URL. BaseURLEnv = "TYPESAFE_BASE_URL" // DefaultModelEnv is the environment variable for the default model. DefaultModelEnv = "TYPESAFE_DEFAULT_MODEL" // LogLevelEnv is the environment variable for the logging level. LogLevelEnv = "TYPESAFE_LOG_LEVEL" )
Environment variable names.
const ( // DefaultBaseURL is the default API root URL. DefaultBaseURL = "https://api.typesafe.ai" // DefaultModel is the default model name. DefaultModel = "jev-latest" // ModelJevLatest is the alias for the latest stable model release (currently jev-1.13.0). ModelJevLatest = "jev-latest" // ModelJevPreview is the alias for the latest preview release (currently jev-1.14.0). ModelJevPreview = "jev-preview" // ModelJev114 is the versioned ID for Jev 1.14. ModelJev114 = "jev-1.14.0" // ModelJev113 is the versioned ID for Jev 1.13. ModelJev113 = "jev-1.13.0" // DefaultTimeout is the default HTTP timeout for operations. DefaultTimeout = 10 * time.Second // SDKName is the name of this SDK. SDKName = "typesafe-sdk-go" // SDKVersion is the current version of this SDK. SDKVersion = "0.13.0" // MaxErrorBodyLength limits the raw error body length included in error messages. MaxErrorBodyLength = 200 // MaxRequestBodyLimit is the maximum request body size (32 MiB) accepted by the API. MaxRequestBodyLimit = 32 * 1024 * 1024 // MaxResponseBodyLimit limits the maximum response body read (32 MiB) matching API spec. MaxResponseBodyLimit = 32 * 1024 * 1024 // MaxImageSizeLimit is the maximum size (16 MiB) for an individual image file. MaxImageSizeLimit = 16 * 1024 * 1024 // MinCompressionBytes is the minimum request body size (1 KiB) for automatic compression. MinCompressionBytes = 1024 )
Client and protocol defaults.
const ( SystemOnePath = "/v1/systemone" ModelsPath = "/v1/models" )
API Endpoint paths.
const ( // StatusOverloaded is the HTTP 529 status code returned when TypeSafe is temporarily overloaded. StatusOverloaded = 529 // StatusPayloadTooLarge is HTTP 413 Payload Too Large. StatusPayloadTooLarge = 413 // StatusUnsupportedMediaType is HTTP 415 Unsupported Media Type. StatusUnsupportedMediaType = 415 )
HTTP Status codes.
const ( HeaderAuthorization = "Authorization" HeaderAccept = "Accept" HeaderContentType = "Content-Type" HeaderUserAgent = "User-Agent" HeaderSDK = "X-TypeSafe-SDK" HeaderRuntime = "X-TypeSafe-Runtime" HeaderRetryCount = "X-TypeSafe-Retry-Count" HeaderRequestID = "x-typesafe-request-id" HeaderRetryAfter = "retry-after" HeaderRetryAfterMs = "retry-after-ms" ContentTypeJSON = "application/json" // Danger Zone feature headers. HeaderDangerZoneImages = "TypeSafe-Danger-Zone-Images" HeaderDangerZoneLongContext = "TypeSafe-Danger-Zone-Long-Context" // Compression headers. HeaderContentEncoding = "Content-Encoding" EncodingGzip = "gzip" EncodingZstd = "zstd" )
Protocol headers.
Variables ¶
This section is empty.
Functions ¶
func DefaultRetryStatuses ¶
DefaultRetryStatuses returns the set of HTTP status codes the SDK retries by default: 408, 429, and every 5xx.
func NormalizeQuestions ¶
NormalizeQuestions validates the questions before they are encoded and returns the map that is sent on the wire.
It accepts Questions, map[string]Question, map[string]*NoulQuestion and the sibling maps, map[string]any, and RawQuestion values.
Example ¶
normalized, err := NormalizeQuestions(Questions{
"billing": NewNoul("Is this message about billing?"),
"tone": NewChoice(map[string]any{"calm": nil, "angry": nil}),
})
if err != nil {
panic(err)
}
fmt.Println(slices.Sorted(maps.Keys(normalized)))
fmt.Println(normalized["tone"].(Question).QuestionType())
Output: [billing tone] choice
func ParseLogLevel ¶
ParseLogLevel converts a level name into a slog.Level. It accepts "debug", "info", "warn", "warning", "error", and "off", and reports false for any other value.
func RuntimeString ¶
func RuntimeString() string
RuntimeString returns the runtime environment string for SDK identification, sent in the X-TypeSafe-Runtime header.
func SystemOneAs ¶
func SystemOneAs[T any](ctx context.Context, client *Client, state any, questions any, opts ...RequestOption) (*T, error)
SystemOneAs answers questions and decodes the response into T, a caller-defined struct.
T may declare the envelope fields ("model", "usage", "answers") and, additionally, one field per answer, named after the question. Each such field is populated from the matching entry of "answers":
type Ticket struct {
Model string `json:"model"`
Usage typesafe.Usage `json:"usage"`
Billing typesafe.NoulAnswer `json:"billing"`
Tone typesafe.ChoiceAnswer `json:"tone"`
}
result, err := typesafe.SystemOneAs[Ticket](ctx, client, state, questions)
A top-level field that is not a pointer, map, slice, or interface, and that is not tagged `omitempty`, is required: its absence is reported as an APIResponseValidationError naming the field rather than silently decoding to a zero value. Answer types this SDK version does not model are dropped from the decoded document, exactly as in the Client.SystemOne path.
Types ¶
type APIConnectionError ¶
type APIConnectionError struct {
// Message describes the transport failure.
Message string
// Cause is the underlying transport error.
Cause error
}
APIConnectionError is returned when the request never produced an HTTP response.
func (*APIConnectionError) Error ¶
func (e *APIConnectionError) Error() string
func (*APIConnectionError) Unwrap ¶
func (e *APIConnectionError) Unwrap() error
Unwrap returns the underlying transport error.
type APIError ¶
type APIError struct {
// Status is the HTTP response status code.
Status int
// Body is the decoded JSON error body, the raw text for a non-JSON body, or nil for an empty body.
Body any
// RawBody is the exact response body as received.
RawBody []byte
// Headers holds the response headers.
Headers http.Header
// Endpoint is "METHOD URL" with credentials, query parameters, and fragments removed.
// Empty when the response has no originating request.
Endpoint string
// RequestID is the x-typesafe-request-id response header, or empty when absent.
RequestID string
// Message is the human-readable detail shown by Error. The SDK fills it from Body when the
// error is built; a caller constructing an APIError may leave it empty to derive it lazily or
// set it to override the derived text.
Message string
}
APIError is an unsuccessful HTTP response, carrying the full response metadata.
Typed subclasses such as RateLimitError embed APIError and unwrap to it, so a single
var apiErr *typesafe.APIError errors.As(err, &apiErr)
matches every HTTP failure the SDK returns.
func AsAPIError ¶
AsAPIError extracts the APIError carried by any HTTP failure this SDK returns. It reports false for connection, timeout, validation-of-input, and configuration errors.
type APIResponseValidationError ¶
type APIResponseValidationError struct {
APIError
// FieldPath is the dotted path to the offending field, such as "answers.tone.confidence".
FieldPath string
}
APIResponseValidationError is returned for a successful HTTP status whose body does not match the expected schema.
func AsValidationError ¶
func AsValidationError(err error) (*APIResponseValidationError, bool)
AsValidationError extracts the APIResponseValidationError when a successful response could not be decoded.
func (*APIResponseValidationError) Error ¶
func (e *APIResponseValidationError) Error() string
Error returns the formatted validation message.
type APITimeoutError ¶
type APITimeoutError struct {
APIConnectionError
// Timeout is the timeout that was in effect for the request.
Timeout time.Duration
}
APITimeoutError is returned when a request exceeds its configured timeout.
func AsTimeoutError ¶
func AsTimeoutError(err error) (*APITimeoutError, bool)
AsTimeoutError extracts the APITimeoutError when the request exceeded its timeout.
func (*APITimeoutError) Error ¶
func (e *APITimeoutError) Error() string
Error returns the formatted timeout message.
type Answer ¶
type Answer interface {
// AnswerType returns the wire discriminator: "noul", "choice", "score", or "box".
AnswerType() string
}
Answer is a single answer to a single question. The concrete type is NoulAnswer, ChoiceAnswer, ScoreAnswer, or BoxAnswer, and always matches the corresponding question's type.
type Answers ¶
Answers is a map of question names to answers, decoded by each entry's "type" discriminator.
SystemOneResponse.Answers is a plain map because its entries are already decoded. Answers exists for caller-defined response models passed to SystemOneAs, where Go needs a concrete type to decode into — a bare map[string]Answer cannot be decoded, because an interface type carries no information about which concrete answer to build:
type Analysis struct {
Model string `json:"model"`
Usage typesafe.Usage `json:"usage"`
Answers typesafe.Answers `json:"answers"`
}
func (*Answers) UnmarshalJSON ¶
UnmarshalJSON decodes the answers object, dispatching each entry on its "type" field.
type Asset ¶ added in v0.13.0
type Asset struct {
// Type is the kind of asset; currently always "image".
Type string `json:"type,omitzero"`
// Part is the name of the file part in a multipart request.
Part string `json:"part,omitzero"`
// DataBase64 is the standard base64-encoded image content.
DataBase64 string `json:"data_base64,omitzero"`
// Format is the image format: "png", "jpg", or "jpeg".
Format string `json:"format,omitzero"`
}
Asset describes an asset attached to a System One request.
type Assets ¶ added in v0.13.0
Assets maps reference strings to their Asset descriptions.
func CollectAssets ¶ added in v0.13.0
CollectAssets returns an Assets map containing all the given images.
type AuthenticationError ¶
type AuthenticationError struct{ APIError }
AuthenticationError is an HTTP 401 response.
type BadRequestError ¶
type BadRequestError struct{ APIError }
BadRequestError is an HTTP 400 response.
type BoxAnswer ¶ added in v0.13.0
type BoxAnswer struct {
// Type is always "box".
Type string `json:"type"`
// Box holds the bounding box edges as fractions from 0 to 1.
Box BoxCoordinates `json:"box"`
// Confidence is the statistical certainty of the box from 0 to 1, or nil when the API
// did not report one.
Confidence *float64 `json:"confidence"`
}
BoxAnswer is a bounding box locating an object or subject in an image.
See the box primitive (https://docs.typesafe.ai/primitives/box) for details.
func (*BoxAnswer) AnswerType ¶ added in v0.13.0
AnswerType returns the wire discriminator.
type BoxCoordinates ¶ added in v0.13.0
type BoxCoordinates struct {
// Top is the top edge, as a fraction of image height from the top (0 to 1).
Top float64 `json:"top"`
// Bottom is the bottom edge, as a fraction of image height from the top (0 to 1).
Bottom float64 `json:"bottom"`
// Left is the left edge, as a fraction of image width from the left (0 to 1).
Left float64 `json:"left"`
// Right is the right edge, as a fraction of image width from the left (0 to 1).
Right float64 `json:"right"`
}
BoxCoordinates holds a bounding box's edges as fractions of an image's height (top, bottom) and width (left, right).
type BoxQuestion ¶ added in v0.13.0
type BoxQuestion struct {
// Type is always "box".
Type string `json:"type"`
// Instructions is what to locate, expressed as a string, a JSON object, or an array.
Instructions any `json:"instructions,omitzero"`
// contains filtered or unexported fields
}
BoxQuestion locates what its instructions describe in an image.
Box questions find where something is in an image and return bounding box coordinates as fractions of the image's width and height. Requires the TypeSafe-Danger-Zone-Images: true header and the jev-preview / jev-1.14.0 model.
See the box primitive (https://docs.typesafe.ai/primitives/box) for details.
func NewBox ¶ added in v0.13.0
func NewBox(instructions any, opts ...QuestionOption) *BoxQuestion
NewBox creates a box question to locate a subject in an image.
typesafe.NewBox("the coffee mug in photo")
func (*BoxQuestion) MarshalJSON ¶ added in v0.13.0
func (q *BoxQuestion) MarshalJSON() ([]byte, error)
MarshalJSON encodes the question, including any fields added by WithQuestionField.
func (*BoxQuestion) QuestionType ¶ added in v0.13.0
func (q *BoxQuestion) QuestionType() string
QuestionType returns the wire discriminator.
func (*BoxQuestion) Validate ¶ added in v0.13.0
func (q *BoxQuestion) Validate(string) error
Validate accepts every box question (box questions take no criteria).
type ChoiceAnswer ¶
type ChoiceAnswer struct {
// Type is always "choice".
Type string `json:"type"`
// Choice is the criteria key with the highest probability.
Choice string `json:"choice"`
// Confidence is the statistical certainty of the choice, from 0 to 1, derived from how the
// probability is concentrated across alternatives. Higher values indicate a clear winner; lower
// values indicate uncertainty or split probabilities. It is the primary signal for confidence-gated
// routing, but where the bands fall is a decision for the caller, because it trades the cost of a
// wrong automatic action against the cost of a human review. The docs gate at 0.5 for a
// high-stakes decision (https://docs.typesafe.ai/confidence) and at 0.6 for a moderation queue
// (https://docs.typesafe.ai/patterns/confidence-routing); treat any number, including 0.5 and
// 0.85, as an example rather than an API-defined threshold.
Confidence float64 `json:"confidence"`
// Probabilities is the probability of each criteria key, from 0 to 1.
Probabilities map[string]float64 `json:"probabilities"`
}
ChoiceAnswer is a selected label with its alternatives.
See the choice primitive (https://docs.typesafe.ai/primitives/choice) for details.
func (*ChoiceAnswer) AnswerType ¶
func (a *ChoiceAnswer) AnswerType() string
AnswerType returns the wire discriminator.
type ChoiceQuestion ¶
type ChoiceQuestion struct {
// Type is always "choice".
Type string `json:"type"`
// Criteria maps each label to its description: a string, a JSON object, an array, or nil for
// an undescribed label. Supports up to 255 options.
Criteria map[string]any `json:"criteria"`
// Instructions is the question to ask, expressed as a string, a JSON object, or an array.
Instructions any `json:"instructions,omitzero"`
// contains filtered or unexported fields
}
ChoiceQuestion selects between named alternatives.
A Choice question picks one option from a defined set of up to 255 alternatives. The response includes the selected option, the full probability distribution, and a confidence score.
See the choice primitive (https://docs.typesafe.ai/primitives/choice) for details.
func NewChoice ¶
func NewChoice(criteria map[string]any, opts ...QuestionOption) *ChoiceQuestion
NewChoice creates a choice question with up to 255 alternative options.
typesafe.NewChoice(
map[string]any{"calm": nil, "angry": "An upset or hostile message"},
typesafe.WithInstructions("What is the tone of this message?"),
)
Example ¶
question := NewChoice(
map[string]any{"calm": nil, "angry": "An upset or hostile message"},
WithInstructions("What is the tone of this message?"),
)
encoded, err := json.Marshal(question)
if err != nil {
panic(err)
}
fmt.Println(string(encoded))
Output: {"type":"choice","criteria":{"angry":"An upset or hostile message","calm":null},"instructions":"What is the tone of this message?"}
func (*ChoiceQuestion) MarshalJSON ¶
func (q *ChoiceQuestion) MarshalJSON() ([]byte, error)
MarshalJSON encodes the question, including any fields added by WithQuestionField.
func (*ChoiceQuestion) QuestionType ¶
func (q *ChoiceQuestion) QuestionType() string
QuestionType returns the wire discriminator.
func (*ChoiceQuestion) Validate ¶
func (q *ChoiceQuestion) Validate(name string) error
Validate reports a choice question with no criteria field at all, or with more than 255 options.
An empty criteria object is sent rather than refused: the request schema requires the field, not a minimum number of entries, and the official client SDKs make no such check.
type Client ¶
type Client struct {
// Models provides access to the Models API resource.
Models *ModelsService
// contains filtered or unexported fields
}
Client is the TypeSafe AI API client.
A Client is safe for concurrent use by multiple goroutines: it holds no per-request state, and the underlying http.Client pools connections across calls. Create one Client and share it. All request methods take a context.Context, which is the only cancellation and concurrency control the SDK needs.
func NewClient ¶
NewClient creates a client for the TypeSafe AI API.
Configuration is resolved from the functional options first, then the environment, then the SDK defaults:
client, err := typesafe.NewClient(typesafe.WithTimeout(30*time.Second))
TYPESAFE_API_KEY is required unless WithAPIKey supplies the key.
func (*Client) Close ¶
Close releases the connection pool held by the client's transport.
A transport supplied through WithTransport or WithHTTPClient is closed when it implements io.Closer, so the client owns the resources it was given. Close is idempotent: later calls return the first call's error without touching the transport again.
func (*Client) HTTPClient ¶
HTTPClient returns the underlying *http.Client. A client constructed with WithHTTPClient returns that value; otherwise it returns the SDK's own client.
func (*Client) SystemOne ¶
func (c *Client) SystemOne(ctx context.Context, state any, questions any, opts ...RequestOption) (*SystemOneResponse, error)
SystemOne answers named questions about text or structured state.
See System One (https://docs.typesafe.ai/concepts/system-one) for details.
The response carries every answer keyed by the question name supplied here, alongside the model that answered and the token usage for the evaluation:
response, err := client.SystemOne(ctx,
map[string]any{"message": "I was charged twice. Please help."},
typesafe.Questions{
"billing": typesafe.NewNoul("Is this message about billing?"),
"tone": typesafe.NewChoice(
map[string]any{"calm": nil, "angry": nil},
typesafe.WithInstructions("What is the tone?"),
),
},
)
if err != nil {
return err
}
fmt.Println(response.Nouls()["billing"].Noul)
State can be a string, a JSON-serializable struct, a slice, or a map[string]any. Keep state focused on the relevant context to avoid distractor noise. Questions accepts Questions, map[string]Question, or map[string]any.
Errors are typed: SDKError for invalid input, APIError and its status-specific subclasses (BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, UnprocessableEntityError, RateLimitError, OverloadedError, InternalServerError) for unsuccessful responses, APIConnectionError and APITimeoutError for transport failures, and APIResponseValidationError for a success response that could not be decoded.
type Config ¶
type Config struct {
// APIKey is the credential sent as a bearer token.
APIKey string
// BaseURL is the API root, without a trailing slash.
BaseURL string
// DefaultModel is the model used when a call does not name one.
DefaultModel string
// Timeout is the HTTP timeout for one attempt, in effect for every call.
Timeout time.Duration
// DefaultHeaders holds headers sent with every request. Client identification and credentials
// are applied after these, so a default header cannot displace them.
DefaultHeaders http.Header
// Logger receives the SDK's structured log records.
Logger *slog.Logger
// RetryPolicy is the retry policy in effect for every call.
RetryPolicy *RetryPolicy
// HTTPClient is the caller-supplied HTTP client, or nil when the SDK owns its client.
HTTPClient *http.Client
// Transport is the caller-supplied transport, or nil when the SDK owns its transport.
Transport http.RoundTripper
// Compression enables automatic request body compression for bodies >= 1 KiB.
// Defaults to true.
Compression bool
// LongContext enables the TypeSafe-Danger-Zone-Long-Context header by default (262k token context).
LongContext bool
// Images enables the TypeSafe-Danger-Zone-Images header by default.
Images bool
}
Config is the resolved client configuration.
type Image ¶ added in v0.13.0
type Image struct {
// Ref is the unique reference string used to refer to this image.
Ref string
// Format is the normalized format ("png" or "jpg").
Format string
// Data is the raw image file bytes.
Data []byte
// Base64 is the base64-encoded representation of Data.
Base64 string
}
Image represents an image asset that can be referenced in state, instructions, or criteria.
func NewImage ¶ added in v0.13.0
NewImage creates an image asset with an auto-generated unique reference.
Accepted formats are "png", "jpg", and "jpeg". Maximum size is 16 MiB.
func NewImageFromBase64 ¶ added in v0.13.0
NewImageFromBase64 creates an image asset from a base64 string.
func NewImageFromFile ¶ added in v0.13.0
NewImageFromFile loads an image from disk and creates an Image asset.
func NewImageWithRef ¶ added in v0.13.0
NewImageWithRef creates an image asset with a caller-chosen reference string.
func (*Image) MarshalJSON ¶ added in v0.13.0
MarshalJSON encodes the image as its reference string, allowing Image objects to be embedded directly inside state, instructions, or criteria.
type InternalServerError ¶
type InternalServerError struct{ APIError }
InternalServerError is an HTTP 5xx response.
type ListModelsResponse ¶
type ListModelsResponse struct {
// Models holds the available models.
Models []ModelMetadata `json:"models"`
// contains filtered or unexported fields
}
ListModelsResponse holds the models available to the account.
func (*ListModelsResponse) MarshalJSON ¶
func (r *ListModelsResponse) MarshalJSON() ([]byte, error)
MarshalJSON encodes only the API payload, leaving HTTP metadata out of the result.
func (*ListModelsResponse) RawBody ¶
func (r *ListModelsResponse) RawBody() []byte
RawBody returns the response payload exactly as received.
func (*ListModelsResponse) RawHTTPResponse ¶
func (r *ListModelsResponse) RawHTTPResponse() (*http.Response, error)
RawHTTPResponse returns the underlying *http.Response.
func (*ListModelsResponse) RawRequestID ¶
func (r *ListModelsResponse) RawRequestID() string
RawRequestID returns the request ID, or the empty string when absent.
func (*ListModelsResponse) RequestID ¶
func (r *ListModelsResponse) RequestID() (string, error)
RequestID returns the x-typesafe-request-id response header. It reports an error when the response did not carry one.
type ModelMetadata ¶
type ModelMetadata struct {
// Name is the model name or alias accepted by a request's model field.
Name string `json:"name"`
// Description describes the model and its capabilities.
Description string `json:"description"`
// ReleaseDate is the model's release date as the API reports it. The published schema
// describes a YYYY-MM-DD date; the live API currently returns a full timestamp.
ReleaseDate string `json:"release_date"`
}
ModelMetadata describes a model available to the account.
type ModelsService ¶
type ModelsService struct {
// contains filtered or unexported fields
}
ModelsService exposes the Models API resource. Reach it through Client.Models.
func (*ModelsService) List ¶
func (s *ModelsService) List(ctx context.Context, opts ...RequestOption) (*ListModelsResponse, error)
List returns the models available to the account, with each model's name, description, and release date.
response, err := client.Models.List(ctx)
for _, model := range response.Models {
fmt.Println(model.Name, model.ReleaseDate)
}
type NoulAnswer ¶
type NoulAnswer struct {
// Type is always "noul".
Type string `json:"type"`
// Noul is the probability of a yes answer or a true statement, from 0 to 1.
Noul float64 `json:"noul"`
}
NoulAnswer is a yes/no answer.
See the noul primitive (https://docs.typesafe.ai/primitives/noul) for details.
func (*NoulAnswer) AnswerType ¶
func (a *NoulAnswer) AnswerType() string
AnswerType returns the wire discriminator.
type NoulCriteria ¶
type NoulCriteria struct {
// True describes what counts as a yes answer.
True any `json:"true,omitzero"`
// False describes what counts as a no answer.
False any `json:"false,omitzero"`
}
NoulCriteria describes what counts as a yes or no answer. Both fields accept a string, a map, or a slice, and may be left nil.
type NoulQuestion ¶
type NoulQuestion struct {
// Type is always "noul".
Type string `json:"type"`
// Instructions is the question to ask, expressed as a string, a JSON object, or an array.
Instructions any `json:"instructions,omitzero"`
// Criteria describes what counts as a yes or no answer.
Criteria *NoulCriteria `json:"criteria,omitzero"`
// contains filtered or unexported fields
}
NoulQuestion is a yes/no question or statement.
See the noul primitive (https://docs.typesafe.ai/primitives/noul) for details.
func NewNoul ¶
func NewNoul(instructions any, opts ...QuestionOption) *NoulQuestion
NewNoul creates a yes/no question. The instructions may be a string, a map, or a slice, and may be nil when criteria alone describe the question; the request schema requires neither field.
typesafe.NewNoul("Is this message spam?")
typesafe.NewNoul("Is this spam?", typesafe.WithNoulCriteria(typesafe.NoulCriteria{
True: "Unsolicited advertising",
False: "A legitimate conversation",
}))
Options refine the question: WithInstructions overrides the instructions given positionally.
Example ¶
question := NewNoul("Is this message about billing?")
fmt.Println(question.QuestionType())
fmt.Println(question.Instructions)
Output: noul Is this message about billing?
func (*NoulQuestion) MarshalJSON ¶
func (q *NoulQuestion) MarshalJSON() ([]byte, error)
MarshalJSON encodes the question, including any fields added by WithQuestionField.
func (*NoulQuestion) QuestionType ¶
func (q *NoulQuestion) QuestionType() string
QuestionType returns the wire discriminator.
func (*NoulQuestion) Validate ¶
func (q *NoulQuestion) Validate(string) error
Validate accepts every noul question. The request schema requires no field for a noul, so a bare statement, a statement with criteria, and criteria alone are all well-formed requests.
type Option ¶
type Option func(*configOptions)
Option configures a Client at construction time.
func WithAPIKey ¶
WithAPIKey sets the API key, overriding the TYPESAFE_API_KEY environment variable.
func WithBaseURL ¶
WithBaseURL sets the API root, overriding the TYPESAFE_BASE_URL environment variable.
func WithCompression ¶ added in v0.13.0
WithCompression sets whether request bodies >= 1 KiB are compressed (gzip). Default is true. Pass false to send uncompressed bodies.
func WithDefaultModel ¶
WithDefaultModel sets the model used when a call does not name one, overriding the TYPESAFE_DEFAULT_MODEL environment variable.
func WithHTTPClient ¶
WithHTTPClient supplies the http.Client the SDK sends through, together with its transport. Mutually exclusive with WithTransport.
func WithHeader ¶
WithHeader sets a default header sent with every request. Client identification and credentials are applied afterwards and cannot be displaced.
func WithHeaders ¶
WithHeaders sets default headers sent with every request, merging with any set by WithHeader.
func WithImages ¶ added in v0.13.0
WithImages sets whether to send TypeSafe-Danger-Zone-Images: true with every request.
func WithLogger ¶
WithLogger sets the structured logger. The SDK logs requests, responses, and retries at info level, and headers and bodies at debug level, with credential headers redacted.
func WithLongContext ¶ added in v0.13.0
WithLongContext sets whether to send TypeSafe-Danger-Zone-Long-Context: true with every request.
func WithRetryPolicy ¶
func WithRetryPolicy(policy *RetryPolicy) Option
WithRetryPolicy sets the retry policy for every call.
func WithTimeout ¶
WithTimeout sets the HTTP timeout for one attempt. It must be positive.
The timeout has no environment variable. When WithHTTPClient supplies both a client and no explicit timeout, the client's own Timeout is adopted instead.
func WithTransport ¶
func WithTransport(transport http.RoundTripper) Option
WithTransport supplies the http.RoundTripper the SDK sends through. Mutually exclusive with WithHTTPClient.
type OverloadedError ¶ added in v0.10.1
type OverloadedError struct {
APIError
// RetryAfterMS is the wait the server requested in milliseconds, or nil when the
// response carried no usable Retry-After or retry-after-ms header.
RetryAfterMS *float64
}
OverloadedError is an HTTP 529 response indicating that TypeSafe is temporarily overloaded.
func AsOverloadedError ¶ added in v0.10.1
func AsOverloadedError(err error) (*OverloadedError, bool)
AsOverloadedError extracts the OverloadedError when the failure was an HTTP 529.
func (*OverloadedError) RetryAfter ¶ added in v0.10.1
func (e *OverloadedError) RetryAfter() (time.Duration, bool)
RetryAfter returns the server-requested wait and whether the response provided one.
type PayloadTooLargeError ¶ added in v0.13.0
type PayloadTooLargeError struct{ APIError }
PayloadTooLargeError is an HTTP 413 response.
func AsPayloadTooLargeError ¶ added in v0.13.0
func AsPayloadTooLargeError(err error) (*PayloadTooLargeError, bool)
AsPayloadTooLargeError extracts the PayloadTooLargeError when the failure was an HTTP 413.
type PermissionDeniedError ¶
type PermissionDeniedError struct{ APIError }
PermissionDeniedError is an HTTP 403 response.
type Question ¶
type Question interface {
// QuestionType returns the wire discriminator: "noul", "choice", "score", or "box".
QuestionType() string
// Validate reports whether the question is well formed under the given name.
Validate(name string) error
}
Question is implemented by every question the SDK can send: NoulQuestion, ChoiceQuestion, ScoreQuestion, BoxQuestion, and RawQuestion.
type QuestionOption ¶
type QuestionOption func(*questionOptions)
QuestionOption refines a question constructed by NewNoul, NewChoice, or NewScore.
func WithInstructions ¶
func WithInstructions(instructions any) QuestionOption
WithInstructions sets the question's instructions: the question to ask, expressed as a string, a JSON object, or an array.
func WithNoulCriteria ¶
func WithNoulCriteria(criteria NoulCriteria) QuestionOption
WithNoulCriteria sets the criteria describing the yes and no outcomes of a noul question.
Example ¶
question := NewNoul("Is this spam?", WithNoulCriteria(NoulCriteria{
True: "Unsolicited advertising",
False: "A legitimate conversation",
}))
encoded, err := json.Marshal(question)
if err != nil {
panic(err)
}
fmt.Println(string(encoded))
Output: {"type":"noul","instructions":"Is this spam?","criteria":{"true":"Unsolicited advertising","false":"A legitimate conversation"}}
func WithQuestionField ¶
func WithQuestionField(key string, value any) QuestionOption
WithQuestionField adds a field to a question's wire form. It exists for forward compatibility with request fields this SDK version does not model; a field that collides with a modeled one replaces it.
Example ¶
question := NewNoul("Is this message about billing?", WithQuestionField("language", "en"))
encoded, err := json.Marshal(question)
if err != nil {
panic(err)
}
fmt.Println(string(encoded))
Output: {"instructions":"Is this message about billing?","language":"en","type":"noul"}
type Questions ¶
Questions maps the names you choose to the questions they identify. The names key the answers in the response.
The values are typed as Question, so a value that is not a question is a compile error. Build them with NewNoul, NewChoice, NewScore, and NewBox, or with RawQuestion for a question shape this version does not model. To pass a plain map[string]any, hand it to the client directly — the question parameter accepts any accepted container, which NormalizeQuestions validates.
type RateLimitError ¶
type RateLimitError struct {
APIError
// RetryAfterMS is the wait the server requested in milliseconds, or nil when the
// response carried no usable Retry-After or retry-after-ms header.
RetryAfterMS *float64
}
RateLimitError is an HTTP 429 response.
func AsRateLimitError ¶
func AsRateLimitError(err error) (*RateLimitError, bool)
AsRateLimitError extracts the RateLimitError when the failure was an HTTP 429. If the failure was an HTTP 529 OverloadedError, it produces a compatible RateLimitError so rate-limiting and overload backoff logic can treat them interchangeably.
func (*RateLimitError) RetryAfter ¶
func (e *RateLimitError) RetryAfter() (time.Duration, bool)
RetryAfter returns the server-requested wait and whether the response provided one.
type RawQuestion ¶
RawQuestion is a question sent as a plain map, for request fields this SDK version does not model:
typesafe.RawQuestion{"type": "noul", "instructions": "Is this about billing?"}
func (RawQuestion) QuestionType ¶
func (q RawQuestion) QuestionType() string
QuestionType returns the "type" field, or the empty string when absent.
func (RawQuestion) Validate ¶
func (q RawQuestion) Validate(name string) error
Validate applies the structural checks the SDK can make without duplicating the server's schema: the type must be a non-empty string, and a choice or score question must carry criteria. A choice question must also declare no more than 255 countable options.
type RedactingHandler ¶
type RedactingHandler struct {
// contains filtered or unexported fields
}
RedactingHandler wraps an slog.Handler and redacts credential-bearing attributes before they reach it.
The SDK already redacts the headers it logs itself; this handler extends that guarantee to records the caller routes through the SDK's logger:
logger := slog.New(typesafe.NewRedactingHandler(slog.NewJSONHandler(os.Stdout, nil))) client, err := typesafe.NewClient(typesafe.WithLogger(logger))
Values held in a map[string]string under any attribute are inspected key by key.
func NewRedactingHandler ¶
func NewRedactingHandler(handler slog.Handler) *RedactingHandler
NewRedactingHandler wraps handler so that credential-bearing attributes are redacted.
func (*RedactingHandler) Handle ¶
Handle redacts the record's attributes and forwards it to the wrapped handler. Attributes that carry no credential are passed through unchanged.
type RequestOption ¶
type RequestOption func(*requestOptions)
RequestOption overrides client configuration for a single call.
func WithAssets ¶ added in v0.13.0
func WithAssets(assets any) RequestOption
WithAssets attaches an assets map to the request, containing image assets. It accepts Assets, map[string]Asset, or map[string]any.
func WithCallCompression ¶ added in v0.13.0
func WithCallCompression(enabled bool) RequestOption
WithCallCompression overrides body compression for a single call.
func WithCallHeader ¶
func WithCallHeader(key, value string) RequestOption
WithCallHeader sets or overrides a request header for a single call.
func WithCallHeaders ¶
func WithCallHeaders(headers map[string]string) RequestOption
WithCallHeaders sets or overrides request headers for a single call, merging with any set by WithCallHeader.
func WithCallImages ¶ added in v0.13.0
func WithCallImages(enabled bool) RequestOption
WithCallImages sets TypeSafe-Danger-Zone-Images: true for a single call.
func WithCallLongContext ¶ added in v0.13.0
func WithCallLongContext(enabled bool) RequestOption
WithCallLongContext sets TypeSafe-Danger-Zone-Long-Context: true for a single call.
func WithCallRetry ¶
func WithCallRetry(policy *RetryPolicy) RequestOption
WithCallRetry overrides the retry policy for a single call.
func WithCallTimeout ¶
func WithCallTimeout(timeout time.Duration) RequestOption
WithCallTimeout overrides the HTTP timeout for a single call. It must be positive.
func WithExtraBody ¶
func WithExtraBody(extra map[string]any) RequestOption
WithExtraBody adds top-level fields to a request body, shallow-merged over "state", "model", and "questions" after they are set. Merging is last-write-wins: a colliding key replaces the SDK's value, and object values are replaced rather than deep-merged.
func WithModel ¶
func WithModel(model string) RequestOption
WithModel overrides the model for a single call.
type RetryPolicy ¶
type RetryPolicy struct {
// MaxRetries is the number of retries after the initial attempt. Zero disables retries.
MaxRetries int
// BackoffInitial is the first backoff delay; it doubles per attempt up to BackoffMax.
// Zero disables backoff.
BackoffInitial time.Duration
// BackoffMax caps the backoff delay. Zero disables backoff.
BackoffMax time.Duration
// BackoffJitter is the fraction of each backoff delay that is randomly subtracted,
// between zero and one.
BackoffJitter float64
// HTTPStatuses holds the response status codes that are retried.
HTTPStatuses map[int]bool
// RespectRetryAfter honors the retry-after-ms and Retry-After response headers.
RespectRetryAfter bool
// MaxRetryAfter caps how long a server retry hint is honored, matching the official client SDKs:
// a longer hint is ignored in favor of the computed backoff. Zero honors any hint.
MaxRetryAfter time.Duration
// APIConnectionError retries [APIConnectionError] failures.
APIConnectionError bool
// APITimeoutError retries [APITimeoutError] failures.
APITimeoutError bool
// RetryErrors holds additional error values that trigger a retry. A failure is retried when
// errors.Is reports a match against any entry.
RetryErrors []error
// Predicate is consulted for every failure. Returning true triggers a retry, in addition to
// the rules above.
Predicate func(error) bool
// Timeout is an optional total budget for one SDK call, covering the initial attempt, retries,
// and delays. A retry whose delay would reach or exceed the remaining budget is abandoned and the
// last error is returned.
//
// The official client SDKs bound each attempt and the number of attempts but apply no overall
// budget, so the default policy leaves this nil. Set it, for example to new(30*time.Second), when
// a call must return within a known time.
Timeout *time.Duration
// Sleep waits between attempts. It is a seam for tests; nil uses a context-aware timer.
Sleep func(ctx context.Context, delay time.Duration) error
// RandFloat returns a value in [0, 1) used for backoff jitter. It is a seam for tests;
// nil uses the global math/rand/v2 source.
RandFloat func() float64
}
RetryPolicy configures how the client retries failed requests.
The zero value is not usable; start from DefaultRetryPolicy and adjust, or set the fields you care about and leave the rest zero:
policy := typesafe.DefaultRetryPolicy() policy.MaxRetries = 3 policy.Timeout = new(30 * time.Second) // bound the whole call
A non-nil policy passed to WithRetryPolicy or WithCallRetry is validated when it is used.
func DefaultRetryPolicy ¶
func DefaultRetryPolicy() *RetryPolicy
DefaultRetryPolicy returns a fresh copy of the retry policy the SDK uses when none is supplied.
The values match the official client SDKs: two retries after the initial attempt, a jittered exponential backoff from 500ms to 5s, retries for 408, 429, and every 5xx and for connection and timeout failures, and server retry hints no longer than a minute. No overall budget is applied.
func (*RetryPolicy) Clone ¶
func (p *RetryPolicy) Clone() *RetryPolicy
Clone returns a deep copy of the policy, so a per-call override can be adjusted without mutating the client's policy.
func (*RetryPolicy) Execute ¶
Execute runs fn under this policy, retrying per the policy's rules.
fn receives the zero-based attempt index. Execute stops early, returning the last failure, when the retry budget would be exceeded, when the failure is not retryable, or when the caller's context ends. A cancelled or expired context is never retried.
func (*RetryPolicy) Validate ¶
func (p *RetryPolicy) Validate() error
Validate reports whether the policy is well formed.
type SDKError ¶
type SDKError struct {
// Message describes the failure.
Message string
// Cause is the wrapped error, when one exists.
Cause error
}
SDKError is a client-side failure: invalid configuration, an unencodable body, or a response that could not be read. It never represents an unsuccessful HTTP status.
type ScoreAnswer ¶
type ScoreAnswer struct {
// Type is always "score".
Type string `json:"type"`
// Score is the probability-weighted average across discrete rubric levels (0 to len(Legend)-1);
// it may fall between levels. Suitable for threshold comparison, not for continuous magnitude reconstruction.
Score float64 `json:"score"`
// Confidence is the confidence in the rating, from 0 to 1.
Confidence float64 `json:"confidence"`
// Legend maps each rubric level to the criteria description supplied in the request. Keys are the
// level numbers as the API sends them — strings — and the values stay untyped because a level
// description may be a string, an object, or an array. [ScoreAnswer.LegendFor] reads a level by
// number, the way Probabilities is keyed.
Legend map[string]any `json:"legend"`
// Probabilities is the probability of each rubric level, keyed by the integer level number.
Probabilities map[int]float64 `json:"probabilities"`
}
ScoreAnswer is a rating against an ordered rubric.
Model Behavior Note (Jev 1.13): Score is the probability-weighted average of discrete rubric levels. It is calibrated for threshold gating and ordinal classification (e.g. score >= 1.5). Do NOT use Score as a continuous linear interpolator or calculator to reconstruct exact numerical magnitudes between levels, because System One models are qualitative decision engines, not numeric calculators.
See the score primitive (https://docs.typesafe.ai/primitives/score) and model jaggedness (https://docs.typesafe.ai/model-jaggedness/jev-1.13) for details.
func (*ScoreAnswer) AnswerType ¶
func (a *ScoreAnswer) AnswerType() string
AnswerType returns the wire discriminator.
func (*ScoreAnswer) LegendFor ¶ added in v0.11.0
func (a *ScoreAnswer) LegendFor(level int) (any, bool)
LegendFor returns the legend entry for a rubric level number, the level Probabilities is keyed by. It reports false when the level is absent from the legend.
func (*ScoreAnswer) MarshalJSON ¶
func (a *ScoreAnswer) MarshalJSON() ([]byte, error)
MarshalJSON encodes the rubric probabilities with their integer levels as JSON object keys.
type ScoreError ¶
type ScoreError struct {
// Name is the question name that failed validation.
Name string
}
ScoreError reports a score question with an invalid rubric.
func (*ScoreError) Error ¶
func (e *ScoreError) Error() string
type ScoreQuestion ¶
type ScoreQuestion struct {
// Type is always "score".
Type string `json:"type"`
// Criteria is the ordered rubric: each entry's position is its score, starting at zero. Each
// entry is a string, a JSON object, or an array. Must contain between 2 and 10 levels.
Criteria []any `json:"criteria"`
// Instructions is the question to ask, expressed as a string, a JSON object, or an array.
Instructions any `json:"instructions,omitzero"`
// contains filtered or unexported fields
}
ScoreQuestion rates content using an ordered rubric.
A Score rubric requires between 2 and 10 levels. The response includes an expected score (probability-weighted average), a probability for each level, and a confidence score. Use Score for threshold gating rather than continuous numeric calculations.
See the score primitive (https://docs.typesafe.ai/primitives/score) for details.
func NewScore ¶
func NewScore(criteria []any, opts ...QuestionOption) *ScoreQuestion
NewScore creates a score question with an ordered rubric containing between 2 and 10 levels.
typesafe.NewScore(
[]any{"can wait", "needs attention this week", "needs attention today"},
typesafe.WithInstructions("How urgent is this message?"),
)
Example ¶
question := NewScore(
[]any{"can wait", "needs attention this week", "needs attention today"},
WithInstructions("How urgent is this message?"),
)
encoded, err := json.Marshal(question)
if err != nil {
panic(err)
}
fmt.Println(string(encoded))
Output: {"type":"score","criteria":["can wait","needs attention this week","needs attention today"],"instructions":"How urgent is this message?"}
func (*ScoreQuestion) MarshalJSON ¶
func (q *ScoreQuestion) MarshalJSON() ([]byte, error)
MarshalJSON encodes the question, including any fields added by WithQuestionField.
func (*ScoreQuestion) QuestionType ¶
func (q *ScoreQuestion) QuestionType() string
QuestionType returns the wire discriminator.
func (*ScoreQuestion) Validate ¶
func (q *ScoreQuestion) Validate(name string) error
Validate reports a score question whose rubric does not have between 2 and 10 levels.
type SystemOneResponse ¶
type SystemOneResponse struct {
// Model is the name of the model that answered the questions; it may differ from the alias
// supplied in the request.
Model string `json:"model"`
// Usage reports the token counts for this evaluation.
Usage Usage `json:"usage"`
// Answers holds every answer keyed by the question name supplied in the request. Answer types
// this SDK version does not model are omitted here and remain reachable through RawBody.
Answers map[string]Answer `json:"answers"`
// contains filtered or unexported fields
}
SystemOneResponse holds the answers to a System One request, grouped by question kind.
See System One (https://docs.typesafe.ai/concepts/system-one) for details.
func (*SystemOneResponse) Boxes ¶ added in v0.13.0
func (r *SystemOneResponse) Boxes() map[string]*BoxAnswer
Boxes returns the box answers keyed by question name.
func (*SystemOneResponse) Choices ¶
func (r *SystemOneResponse) Choices() map[string]*ChoiceAnswer
Choices returns the choice answers keyed by question name.
func (*SystemOneResponse) MarshalJSON ¶
func (r *SystemOneResponse) MarshalJSON() ([]byte, error)
MarshalJSON encodes only the API payload, leaving HTTP metadata out of the result.
func (*SystemOneResponse) Nouls ¶
func (r *SystemOneResponse) Nouls() map[string]*NoulAnswer
Nouls returns the yes/no answers keyed by question name.
func (*SystemOneResponse) RawBody ¶
func (r *SystemOneResponse) RawBody() []byte
RawBody returns the response payload exactly as received, including any answer types this SDK version does not model.
func (*SystemOneResponse) RawHTTPResponse ¶
func (r *SystemOneResponse) RawHTTPResponse() (*http.Response, error)
RawHTTPResponse returns the underlying *http.Response.
func (*SystemOneResponse) RawRequestID ¶
func (r *SystemOneResponse) RawRequestID() string
RawRequestID returns the request ID, or the empty string when absent.
func (*SystemOneResponse) RequestID ¶
func (r *SystemOneResponse) RequestID() (string, error)
RequestID returns the x-typesafe-request-id response header. It reports an error when the response did not carry one.
func (*SystemOneResponse) Scores ¶
func (r *SystemOneResponse) Scores() map[string]*ScoreAnswer
Scores returns the score answers keyed by question name.
func (*SystemOneResponse) String ¶
func (r *SystemOneResponse) String() string
String implements fmt.Stringer for convenient debugging of a response.
type TypeSafeError ¶
type TypeSafeError interface {
error
// contains filtered or unexported methods
}
TypeSafeError is the marker interface implemented by every error this SDK returns.
Match it with errors.As:
if err != nil {
var sdkErr typesafe.TypeSafeError
if errors.As(err, &sdkErr) {
// the failure came from the SDK
}
}
type UnprocessableEntityError ¶
type UnprocessableEntityError struct{ APIError }
UnprocessableEntityError is an HTTP 422 response.
type UnsupportedMediaTypeError ¶ added in v0.13.0
type UnsupportedMediaTypeError struct{ APIError }
UnsupportedMediaTypeError is an HTTP 415 response.
func AsUnsupportedMediaTypeError ¶ added in v0.13.0
func AsUnsupportedMediaTypeError(err error) (*UnsupportedMediaTypeError, bool)
AsUnsupportedMediaTypeError extracts the UnsupportedMediaTypeError when the failure was an HTTP 415.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
typesafe
command
Command typesafe is a command-line client for the TypeSafe AI API.
|
Command typesafe is a command-line client for the TypeSafe AI API. |
|
examples
|
|
|
advanced
command
Command advanced exercises the parts of the TypeSafe AI Go SDK a production caller reaches for: per-call overrides, a custom retry policy, a typed response model, a second API resource, and the typed error taxonomy.
|
Command advanced exercises the parts of the TypeSafe AI Go SDK a production caller reaches for: per-call overrides, a custom retry policy, a typed response model, a second API resource, and the typed error taxonomy. |
|
quickstart
command
Command quickstart is the smallest useful TypeSafe AI Go SDK program: one System One request that answers a noul, a choice, and a score question about a structured state.
|
Command quickstart is the smallest useful TypeSafe AI Go SDK program: one System One request that answers a noul, a choice, and a score question about a structured state. |