8.9 KiB
Переменные и макросы AgentUI
Этот файл — простая шпаргалка по переменным/макросам, которые можно использовать в шаблонах узла ProviderCall и в Prompt Blocks.
Правила ввода:
- Квадратные макросы ... — простая подстановка. Хорошо подходят для строк и для URL/заголовков.
- Фигурные {{ ... }} — «джинджа‑лайт»: умеют фильтр |default(...), корректно вставляют объекты и массивы внутрь JSON без лишних кавычек.
- Любые значения, вставляемые в JSON через макросы, приводятся к корректному JSON когда это возможно.
Служебные файлы/строки реализации:
- Рендеринг и макросы: render_template_simple()
- Провайдерный узел с формированием PROMPT: ProviderCallNode.run()
Общие переменные контекста
- model — активная модель (строка)
- vendor_format — openai | gemini | claude | unknown
- system — системный текст, если был во входящем запросе
- params.temperature, params.max_tokens, params.top_p, params.stop
- chat.last_user — последнее user‑сообщение
- chat.messages — массив унифицированных сообщений
- incoming.path — путь входящего HTTP‑запроса
- incoming.query — строка query (?a=1&b=2)
- incoming.query_params — объект query, например {"key":"..."}
- incoming.headers — заголовки входящего запроса
- incoming.json — JSON‑тело входящего запроса клиента
- incoming.api_keys.authorization — значение Authorization (если есть)
- incoming.api_keys.key — значение ?key=... в URL (удобно для Gemini)
- incoming.api_keys.secret — запасной слот
Те же поля доступны через {{ ... }}: например {{ params.temperature|default(0.7) }}, {{ incoming.json }} и т.д.
Макросы OUT (выходы нод)
Доступ к выходам нод возможен в двух формах:
1) Короткая форма (best‑effort текст)
Что делает «best‑effort текст»:
- Если нода вернула response_text или text — берётся он
- Если нода вернула объект провайдера:
- OpenAI: choices[0].message.content
- Gemini: candidates[0].content.parts[0].text
- Claude: content[].text (склейка)
- Если ничего из выше не подошло — выполняется глубокий поиск текстовых полей ("text"/"content")
Реализация: _best_text_from_outputs() и подстановка коротких OUT: render_template_simple()
2) Полная форма (точный путь)
- OUT:n1.result — целиком результат ноды n1
- OUT:n1.result.candidates.0.content.parts.0.text — конкретный путь
- Эквивалент через фигурные скобки: {{ OUT.n1.result.candidates.0.content.parts.0.text }}
Совет: используйте короткий OUTx если нужно «просто текст». Используйте полную форму, если нужен конкретный фрагмент/массив.
Единый фрагмент PROMPT
PROMPT — это уже собранный JSON‑фрагмент из ваших Prompt Blocks. Он зависит от выбранного провайдера ноды:
- OpenAI → "messages": [...]
- Gemini → "contents": [...], "systemInstruction": {...}
- Claude → "system": "...", "messages": [...]
Как использовать внутри JSON‑шаблона:
{ "model": "{{ model }}", PROMPT, "temperature": {{ params.temperature|default(0.7) }} }
Вы также можете использовать сырьевые структуры:
- {{ pm.messages }}
- {{ pm.contents }}
- {{ pm.systemInstruction }}
- {{ pm.system_text }}
Но рекомендуемый путь — PROMPT: меньше шансов сломать JSON.
Примеры по провайдерам
OpenAI (/v1/chat/completions)
{ "model": "{{ model }}", PROMPT, "temperature": {{ incoming.json.temperature|default(params.temperature|default(0.7)) }}, "top_p": {{ incoming.json.top_p|default(params.top_p|default(1)) }}, "max_tokens": {{ incoming.json.max_tokens|default(params.max_tokens|default(256)) }}, "stop": {{ incoming.json.stop|default(params.stop|default([])) }} }
Gemini (/v1beta/models/{model}:generateContent?key=...)
{ "model": "{{ model }}", PROMPT, "safetySettings": {{ incoming.json.safetySettings|default([]) }}, "generationConfig": { "temperature": {{ incoming.json.generationConfig.temperature|default(params.temperature|default(0.7)) }}, "topP": {{ incoming.json.generationConfig.topP|default(params.top_p|default(1)) }}, "maxOutputTokens": {{ incoming.json.generationConfig.maxOutputTokens|default(params.max_tokens|default(256)) }}, "stopSequences": {{ incoming.json.generationConfig.stopSequences|default(params.stop|default([])) }} } }
Claude (/v1/messages)
{ "model": "{{ model }}", PROMPT, "temperature": {{ incoming.json.temperature|default(params.temperature|default(0.7)) }}, "top_p": {{ incoming.json.top_p|default(params.top_p|default(1)) }}, "max_tokens": {{ incoming.json.max_tokens|default(params.max_tokens|default(256)) }} }
Частые кейсы
- Взять текст пользователя из входящего запроса и передать в Prompt Blocks
- Gemini: VAR:incoming.json.contents.0.parts.0.text
- OpenAI: VAR:incoming.json.messages.0.content
- Claude: VAR:incoming.json.messages.0.content.0.text
- Переписать ответ предыдущей ноды «как текст»
- OUT1 — если предыдущая нода имеет id n1
- Добавить ключ Gemini из query в endpoint
- /v1beta/models/{{ model }}:generateContent?key=VAR:incoming.api_keys.key
Почему местами нужны {{ ... }}
Внутри JSON нам важно вставлять объекты/массивы без кавычек и иметь дефолты:
- {{ pm.contents }} — вставит массив как массив
- {{ params.temperature|default(0.7) }} — если нет значения, подставится 0.7
Квадратные ... хорошо подходят для строк/простых значений и для URL/заголовков.
Отладка
- Проверьте лог DEBUG в консоли: ProviderCallNode показывает провайдера, URL и первые 400 символов тела запроса.
- Если «ничего не подставилось»:
- убедитесь, что не подаёте входной payload в ProviderCall (иначе шаблон игнорируется);
- проверьте валидность JSON после подстановок;
- проверьте, что макрос написан корректно (OUT против OUTn).
Мини‑FAQ
В: Почему OUT1 пустой? О: Возможно, нода n1 не вернула текстового поля, и глубокий поиск не нашёл текста. Уточните путь через полную форму OUT:n1.....
В: Можно ли получить весь «сырой» ответ? О: OUT:n1.result — вернёт весь JSON результата ноды n1.
В: Почему фигурные скобки иногда обязательны? О: Они умеют |default(...) и корректно вставляют объекты/массивы внутрь JSON.
Ссылки на реализацию
- Макросы/рендер: render_template_simple()
- Единый PROMPT: ProviderCallNode.run()
- Короткий OUTx и извлечение текста: render_template_simple(), _best_text_from_outputs()
Удачного редактирования!