Spaces:
Sleeping
Sleeping
Commit ·
d10324f
1
Parent(s): 38e44da
iiinit skills agents and model
Browse files- .cursor/plans/skill_agent_pptx_5413e3c2.plan.md +1 -1
- libs/agent/README.md +17 -0
- libs/agent/pyproject.toml +22 -0
- libs/agent/src/agent/__init__.py +11 -0
- libs/agent/src/agent/models.py +20 -0
- libs/agent/src/agent/trace.py +78 -0
.cursor/plans/skill_agent_pptx_5413e3c2.plan.md
CHANGED
|
@@ -4,7 +4,7 @@ overview: Add a Hermes-style skill agent library on top of your existing Transfo
|
|
| 4 |
todos:
|
| 5 |
- id: agent-lib
|
| 6 |
content: "Create libs/agent: SkillRegistry, ToolRegistry, AgentRunner, TraceRecorder, pydantic outline models"
|
| 7 |
-
status:
|
| 8 |
- id: pptx-skill
|
| 9 |
content: Add skills/education-pptx/SKILL.md and create_pptx tool (python-pptx)
|
| 10 |
status: pending
|
|
|
|
| 4 |
todos:
|
| 5 |
- id: agent-lib
|
| 6 |
content: "Create libs/agent: SkillRegistry, ToolRegistry, AgentRunner, TraceRecorder, pydantic outline models"
|
| 7 |
+
status: in_progress
|
| 8 |
- id: pptx-skill
|
| 9 |
content: Add skills/education-pptx/SKILL.md and create_pptx tool (python-pptx)
|
| 10 |
status: pending
|
libs/agent/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# agent
|
| 2 |
+
|
| 3 |
+
Hermes-style skill agent on top of the local `inference` backends.
|
| 4 |
+
|
| 5 |
+
```python
|
| 6 |
+
from agent.runner import AgentRunner
|
| 7 |
+
from inference.factory import get_backend
|
| 8 |
+
|
| 9 |
+
runner = AgentRunner()
|
| 10 |
+
result = runner.run_education_pptx(
|
| 11 |
+
topic="Photosynthesis",
|
| 12 |
+
grade="6",
|
| 13 |
+
slide_count=5,
|
| 14 |
+
model_key="minicpm5-1b",
|
| 15 |
+
backend=get_backend("minicpm5-1b"),
|
| 16 |
+
)
|
| 17 |
+
```
|
libs/agent/pyproject.toml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "agent"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "Skill-based local agent loop for hackathon tasks"
|
| 5 |
+
readme = "README.md"
|
| 6 |
+
authors = [
|
| 7 |
+
{ name = "MSGhais", email = "msghais135@gmail.com" }
|
| 8 |
+
]
|
| 9 |
+
requires-python = ">=3.12"
|
| 10 |
+
dependencies = [
|
| 11 |
+
"inference",
|
| 12 |
+
"pydantic>=2.0.0",
|
| 13 |
+
"python-pptx>=1.0.0",
|
| 14 |
+
"pyyaml>=6.0.2",
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
[tool.uv.sources]
|
| 18 |
+
inference = { workspace = true }
|
| 19 |
+
|
| 20 |
+
[build-system]
|
| 21 |
+
requires = ["uv_build>=0.8.13,<0.9.0"]
|
| 22 |
+
build-backend = "uv_build"
|
libs/agent/src/agent/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from agent.runner import AgentResult, AgentRunner
|
| 2 |
+
from agent.skills import Skill, SkillRegistry
|
| 3 |
+
from agent.trace import TraceRecorder
|
| 4 |
+
|
| 5 |
+
__all__ = [
|
| 6 |
+
"AgentResult",
|
| 7 |
+
"AgentRunner",
|
| 8 |
+
"Skill",
|
| 9 |
+
"SkillRegistry",
|
| 10 |
+
"TraceRecorder",
|
| 11 |
+
]
|
libs/agent/src/agent/models.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from pydantic import BaseModel, Field
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class SlideSpec(BaseModel):
|
| 7 |
+
title: str
|
| 8 |
+
bullets: list[str] = Field(default_factory=list, min_length=1)
|
| 9 |
+
speaker_note: str = ""
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class SlideOutline(BaseModel):
|
| 13 |
+
title: str
|
| 14 |
+
slides: list[SlideSpec] = Field(min_length=1)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class EducationPptxInput(BaseModel):
|
| 18 |
+
topic: str
|
| 19 |
+
grade: str
|
| 20 |
+
slide_count: int = Field(ge=3, le=8)
|
libs/agent/src/agent/trace.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import hashlib
|
| 4 |
+
import json
|
| 5 |
+
import uuid
|
| 6 |
+
from dataclasses import dataclass, field
|
| 7 |
+
from datetime import UTC, datetime
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
from typing import Any
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def _prompt_hash(text: str) -> str:
|
| 13 |
+
return hashlib.sha256(text.encode()).hexdigest()[:16]
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
@dataclass
|
| 17 |
+
class TraceRecorder:
|
| 18 |
+
skill: str
|
| 19 |
+
model: str
|
| 20 |
+
user_input: dict[str, Any]
|
| 21 |
+
run_id: str = field(default_factory=lambda: uuid.uuid4().hex[:12])
|
| 22 |
+
steps: list[dict[str, Any]] = field(default_factory=list)
|
| 23 |
+
artifact: str | None = None
|
| 24 |
+
created_at: str = field(default_factory=lambda: datetime.now(UTC).isoformat())
|
| 25 |
+
|
| 26 |
+
def log_llm(self, prompt: str, output: str) -> None:
|
| 27 |
+
self.steps.append(
|
| 28 |
+
{
|
| 29 |
+
"type": "llm",
|
| 30 |
+
"prompt_hash": _prompt_hash(prompt),
|
| 31 |
+
"output": output,
|
| 32 |
+
}
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
def log_tool(self, name: str, arguments: dict[str, Any], result: str) -> None:
|
| 36 |
+
self.steps.append(
|
| 37 |
+
{
|
| 38 |
+
"type": "tool",
|
| 39 |
+
"name": name,
|
| 40 |
+
"arguments": arguments,
|
| 41 |
+
"result": result,
|
| 42 |
+
}
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
def set_artifact(self, path: str) -> None:
|
| 46 |
+
self.artifact = path
|
| 47 |
+
|
| 48 |
+
def to_dict(self) -> dict[str, Any]:
|
| 49 |
+
return {
|
| 50 |
+
"run_id": self.run_id,
|
| 51 |
+
"skill": self.skill,
|
| 52 |
+
"model": self.model,
|
| 53 |
+
"input": self.user_input,
|
| 54 |
+
"steps": self.steps,
|
| 55 |
+
"artifact": self.artifact,
|
| 56 |
+
"created_at": self.created_at,
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
def to_json(self, *, indent: int = 2) -> str:
|
| 60 |
+
return json.dumps(self.to_dict(), indent=indent)
|
| 61 |
+
|
| 62 |
+
def save(self, traces_dir: Path | None = None) -> Path:
|
| 63 |
+
base = traces_dir or _default_traces_dir()
|
| 64 |
+
base.mkdir(parents=True, exist_ok=True)
|
| 65 |
+
path = base / f"{self.run_id}.json"
|
| 66 |
+
path.write_text(self.to_json())
|
| 67 |
+
return path
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _default_traces_dir() -> Path:
|
| 71 |
+
env = __import__("os").environ.get("AGENT_TRACES_DIR")
|
| 72 |
+
if env:
|
| 73 |
+
return Path(env)
|
| 74 |
+
for base in (Path.cwd(), *Path.cwd().parents):
|
| 75 |
+
candidate = base / "outputs" / "traces"
|
| 76 |
+
if (base / "models.yaml").is_file() or (base / "pyproject.toml").is_file():
|
| 77 |
+
return candidate
|
| 78 |
+
return Path.cwd() / "outputs" / "traces"
|