doctor
ELIZA chatbot, multi-turn
doctor/doctor.plumb
(* Dr Plumb — an ELIZA/DOCTOR chatbot.
No API key required. Run interactively:
plumb-chat examples/doctor/doctor.plumb
Or pipe input:
echo '"I feel sad today"' | plumb examples/doctor/doctor.plumb
*)
let doctor : !string -> !string = agent {
provider: "eliza",
model: "doctor"
}
let main : !string -> !string = plumb(input, output) {
input ; doctor ; output
}
doctor/doctor.py
"""Dr Plumb — interactive ELIZA chatbot.
No API key required. Uses the ELIZA provider built into the
plumbing runtime.
Usage:
python doctor.py
Type messages at the prompt. Press Ctrl-D (EOF) to quit.
"""
import asyncio
import sys
from pathlib import Path
import plumbing as pb
async def main() -> None:
spec = Path(__file__).parent / "doctor.plumb"
async with await pb.run(spec, verbose=False) as pipeline:
print("Dr Plumb is in. Type your thoughts (Ctrl-D to quit).\n")
try:
while True:
line = await asyncio.get_event_loop().run_in_executor(
None, lambda: input("> ")
)
if not line.strip():
continue
await pipeline.send(line.strip())
response = await pipeline.recv()
if response is None:
break
print(f"\nDoctor: {response}\n")
except EOFError:
print()
if __name__ == "__main__":
asyncio.run(main())
doctor/pydantic_agent.py
"""Dr Plumb via Pydantic AI — interactive ELIZA chatbot.
PlumbingModel is an interop adapter for the Pydantic AI ecosystem;
see doctor.py for the canonical bare API interface.
No API key required. Uses the ELIZA provider built into the
plumbing runtime.
Usage:
pip install plumbing[pydantic]
python pydantic_agent.py
"""
import asyncio
from pathlib import Path
from pydantic_ai import Agent
from persevere.plumbing.provider import PlumbingModel
async def main() -> None:
spec = Path(__file__).parent / "doctor.plumb"
# PlumbingModel maintains a stateful pipeline — the ELIZA agent
# remembers prior turns without needing message_history.
async with PlumbingModel(spec) as model:
agent = Agent(model)
print("Dr Plumb is in (Pydantic AI). Ctrl-D to quit.\n")
history = None
try:
while True:
line = await asyncio.get_event_loop().run_in_executor(
None, lambda: input("> ")
)
if not line.strip():
continue
result = await agent.run(
line.strip(),
message_history=history,
)
history = result.all_messages()
print(f"\nDoctor: {result.output}\n")
except EOFError:
print()
if __name__ == "__main__":
asyncio.run(main())