Сквозной туториал
Здесь всё связывается воедино: агент, который сортирует тикет поддержки, используя LLM-шаг, зарегистрированный инструмент, запись в память и финальный шаг-черновик.
1. Опишите шаги
Заголовок раздела «1. Опишите шаги»from mmar_carl import ( ReasoningChain, ReasoningContext, Language, LLMStepDescription, ToolStepDescription, ToolStepConfig, MemoryStepDescription, MemoryStepConfig, MemoryOperation, OpenAICompatibleClient, OpenAIClientConfig,)
steps = [ LLMStepDescription( number=1, title="Classify severity", aim="Classify the ticket severity as low, medium, or high.", reasoning_questions="How urgent and impactful is this issue?", step_context_queries=["error", "outage", "deadline"], stage_action="Reply with a single word: low / medium / high.", example_reasoning="A production outage is high; a typo is low.", ), ToolStepDescription( number=2, title="Look up SLA", dependencies=[1], config=ToolStepConfig( tool_name="lookup_sla", input_mapping={"severity": "$history[-1]"}, ), ), MemoryStepDescription( number=3, title="Record triage", dependencies=[2], config=MemoryStepConfig( operation=MemoryOperation.WRITE, memory_key="sla", value_source="$history[-1]", namespace="triage", ), ), LLMStepDescription( number=4, title="Draft reply", aim="Draft a customer reply that states the SLA from memory.", reasoning_questions="What should we tell the customer about timing?", dependencies=[3], step_context_queries=["customer", "request"], stage_action="Write a short, friendly reply mentioning the SLA.", example_reasoning="Setting clear expectations reduces follow-ups.", ),]
chain = ReasoningChain(steps=steps, max_workers=2)2. Зарегистрируйте инструмент
Заголовок раздела «2. Зарегистрируйте инструмент»def lookup_sla(severity: str) -> str: table = {"high": "1 hour", "medium": "1 business day", "low": "3 business days"} return table.get(severity.strip().lower(), "3 business days")3. Запустите
Заголовок раздела «3. Запустите»client = OpenAICompatibleClient(OpenAIClientConfig( base_url="https://openrouter.ai/api/v1", api_key="sk-or-v1-...", model="qwen/qwen3-coder",))
context = ReasoningContext( outer_context="Our checkout has been down for 20 minutes — customers can't pay!", api=client, language=Language.ENGLISH, system_prompt="You are a concise, helpful support engineer.",)context.register_tool("lookup_sla", lookup_sla)
result = chain.execute(context)print(result.get_final_output()) # черновик ответаprint(result.success, len(result.step_results))4. Изучите прогон
Заголовок раздела «4. Изучите прогон»print(result.format_profiling_table()) # стоимость / латентность по шагамprint(chain.to_mermaid()) # DAGresult.trace.to_html("triage.html") # анимированный плейбэкКуда дальше
Заголовок раздела «Куда дальше»- Добавьте conditional-шаг, чтобы эскалировать
highна отдельный путь. - Добавьте метрики и прогоните на датасете.
- Эволюционируйте цепочку для улучшения качества ответов.
- Полистайте полный cookbook.