Skip to content

Commit 0276f06

Browse files
author
Arena AI Agent
committed
feat(adas): 🧬 implement Automated Design of Agentic Systems (Self-Evolving Architecture) allowing the system to dynamically program and inject new Pydantic-enforced expert nodes at runtime
1 parent fc0f232 commit 0276f06

3 files changed

Lines changed: 84 additions & 0 deletions

File tree

‎epistemic_forge/models.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,14 @@ class FinalPeerReview(BaseModel):
224224
revision_needed: List[str] = Field(description="Areas that still need work if any.")
225225
verdict: str = Field(description="Must be one of: 'accept', 'accept_with_minor_revisions', 'major_revisions', 'reject'")
226226
final_comments: str = Field(description="A formal peer-review summary.")
227+
228+
class DynamicExpertSchema(BaseModel):
229+
"""Schema for ADAS (Automated Design of Agentic Systems).
230+
The LLM designs a new Pydantic schema structure for a novel expert.
231+
"""
232+
expert_class_name: str = Field(description="Name of the expert, e.g., 'QuantumMechanicsExpert'")
233+
expert_description: str = Field(description="What this expert analyzes.")
234+
fields_to_extract: List[Dict[str, str]] = Field(
235+
description="List of fields the expert must extract. Format: {'field_name': 'description'}"
236+
)
237+
system_prompt: str = Field(description="The ruthless, highly specific prompt guiding this new expert.")
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""L1.5 — Automated Design of Agentic Systems (ADAS).
2+
3+
Self-Evolving Architecture: If the static experts (Hegelian, Rigor Sentinel)
4+
are insufficient for a highly specific query, this layer dynamically writes
5+
a custom Pydantic Schema and instantiates a new Expert Node on the fly.
6+
"""
7+
from typing import Dict, Any, Type
8+
from pydantic import BaseModel, create_model, Field
9+
from loguru import logger
10+
11+
from epistemic_forge.models import ProjectSpec, DynamicExpertSchema
12+
from epistemic_forge.llm import generate_structured
13+
from epistemic_forge.experts.base import EpistemicExpert
14+
15+
def generate_dynamic_expert(spec: ProjectSpec) -> EpistemicExpert:
16+
"""Uses LLM to design a custom expert class and Pydantic schema."""
17+
18+
logger.info("🧬 L1.5 ADAS: Generating a custom Self-Evolving Expert tailored to this query...")
19+
20+
messages = [
21+
{"role": "system", "content": "You are a Meta-Architect (ADAS). Your job is to design a highly specialized 'AI Expert Node' that is perfectly tailored to solve the user's specific problem. Define its output schema and its system prompt."},
22+
{"role": "user", "content": f"Problem: {spec.question}\nKeywords: {spec.keywords}\n\nDesign the perfect expert to analyze this."}
23+
]
24+
25+
blueprint: DynamicExpertSchema = generate_structured(
26+
messages=messages,
27+
response_model=DynamicExpertSchema,
28+
model=spec.target_model,
29+
api_base=spec.api_base
30+
)
31+
32+
logger.debug(f"🧬 Blueprint acquired: {blueprint.expert_class_name}")
33+
34+
# Dynamically create the Pydantic Model based on the LLM's design
35+
field_definitions = {}
36+
for f in blueprint.fields_to_extract:
37+
for fname, fdesc in f.items():
38+
# Clean field name to be a valid python identifier
39+
safe_fname = "".join(c for c in fname if c.isalnum() or c == "_").lower()
40+
if safe_fname:
41+
field_definitions[safe_fname] = (str, Field(description=fdesc))
42+
43+
DynamicModel = create_model(f"{blueprint.expert_class_name}Output", **field_definitions)
44+
45+
# Create the Expert Class dynamically
46+
class DynamicallyGeneratedExpert(EpistemicExpert):
47+
@property
48+
def expert_name(self) -> str:
49+
return blueprint.expert_class_name
50+
51+
def analyze(self, spec: ProjectSpec, context: Dict[str, Any]) -> BaseModel:
52+
logger.debug(f"Activating dynamically generated expert: {self.expert_name}")
53+
msgs = [
54+
{"role": "system", "content": blueprint.system_prompt},
55+
{"role": "user", "content": f"Problem: {spec.question}\nContext: {context}\nAnalyze this."}
56+
]
57+
return generate_structured(
58+
messages=msgs,
59+
response_model=DynamicModel,
60+
model=spec.target_model,
61+
api_base=spec.api_base
62+
)
63+
64+
return DynamicallyGeneratedExpert()

‎epistemic_forge/pipeline/l2_conductor.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from epistemic_forge.experts.claim_expert import ClaimLatticeExpert
1313
from epistemic_forge.experts.dialectic_expert import HegelianExpert
1414
from epistemic_forge.experts.kaggle_expert import RigorSentinelExpert
15+
from epistemic_forge.pipeline.l1_5_adas import generate_dynamic_expert
1516

1617

1718
class SemanticConductor:
@@ -24,6 +25,14 @@ def __init__(self):
2425
def _route_experts(self, domain: str) -> list[EpistemicExpert]:
2526
"""Determines which experts are required based on the domain."""
2627
active_experts = [ClaimLatticeExpert()]
28+
29+
# 🧬 ADAS: Inject a dynamically generated expert specific to this domain!
30+
try:
31+
dynamic_expert = generate_dynamic_expert(spec)
32+
active_experts.append(dynamic_expert)
33+
except Exception as e:
34+
logger.warning(f"ADAS failed to generate dynamic expert, continuing with standard nodes. Error: {e}")
35+
2736
if domain in ["philosophy", "research", "hybrid"]:
2837
active_experts.append(HegelianExpert())
2938
if domain in ["kaggle", "research", "hybrid"]:

0 commit comments

Comments
 (0)