Главная / Статьи

Требуются ли специальные модели для глубоких агентов? Демонстрация в банковской сфере с LangSmith

LangChain Deep Agents теоретически не зависит от конкретной модели, но на практике чувствителен к ней. Пример банковского агента с пятью инструментами, проанализированный с помощью LangSmith, показывает, какая модель используется в каждом случае.

Издатель: REACTAPP.TOP9 мин чтения2109 слов

Источники: Beyond Simple Agents: Engineering DeepAgents for Enterprise with LangChain — 2

Естественным вопросом при разработке агентов с использованием фреймворка Deep Agents является вопрос о том, требуется ли для их эффективной работы определенная модель. Честный ответ имеет две части: с архитектурной точки зрения Deep Agents не зависит от того, какую модель вы используете; однако на практике результаты в значительной степени зависят от выбранной модели.

Архитектурно независим от модели

В фреймворке нет ничего, что бы принудительно задавало использование конкретной модели, и код это подтверждает. Можно использовать любую модель чата:

from langchain.chat_models import init_chat_model

# Swap any model in — the harness doesn't care
agent = create_deep_agent(
    model=init_chat_model("openai:gpt-4o"),
    tools=[...],
    system_prompt="..."
)

# Or Anthropic
agent = create_deep_agent(
    model=init_chat_model("anthropic:claude-opus-4-6"),
    tools=[...],
)

# Or Google
agent = create_deep_agent(
    model=init_chat_model("google_vertexai:gemini-2.0-flash"),
    tools=[...],
)

Инструмент планирования, файловая система, создание подагентов и детальные промпты — эти четыре основных компонента реализованы на уровне фреймворка. LangGraph обеспечивает среду выполнения, а большая языковая модель представляет собой просто двигатель рассуждений, подключенный к этой среде.

Практическая чувствительность к модели

Фреймворк опирается на такие поведенческие особенности, которые не у всех моделей проявляются одинаково хорошо.

  • Надежное вызов инструментов. Вся работа зависит от того, как модель вызывает инструменты в правильном формате с корректными аргументами. Более слабые модели выдумывают названия инструментов, передают неверные типы параметров или пропускают вызов и отвечают в прозе.
  • Следование длинным системным промптам. Встроенные промпты довольно длинные. Они указывают модели сначала спланировать действия, использовать список задач, изолировать контекст в подагентах и проверить свою работу. Модели, плохо выполняющие инструкции, отклоняются от этих рекомендаций уже на середине выполнения задачи.
  • Согласованность на протяжении множества шагов. При длительных выполнениях с большим количеством вызовов инструментов модель должна помнить, что она делает, что уже завершено и что следует сделать дальше. Менее мощные или слабые модели теряют нить развития задачи.
  • Умение остановиться в нужный момент. Хорошо настроенные агенты понимают, когда достигнут цели, и прекращают работу. Плохо настроенные модели завершают работу слишком рано или застревают в бесконечных циклах.
  • Примерное положение моделей

    Уровень модели Поведение с продвинутым агентом
    Модели передового уровня Надежное использование инструментов, выполнение сложных запросов, сохранение согласованности при длительных задачах
    Мощные средние модели Подходят для большинства задач, но иногда демонстрируют сбои при очень длинных процессах
    Менее мощные или open-source модели Результаты работают нестабильно: часто встречаются ошибки формата инструментов, смещение понимания запроса и преждевременное завершение работы

    Названия уровней приведены в качестве примеров на момент написания текста, и рейтинги моделей быстро меняются, поэтому тестируйте их на собственных задачах.

    Выводы

    Представьте кузов гоночной машины с возможностью замены двигателя: что бы вы ни установили, максимальная скорость определяется двигателем. Система связей обеспечивает структуру — планирование, память, вспомогательные агенты и маршрутизацию. Модель же обеспечивает способность правильно использовать всё это. Для промышленного применения, особенно в банке, где вымышленный список банкоматов или фальшивый инвестиционный сотрудник могут причинить реальный ущерб, следует использовать передовые модели и не экономить на их качестве.

    Время создавать что-то

    Хватит теории. Существует известный анекдот о документации без кода: двести страниц документации, пятнадцать диаграмм, отлаженный файл README — но ничего, что бы действительно работало. Поэтому вот рабочая демонстрация с пятью банковскими инструментами и фиктивными данными.

    Быстрое начало

    Создайте ключ API в консоли Anthropic, затем настройте проект:

    mkdir firstdeepagent && cd firstdeepagent
    uv add deepagent anthropic
    export ANTHROPIC_API_KEY='asdkjfbaepiufas;dkjcnaisdf'
    touch agent.py bank_tools.py mock_data.py
    

    Эти команды создают папку, устанавливают пакеты, экспортируют ключ (используйте свой собственный реальный ключ, никогда не используйте сохранённый) и создают три файла. Инструменты для bank_tools.py следующие:

    from mock_data import (OFFICERS_DATA, PORTFOLIO_DATA, ATM_DATA,
                           RETIREMENT_DATA, LOCATIONS_DATA)
    
    def get_atm_centers(zipcode: str) -> dict:
        data = ATM_DATA.get(str(zipcode).strip())
        if not data:
            return {
                "error": f"No ATM data for zipcode '{zipcode}'.",
                "available_zipcodes": list(ATM_DATA.keys()),
            }
        return {"zipcode": zipcode, "atm_centers": data, "total": len(data)}
    
    
    def get_investment_officers(city: str) -> dict:
        key = city.strip().lower()
        data = OFFICERS_DATA.get(key)
        if not data:
            return {
                "error": f"No investment officers found in '{city}'.",
                "available_cities": [c.title() for c in OFFICERS_DATA],
            }
        return {"city": city, "officers": data, "total": len(data)}
    
    
    def get_portfolio_companies(sector: str = "all") -> dict:
        companies = PORTFOLIO_DATA
        if sector and sector.lower() != "all":
            companies = [c for c in companies if sector.lower() in c["sector"].lower()]
        return {"companies": companies, "total": len(companies), "total_aum": "$6.35B"}
    
    
    def get_retirement_plans(plan_type: str = "all") -> dict:
        plans = RETIREMENT_DATA
        if plan_type and plan_type.lower() != "all":
            plans = [
                p for p in plans
                if plan_type.lower() in p["name"].lower() or plan_type.lower() in p["type"].lower()
            ]
        return {"plans": plans, "total": len(plans)}
    
    
    def get_bank_locations(city: str = "all") -> dict:
        locations = LOCATIONS_DATA
        if city and city.lower() != "all":
            locations = [l for l in locations if city.lower() in l["city"].lower()]
        total_branches = sum(l["branches"] for l in locations)
        return {"locations": locations, "total_branches": total_branches}
    

    Модуль mock_data содержит примерные записи, а модуль tools-config хранит схемы инструментов, соответствие между именами и функциями, а также системное сообщение. Храните их в отдельных файлах, чтобы код агента оставался компактным. Основной цикл в файле agent.py выглядит следующим образом:

    import os
    import json
    import anthropic
    from tools_config import TOOL_SCHEMAS, TOOL_FN_MAP, SYSTEM_PROMPT
    
    
    def run_agent(client: anthropic.Anthropic, conversation: list[dict]) -> str:
        MAX_ITERATIONS = 10
        messages = list(conversation)
    
        for _ in range(MAX_ITERATIONS):
            response = client.messages.create(
                model="claude-sonnet-4-6",
                max_tokens=2048,
                system=SYSTEM_PROMPT,
                tools=TOOL_SCHEMAS,
                messages=messages,
            )
    
            tool_use_blocks = [b for b in response.content if b.type == "tool_use"]
    
            if not tool_use_blocks:
                text_parts = [b.text for b in response.content if b.type == "text"]
                return "\n".join(text_parts).strip()
    
            tool_results = []
            for block in tool_use_blocks:
                fn = TOOL_FN_MAP.get(block.name)
                result = fn(**block.input) if fn else {"error": f"Unknown tool: {block.name}"}
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": json.dumps(result),
                })
    
            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user",      "content": tool_results})
    
        return "[Max iterations reached — partial answer may be incomplete.]"
    
    
    def main():
        api_key = os.environ.get("ANTHROPIC_API_KEY")
        if not api_key:
            print("Error: ANTHROPIC_API_KEY environment variable not set.")
            print("  export ANTHROPIC_API_KEY=your_key_here")
            raise SystemExit(1)
    
        client = anthropic.Anthropic(api_key=api_key)
        conversation: list[dict] = []
    
        print("XYZ Bank Agent — type 'quit' to exit.\n")
    
        while True:
            try:
                user_input = input("You > ").strip()
            except (EOFError, KeyboardInterrupt):
                print("\nGoodbye!")
                break
    
            if not user_input:
                continue
            if user_input.lower() in {"quit", "exit", "q"}:
                print("Goodbye!")
                break
    
            conversation.append({"role": "user", "content": user_input})
            answer = run_agent(client, conversation)
            conversation.append({"role": "assistant", "content": answer})
    
            print(f"\n{answer}\n")
    
    
    if __name__ == "__main__":
        main()
    

    Запуск

    Убедитесь, что ключ экспортирован, затем запустите агента с помощью команды uv run agent.py. Пример сессии:

    XYZ Bank Agent — type 'quit' to exit.
    
    You > Who are the investment officers in Chicago? Also what retirement plans do you offer?
    
    Here's everything you need!
    
    ---
    
    ## 👔 Investment Officers in Chicago
    
    | Name | Title | Specialty | Phone | Email |
    |---|---|---|---|---|
    | **Margaret Chen** | Senior Investment Officer | Equities & ETFs | 312-555-0101 | m.chen@xyzbank.com |
    | **David Okafor** | Investment Officer | Fixed Income | 312-555-0182 | d.okafor@xyzbank.com |
    | **Sarah Kowalski** | Wealth Manager | Retirement Planning | 312-555-0147 | s.kowalski@xyzbank.com |
    
    ---
    
    ## 🏦 Retirement Plans Offered by XYZ Bank
    
    1. **XYZ Gold 401(k)**
       - Min. Contribution: $50/month | Employer match up to 6%
       - Features: Roth option, target date funds, low expense ratios
    
    2. **XYZ Silver IRA (Traditional)**
       - Min. Contribution: $25/month
       - Features: Tax-deferred growth, flexible contributions, 600+ fund choices
    
    3. **XYZ Roth IRA**
       - Min. Contribution: $25/month
       - Features: Tax-free withdrawals, no required minimum distributions, estate planning benefits
    
    4. **XYZ Executive SEP-IRA**
       - Contribute up to 25% of income
       - Features: High contribution limits, self-employed friendly, simple administration
    
    ---
    
    If you'd like to learn more about any of these plans or get in touch with one of our Chicago investment officers (especially **Sarah Kowalski**, who specializes in retirement planning!), feel free to ask! 😊
    
    You >
    

    Агент разделяет запрос на выполнимые шаги, выбирает подходящие инструменты, запускает их и собирает результаты. Если помогает умственная карта, то последовательность действий выглядит так: поступление вопроса, планирование, вызов инструментов, сбор результатов, окончательный ответ.

    Наблюдаемость

    Для такой системы необходима телеметрия, поэтому добавьте LangSmith. Интеграция проста: две переменные окружения и примерно три строки кода. LangSmith оборачивает существующие вызовы вместо того, чтобы заменять их.

    Этот скрипт вызывает напрямую SDK Anthropic, а не LangChain, поэтому для более подробных отслеживаний вы можете по желанию декорировать функцию run_agent() атрибутом @traceable:

    from langsmith import traceable
    
    @traceable(name="xyz-bank-agent-run")
    def run_agent(client, conversation):
       ....................
       ....................
    

    Каждый вызов инструмента, решение модели, количество токенов и время задержки отображаются на панели управления LangSmith без необходимости изменения структуры цикла агента. Запустите его снова, задав более общий вопрос:

    uv run agent.py
    XYZ Bank Agent — type 'quit' to exit.
    
    You > Show ATMs in 10001, investment officers in New York, and all branch locations
    
    Here's a complete overview across all three categories:
    
    ---
    
    ## 🏧 ATMs in ZIP Code 10001
    
    | ATM Name | Address | Hours | Fee |
    |---|---|---|---|
    | Midtown Manhattan ATM | 350 5th Ave | 24/7 | No fee |
    | Penn Station ATM | 8 W 31st St | 24/7 | $2.50 (non-members) |
    
    ---
    
    ## 💼 Investment Officers — New York
    
    1. **James Thornton** — Chief Investment Officer
       - Specialty: Alternative Assets
       - 📞 212-555-0201 | ✉️ j.thornton@xyzbank.com
    
    2. **Priya Nair** — Investment Officer
       - Specialty: ESG Portfolios
       - 📞 212-555-0233 | ✉️ p.nair@xyzbank.com
    
    ---
    
    ## 🏦 All Branch Locations (61 Branches Nationwide)
    
    | City | Branches | Flagship Address | Hours |
    |---|---|---|---|
    | Chicago | 14 | 200 W Adams St, Chicago IL 60606 | Mon–Fri 9am–5pm, Sat 9am–1pm |
    | New York | 22 | 1 World Trade Center, NY 10007 | Mon–Fri 8am–6pm, Sat 9am–2pm |
    | Los Angeles | 11 | 333 S Grand Ave, LA 90071 | Mon–Fri 9am–5pm, Sat 9am–1pm |
    | Houston | 8 | 1000 Main St, Houston TX 77002 | Mon–Fri 9am–5pm |
    | Boston | 6 | 100 Federal St, Boston MA 02110 | Mon–Fri 9am–5pm, Sat 10am–1pm |
    
    ---
    
    Is there anything else you'd like to explore, such as retirement plans or our investment portfolio? 😊
    
    You > What companies are in XYZ Bank's portfolio? List only Technology sector companies
    
    Here are the **Technology sector companies** in XYZ Bank's investment portfolio:
    
    ---
    
    ## 💻 Technology Portfolio Companies
    
    | Company | Stake | Value | Rating |
    |---|---|---|---|
    | **Apex Technologies Inc.** | 4.2% | $840M | A+ |
    | **Sentinel Cybersecurity** | 7.3% | $1.5B | A+ |
    
    ---
    
    ### 📊 Summary
    - **Total Technology Holdings:** 2 companies
    - **Total Portfolio AUM:** $6.35B
    - Both companies carry an **A+ rating**, reflecting strong investment quality.
    
    ---
    
    Would you like to explore other sectors, view the full portfolio, or learn about our investment officers? Let me know! 😊
    
    You >
    

    Затем откройте сайт LangSmith и посмотрите записи выполнений. В каждой записи указаны шаги с входными данными, выходными данными, временем выполнения и ошибками.

    Бесплатный тариф

    На момент написания статьи план Developer является бесплатным: он предоставляет 5 000 записей выполнений в месяц и не требует наличия кредитной карты. Он включает полный отслеживание и отладку каждого шага, включая входные и выходные данные, задержку, использование токенов и ошибки, а также площадку для тестирования запросов. Он ограничен одним аккаунтом и одним рабочим пространством, срок хранения записей составляет 14 дней; это подходит для индивидуальных прототипов и демонстраций концепций. LangSmith заявляет, что не обучает модели на ваших записях, которые остаются конфиденциальными для вашей организации. Перед тем как полагаться на эти ограничения, ознакомьтесь с текущими тарифами.

    Короче говоря, начните с бесплатного тарифа. Он не стоит ничего, на его настройку уходит примерно четверть часа, и сразу отображаются все вызовы инструментов и принятые решения. Переходите на более дорогие тарифы только тогда, когда объем рабочей нагрузки приближается к производственному уровню.

    Что делать дальше

    • Замените фиктивные данные на реальные источники, такие как система корпоративного банкинга, CRM или внутренние API.
    • Создайте иерархию, в которой оркестратор-шлюз направляет запросы к агентам конкретных доменов.
    • Внедрите механизмы контроля, которые вежливо отклоняют запросы, выходящие за рамки задачи, и передают их людям.
    • Храните историю разговоров между взаимодействиями с помощью Redis или базы данных.
    • Добавьте межсессионную память, чтобы запоминать прошлые запросы и предпочтения возвращающихся пользователей.
    • Установите лимиты на частоту запросов и бюджеты токенов для каждого пользователя и сессии.
    • Составьте набор из 30–50 репрезентативных запросов с ожидаемыми результатами для тестирования.
  • Повторно запускайте этот набор оценки каждый раз, когда меняется код или запросы, чтобы регрессии проявлялись как можно раньше.
  • Добавляйте каждую новую область как отдельного агента, зарегистрированного через шлюз.