184 lines
7.3 KiB
Markdown
184 lines
7.3 KiB
Markdown
# Package `scriptorium`
|
|
|
|
Import path:
|
|
|
|
```go
|
|
import "gitea.maximumdirect.net/eric/scriptorium"
|
|
```
|
|
|
|
This is the canonical public Go contract for in-process prompt preparation and
|
|
execution. Prompt, profile, and schema file formats are defined in the
|
|
[configuration reference](../config.md).
|
|
|
|
## Engine Construction
|
|
|
|
`NewEngine(Config, ...Option)` constructs an engine. `Config` has these
|
|
fields:
|
|
|
|
| Field | Meaning |
|
|
| --- | --- |
|
|
| `PromptDir` | Prompt-definition directory, required unless a prompt source option is supplied. |
|
|
| `ProfileDir` | Optional custom profile directory over built-ins. |
|
|
| `SchemaDir` | Schema directory; empty uses `.`. |
|
|
| `Timeout` | Transport-wide safety cap for the built-in OpenAI-compatible client when `HTTPClient` is absent or has a non-positive timeout. A non-positive value uses the internal ten-minute default. |
|
|
| `HTTPClient` | Optional HTTP client for that built-in client. It is cloned; a positive `Timeout` on it is the transport cap and takes precedence over `Config.Timeout`. A non-positive client timeout is treated as unset. |
|
|
|
|
Nil options are ignored. Invalid construction, including
|
|
`WithLLMClient(nil)`, returns an error matching `ErrInvalidConfig`.
|
|
|
|
Profile and request `timeout_seconds` values select a per-generation-call
|
|
deadline independently of the transport cap. An explicit request override of
|
|
zero disables that generation deadline only. The complete interaction with the
|
|
caller context is defined in the
|
|
[OpenAI-compatible integration contract](../integrations/openai-compatible-chat.md#authentication-and-timeout).
|
|
|
|
Source options replace their matching directory source:
|
|
|
|
- prompts: `WithPromptFS(fsys, root)`, `WithPromptFile(path)`;
|
|
- profiles: `WithProfileFS(fsys, root)`, `WithProfileFile(path)`, and
|
|
`WithProfiles(profiles...)`;
|
|
- schemas: `WithSchemaFS(fsys, root)`, `WithSchemaFile(path)`; and
|
|
- LLM client: `WithLLMClient(client)`.
|
|
|
|
`fs.FS` prompt-content and schema paths stay inside their configured roots.
|
|
Single-file prompt and profile sources are selected by their YAML `id`, not
|
|
their file names. `WithPromptFile` resolves relative `content_file` paths from
|
|
the prompt file's directory. `WithSchemaFile` exposes its schema by the schema
|
|
file's base name. In-memory profiles take precedence over an explicit or
|
|
directory-backed profile source, which in turn takes precedence over built-ins.
|
|
File and filesystem sources use the format and credential rules in the
|
|
[configuration reference](../config.md).
|
|
|
|
## Prepare And Run
|
|
|
|
`Prepare(ctx, request)` resolves the prompt, profile, input artifacts,
|
|
validation contract, and rendered messages without calling an LLM.
|
|
`Run(ctx, request)` performs that preparation, calls the configured client,
|
|
and validates generated content.
|
|
|
|
```go
|
|
engine, err := scriptorium.NewEngine(scriptorium.Config{
|
|
PromptDir: "./examples/prompts",
|
|
ProfileDir: "./examples/profiles",
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
prepared, err := engine.Prepare(ctx, scriptorium.RunRequest{
|
|
PromptID: "generic.markdown_summary",
|
|
Inputs: map[string]scriptorium.ArtifactRef{
|
|
"transcript": scriptorium.File("./examples/fixtures/transcript.md"),
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_ = prepared.Messages
|
|
```
|
|
|
|
The maintained package example is
|
|
[`examples/go-library/prepare`](../../examples/go-library/prepare).
|
|
|
|
`PreparedRun` exposes prompt, selected-profile, effective-model, output
|
|
contract, structured-output, input-hash, rendered-message, and timing
|
|
information. It does not include a resolved API key, model output, validation
|
|
result, or target-presence metadata.
|
|
|
|
`RunResult` adds run ID, artifact, raw output, validation, model metadata,
|
|
usage, and duration. Generated-content validation failures return a result with
|
|
`Validation.Status == ValidationFailed`; schema or validator runtime failures
|
|
return an error matching `ErrValidation`.
|
|
|
|
## Public Values
|
|
|
|
`ArtifactRef` has `Type`, `URI`, and `Body`; `Artifact` has `Name`,
|
|
`ContentType`, `Body`, `URI`, `Size`, and `Hash`. `ExecutionTarget` exposes the
|
|
effective endpoint, model, numeric settings, credential-environment name,
|
|
service tier, reasoning effort, and extra parameters. `ValidationResult`
|
|
contains status, mode, errors, schema path, repair attempts, and validity.
|
|
|
|
The exported constants define these serialized values:
|
|
|
|
- artifact types: `inline` and `file`;
|
|
- output formats: `text`, `markdown`, and `json`;
|
|
- validation modes: `none`, `basic`, `json`, and `json_schema`; and
|
|
- validation statuses: `passed`, `failed`, and `skipped`.
|
|
|
|
`TokenUsage` reports prompt, completion, total, cached, and cache-write token
|
|
counts. `RenderedPrompt`, `RenderedMessage`, `CacheControl`, and
|
|
`StructuredOutputSpec` are the public shapes used by injected LLM clients.
|
|
|
|
## Requests, Inputs, And Overrides
|
|
|
|
`RunRequest` fields are `PromptID`, `PromptVersion`, `ProfileID`,
|
|
`APIKey`, `Inputs`, `Vars`, `Execution`, `Validation`, and
|
|
`Metadata`.
|
|
|
|
Input helpers are:
|
|
|
|
- `File(path)` for a file-backed artifact;
|
|
- `Inline(body)` for inline content; and
|
|
- `InlineWithURI(uri, body)` for inline content with URI metadata.
|
|
|
|
Required declared inputs must be supplied. Template rendering must also resolve
|
|
every input name the prompt actually references. Extra entries in `Inputs`
|
|
are not rejected solely because they are undeclared.
|
|
|
|
`ExecutionTargetOverride` supplies endpoint, model, credential-environment,
|
|
service-tier, reasoning-effort, and extra-parameter overrides. Its numeric
|
|
fields (`Temperature`, `MaxTokens`, `TopP`, and `TimeoutSeconds`) are
|
|
pointers so explicit zero values are preserved. `OutputContract` supplies
|
|
`Format`, `ValidationMode`, `SchemaPath`, and `RepairAttempts`.
|
|
|
|
`ExtraParams` accepts JSON-compatible values: strings, booleans, finite
|
|
numbers, objects with string keys, arrays or slices, and nil. Unsupported
|
|
values, non-string map keys, non-finite floats, and cycles return
|
|
`ErrInvalidConfig` for profiles or `ErrInvalidRequest` for request
|
|
overrides.
|
|
|
|
## Profiles And Credentials
|
|
|
|
`OpenAICompatibleProfile(OpenAICompatibleProfileConfig)` creates an
|
|
in-memory `Profile`. Its public fields are `ID`, `Endpoint`, `Model`,
|
|
`Temperature`, `MaxTokens`, `TopP`, `TimeoutSeconds`, `ServiceTier`,
|
|
`ReasoningEffort`, `APIKeyRequired`, and `ExtraParams`.
|
|
`WithProfiles` rejects duplicate IDs in one call.
|
|
|
|
A direct `RunRequest.APIKey` is request-scoped and takes precedence over
|
|
`api_key_env` for the built-in client. It is excluded from JSON output and
|
|
from `PreparedRun` and `RunResult`. The package's `String` and
|
|
`GoString` methods report only whether a direct key is set. Do not use
|
|
reflection-based dumps of request structs, which can bypass that redaction.
|
|
|
|
## Injected LLM Clients
|
|
|
|
`LLMClient` implements:
|
|
|
|
```go
|
|
Generate(context.Context, GenerateRequest) (*GenerateResponse, error)
|
|
```
|
|
|
|
Injected clients receive the rendered prompt, effective execution target, numeric
|
|
target-presence metadata, optional structured-output specification, and direct
|
|
request API key. `GenerateResponse` returns content and `TokenUsage`.
|
|
Custom clients should avoid logging raw prompts or credentials.
|
|
|
|
## Errors
|
|
|
|
Public methods preserve these sentinel checks through `errors.Is`:
|
|
|
|
- `ErrInvalidConfig`
|
|
- `ErrInvalidRequest`
|
|
- `ErrPromptNotFound`
|
|
- `ErrProfileNotFound`
|
|
- `ErrPromptLoad`
|
|
- `ErrProfileLoad`
|
|
- `ErrArtifactLoad`
|
|
- `ErrPromptRender`
|
|
- `ErrLLMGenerate`
|
|
- `ErrValidation`
|
|
|
|
For interface selection and operational responsibilities, see the
|
|
[consumer integration overview](api.md).
|