Migrate repo fixtures to separated prompts/ and execution profiles/ with file-backed prompt templates
This commit is contained in:
15
README.md
15
README.md
@@ -51,13 +51,14 @@ go test ./...
|
|||||||
|
|
||||||
Required flags:
|
Required flags:
|
||||||
|
|
||||||
|
- `--prompt-dir`
|
||||||
- `--profile-dir`
|
- `--profile-dir`
|
||||||
- `--prompt-id`
|
- `--prompt`
|
||||||
- `--input` (repeatable `name=path`)
|
- `--input` (repeatable `name=path`)
|
||||||
|
|
||||||
Common optional flags:
|
Common optional flags:
|
||||||
|
|
||||||
- `--profile-id` (execution profile selector; falls back to prompt `default_profile`)
|
- `--profile` (execution profile selector; falls back to prompt `default_profile`)
|
||||||
- `--var` (repeatable `name=value`)
|
- `--var` (repeatable `name=value`)
|
||||||
- `--out`
|
- `--out`
|
||||||
- `--llm-base-url`
|
- `--llm-base-url`
|
||||||
@@ -76,9 +77,10 @@ Example:
|
|||||||
export SCRIPTORIUM_API_KEY="your-key"
|
export SCRIPTORIUM_API_KEY="your-key"
|
||||||
|
|
||||||
go run ./cmd/scriptorium run \
|
go run ./cmd/scriptorium run \
|
||||||
|
--prompt-dir ./prompts \
|
||||||
--profile-dir ./profiles \
|
--profile-dir ./profiles \
|
||||||
--prompt-id generic.markdown_summary \
|
--prompt generic.markdown_summary \
|
||||||
--profile-id local-default \
|
--profile local-fast \
|
||||||
--input transcript=./examples/fixtures/transcript.md \
|
--input transcript=./examples/fixtures/transcript.md \
|
||||||
--input glossary=./examples/fixtures/glossary.yml \
|
--input glossary=./examples/fixtures/glossary.yml \
|
||||||
--llm-base-url http://localhost:8000/v1 \
|
--llm-base-url http://localhost:8000/v1 \
|
||||||
@@ -99,8 +101,8 @@ Starts HTTP API.
|
|||||||
|
|
||||||
Required flags:
|
Required flags:
|
||||||
|
|
||||||
|
- `--prompt-dir`
|
||||||
- `--profile-dir`
|
- `--profile-dir`
|
||||||
- `--llm-base-url`
|
|
||||||
|
|
||||||
Common optional flags:
|
Common optional flags:
|
||||||
|
|
||||||
@@ -267,7 +269,8 @@ Validation content failures are returned in the structured result; raw model out
|
|||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
- Prompt definitions: `profiles/`
|
- Prompt definitions: `prompts/`
|
||||||
|
- Execution profiles: `profiles/`
|
||||||
- Schemas: `schemas/`
|
- Schemas: `schemas/`
|
||||||
- Fixtures: `examples/fixtures/`
|
- Fixtures: `examples/fixtures/`
|
||||||
- Local experimentation: `local-test/`
|
- Local experimentation: `local-test/`
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ func TestRunCommandVarsOptional(t *testing.T) {
|
|||||||
var stderr bytes.Buffer
|
var stderr bytes.Buffer
|
||||||
|
|
||||||
code := runCommand([]string{
|
code := runCommand([]string{
|
||||||
"--prompt-dir", "./profiles",
|
"--prompt-dir", "./prompts",
|
||||||
"--profile-dir", "./profiles",
|
"--profile-dir", "./profiles",
|
||||||
"--prompt", "p",
|
"--prompt", "p",
|
||||||
"--input", "transcript=./t.md",
|
"--input", "transcript=./t.md",
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package usecase
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -27,24 +26,21 @@ func (f *integrationLLM) Generate(ctx context.Context, req domain.GenerateReques
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunnerIntegrationWithProfilesFixturesAndValidation(t *testing.T) {
|
func TestRunnerIntegrationWithPromptAndProfileFixturesAndValidation(t *testing.T) {
|
||||||
root, err := filepath.Abs(filepath.Join("..", ".."))
|
root, err := filepath.Abs(filepath.Join("..", ".."))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to resolve repo root: %v", err)
|
t.Fatalf("failed to resolve repo root: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
promptsDir := filepath.Join(root, "prompts")
|
||||||
profilesDir := filepath.Join(root, "profiles")
|
profilesDir := filepath.Join(root, "profiles")
|
||||||
execProfilesDir := t.TempDir()
|
|
||||||
schemasDir := filepath.Join(root, "schemas")
|
schemasDir := filepath.Join(root, "schemas")
|
||||||
fixturesDir := filepath.Join(root, "examples", "fixtures")
|
fixturesDir := filepath.Join(root, "examples", "fixtures")
|
||||||
if err := os.WriteFile(filepath.Join(execProfilesDir, "local-default.yaml"), []byte(
|
t.Setenv("SCRIPTORIUM_API_KEY", "test-key")
|
||||||
"id: local-default\nendpoint: http://llm/v1\nmodel: test-model\n"), 0644); err != nil {
|
|
||||||
t.Fatalf("failed to write execution profile fixture: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
runner := NewRunner(
|
runner := NewRunner(
|
||||||
promptdef.NewFilesystemRepository(profilesDir),
|
promptdef.NewFilesystemRepository(promptsDir),
|
||||||
profile.NewFilesystemRepository(execProfilesDir),
|
profile.NewFilesystemRepository(profilesDir),
|
||||||
artifact.NewCompositeReader(),
|
artifact.NewCompositeReader(),
|
||||||
prompt.NewGoRenderer(),
|
prompt.NewGoRenderer(),
|
||||||
&integrationLLM{},
|
&integrationLLM{},
|
||||||
@@ -53,7 +49,6 @@ func TestRunnerIntegrationWithProfilesFixturesAndValidation(t *testing.T) {
|
|||||||
|
|
||||||
res, err := runner.Run(context.Background(), domain.RunRequest{
|
res, err := runner.Run(context.Background(), domain.RunRequest{
|
||||||
PromptID: "generic.structured_events",
|
PromptID: "generic.structured_events",
|
||||||
ProfileID: "local-default",
|
|
||||||
Inputs: map[string]domain.ArtifactRef{
|
Inputs: map[string]domain.ArtifactRef{
|
||||||
"transcript": {
|
"transcript": {
|
||||||
Type: domain.ArtifactRefFile,
|
Type: domain.ArtifactRefFile,
|
||||||
@@ -72,6 +67,9 @@ func TestRunnerIntegrationWithProfilesFixturesAndValidation(t *testing.T) {
|
|||||||
if res.PromptID != "generic.structured_events" {
|
if res.PromptID != "generic.structured_events" {
|
||||||
t.Fatalf("unexpected prompt id: %q", res.PromptID)
|
t.Fatalf("unexpected prompt id: %q", res.PromptID)
|
||||||
}
|
}
|
||||||
|
if res.SelectedProfileID != "local-quality" {
|
||||||
|
t.Fatalf("expected selected profile local-quality from prompt default, got %q", res.SelectedProfileID)
|
||||||
|
}
|
||||||
if res.RunID == "" {
|
if res.RunID == "" {
|
||||||
t.Fatal("expected run id")
|
t.Fatal("expected run id")
|
||||||
}
|
}
|
||||||
|
|||||||
7
profiles/local-fast.yaml
Normal file
7
profiles/local-fast.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
id: local-fast
|
||||||
|
endpoint: http://localhost:8000/v1
|
||||||
|
model: gpt-4o-mini
|
||||||
|
temperature: 0.2
|
||||||
|
max_tokens: 500
|
||||||
|
top_p: 1.0
|
||||||
|
timeout_seconds: 90
|
||||||
8
profiles/local-quality.yaml
Normal file
8
profiles/local-quality.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
id: local-quality
|
||||||
|
endpoint: http://localhost:8000/v1
|
||||||
|
model: gpt-4.1
|
||||||
|
temperature: 0.0
|
||||||
|
max_tokens: 1200
|
||||||
|
top_p: 1.0
|
||||||
|
timeout_seconds: 180
|
||||||
|
api_key_env: SCRIPTORIUM_API_KEY
|
||||||
2
prompts/dnd.session_recap.system.md
Normal file
2
prompts/dnd.session_recap.system.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
You create concise tabletop RPG session recaps.
|
||||||
|
Stay factual and avoid inventing events.
|
||||||
10
prompts/dnd.session_recap.user.md
Normal file
10
prompts/dnd.session_recap.user.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Produce a recap with these sections:
|
||||||
|
- Session Highlights
|
||||||
|
- Open Threads
|
||||||
|
- NPC Mentions
|
||||||
|
|
||||||
|
Transcript:
|
||||||
|
{{input "transcript"}}
|
||||||
|
|
||||||
|
Glossary:
|
||||||
|
{{input "glossary"}}
|
||||||
@@ -1,31 +1,21 @@
|
|||||||
id: dnd.session_recap
|
id: dnd.session_recap
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
default_profile: local-default
|
default_profile: local-quality
|
||||||
description: Example D&D session recap prompt definition for demonstration only.
|
description: Example D&D session recap prompt definition for demonstration only.
|
||||||
inputs:
|
inputs:
|
||||||
- name: transcript
|
- name: transcript
|
||||||
required: true
|
required: true
|
||||||
content_type: text/markdown
|
content_type: text/markdown
|
||||||
|
description: Session source content
|
||||||
- name: glossary
|
- name: glossary
|
||||||
required: false
|
required: false
|
||||||
content_type: text/yaml
|
content_type: text/yaml
|
||||||
|
description: Optional glossary context
|
||||||
messages:
|
messages:
|
||||||
- role: system
|
- role: system
|
||||||
content: |
|
content_file: ./dnd.session_recap.system.md
|
||||||
You create concise tabletop RPG session recaps.
|
|
||||||
Stay factual and avoid inventing events.
|
|
||||||
- role: user
|
- role: user
|
||||||
content: |
|
content_file: ./dnd.session_recap.user.md
|
||||||
Produce a recap with these sections:
|
|
||||||
- Session Highlights
|
|
||||||
- Open Threads
|
|
||||||
- NPC Mentions
|
|
||||||
|
|
||||||
Transcript:
|
|
||||||
{{input "transcript"}}
|
|
||||||
|
|
||||||
Glossary:
|
|
||||||
{{input "glossary"}}
|
|
||||||
output:
|
output:
|
||||||
format: markdown
|
format: markdown
|
||||||
validation_mode: basic
|
validation_mode: basic
|
||||||
2
prompts/generic.markdown_summary.system.md
Normal file
2
prompts/generic.markdown_summary.system.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
You are a concise analysis assistant.
|
||||||
|
Write clear Markdown output.
|
||||||
7
prompts/generic.markdown_summary.user.md
Normal file
7
prompts/generic.markdown_summary.user.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Summarize the following source transcript:
|
||||||
|
|
||||||
|
{{input "transcript"}}
|
||||||
|
|
||||||
|
Reference glossary:
|
||||||
|
|
||||||
|
{{input "glossary"}}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
id: generic.markdown_summary
|
id: generic.markdown_summary
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
default_profile: local-default
|
default_profile: local-fast
|
||||||
description: Generic markdown summary from transcript and glossary.
|
description: Generic markdown summary from transcript and glossary.
|
||||||
inputs:
|
inputs:
|
||||||
- name: transcript
|
- name: transcript
|
||||||
@@ -13,18 +13,9 @@ inputs:
|
|||||||
description: Optional glossary context
|
description: Optional glossary context
|
||||||
messages:
|
messages:
|
||||||
- role: system
|
- role: system
|
||||||
content: |
|
content_file: ./generic.markdown_summary.system.md
|
||||||
You are a concise analysis assistant.
|
|
||||||
Write clear Markdown output.
|
|
||||||
- role: user
|
- role: user
|
||||||
content: |
|
content_file: ./generic.markdown_summary.user.md
|
||||||
Summarize the following source transcript:
|
|
||||||
|
|
||||||
{{input "transcript"}}
|
|
||||||
|
|
||||||
Reference glossary:
|
|
||||||
|
|
||||||
{{input "glossary"}}
|
|
||||||
output:
|
output:
|
||||||
format: markdown
|
format: markdown
|
||||||
validation_mode: basic
|
validation_mode: basic
|
||||||
2
prompts/generic.structured_events.system.md
Normal file
2
prompts/generic.structured_events.system.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Return only JSON following the requested schema.
|
||||||
|
Do not include commentary.
|
||||||
7
prompts/generic.structured_events.user.md
Normal file
7
prompts/generic.structured_events.user.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Extract important events from the transcript and emit JSON.
|
||||||
|
|
||||||
|
Transcript:
|
||||||
|
{{input "transcript"}}
|
||||||
|
|
||||||
|
Glossary:
|
||||||
|
{{input "glossary"}}
|
||||||
@@ -1,28 +1,21 @@
|
|||||||
id: generic.structured_events
|
id: generic.structured_events
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
default_profile: local-default
|
default_profile: local-quality
|
||||||
description: Produce structured event JSON from a transcript.
|
description: Produce structured event JSON from a transcript.
|
||||||
inputs:
|
inputs:
|
||||||
- name: transcript
|
- name: transcript
|
||||||
required: true
|
required: true
|
||||||
content_type: text/markdown
|
content_type: text/markdown
|
||||||
|
description: Source transcript content
|
||||||
- name: glossary
|
- name: glossary
|
||||||
required: false
|
required: false
|
||||||
content_type: text/yaml
|
content_type: text/yaml
|
||||||
|
description: Optional glossary context
|
||||||
messages:
|
messages:
|
||||||
- role: system
|
- role: system
|
||||||
content: |
|
content_file: ./generic.structured_events.system.md
|
||||||
Return only JSON following the requested schema.
|
|
||||||
Do not include commentary.
|
|
||||||
- role: user
|
- role: user
|
||||||
content: |
|
content_file: ./generic.structured_events.user.md
|
||||||
Extract important events from the transcript and emit JSON.
|
|
||||||
|
|
||||||
Transcript:
|
|
||||||
{{input "transcript"}}
|
|
||||||
|
|
||||||
Glossary:
|
|
||||||
{{input "glossary"}}
|
|
||||||
output:
|
output:
|
||||||
format: json
|
format: json
|
||||||
validation_mode: json_schema
|
validation_mode: json_schema
|
||||||
Reference in New Issue
Block a user