Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """Compose a custom ACE pipeline from individual steps. | |
| Demonstrates: | |
| 1. Pipeline composition with a single import line from ace | |
| 2. Adding a custom step to the pipeline | |
| 3. Inspecting runner presets via build_steps() | |
| 4. Running the pipeline directly via ACERunner | |
| Requires: | |
| pip install ace-framework | |
| export OPENAI_API_KEY=... # or any LiteLLM-supported provider | |
| """ | |
| from __future__ import annotations | |
| from ace import ( | |
| # Pipeline engine | |
| Pipeline, | |
| StepProtocol, | |
| # ACE context | |
| ACEStepContext, | |
| ACERunner, | |
| # Roles | |
| Agent, | |
| Reflector, | |
| SkillManager, | |
| # Steps | |
| AgentStep, | |
| EvaluateStep, | |
| learning_tail, | |
| # Types | |
| ACE, | |
| LiteLLMClient, | |
| Sample, | |
| Skillbook, | |
| SimpleEnvironment, | |
| ) | |
| # ------------------------------------------------------------------ | |
| # 1. Custom step — print the agent's answer between execute and learn | |
| # ------------------------------------------------------------------ | |
| class LogAnswerStep: | |
| """A custom step that logs the agent's output before learning.""" | |
| requires = frozenset({"agent_output"}) | |
| provides = frozenset() | |
| def __call__(self, ctx: ACEStepContext) -> ACEStepContext: | |
| print(f" -> Agent answered: {ctx.agent_output.final_answer}") | |
| return ctx | |
| # ------------------------------------------------------------------ | |
| # 2. Compose a custom pipeline | |
| # ------------------------------------------------------------------ | |
| MODEL = "gpt-4o-mini" | |
| llm = LiteLLMClient(model=MODEL) | |
| skillbook = Skillbook() | |
| pipe = Pipeline( | |
| [ | |
| AgentStep(Agent(llm), skillbook), | |
| EvaluateStep(SimpleEnvironment()), | |
| LogAnswerStep(), # <-- custom step injected here | |
| *learning_tail(Reflector(llm), SkillManager(llm), skillbook), | |
| ] | |
| ) | |
| print(f"Custom pipeline: {len(pipe._steps)} steps") | |
| print(f" requires: {pipe.requires}") | |
| print(f" provides: {pipe.provides}") | |
| # ------------------------------------------------------------------ | |
| # 3. Run using ACERunner | |
| # ------------------------------------------------------------------ | |
| runner = ACERunner(pipeline=pipe, skillbook=skillbook) | |
| samples = [ | |
| Sample(question="What is 2+2?", context="", ground_truth="4"), | |
| Sample(question="Capital of France?", context="", ground_truth="Paris"), | |
| ] | |
| # Note: ACERunner._build_context is abstract, so we use ACE which | |
| # provides _build_context for Sample objects. | |
| runner_ace = ACE(pipeline=pipe, skillbook=skillbook) | |
| results = runner_ace.run(samples, epochs=1) | |
| print(f"\nResults: {len(results)} samples processed") | |
| print(f"Skills learned: {len(skillbook.skills())}") | |
| # ------------------------------------------------------------------ | |
| # 4. Inspect and modify a runner's default steps with build_steps() | |
| # ------------------------------------------------------------------ | |
| print("\n--- Inspecting ACE.build_steps() ---") | |
| default_steps = ACE.build_steps( | |
| agent=Agent(llm), | |
| reflector=Reflector(llm), | |
| skill_manager=SkillManager(llm), | |
| environment=SimpleEnvironment(), | |
| skillbook=Skillbook(), | |
| ) | |
| for i, step in enumerate(default_steps): | |
| print(f" [{i}] {type(step).__name__}") | |
| # Modify: insert LogAnswerStep after EvaluateStep | |
| default_steps.insert(2, LogAnswerStep()) | |
| print(f"\nAfter inserting LogAnswerStep: {len(default_steps)} steps") | |
| # Build a new pipeline from the modified steps | |
| modified_pipe = Pipeline(default_steps) | |
| print(f"Modified pipeline ready with {len(modified_pipe._steps)} steps") | |