182 lines
8.9 KiB
Markdown
182 lines
8.9 KiB
Markdown
# Переменные и макросы AgentUI
|
||
|
||
Этот файл — простая шпаргалка по переменным/макросам, которые можно использовать в шаблонах узла ProviderCall и в Prompt Blocks.
|
||
|
||
Правила ввода:
|
||
- Квадратные макросы [[...]] — простая подстановка. Хорошо подходят для строк и для URL/заголовков.
|
||
- Фигурные {{ ... }} — «джинджа‑лайт»: умеют фильтр |default(...), корректно вставляют объекты и массивы внутрь JSON без лишних кавычек.
|
||
- Любые значения, вставляемые в JSON через макросы, приводятся к корректному JSON когда это возможно.
|
||
|
||
Служебные файлы/строки реализации:
|
||
- Рендеринг и макросы: [render_template_simple()](agentui/pipeline/executor.py:125)
|
||
- Провайдерный узел с формированием PROMPT: [ProviderCallNode.run()](agentui/pipeline/executor.py:565)
|
||
|
||
---
|
||
|
||
## Общие переменные контекста
|
||
|
||
- [[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 текст)
|
||
- [[OUT1]] — «текст» из ноды n1
|
||
- [[OUT2]] — из ноды n2 и т.д.
|
||
|
||
Что делает «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()](agentui/pipeline/executor.py:45) и подстановка коротких OUT: [render_template_simple()](agentui/pipeline/executor.py:155)
|
||
|
||
### 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)) }}
|
||
}
|
||
|
||
---
|
||
|
||
## Частые кейсы
|
||
|
||
1) Взять текст пользователя из входящего запроса и передать в 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]]
|
||
|
||
2) Переписать ответ предыдущей ноды «как текст»
|
||
- [[OUT1]] — если предыдущая нода имеет id n1
|
||
|
||
3) Добавить ключ 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()](agentui/pipeline/executor.py:125)
|
||
- Единый [[PROMPT]]: [ProviderCallNode.run()](agentui/pipeline/executor.py:604)
|
||
- Короткий [[OUTx]] и извлечение текста: [render_template_simple()](agentui/pipeline/executor.py:155), [_best_text_from_outputs()](agentui/pipeline/executor.py:45)
|
||
|
||
Удачного редактирования! |