Documentation
¶
Overview ¶
Package typesafe provides a Go client SDK for the TypeSafe AI System One API.
TypeSafe's System One models make fast, structured decisions for software. Send state and typed questions; get structured answers your code can use directly.
Quick start ¶
client, err := typesafe.NewClient(typesafe.WithAPIKey("your-api-key"))
if err != nil {
log.Fatal(err)
}
resp, err := client.SystemOne(ctx, &typesafe.SystemOneRequest{
State: "Help! My payouts have been failing for 3 days.",
Model: typesafe.ModelJevLatest,
Questions: typesafe.Questions{
"is_urgent": typesafe.Noul("Does this convey urgency?"),
},
})
if err != nil {
log.Fatal(err)
}
noul, _ := resp.Answers["is_urgent"].AsNoul()
fmt.Printf("Urgent: %.0f%%\n", noul.Value*100) // Urgent: 95%
Authentication ¶
The client reads credentials in this order:
- Explicit WithAPIKey option
- TYPESAFE_API_KEY environment variable
Concurrency ¶
A Client is safe for concurrent use by multiple goroutines. Do not copy a Client after first use.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
client, err := typesafe.NewClient() // reads TYPESAFE_API_KEY
if err != nil {
log.Fatal(err)
}
resp, err := client.SystemOne(context.Background(), &typesafe.SystemOneRequest{
State: "Help! My payouts have been failing for 3 days.",
Questions: typesafe.Questions{
"is_urgent": typesafe.Noul("Does this convey urgency?"),
},
})
if err != nil {
log.Fatal(err)
}
urgent, err := resp.Answers["is_urgent"].AsNoul()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Urgent: %.0f%%\n", urgent.Value*100)
}
Output:
Index ¶
- Constants
- Variables
- func IsNotFound(err error) bool
- func IsOverloaded(err error) bool
- func IsRateLimited(err error) bool
- func IsUnauthorized(err error) bool
- func IsUnprocessableEntity(err error) bool
- type APIError
- type Answer
- type ChoiceAnswer
- type Client
- type Error
- type ListModelsResponse
- type ModelCard
- type ModelsService
- type NoulAnswer
- type NoulCriteria
- type Option
- func WithAPIKey(key string) Option
- func WithBaseURL(url string) Option
- func WithDefaultModel(model string) Option
- func WithHTTPClient(hc *http.Client) Option
- func WithLogger(l *slog.Logger) Option
- func WithRetryPolicy(p RetryPolicy) Option
- func WithTimeout(d time.Duration) Option
- func WithUserAgentSuffix(suffix string) Option
- type Question
- type QuestionType
- type Questions
- type RequestOption
- type RetryPolicy
- type ScoreAnswer
- type SystemOneRequest
- type SystemOneResponse
- type Usage
Examples ¶
Constants ¶
const ( // Version is the SDK version. Version = "0.1.0" // DefaultBaseURL is the default TypeSafe API base URL. DefaultBaseURL = "https://api.typesafe.ai" // DefaultTimeout is the default HTTP request timeout. DefaultTimeout = 10 * time.Second // DefaultModel is the default model name, matching the Python SDK. DefaultModel = "jev-latest" // EnvAPIKey is the environment variable for the API key. //nolint:gosec // G101 false positive: this is an environment variable name, not a credential. EnvAPIKey = "TYPESAFE_API_KEY" // EnvBaseURL is the environment variable for the base URL. EnvBaseURL = "TYPESAFE_BASE_URL" // EnvDefaultModel is the environment variable for the default model. EnvDefaultModel = "TYPESAFE_DEFAULT_MODEL" )
const ( // ModelJevLatest points to the most recent stable, official Jev release. ModelJevLatest = "jev-latest" // ModelJevPreview points to the most recent release, whether or not // it is an official one. ModelJevPreview = "jev-preview" // ModelJev1_13_0 is the versioned ID for Jev 1.13.0. ModelJev1_13_0 = "jev-1.13.0" )
Model aliases and versioned IDs.
Variables ¶
var ( // ErrBadRequest is returned for 400 responses. ErrBadRequest = errors.New("typesafe: bad request") ErrUnauthorized = errors.New("typesafe: unauthorized") // ErrForbidden is returned for 403 responses. ErrForbidden = errors.New("typesafe: forbidden") // ErrNotFound is returned for 404 responses. ErrNotFound = errors.New("typesafe: not found") // ErrUnprocessableEntity is returned for 422 responses. ErrUnprocessableEntity = errors.New("typesafe: unprocessable entity") // ErrRateLimited is returned for 429 responses. ErrRateLimited = errors.New("typesafe: rate limited") // ErrOverloaded is returned for 529 responses. ErrOverloaded = errors.New("typesafe: overloaded") // ErrInternalServer is returned for 5xx responses. ErrInternalServer = errors.New("typesafe: internal server error") )
Sentinel errors used with errors.Is for common HTTP status codes.
var ErrResponseTooLarge = transport.ErrResponseTooLarge
ErrResponseTooLarge is returned when a successful response body exceeds the SDK's read limit. The response is not decoded and the request is not retried, since a retry would return the same oversized body.
Functions ¶
func IsNotFound ¶
IsNotFound reports whether err is a 404 Not Found error.
func IsOverloaded ¶
IsOverloaded reports whether err is a 529 Overloaded error.
func IsRateLimited ¶
IsRateLimited reports whether err is a 429 Too Many Requests error.
func IsUnauthorized ¶
IsUnauthorized reports whether err is a 401 Unauthorized error.
func IsUnprocessableEntity ¶
IsUnprocessableEntity reports whether err is a 422 Unprocessable Entity error.
Types ¶
type APIError ¶
type APIError struct {
// StatusCode is the HTTP status code.
StatusCode int
// Message is a human-readable error message extracted from the response body.
Message string
// RequestID is the value of the x-typesafe-request-id header, if present.
RequestID string
// Body is the raw response body, truncated to [maxErrorBodyLen].
Body string
// contains filtered or unexported fields
}
APIError is returned when the TypeSafe API responds with a non-2xx status.
Example ¶
Inspect an *APIError for the status code and the request ID to quote in a support thread, and use the sentinel helpers for common cases.
package main
import (
"context"
"errors"
"fmt"
"log"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
client, err := typesafe.NewClient()
if err != nil {
log.Fatal(err)
}
_, err = client.SystemOne(context.Background(), &typesafe.SystemOneRequest{
State: "...",
Questions: typesafe.Questions{"ok": typesafe.Noul("Is this fine?")},
})
if err != nil {
var apiErr *typesafe.APIError
if errors.As(err, &apiErr) {
fmt.Printf("status=%d request_id=%s: %s\n",
apiErr.StatusCode, apiErr.RequestID, apiErr.Message)
}
switch {
case typesafe.IsRateLimited(err):
fmt.Println("slow down")
case typesafe.IsOverloaded(err):
fmt.Println("try again shortly")
case typesafe.IsUnauthorized(err):
fmt.Println("check the API key")
}
}
}
Output:
type Answer ¶
type Answer struct {
// Type matches the question type that produced this answer.
Type QuestionType `json:"type"`
// Raw holds the undecoded JSON for this answer, useful for forward
// compatibility with future answer types.
Raw json.RawMessage `json:"-"`
// contains filtered or unexported fields
}
Answer is a polymorphic answer returned by the API. Use Answer.AsNoul, Answer.AsChoice, or Answer.AsScore to access type-specific fields.
Unknown answer types (from future API versions) are preserved in Answer.Raw and silently skipped by the typed accessors.
func (Answer) AsChoice ¶
func (a Answer) AsChoice() (ChoiceAnswer, error)
AsChoice returns a typed ChoiceAnswer. Returns an error if the answer type is not "choice".
func (Answer) AsNoul ¶
func (a Answer) AsNoul() (NoulAnswer, error)
AsNoul returns a typed NoulAnswer. Returns an error if the answer type is not "noul".
func (Answer) AsScore ¶
func (a Answer) AsScore() (ScoreAnswer, error)
AsScore returns a typed ScoreAnswer. Returns an error if the answer type is not "score".
Example ¶
AsScore reports the probability-weighted score, which can land between levels, along with the legend and per-level probabilities.
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
var a typesafe.Answer
const payload = `{"type":"score","score":2.4,"legend":{"1":"low","2":"mid","3":"high"},` +
`"probabilities":{"1":0.1,"2":0.4,"3":0.5},"confidence":0.62}`
if err := json.Unmarshal([]byte(payload), &a); err != nil {
log.Fatal(err)
}
s, err := a.AsScore()
if err != nil {
log.Fatal(err)
}
fmt.Printf("score=%.1f confidence=%.2f top=%s\n", s.Score, s.Confidence, s.Legend["3"])
}
Output: score=2.4 confidence=0.62 top=high
func (Answer) MarshalJSON ¶
MarshalJSON encodes the answer back to JSON. If Raw is available it is returned directly; otherwise the typed fields are serialized.
This is a value method so that marshaling an Answer, a *Answer, or a struct with an Answer field all produce the same output.
func (*Answer) UnmarshalJSON ¶
UnmarshalJSON decodes an answer from JSON, preserving unknown answer types for forward compatibility.
type ChoiceAnswer ¶
type ChoiceAnswer struct {
// Choice is the highest-probability option.
Choice string
// Probabilities maps every option to its probability (floats that sum to 1).
Probabilities map[string]float64
// Confidence is how certain the model is, derived from probabilities (0 to 1).
Confidence float64
}
ChoiceAnswer is a typed choice answer.
type Client ¶
type Client struct {
// Models provides access to the models listing endpoint.
Models *ModelsService
// contains filtered or unexported fields
}
Client is the TypeSafe API client. It is safe for concurrent use by multiple goroutines. Do not copy a Client after first use.
func NewClient ¶
NewClient creates a new TypeSafe client with the given options. It returns an error if the configuration is invalid (e.g. missing API key).
Credentials are resolved in this order:
- Explicit WithAPIKey option
- TYPESAFE_API_KEY environment variable
Example ¶
package main
import (
"log"
"os"
"time"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
client, err := typesafe.NewClient(
typesafe.WithAPIKey(os.Getenv("MY_TYPESAFE_KEY")),
typesafe.WithDefaultModel(typesafe.ModelJevLatest),
typesafe.WithTimeout(30*time.Second),
typesafe.WithUserAgentSuffix("my-service/1.4"),
)
if err != nil {
log.Fatal(err)
}
_ = client
}
Output:
func (*Client) SystemOne ¶
func (c *Client) SystemOne(ctx context.Context, req *SystemOneRequest, opts ...RequestOption) (*SystemOneResponse, error)
SystemOne evaluates the state against a set of typed questions and returns structured answers. This is the primary API method.
See https://docs.typesafe.ai/api for the full endpoint reference.
Example ¶
Ask several typed questions in one call and read each answer back by name.
package main
import (
"context"
"fmt"
"log"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
client, err := typesafe.NewClient()
if err != nil {
log.Fatal(err)
}
resp, err := client.SystemOne(context.Background(), &typesafe.SystemOneRequest{
State: []map[string]string{
{"role": "customer", "text": "Where is my refund? It has been two weeks."},
{"role": "agent", "text": "Let me look into that for you."},
},
Questions: typesafe.Questions{
"needs_escalation": typesafe.Noul("Should a human take over?"),
"topic": typesafe.Choice("What is this about?", map[string]any{
"billing": "payments, invoices, refunds",
"technical": "bugs, outages, integration problems",
"other": nil,
}),
"severity": typesafe.Score("How severe is this?", []any{
"cosmetic, no user impact",
"degraded but usable",
"fully broken, revenue affected",
}),
},
})
if err != nil {
log.Fatal(err)
}
for name, n := range resp.Nouls() {
fmt.Printf("%s: %.2f\n", name, n.Value)
}
for name, c := range resp.Choices() {
fmt.Printf("%s: %s (confidence %.2f)\n", name, c.Choice, c.Confidence)
}
for name, s := range resp.Scores() {
fmt.Printf("%s: %.2f\n", name, s.Score)
}
fmt.Printf("model=%s tokens=%d request_id=%s\n",
resp.Model, resp.Usage.InputTokens, resp.RequestID)
}
Output:
Example (RequestOptions) ¶
Per-request options override the client for a single call.
package main
import (
"context"
"log"
"net/http"
"time"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
client, err := typesafe.NewClient()
if err != nil {
log.Fatal(err)
}
_, err = client.SystemOne(context.Background(),
&typesafe.SystemOneRequest{
State: "a very large batch of state",
Questions: typesafe.Questions{"ok": typesafe.Noul("Is this fine?")},
},
typesafe.WithRequestTimeout(2*time.Minute),
typesafe.WithRequestRetryPolicy(typesafe.NoRetryPolicy()),
typesafe.WithExtraHeaders(http.Header{"X-Trace-Id": {"abc-123"}}),
)
if err != nil {
log.Fatal(err)
}
}
Output:
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error is the base error type for SDK failures that are not HTTP responses.
type ListModelsResponse ¶
type ListModelsResponse struct {
// Models is the list of available models.
Models []ModelCard `json:"models"`
// RequestID is the x-typesafe-request-id header from the response.
RequestID string `json:"-"`
}
ListModelsResponse is the response from GET /v1/models.
type ModelCard ¶
type ModelCard struct {
// Name is the model ID or alias, as accepted by the model field.
Name string `json:"name"`
// Description is a human-readable description of the model.
Description string `json:"description"`
// ReleaseDate is the model release date, formatted as YYYY-MM-DD.
ReleaseDate string `json:"release_date"`
}
ModelCard describes a single model returned by the List Models endpoint.
type ModelsService ¶
type ModelsService struct {
// contains filtered or unexported fields
}
ModelsService provides access to the models listing endpoint, reached 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.
See https://docs.typesafe.ai/models for details on model names and aliases.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
client, err := typesafe.NewClient()
if err != nil {
log.Fatal(err)
}
models, err := client.Models.List(context.Background())
if err != nil {
log.Fatal(err)
}
for _, m := range models.Models {
fmt.Printf("%s (%s): %s\n", m.Name, m.ReleaseDate, m.Description)
}
}
Output:
type NoulAnswer ¶
type NoulAnswer struct {
// Value is the probability the answer is yes, from 0 (no) to 1 (yes).
Value float64
}
NoulAnswer is a typed yes/no answer.
type NoulCriteria ¶
type NoulCriteria struct {
// True describes what a yes (value near 1) means.
True any `json:"true,omitempty"`
// False describes what a no (value near 0) means.
False any `json:"false,omitempty"`
}
NoulCriteria describes what yes and no mean for a Noul question.
type Option ¶
type Option func(*clientConfig) error
Option configures a Client. Use the With* functions to create options.
func WithAPIKey ¶
WithAPIKey sets the API key. If not provided, the TYPESAFE_API_KEY environment variable is used.
func WithBaseURL ¶
WithBaseURL overrides the default API base URL.
func WithDefaultModel ¶
WithDefaultModel sets the default model used when SystemOneRequest.Model is empty.
func WithHTTPClient ¶
WithHTTPClient sets a custom http.Client.
func WithLogger ¶
WithLogger sets a structured logger. By default no logging occurs. Request and response bodies are never logged.
func WithRetryPolicy ¶
func WithRetryPolicy(p RetryPolicy) Option
WithRetryPolicy sets a custom retry policy.
func WithTimeout ¶
WithTimeout sets the per-request timeout.
func WithUserAgentSuffix ¶
WithUserAgentSuffix appends a custom suffix to the User-Agent header.
type Question ¶
type Question struct {
// Type identifies the question kind.
Type QuestionType `json:"type"`
// Instructions is the question to evaluate. Accepts string, map, or slice.
Instructions any `json:"instructions,omitempty"`
// Criteria varies by type: [NoulCriteria] for noul, map[string]any for choice,
// []any for score. Use the constructors instead of setting this directly.
Criteria any `json:"criteria,omitempty"`
}
Question is a typed question to evaluate against the state. Use the Noul, NoulWithCriteria, Choice, or Score constructors.
func Choice ¶
Choice creates a question that picks one option from a defined set. The criteria map keys are option names; values are descriptions (use nil when an option needs no extra detail). Maximum 255 options.
See https://docs.typesafe.ai/primitives/choice for details.
Example ¶
Choice picks one option from a set. A nil value means the option needs no extra description.
package main
import (
"encoding/json"
"fmt"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
q := typesafe.Choice("What is this about?", map[string]any{
"billing": "payments, invoices, refunds",
"other": nil,
})
out, _ := json.Marshal(q)
fmt.Println(string(out))
}
Output: {"criteria":{"billing":"payments, invoices, refunds","other":null},"instructions":"What is this about?","type":"choice"}
func Noul ¶
Noul creates a yes/no question. Returns the probability the answer is yes.
The instructions parameter accepts a string, map, or slice. See https://docs.typesafe.ai/primitives/noul for details.
Example ¶
Noul asks a yes/no question and gets back a probability.
package main
import (
"encoding/json"
"fmt"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
q := typesafe.Noul("Does this convey urgency?")
out, _ := json.Marshal(q)
fmt.Println(string(out))
}
Output: {"instructions":"Does this convey urgency?","type":"noul"}
func NoulWithCriteria ¶
func NoulWithCriteria(instructions any, criteria NoulCriteria) Question
NoulWithCriteria creates a yes/no question with explicit criteria describing what yes and no mean.
Example ¶
NoulWithCriteria spells out what yes and no mean when they are ambiguous.
package main
import (
"encoding/json"
"fmt"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
q := typesafe.NoulWithCriteria("Is this spam?", typesafe.NoulCriteria{
True: "unsolicited bulk promotion",
False: "a real message from a real person",
})
out, _ := json.Marshal(q)
fmt.Println(string(out))
}
Output: {"criteria":{"true":"unsolicited bulk promotion","false":"a real message from a real person"},"instructions":"Is this spam?","type":"noul"}
func Score ¶
Score creates a question that rates the state along an ordered rubric. The criteria slice must have at least 2 and at most 10 level descriptions.
See https://docs.typesafe.ai/primitives/score for details.
Example ¶
Score rates the state along an ordered rubric of 2 to 10 levels.
package main
import (
"encoding/json"
"fmt"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
q := typesafe.Score("How severe is this?", []any{
"cosmetic, no user impact",
"degraded but usable",
"fully broken, revenue affected",
})
out, _ := json.Marshal(q)
fmt.Println(string(out))
}
Output: {"criteria":["cosmetic, no user impact","degraded but usable","fully broken, revenue affected"],"instructions":"How severe is this?","type":"score"}
func (Question) MarshalJSON ¶
marshalQuestion produces the JSON form, omitting nil-valued optional fields while preserving explicit null values nested inside criteria/instructions.
type QuestionType ¶
type QuestionType string
QuestionType identifies the kind of question.
const ( // QuestionTypeNoul is a yes/no question returning a probability. QuestionTypeNoul QuestionType = "noul" // QuestionTypeChoice picks one option from a defined set. QuestionTypeChoice QuestionType = "choice" // QuestionTypeScore rates state along an ordered rubric. QuestionTypeScore QuestionType = "score" )
type Questions ¶
Questions is a named map of questions. You choose each key; answers come back under the same keys.
type RequestOption ¶
type RequestOption func(*requestConfig)
RequestOption configures a single API call, overriding client-level settings.
func WithExtraHeaders ¶
func WithExtraHeaders(h http.Header) RequestOption
WithExtraHeaders adds additional headers to a single request.
Headers the SDK sets itself are reserved and silently dropped: Authorization, User-Agent, Content-Type, Accept, X-TypeSafe-SDK, X-TypeSafe-Runtime, and X-TypeSafe-Retry-Count. Use WithUserAgentSuffix to extend the User-Agent.
func WithRequestRetryPolicy ¶
func WithRequestRetryPolicy(p RetryPolicy) RequestOption
WithRequestRetryPolicy overrides the client retry policy for a single request. A negative RetryPolicy.MaxRetries is treated as zero.
func WithRequestTimeout ¶
func WithRequestTimeout(d time.Duration) RequestOption
WithRequestTimeout overrides the client timeout for a single request.
type RetryPolicy ¶
type RetryPolicy struct {
// MaxRetries is the maximum number of retry attempts after the initial
// request. Zero disables retries; a negative value is treated as zero.
// Default: 2.
MaxRetries int
// InitialBackoff is the delay before the first retry. Default: 500ms.
InitialBackoff time.Duration
// MaxBackoff caps the backoff duration. Default: 5s.
MaxBackoff time.Duration
// BackoffJitter is the fraction of each backoff delay randomly subtracted,
// between 0 and 1. Default: 0.25.
BackoffJitter float64
// RetryableStatuses is the set of HTTP status codes that trigger a retry.
// Default: {408, 429, 500, 502, 503, 504, 529}.
RetryableStatuses map[int]bool
// RespectRetryAfter controls whether Retry-After and retry-after-ms
// response headers are honored. Default: true.
RespectRetryAfter *bool
// contains filtered or unexported fields
}
RetryPolicy configures automatic retry behavior. The zero value is a valid policy that disables retries.
Example ¶
package main
import (
"log"
"time"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
client, err := typesafe.NewClient(typesafe.WithRetryPolicy(typesafe.RetryPolicy{
MaxRetries: 5,
InitialBackoff: 200 * time.Millisecond,
MaxBackoff: 10 * time.Second,
BackoffJitter: 0.3,
}))
if err != nil {
log.Fatal(err)
}
_ = client
}
Output:
func DefaultRetryPolicy ¶
func DefaultRetryPolicy() RetryPolicy
DefaultRetryPolicy returns the default retry policy, matching the Python SDK's defaults.
func NoRetryPolicy ¶
func NoRetryPolicy() RetryPolicy
NoRetryPolicy returns a policy that disables automatic retries.
Example ¶
A zero-value RetryPolicy is valid and disables retries, as does NoRetryPolicy.
package main
import (
"log"
"github.com/sachin-handiekar/typesafe-go"
)
func main() {
client, err := typesafe.NewClient(typesafe.WithRetryPolicy(typesafe.NoRetryPolicy()))
if err != nil {
log.Fatal(err)
}
_ = client
}
Output:
type ScoreAnswer ¶
type ScoreAnswer struct {
// Score is the probability-weighted value across the levels; can land between levels.
Score float64
// Legend maps each level number (as string) to its description.
Legend map[string]string
// Probabilities maps each level (as string key) to its probability (floats that sum to 1).
Probabilities map[string]float64
// Confidence is how certain the model is, derived from probabilities (0 to 1).
Confidence float64
}
ScoreAnswer is a typed score answer.
type SystemOneRequest ¶
type SystemOneRequest struct {
// State is the content to evaluate. A plain string for text, or structured
// data (object/array) for chat logs, records, or application state.
State any `json:"state"`
// Model selects which model handles the request. If empty, the client's
// default model is used.
Model string `json:"model,omitempty"`
// Questions is a map of named, typed questions to evaluate against the
// state.
Questions Questions `json:"questions"`
}
SystemOneRequest is the request body for the System One evaluation endpoint.
type SystemOneResponse ¶
type SystemOneResponse struct {
// Model is the versioned model ID that performed the evaluation.
Model string `json:"model"`
// Answers contains one answer per question, keyed by the same IDs used
// in the request's Questions map.
Answers map[string]*Answer `json:"answers"`
// Usage contains token usage for the request.
Usage Usage `json:"usage"`
// RequestID is the x-typesafe-request-id header from the response.
RequestID string `json:"-"`
}
SystemOneResponse is the response from the System One evaluation endpoint.
func (*SystemOneResponse) Choices ¶
func (r *SystemOneResponse) Choices() map[string]ChoiceAnswer
Choices returns only the choice answers, keyed by question name. Null answers in the response are skipped.
func (*SystemOneResponse) Nouls ¶
func (r *SystemOneResponse) Nouls() map[string]NoulAnswer
Nouls returns only the noul answers, keyed by question name. Null answers in the response are skipped.
func (*SystemOneResponse) Scores ¶
func (r *SystemOneResponse) Scores() map[string]ScoreAnswer
Scores returns only the score answers, keyed by question name. Null answers in the response are skipped.