Finish implementation of the scriptorium migration
This commit is contained in:
@@ -1,295 +1,33 @@
|
||||
# Scriptorium LLM Runtime Roadmap
|
||||
|
||||
This roadmap describes the target state for replacing Notarius' local
|
||||
OpenAI-compatible LLM adapter with an integration based on
|
||||
`gitea.maximumdirect.net/eric/scriptorium`.
|
||||
|
||||
The upgrade is worthwhile only if it preserves Notarius' architectural
|
||||
boundaries:
|
||||
|
||||
- modules own prompt intent, prompt variables, response schemas, validation, and
|
||||
domain interpretation;
|
||||
- provider plumbing stays behind framework LLM contracts;
|
||||
- diagnostics and manifests remain Notarius-owned and secret-free;
|
||||
- raw API keys are resolved operationally and must not be stored in config,
|
||||
diagnostics, manifests, examples, or prompt/profile assets;
|
||||
- Scriptorium types do not leak into chunk, extract, or normalize module
|
||||
contracts unless explicitly chosen as a future public contract.
|
||||
|
||||
## Motivation
|
||||
|
||||
Notarius currently has a local structured-output OpenAI-compatible adapter. That
|
||||
adapter is intentionally narrow, but it makes Notarius responsible for provider
|
||||
request shape, profile support, structured-output retries, model-specific
|
||||
extensions, and future cache-related request fields.
|
||||
|
||||
Scriptorium adds capabilities that are directly useful for Notarius:
|
||||
|
||||
- built-in profiles for many providers and model families, including OpenRouter
|
||||
and local OpenAI-compatible inference endpoints;
|
||||
- prompt definitions with multiple system and user messages;
|
||||
- per-prompt `session_id` support for sticky provider routing and input cache
|
||||
affinity;
|
||||
- per-message `cache_control` support for providers that understand it;
|
||||
- a simple structured-output path where a prompt supplies a schema and
|
||||
Scriptorium sends it upstream and retries non-compliant responses.
|
||||
|
||||
The most important near-term motivation is input-cache reuse. Existing D&D
|
||||
recap prompts already use a cacheable user message shaped as:
|
||||
|
||||
```text
|
||||
A transcript of a Dungeons & Dragons gameplay session is provided below.
|
||||
|
||||
{{ input "transcript" }}
|
||||
```
|
||||
|
||||
The `transcript` input is the same Seriatim JSON transcript that Notarius
|
||||
already accepts as MVP input, including stable numbered segments. Notarius
|
||||
should align chunk, extract, and normalize LLM calls so this transcript message
|
||||
can be byte-identical across recap generation and structured extraction work.
|
||||
For large transcripts, this can materially reduce provider cost when cached
|
||||
input reads are available.
|
||||
|
||||
## Target State
|
||||
|
||||
Notarius uses Scriptorium as the production LLM execution engine behind the
|
||||
existing module-facing LLM boundary.
|
||||
|
||||
Chunk, extract, and normalize modules continue to receive a Notarius
|
||||
`StructuredLLMClient` through their existing request contracts. They do not
|
||||
construct provider clients, read secrets, or depend directly on Scriptorium
|
||||
request/result types.
|
||||
|
||||
The production CLI constructs a Scriptorium-backed client from the effective
|
||||
Notarius configuration, wraps it in Notarius scheduling and diagnostics policy
|
||||
where needed, and returns Notarius-owned non-secret LLM profile manifest
|
||||
metadata.
|
||||
|
||||
Module-owned prompts are rendered as ordered chat messages, not only as one
|
||||
system message and one user message. Prompt rendering must support:
|
||||
|
||||
- repeated roles;
|
||||
- shared input messages;
|
||||
- module-specific task and instruction messages;
|
||||
- optional cache-control metadata;
|
||||
- a stable session ID for calls that should share provider routing/cache
|
||||
affinity;
|
||||
- structured-output schema metadata owned by the module.
|
||||
|
||||
The shared D&D transcript message should be rendered from the original Seriatim
|
||||
input bytes, not reconstructed from normalized source units. The parsed source
|
||||
document remains the canonical source-reference model for validation and
|
||||
artifact grounding, but the cacheable transcript prompt message should preserve
|
||||
the exact transcript payload supplied to the run.
|
||||
|
||||
Other large text inputs, including references such as campaign glossaries,
|
||||
rosters, previous recaps, and future reference producers, should follow the same
|
||||
input-material model. They should be available to prompt rendering as stable
|
||||
input artifacts that can be placed in cacheable messages without being copied
|
||||
into manifests or diagnostics.
|
||||
|
||||
## Boundary Requirements
|
||||
|
||||
### Provider Plumbing
|
||||
|
||||
Provider-specific request fields, profile expansion, and OpenAI-compatible wire
|
||||
details should be isolated in the framework LLM runtime or in the
|
||||
Scriptorium-backed adapter. Stage modules should request structured completion
|
||||
through Notarius contracts and should not know whether the backing client is the
|
||||
legacy local adapter or Scriptorium.
|
||||
|
||||
### Prompt Ownership
|
||||
|
||||
Modules remain responsible for prompt intent, prompt versioning, response schema
|
||||
selection, and semantic validation. Scriptorium provides the prompt definition,
|
||||
rendering, execution, and structured-output workflow, but it should not become
|
||||
the owner of D&D-specific semantics.
|
||||
|
||||
Shared prompt assets are allowed when they express generic reusable context,
|
||||
such as the D&D transcript input message. Module-specific task prompts should
|
||||
remain owned by the relevant module.
|
||||
|
||||
### Diagnostics And Manifests
|
||||
|
||||
Notarius should continue to decide what appears in diagnostics and run
|
||||
manifests. Scriptorium prepared/run metadata may be useful input, but Notarius
|
||||
must filter it through existing policy:
|
||||
|
||||
- no raw prompt payloads by default;
|
||||
- no raw response schema content in manifests;
|
||||
- no source transcript payloads in manifests;
|
||||
- no API keys or bearer tokens;
|
||||
- enough prompt/profile/schema hashes and IDs to audit a run later.
|
||||
|
||||
### Secret Handling
|
||||
|
||||
Raw API keys should stay out of durable config and prompt/profile assets.
|
||||
Notarius may continue resolving API keys from configured environment-variable
|
||||
names, then pass the secret request-scope to Scriptorium. Redacted diagnostics
|
||||
must continue to prove that resolved secrets are not serialized.
|
||||
|
||||
## Prompt And Cache Strategy
|
||||
|
||||
The desired D&D LLM prompt shape is:
|
||||
|
||||
1. stable shared system message;
|
||||
2. stable shared transcript user message containing the original Seriatim JSON;
|
||||
3. optional stable cacheable context messages, such as previous recap,
|
||||
glossary, roster, or other references;
|
||||
4. module-specific task message;
|
||||
5. module-specific instruction message;
|
||||
6. module-owned structured-output schema, when the module expects JSON.
|
||||
|
||||
The transcript message should be byte-identical whenever the same transcript
|
||||
input bytes are used. Avoid reconstructing JSON from parsed source units because
|
||||
formatting, key order, whitespace, or escaping changes would defeat cache reuse.
|
||||
|
||||
The transcript and large reference messages should be cacheable when the active
|
||||
provider path supports cache-control metadata. Providers that ignore cache
|
||||
controls should still receive a valid prompt.
|
||||
|
||||
The session ID should be stable for all LLM calls that operate on the same
|
||||
session transcript and should be explicitly visible in diagnostics or manifest
|
||||
metadata only as a non-secret identifier.
|
||||
|
||||
Notarius should provide an easy CLI UX for setting the session ID. This lets an
|
||||
external D&D pipeline orchestrator pass the same session ID used by recap or
|
||||
other LLM steps, maximizing provider routing affinity and cached input reuse.
|
||||
|
||||
## Configuration Intent
|
||||
|
||||
Notarius configuration should remain the user-facing source of pipeline
|
||||
composition and operational settings. For LLM execution profiles, Notarius
|
||||
should cut over to Scriptorium profile configuration instead of maintaining a
|
||||
separate Notarius-specific profile schema.
|
||||
|
||||
Notarius should allow configuration to select Scriptorium built-in profiles and
|
||||
to point at Scriptorium profile files or directories. This avoids evolving two
|
||||
nearly identical profile systems and gives users immediate access to the
|
||||
provider and model catalog that motivated the migration.
|
||||
|
||||
Notarius still owns validation, redaction, and manifest provenance for the
|
||||
effective pipeline. The integration should wrap Scriptorium profile loading so
|
||||
that errors are actionable, secrets remain environment-based, and emitted
|
||||
metadata stays non-secret.
|
||||
|
||||
## Compatibility Policy
|
||||
|
||||
This feature should be a hard cutover to Scriptorium-backed prompt execution and
|
||||
profile loading. Backward compatibility with the local Notarius prompt renderer,
|
||||
local LLM profile schema, or local OpenAI-compatible adapter is not a product
|
||||
requirement for this migration.
|
||||
|
||||
The final production runtime should have one documented LLM execution path.
|
||||
Module behavior may still be tested with fake Notarius `StructuredLLMClient`
|
||||
implementations, but production runtime behavior should be Scriptorium-backed.
|
||||
|
||||
## Documentation Outcomes
|
||||
|
||||
When this feature is implemented, current-behavior docs should be updated to
|
||||
describe:
|
||||
|
||||
- the implemented production LLM runtime;
|
||||
- supported LLM profile fields and provider/profile selection behavior;
|
||||
- cacheable transcript prompt behavior, if exposed to users;
|
||||
- session ID behavior;
|
||||
- diagnostics and manifest provenance;
|
||||
- troubleshooting for Scriptorium profile, prompt, schema, and validation
|
||||
failures.
|
||||
|
||||
The OpenAI-compatible integration doc should either be retired, narrowed to the
|
||||
legacy fallback, or reframed as an upstream provider contract delegated through
|
||||
Scriptorium, depending on the final runtime shape.
|
||||
|
||||
## Deferred Work
|
||||
|
||||
The Scriptorium migration does not itself require:
|
||||
|
||||
- a general workflow language;
|
||||
- arbitrary per-stage prompt authoring by end users;
|
||||
- token budgeting or context-window planning;
|
||||
- non-file reference producers;
|
||||
- semantic retrieval over transcript or reference content;
|
||||
- multiple effective LLM profiles in one Notarius run.
|
||||
|
||||
Those remain separate future features.
|
||||
|
||||
## Resolved Design Choices
|
||||
|
||||
### Prompt Asset Ownership And Format
|
||||
|
||||
Production LLM prompts should cut over to Scriptorium-compatible prompt
|
||||
definitions without preserving backward compatibility for the current Notarius
|
||||
system/user prompt renderer.
|
||||
|
||||
Module-owned prompt definitions should keep task prompts and schemas near the
|
||||
module that owns the semantic behavior. Shared prompt messages, such as the D&D
|
||||
transcript input message and shared reference/context messages, should live in a
|
||||
shared prompt asset area and be referenced by module-owned prompt definitions.
|
||||
|
||||
This uses Scriptorium's native strengths: ordered messages, cache-control
|
||||
metadata, session IDs, input helpers, profile selection, and schema-backed
|
||||
execution. It also gives Notarius a direct way to reuse the exact transcript and
|
||||
reference messages across D&D recap, chunking, extraction, and normalization
|
||||
work without each module hand-rolling message assembly.
|
||||
|
||||
### Raw Transcript Preservation Location
|
||||
|
||||
Original input bytes should be preserved as run-scoped input material and made
|
||||
available to prompt rendering without storing them in run manifests. The parsed
|
||||
`SourceDocument` should continue to carry normalized source units for framework
|
||||
logic and source-reference validation.
|
||||
|
||||
The same model should apply to all large text inputs, including references.
|
||||
Glossaries, campaign rosters, previous recaps, and other future reference
|
||||
documents may be large enough to deserve their own cacheable messages. They
|
||||
should be treated as prompt input artifacts rather than being copied into source
|
||||
document metadata.
|
||||
|
||||
This keeps the cacheable transcript message byte-identical to the original
|
||||
Seriatim JSON and avoids source-format leakage into chunk, extract, and
|
||||
normalize contracts. It also reduces the risk that raw inputs or references are
|
||||
accidentally serialized into diagnostics or manifests.
|
||||
|
||||
### Session ID Source
|
||||
|
||||
Notarius should add an explicit session ID concept for LLM calls, with a
|
||||
deterministic default derived from the source document identity when no
|
||||
operator-provided value is configured.
|
||||
|
||||
The CLI should provide an easy way to supply this session ID. This lets an
|
||||
external D&D pipeline orchestrator call Notarius with the same session ID used
|
||||
by recap generation or other LLM steps, maximizing provider routing affinity and
|
||||
cached input savings.
|
||||
|
||||
OpenRouter sticky routing and provider cache behavior are most useful when
|
||||
every related call for the same session shares a stable identifier. An explicit
|
||||
concept makes the behavior auditable and avoids each module inventing its own
|
||||
ID. A deterministic default keeps simple local runs ergonomic.
|
||||
|
||||
### Scriptorium Profile Exposure
|
||||
|
||||
Notarius should cut over to Scriptorium profile configuration instead of
|
||||
maintaining a separate Notarius LLM profile schema. Configuration should be able
|
||||
to select Scriptorium built-in profiles and point at Scriptorium profile files
|
||||
or directories.
|
||||
|
||||
The Scriptorium profile format is already close to the desired Notarius target.
|
||||
Maintaining a separate Notarius profile schema would likely create duplicate
|
||||
configuration that eventually converges back toward Scriptorium's model. A hard
|
||||
cutover avoids that churn and gives users immediate access to Scriptorium's
|
||||
provider and model catalog.
|
||||
|
||||
Notarius still needs to wrap this profile loading with Notarius-owned
|
||||
validation, diagnostics, manifest provenance, and secret-redaction policy.
|
||||
|
||||
### Structured-Output Retry Ownership
|
||||
|
||||
Notarius should use Scriptorium's structured-output execution and retry behavior
|
||||
for production calls, while translating results and errors back into Notarius'
|
||||
`StructuredLLMClient` response and error expectations.
|
||||
|
||||
This avoids duplicating structured-output enforcement in Notarius and lets
|
||||
Scriptorium own provider-specific request and repair mechanics. Notarius still
|
||||
retains module-level validation and source-reference checks after decoded
|
||||
structured output is returned.
|
||||
# Completed Scriptorium LLM Runtime Migration
|
||||
|
||||
The Scriptorium-backed LLM runtime migration is complete. Notarius now uses
|
||||
`gitea.maximumdirect.net/eric/scriptorium` as the production LLM execution
|
||||
engine behind Notarius-owned module contracts, diagnostics, manifest
|
||||
provenance, and secret-handling policy.
|
||||
|
||||
## Implemented Outcomes
|
||||
|
||||
- production LLM execution uses Scriptorium prompt assets and profiles;
|
||||
- chunk, extract, and normalize modules call LLMs through the Notarius
|
||||
`StructuredLLMClient` boundary;
|
||||
- modules pass prompt IDs, prompt versions, profile IDs, session IDs, input
|
||||
materials, and prompt variables instead of locally rendered chat messages;
|
||||
- source transcript input is preserved as run-scoped input material for
|
||||
byte-stable cacheable prompt messages;
|
||||
- Scriptorium profile provenance is recorded in run manifests without raw
|
||||
prompts, schemas, source payloads, references, or secrets.
|
||||
|
||||
## Canonical Docs
|
||||
|
||||
Current behavior is documented in:
|
||||
|
||||
- [Configuration](../config.md)
|
||||
- [CLI Reference](../cli.md)
|
||||
- [Internal LLM Runtime](../internal/llm.md)
|
||||
- [Pipeline Internals](../internal/pipeline.md)
|
||||
- [JSON Output Integration](../integrations/json-output.md)
|
||||
- [Troubleshooting](../troubleshooting.md)
|
||||
|
||||
There is no active Scriptorium-specific roadmap work in this file. Deferred
|
||||
work related to broader LLM, reference, retrieval, context-window, or provider
|
||||
strategy belongs in [Future Roadmap](future.md).
|
||||
|
||||
Reference in New Issue
Block a user