Галоўная / Артыкулы

Адміністрацыя воратаў для кожнага карыстальніка з медыя-элементам LangChain Wrap

Адэнт калькулятара, тры ўровні доступу: мідлвэр у стыле LangChain заменяе спіс засобаў залежна ад тыпу карыстальніка ў момент выканання, замест таго каб клонаваць троха адзінаковых адэнтав.

Выдавец: REACTAPP.TOP4 хв чытання978 слоў

Крыніцы: Wrap-Style Middleware in LangChain

Дынамічна кантролюванне таго, які інструменты агента ўвідны час залежна ад кантэксту карыстальніка.

Агент на базе ШЫ выходзіць у зовнішній свет праз інструменты — маленькія функцыі для арыметыкі, пошуку чыста іншых дзейнасцей. По значэнню стандарту кожная розмова з такім агентам бачыць той самы спіс інструментоў. Адноўсе гэта рэдкая патрэба для продукту. Лобі будынку адкрытае для візітараў, офісы — для спавяльнікаў, а камната сэрвера — толькі для адміністратароў. Адны будынак; разныя ключы.

Тая ж ідэя прыменяецца да агентоў: адна вакласовая дэфініцыя агента, разныя наборы інструментоў для кожнага вызывальніка.

Прыклад

Агент-калькулятор адкрывае чатыры інструменты: аднаўленне, вырахунак, паўнажынанне і дзеленне.

Тры рэвэнія доступу:

  • Внутршняе — аднаўленне і вырахунак
  • Зовнішняе — толькі аднаўленне
  • Адміністратар сістэмы — усе чатыры

Відзначны (паследні) падход

Створыце трохі разлучных агентаў, по аднаму на кожны ранг. Гэта працюе, пакуль не змяніцца запрос сістэмы, настройкі модэлю чыў рэалізацыя інструментаў. Кожную змену трэба павтарыць тры разы. Гэтая дуплікацыя — глыткія помылкі.

Лепшая: мідлвэр у стыле «wrap»

Залічвайце аднаго агента. Разместыце маленькі чэкпоінт пры входзе ў вызыв модэлю. Калі прыйшоў запрос, чэкпоінт чытае, хто ёсць аберанты, і перад запускам модэлю додае толькі разрашаныя інструменты.

Гэты чэкпоінт — мідлвэр. У стыле «wrap» значыць, што ён абгортае звычны вызыв модэлю: пераглядае запрос, адкорэгуе яго, а потым продаўжвае.

Эскіз рэалізацыі

Імпорты

Корыстныя элементы:

  • create_agent — стварае агента
  • @wrap_model_call — дэкаратар мідлвэру у стыле «wrap»
  • ModelRequest / ModelResponse — фарматы вхідных запітоў і выходных адпаведзей
  • HumanMessage — тэкст корыстувача
  • @tool — ператварае функцыю на інструмент
  • Клуч API

    openai_api_key = os.getenv("OPENAI_API_KEY")
    
    if not openai_api_key:
        raise ValueError(
            "Please set the OPENAI_API_KEY environment variable."
        )
    

    Кантэкст выканання

    user_type паводзіць рэвэл рангу доступу: internal, external або sys_admin. Перадайце яго пад час вызову, напрыклад context={"user_type": "internal"}.

    Інструменты

    Апішыце чатыры інструменты для выканання вычыслаў як звычайныя функцыі, адзначаныя як інструменты.

    Мідлвэр

    @wrap_model_call
    def dynamic_tools(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse],
    ) -> ModelResponse:
    
        user_type = request.runtime.context["user_type"]
    
        if user_type == "internal":
    
            tools = [
                addition,
                subtraction,
            ]
    
        elif user_type == "external":
    
            tools = [
                addition,
            ]
    
        elif user_type == "sys_admin":
    
            tools = [
                addition,
                subtraction,
                multiplication,
                division,
            ]
    
        else:
            raise ValueError(f"Unknown user type: {user_type}")
    
        # Dynamically change the tools available to the model
        modified_request = request.override(
            tools=tools
        )
    
        return handler(modified_request)
    

    Алгорытм работы ўнутрь упаковкі:

    1. Чытайце user_type з request.runtime.context
    2. Выбірайце спіс дазволеных інструментаў для данага тыпу
  • Выклікайце request.override(tools=tools), каб клонаваць запіт з новым спісакам
  • Перадайце модыфікаваны запіт у handler(), каб вызов модэлю продаваўся
  • override() копіюе запіт і заменяе толькі тыя поля, якія вы назначылі — у гэтым случае tools.

    Модэль чату

    temperature=0 робіць дэманы дэтэрміністычнымі.

    Стварэнне агента

    Зарэўнавайце всі чатыры інструменты ў агенце. Мідлвэр выбірае, які падскуп модэль насправды бачыць за кожны запіт. Сістэмны прампт павінен паведаміць модэлю выкарыстоўваць наявныя інструменты і паўтарыць, калі запрошаная операцыя недоступна, замест таго каб сама ствараць арытметыку.

    Спяльны прампт для тэстаў

    Выкорыстоўвайце той самы HumanMessage для кожнага рэвя; толькі user_type у кантэксце зменяецца.

    Выклікі

    ## INTERNAL USER
    
    
    print("\n" + "=" * 70)
    print("USER TYPE: INTERNAL")
    print("=" * 70)
    
    result = agent.invoke(
        {
            "messages": [human_message]
        },
        context={
            "user_type": "internal"
        },
    )
    
    print(result["messages"][-1].content)
    
    
    
    ## EXTERNAL USER
    
    print("\n" + "=" * 70)
    print("USER TYPE: EXTERNAL")
    print("=" * 70)
    
    result = agent.invoke(
        {
            "messages": [human_message]
        },
        context={
            "user_type": "external"
        },
    )
    
    print(result["messages"][-1].content)
    
    
    
    ## SYS_ADMIN USER
    
    
    print("\n" + "=" * 70)
    print("USER TYPE: SYS_ADMIN")
    print("=" * 70)
    
    result = agent.invoke(
        {
            "messages": [human_message]
        },
        context={
            "user_type": "sys_admin"
        },
    )
    
    print(result["messages"][-1].content)
    

    Рэзультат дэмана

    Выкананне той самай паведамленні ў трох разных кантэкстах паказвае, што мідлвэр выпаловае свою працу:

    1. Внутршній корыстнік можа дадаць і вычысціць, але не множыць і не дзеліць
    2. Зовнішній корыстнік можа толькі дадаць
    3. Адміністратар сістэмы можа выкорыстоўваць усе чатыры аперацыя

    Основны прынцып

    Ідэя можа быць выказана за калькі ліній:

    @wrap_model_call
    def dynamic_tools(request, handler):
    
        user_type = request.runtime.context["user_type"]
    
        tools = choose_tools(user_type)
    
        modified_request = request.override(
            tools=tools
        )
    
        return handler(modified_request)
    

    Мідлвэр абгортае вызов мадэлі, чытае тып тэкушчага корыстніка, выбірае інструменты, зменяе запіт і перадае яго далей. У гэтым эксперыменце зменяецца толькі спіс інструментоў — гэтага дастаткова, каб паказаць контроль у стыле абгортавання.

    Вывад

    Мідлвэр у стыле абгортавання дазволяе продукту пераформатаваць запіт мадэлі прытаманнае яй, перш чым модэль яго пабачыць. Хутчэйш, ён контролюе інструменты па параметру user_type, тады адна агентка можа обслужваць разныя рэвеніі доступу. Ключоўная частка — гэта:

    modified_request = request.override(tools=tools)
    

    Гэта ствараець ModelRequest на кожны запіт, пры яком узел адпрацоўкі знаходзіцца ў тым жа месца, што і абератар — у лобі, офісе чы ў камнаце сэрвераў, без неабходнасці выкарыстоўвання троха агентаў, скопіяваных з іншых месцаў.

    У працоўным рэжыме трэба яго супакоўваць з аутантыкацыяй, якая задае значэнне user_type на адной з падтвердзілых ідэнтычнасцяў, а не толькі на адной з заданых кліентам стрэлкаў. Логаванне таго, якія інструменты былі прыўязаны да кожнага запіту, таксама дапамагае пад час аўдытав, калі хтось стварае прэтэнзіі, што мадэль “маўла б” матыць прывілейованы інструмент. Трэба трzymаць спісы дазволеных інструментоў маленькімі і пераглядаць іх ўсё час, калі ў агенце калькулятара (чы іншам) з’яўляецца новы інструмент.