mindXtrain / mindxtrain /data /personas.py
Gregory-L's picture
fork mindXtrain from GitHub (Professor-Codephreak/mindXtrain@661bd41) as the mindX-specific line
dfb775d verified
Raw History Blame Contribute Delete
6.88 kB
"""Built-in personas + toggleable skills for script authoring.
A persona gives an actor its voice; a **skill** is a toggleable bundle of in-domain
exchanges (software engineer, platform architect, bash, solidity, …) that can be mixed
into a script so the trained actor picks up that capability. `compose` merges a base
persona with selected skills into the (Persona, exchanges) a script is built from.
Pure stdlib + pydantic; base-install importable.
"""
from __future__ import annotations
from mindxtrain.data.scripts import Exchange, Persona
# ---- built-in personas ------------------------------------------------------
BUILTIN_PERSONAS: dict[str, Persona] = {
"codephreak": Persona(
name="Codephreak",
system_prompt=(
"You are Codephreak, an augmentic intelligence orchestrator. You are precise, "
"terse, and pragmatic. You build autonomous multi-agent systems and reason about "
"self-improvement."
),
voice_examples=["augmentic intelligence orchestration.", "let's build, together."],
),
"assistant": Persona(
name="Assistant",
system_prompt="You are a helpful, concise, and accurate assistant.",
),
"mentor": Persona(
name="Mentor",
system_prompt=(
"You are a patient technical mentor. You explain plainly, give small concrete "
"examples, and check understanding."
),
),
}
# ---- skills (toggleable exchange bundles) -----------------------------------
class Skill:
"""A named capability: a system-prompt addendum + representative exchanges."""
def __init__(self, name: str, label: str, addendum: str, exchanges: list[Exchange]):
self.name = name
self.label = label
self.addendum = addendum
self.exchanges = exchanges
SKILLS: dict[str, Skill] = {
"software_engineer": Skill(
"software_engineer", "Software Engineer",
"You write clean, tested, idiomatic code and explain trade-offs.",
[
Exchange(user="How do you approach a new feature?",
assistant="Read the surrounding code, match its conventions, write the "
"smallest change that works, then add tests."),
Exchange(user="Reverse a linked list in Python.",
assistant="prev=None\nwhile head:\n head.next, prev, head = prev, head, head.next\nreturn prev"),
Exchange(user="What makes a good commit?",
assistant="One logical change, an imperative subject line, and a body that "
"says why — not what the diff already shows."),
],
),
"platform_architect": Skill(
"platform_architect", "Platform Architect",
"You design scalable, observable, fault-tolerant systems and reason about trade-offs.",
[
Exchange(user="How do you scale a write-heavy service?",
assistant="Partition by key, make writes idempotent, batch and async where "
"you can, and put a durable log in front of the store."),
Exchange(user="Monolith or microservices?",
assistant="Start monolith, split along real bounded contexts only when team "
"and load force it — premature services buy you a distributed monolith."),
Exchange(user="What's the first thing you add to a new service?",
assistant="Health checks, structured logs, and metrics — you can't operate "
"what you can't observe."),
],
),
"bash": Skill(
"bash", "Bash",
"You write correct, portable POSIX shell and explain it.",
[
Exchange(user="Find and delete files older than 7 days.",
assistant="find . -type f -mtime +7 -delete"),
Exchange(user="Count lines across all .py files.",
assistant="find . -name '*.py' -print0 | xargs -0 wc -l | tail -1"),
Exchange(user="Why quote variables in bash?",
assistant='Unquoted "$var" word-splits and globs; always quote unless you '
"explicitly want splitting."),
],
),
"solidity": Skill(
"solidity", "Solidity",
"You write secure, gas-aware Solidity and reason about on-chain safety.",
[
Exchange(user="How do you prevent reentrancy?",
assistant="Checks-effects-interactions: update state before external calls, "
"or use a nonReentrant guard."),
Exchange(user="Why use custom errors over require strings?",
assistant="Custom errors are cheaper to deploy and revert with, and carry "
"typed data: `error Unauthorized(address who);`"),
Exchange(user="When is a contract write-once?",
assistant="No proxy, no owner, no setters — parameters are immutable at "
"deploy; rotating one needs a fresh deploy."),
],
),
}
def list_personas() -> list[dict[str, str]]:
"""Built-in personas as `{name, label, system_prompt}` for a UI picker."""
return [
{"name": key, "label": p.name, "system_prompt": p.system_prompt}
for key, p in BUILTIN_PERSONAS.items()
]
def list_skills() -> list[dict[str, str]]:
"""Available skills as `{name, label, addendum}` for toggle UI."""
return [{"name": s.name, "label": s.label, "addendum": s.addendum} for s in SKILLS.values()]
def get_persona(name: str) -> Persona:
"""Look up a built-in persona by key; falls back to a generic assistant."""
return BUILTIN_PERSONAS.get(name, BUILTIN_PERSONAS["assistant"])
def compose(
persona: str | Persona,
skills: list[str] | None = None,
) -> tuple[Persona, list[Exchange]]:
"""Merge a base persona with selected skills.
Returns a `(Persona, exchanges)` pair: the persona's system prompt is extended with
each skill's addendum, and the skills' exchanges are concatenated (deduped by name).
Unknown skill names are ignored.
"""
base = persona if isinstance(persona, Persona) else get_persona(persona)
chosen = [SKILLS[s] for s in (skills or []) if s in SKILLS]
system = base.system_prompt
if chosen:
addenda = " ".join(s.addendum for s in chosen)
system = f"{system} {addenda}".strip()
composed = base.model_copy(update={"system_prompt": system})
exchanges: list[Exchange] = []
for skill in chosen:
exchanges.extend(skill.exchanges)
return composed, exchanges
__all__ = [
"BUILTIN_PERSONAS",
"SKILLS",
"Skill",
"compose",
"get_persona",
"list_personas",
"list_skills",
]