Documentation
¶
Overview ¶
Package needle defines the shared API surface for Needle 3 inference in Go.
Needle 3 (Cactus Compute) is a tiny on-device model for tool calling: text goes in, a JSON tool call comes back. Two interchangeable backends implement the Engine interface defined here:
- engine/cgo: bindings to the prebuilt C/C++ engine (libneedle.a)
- engine/pure: a pure-Go port of the runtime (no cgo, no libc)
The mirror of the Python cactus-needle package:
python go
needle.Needle(tools=[...]) cgo.New(needle.Options{Tools: ...})
agent.complete(text) agent.Complete(text)
agent.run(query) agent.Run(query)
agent.reset() agent.Reset()
agent.embed(text) agent.Embed(text)
needle.extract(text, schema) pure.Extract(text, schema, opts) (same in cgo)
The underlying engine holds one process-global, non-thread-safe model per kind; backends serialize calls with a mutex and expect a single live Agent per process.
Index ¶
- Constants
- Variables
- func Bool(v bool) *bool
- func ExtractAsWith[T any](newEngine EngineFactory, text string, opts Options) (*T, error)
- func ValidateGrounding(text string, schema any, arguments map[string]any, system string, ...) error
- func WithDateFact(system string, now time.Time) string
- type Call
- type Date
- type Described
- type Engine
- type EngineFactory
- type Extraction
- type ExtractionError
- type Options
- type Response
- type Result
- type Schema
- type SchemaProvider
- type Tool
- type Validation
Constants ¶
const ( DefaultBufferSize = 65536 DefaultMaxNewTokens = 512 DefaultMaxSteps = 8 )
Defaults shared by the backends.
const DefaultSchemaName = "extract"
DefaultSchemaName is the tool name used for a schema that does not carry one. It shows up in the prompt and in the model's "name" field.
Variables ¶
var ErrNoExtraction = errors.New("needle: no extraction (the model returned no call)")
ErrNoExtraction is returned when the model produced no call for the text: it read the input as off-topic, or answered instead of extracting.
Functions ¶
func Bool ¶
Bool returns a pointer to v, for turning Extract's defaults off: opts.Strict = needle.Bool(false).
func ExtractAsWith ¶
func ExtractAsWith[T any](newEngine EngineFactory, text string, opts Options) (*T, error)
ExtractAsWith is the typed form of ExtractWith: the schema comes from T and the arguments are decoded into a new T. A strict-grounding rejection still hands back the decoded values along with the *ExtractionError, so callers can use them or ignore them; no call at all gives (nil, ErrNoExtraction).
func ValidateGrounding ¶
func ValidateGrounding(text string, schema any, arguments map[string]any, system string, engineReport *Validation) error
ValidateGrounding is the strict check on its own, for callers who drive the conversation through Engine.Complete or Run instead of Extract: it reports whether arguments are grounded in text, given the schema and the environment facts the model saw. It returns an *ExtractionError, or nil.
The engine's own report folds into the same check: pass resp.Validation (nil for the pure backend) to include its flags.
func WithDateFact ¶
WithDateFact prefixes the local date fact unless the caller already supplied one, so a relative date has something to be relative to. A system prompt that already carries a "date:" key, or any ISO stamp, is left alone; JSON facts (an object) are passed through untouched.
Types ¶
type Date ¶
Date is a calendar date for extraction schemas: it accepts "2026-09-01" (the format the model emits for "format":"date") and RFC 3339 stamps, and renders as the plain date. encoding/json's time.Time rejects the bare date.
func (Date) JSONSchema ¶
JSONSchema marks the field as a date, which is also what switches on the temporal grounding check in a strict Extract.
func (Date) MarshalJSON ¶
MarshalJSON writes the "2006-01-02" form.
type Described ¶
type Described interface {
Description() string
}
Described lets a record type supply the schema description, the Go stand-in for the docstring that pydantic extraction uses. It is called on a zero value, so it must not read the receiver's fields.
type Engine ¶
type Engine interface {
// Complete answers one turn. Feed tool results back as a JSON string.
Complete(text string) (*Response, error)
// Run executes the full agentic loop: the model picks calls, matching
// Tool.Fn handlers are executed, results are fed back, and the final
// response carries the executed outputs in Response.Results.
Run(query string) (*Response, error)
// Reset rewinds the conversation, keeping the tools loaded.
Reset() error
// Embed returns the model's embedding for a text (3072 floats on the
// shipped needle3.cact).
Embed(text string) ([]float32, error)
// Close releases the agent. A new Agent may be created afterwards.
Close() error
}
Engine is implemented by both backends.
type EngineFactory ¶
EngineFactory constructs an agent for a one-shot extraction. The backends' New functions match this signature.
type Extraction ¶
type Extraction struct {
// Schema is the shape that was extracted, defaults filled in.
Schema Schema
// Name is the record name the model used (normally Schema.Name).
Name string
// Arguments holds the extracted fields, keyed by schema property.
Arguments map[string]any
// Reasoning is the model's <think> text for the turn.
Reasoning string
// Confidence is a calibrated score in [0,1]; HasConfidence is false when
// the loaded weights carry no calibration head.
Confidence float64
HasConfidence bool
// Suppressed is true when the engine withheld the call below its
// confidence gate. Extraction still returns the withheld values; a low
// Confidence is the signal to distrust them.
Suppressed bool
// Validation is the engine's own grounding report, when it reports one.
// The cgo backend passes the engine's "validation" object through; the
// pure backend has no engine-side flags and leaves it nil.
Validation *Validation
// Raw is the raw generated text for the turn, useful for debugging.
Raw string
// Response is the full turn the extraction came from.
Response *Response
}
Extraction is the outcome of one extraction turn.
func ExtractWith ¶
func ExtractWith(newEngine EngineFactory, text string, schema any, opts Options) (*Extraction, error)
ExtractWith runs one-shot extraction on an engine built by newEngine and closed afterwards, mirroring the Python package's extract(). The engine is bound to a single tool derived from schema, so a fresh agent is created per call; reuse one agent and call ExtractionFromResponse for a hot loop.
func ExtractionFromResponse ¶
func ExtractionFromResponse(resp *Response, schema Schema, text, system string, strict bool) (*Extraction, error)
ExtractionFromResponse turns a completed turn into an Extraction: the first function call, or the first suppressed one when the confidence gate withheld it. With strict set, values that are not grounded in text raise an *ExtractionError; the Extraction is still returned alongside it so the caller can decide what to do with the values.
func (*Extraction) Decode ¶
func (e *Extraction) Decode(out any) error
Decode copies the extracted arguments into out, which must be a non-nil pointer, typically *T for the same type SchemaOf was given.
type ExtractionError ¶
type ExtractionError struct {
Paths []string
}
ExtractionError reports extracted values that are not grounded in the input, the Go counterpart of Python's ExtractionValidationError. Paths are argument-relative ("total", "items[0].price"); "negated request" marks a turn the engine read as a negation of the requested record.
func (*ExtractionError) Error ¶
func (e *ExtractionError) Error() string
type Options ¶
type Options struct {
// Tools is the toolset bound to this agent. One toolset per session:
// changing tools requires a new Agent.
Tools []Tool
// System is an optional environment-facts string, e.g.
// "date: 2026-07-21 Tue 14:30; locale: en-US; device: phone".
System string
// Weights holds the .cact model bytes; required. Use github.com/.../model
// for the embedded needle3.cact.
Weights []byte
// BufferSize sizes the engine's JSON output buffer. Default 65536.
BufferSize int
// MaxNewTokens caps each generated turn. Default 512.
MaxNewTokens int
// MaxSteps caps the Run agentic loop. Default 8.
MaxSteps int
// Strict makes Extract reject values that are not grounded in the input
// with an *ExtractionError. Nil means true, mirroring the Python default;
// set it to *false to return the model's values as-is. It says nothing
// about Complete and Run, which do not validate.
Strict *bool
// AutoDate adds the local date to Options.System when it carries none, so
// a relative date ("due tomorrow") can be resolved and licensed. Nil
// means true. Used by Extract only.
AutoDate *bool
}
Options configures an Agent.
func (Options) AutoDateFacts ¶
AutoDateFacts reports whether Extract may add the local date fact.
func (Options) ForExtraction ¶
ForExtraction prepares options for a one-shot extraction of schema: the schema becomes the only tool, the environment facts gain the local date when they do not carry one (relative dates such as "tomorrow" are licensed against it), and the defaults are filled in.
func (Options) StrictExtraction ¶
StrictExtraction reports whether Extract should validate grounding; unset means strict, like the Python package.
func (Options) ToolsJSON ¶
ToolsJSON renders the tool list into the minified JSON array the engine consumes: [{"name":...,"description":...,"parameters":{...}}].
func (Options) WithDefaults ¶
type Response ¶
type Response struct {
// Type is "call" when the model wants tool calls (an empty FunctionCalls
// list is the off-topic refusal), or "respond" when the loop is finished.
Type string `json:"type"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
FunctionCalls []Call `json:"function_calls"`
// SuppressedCalls holds a call the engine withheld (low confidence or a
// grounding gate); FunctionCalls is then empty.
SuppressedCalls []Call `json:"suppressed_calls,omitempty"`
Reasoning string `json:"reasoning,omitempty"`
// Confidence is a calibrated score in [0,1]. HasConfidence is false when
// the loaded weights carry no calibration head.
Confidence float64 `json:"confidence"`
HasConfidence bool `json:"-"`
PrefillTPS float64 `json:"prefill_tps,omitempty"`
DecodeTPS float64 `json:"decode_tps,omitempty"`
// Results holds the outputs of executed calls; populated by Run only.
Results []Result `json:"-"`
// Raw carries the raw generated text for this turn (pure backend) or the
// engine's raw field, useful for debugging.
Raw string `json:"raw,omitempty"`
// Validation is the engine's own grounding report for the turn. The C
// engine returns one ("ungrounded" argument paths plus a negation flag);
// the pure backend has no engine-side flags, so it stays nil there.
Validation *Validation `json:"validation,omitempty"`
}
Response is the outcome of one turn, mirroring the JSON object returned by the Python package's complete()/run().
func ParseResponse ¶
ParseResponse decodes the engine's per-turn JSON object into a Response, detecting whether a calibrated confidence was present.
type Schema ¶
type Schema struct {
// Name is the record name offered to the model, e.g. "Invoice". Empty
// becomes DefaultSchemaName.
Name string
// Description is an optional one-liner shown to the model; it is what
// steers ambiguous fields.
Description string
// Parameters is the JSON-schema object for the record: typically
// {"type":"object","properties":{...},"required":[...]}. A nil value
// means an empty object.
Parameters map[string]any
}
Schema is the shape to extract to: one record, expressed as the JSON-schema object the engine consumes for a single tool.
func SchemaFrom ¶
SchemaFrom accepts the schema forms Extract takes:
- Schema (or *Schema) — used as given
- Tool — name, description, parameters
- map[string]any — a tool entry with "parameters", or a bare JSON-schema object
- string / []byte — the same two forms as JSON text
- reflect.Type, struct, *struct, map type — derived like SchemaOf
type SchemaProvider ¶
SchemaProvider lets a type decide what JSON schema is generated for it. A pointer receiver works too: the method is called on a zero value.
type Tool ¶
type Tool struct {
Name string
Description string
// Parameters is a JSON-schema object, e.g.
// {"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}.
// A nil value renders as an empty parameter object.
Parameters map[string]any
// Fn executes this tool during Run. Its result is fed back to the model
// as JSON.
Fn func(args map[string]any) (any, error)
}
Tool describes one callable function exposed to the model, mirroring the raw JSON-schema form that the engine consumes. Fn is optional and only used by Run to execute calls automatically.
type Validation ¶
type Validation struct {
// Ungrounded lists the argument paths the engine considers fabricated,
// qualified by the tool name ("Invoice.due_date").
Ungrounded []string `json:"ungrounded,omitempty"`
// Negation is set when the engine read the turn as a negation of the
// requested record ("no invoice needed").
Negation bool `json:"negation,omitempty"`
}
Validation is the grounding report the engine attaches to a turn.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
needle-ask
command
Command needle-ask is a one-shot Needle 3 tool matcher built on the cgo backend.
|
Command needle-ask is a one-shot Needle 3 tool matcher built on the cgo backend. |
|
engine
|
|
|
cgo
Package cgo is a Go binding to the prebuilt Needle 3 C/C++ engine (libneedle.a from https://huggingface.co/Cactus-Compute/needle3).
|
Package cgo is a Go binding to the prebuilt Needle 3 C/C++ engine (libneedle.a from https://huggingface.co/Cactus-Compute/needle3). |
|
pure
Package pure is a pure-Go port of the Needle 3 runtime: it parses the .cact container, dequantizes CQ weights, runs the Simple Attention Network forward pass, and decodes greedily.
|
Package pure is a pure-Go port of the Needle 3 runtime: it parses the .cact container, dequantizes CQ weights, runs the Simple Attention Network forward pass, and decodes greedily. |
|
examples
|
|
|
needle-cgo
command
Command needle-cgo demonstrates the cgo-backed Needle 3 agent with the model embedded in the binary.
|
Command needle-cgo demonstrates the cgo-backed Needle 3 agent with the model embedded in the binary. |
|
needle-pure
command
Command needle-pure demonstrates the cgo-backed Needle 3 agent with the model embedded in the binary.
|
Command needle-pure demonstrates the cgo-backed Needle 3 agent with the model embedded in the binary. |
|
Package model embeds the needle3.cact weights so a binary can carry the whole model in memory with no runtime file dependencies.
|
Package model embeds the needle3.cact weights so a binary can carry the whole model in memory with no runtime file dependencies. |