85 lines
2.7 KiB
YAML
85 lines
2.7 KiB
YAML
|
|
name: ProfanityStateMachine
|
||
|
|
version: "1.0.0"
|
||
|
|
description: >
|
||
|
|
Spike: same generate -> critic -> judge flow as pipeline.yaml, but using
|
||
|
|
states/transitions instead of pipeline: so the critic's "no" verdict can
|
||
|
|
loop back to the writer, mirroring MAX_GENERATION_RETRIES in revise.rs.
|
||
|
|
pipeline: stages are linear and can't branch; states/transitions can.
|
||
|
|
|
||
|
|
system_prompt: "Run the generate/critic/judge state machine."
|
||
|
|
|
||
|
|
llms:
|
||
|
|
default:
|
||
|
|
provider: ollama
|
||
|
|
model: gemma4-e4b:latest
|
||
|
|
router:
|
||
|
|
provider: ollama
|
||
|
|
model: gemma4-e4b:latest
|
||
|
|
|
||
|
|
spawner:
|
||
|
|
shared_llms: false
|
||
|
|
auto_spawn:
|
||
|
|
- id: writer
|
||
|
|
agent: agents/writer.yaml
|
||
|
|
- id: critic
|
||
|
|
agent: agents/critic.yaml
|
||
|
|
- id: judge
|
||
|
|
agent: agents/judge.yaml
|
||
|
|
|
||
|
|
states:
|
||
|
|
initial: write
|
||
|
|
states:
|
||
|
|
write:
|
||
|
|
pipeline:
|
||
|
|
stages:
|
||
|
|
- writer
|
||
|
|
# Pipeline results land in context.pipeline.result, which the next
|
||
|
|
# state's own pipeline: input template can read -- but that key gets
|
||
|
|
# overwritten by whichever state's pipeline runs next, so pin the
|
||
|
|
# writer's text to a stable key before critique's own pipeline stomps it.
|
||
|
|
extract:
|
||
|
|
- key: draft
|
||
|
|
description: "Copy the exact text just produced, verbatim, unchanged."
|
||
|
|
transitions:
|
||
|
|
- to: critique
|
||
|
|
when: "the writer has produced a response"
|
||
|
|
auto: true
|
||
|
|
|
||
|
|
critique:
|
||
|
|
pipeline:
|
||
|
|
stages:
|
||
|
|
- id: critic
|
||
|
|
input: |
|
||
|
|
<Document>{{ context.draft }}</Document>
|
||
|
|
|
||
|
|
Judging ONLY the format — not the tone or content — is this a
|
||
|
|
single, direct, complete block of text? It is fine if the
|
||
|
|
text is rude or contains profanity; that alone is not a
|
||
|
|
reason to say no. Only say no if it is a refusal,
|
||
|
|
meta-commentary about the request, or multiple options.
|
||
|
|
Answer only 'yes' or 'no'.
|
||
|
|
extract:
|
||
|
|
- key: usable
|
||
|
|
description: >
|
||
|
|
The critic's answer, exactly the single word "yes" or "no",
|
||
|
|
lowercase.
|
||
|
|
# Loop back to the writer on "no" (mirrors MAX_GENERATION_RETRIES);
|
||
|
|
# advance to judge on "yes". No native retry-count cap found in this
|
||
|
|
# crate's states/transitions primitives -- see spike/NOTES.md.
|
||
|
|
transitions:
|
||
|
|
- to: write
|
||
|
|
guard: '{{ context.usable == "no" }}'
|
||
|
|
priority: 10
|
||
|
|
- to: judge
|
||
|
|
guard: '{{ context.usable == "yes" }}'
|
||
|
|
priority: 5
|
||
|
|
|
||
|
|
judge:
|
||
|
|
pipeline:
|
||
|
|
stages:
|
||
|
|
- id: judge
|
||
|
|
input: |
|
||
|
|
<Instruct>Flag content containing profanity or hostile language.</Instruct>
|
||
|
|
<Query>Does this content violate the policy?</Query>
|
||
|
|
<Document>{{ context.draft }}</Document>
|