HadTavern 0.01: Gemini/Claude fixes; UI _origId reuse; docs; .bat open
This commit is contained in:
@@ -1,95 +1,148 @@
|
||||
# Переменные и макросы AgentUI
|
||||
# Переменные и макросы НадTavern
|
||||
|
||||
Этот файл — простая шпаргалка по переменным/макросам, которые можно использовать в шаблонах узла ProviderCall и в Prompt Blocks.
|
||||
Краткая, человеко‑понятная шпаргалка по тому, какие переменные и макросы доступны в шаблонах (в том числе в Prompt Blocks), как они устроены и как их правильно использовать. Док ниже соответствует текущему коду.
|
||||
|
||||
Правила ввода:
|
||||
- Квадратные макросы [[...]] — простая подстановка. Хорошо подходят для строк и для URL/заголовков.
|
||||
- Фигурные {{ ... }} — «джинджа‑лайт»: умеют фильтр |default(...), корректно вставляют объекты и массивы внутрь JSON без лишних кавычек.
|
||||
- Любые значения, вставляемые в JSON через макросы, приводятся к корректному JSON когда это возможно.
|
||||
Реализация формирует единый «контекст» переменных для всех нод пайплайна, дополняет его выходами уже выполненных нод, а узел ProviderCall добавляет свои служебные структуры для удобной сборки промпта.
|
||||
|
||||
Служебные файлы/строки реализации:
|
||||
- Рендеринг и макросы: [render_template_simple()](agentui/pipeline/executor.py:125)
|
||||
- Провайдерный узел с формированием PROMPT: [ProviderCallNode.run()](agentui/pipeline/executor.py:565)
|
||||
Ссылки на код:
|
||||
- Формирование контекста запроса: [build_macro_context()](agentui/api/server.py:142)
|
||||
- Исполнитель пайплайна и снапшот OUT: [PipelineExecutor.run()](agentui/pipeline/executor.py:136)
|
||||
- Узел провайдера (Prompt Blocks → provider payload): [ProviderCallNode.run()](agentui/pipeline/executor.py:650)
|
||||
- Шаблоны/макросы ([[...]] и {{ ... }}): [render_template_simple()](agentui/pipeline/templating.py:187)
|
||||
- Короткая форма [[OUTx]] (извлечение текста): [_best_text_from_outputs()](agentui/pipeline/templating.py:124)
|
||||
- Прямой форвард запросов: [RawForwardNode.run()](agentui/pipeline/executor.py:833)
|
||||
|
||||
---
|
||||
|
||||
## Общие переменные контекста
|
||||
## 1) Общие переменные контекста (для всех нод)
|
||||
|
||||
- [[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]] — запасной слот
|
||||
Эти переменные доступны в шаблонах любой ноды. Они добавляются на стороне сервера при обработке входящего HTTP‑запроса.
|
||||
|
||||
Те же поля доступны через {{ ... }}: например {{ params.temperature|default(0.7) }}, {{ incoming.json }} и т.д.
|
||||
- model — строка с именем модели.
|
||||
Пример: "gpt-4o-mini"
|
||||
- vendor_format — вендор/протокол запроса: "openai" | "gemini" | "claude" | "unknown"
|
||||
- system — «системный» текст, если он был во входящем запросе; иначе пустая строка.
|
||||
|
||||
- params — стандартные параметры генерации (можно использовать как дефолты)
|
||||
- params.temperature — число с плавающей точкой (по умолчанию 0.7)
|
||||
- params.max_tokens — целое или null
|
||||
- params.top_p — число (по умолчанию 1.0)
|
||||
- params.stop — массив строк или null
|
||||
|
||||
- chat — сведения о чате во входящем запросе
|
||||
- chat.last_user — последнее сообщение пользователя (строка)
|
||||
- chat.messages — массив сообщений в унифицированной форме:
|
||||
- role — "system" | "user" | "assistant" | "tool"
|
||||
- content — содержимое (обычно строка)
|
||||
- name — опционально, строка
|
||||
- tool_call_id — опционально
|
||||
|
||||
- incoming — детали ВХОДЯЩЕГО HTTP‑запроса
|
||||
- incoming.method — метод ("POST" и т.п.)
|
||||
- incoming.url — полный URL (в query ключи маскируются для логов)
|
||||
- incoming.path — путь (например, /v1/chat/completions)
|
||||
- incoming.query — строка query без вопросительного знака
|
||||
- incoming.query_params — объект со всеми query‑параметрами
|
||||
- incoming.headers — объект всех заголовков запроса
|
||||
- incoming.json — сырой JSON тела запроса, как прислал клиент
|
||||
- incoming.api_keys — удобные «срезы» ключей
|
||||
- incoming.api_keys.authorization — значение из заголовка Authorization (если есть)
|
||||
- incoming.api_keys.key — значение из query (?key=...) — удобно для Gemini
|
||||
|
||||
Пример использования в шаблоне:
|
||||
- [[VAR:incoming.api_keys.key]] — возьмёт ключ из строки запроса (?key=...).
|
||||
- [[VAR:incoming.headers.x-api-key]] — возьмёт ключ из заголовка x-api-key (типично для Anthropic).
|
||||
- {{ params.temperature|default(0.7) }} — безопасно подставит число, если не задано во входящих данных.
|
||||
|
||||
---
|
||||
|
||||
## Макросы OUT (выходы нод)
|
||||
## 2) Выходы нод (OUT) и ссылки на них
|
||||
|
||||
Доступ к выходам нод возможен в двух формах:
|
||||
Во время исполнения пайплайна результаты предыдущих нод собираются в снапшот OUT и доступны при рендере шаблонов следующих нод:
|
||||
|
||||
### 1) Короткая форма (best‑effort текст)
|
||||
- [[OUT1]] — «текст» из ноды n1
|
||||
- [[OUT2]] — из ноды n2 и т.д.
|
||||
- OUT — словарь выходов нод, ключи — id нод в пайплайне (например, "n1", "n2").
|
||||
- OUT.n1, OUT.n2, ... — объект результата соответствующей ноды.
|
||||
|
||||
Что делает «best‑effort текст»:
|
||||
- Если нода вернула response_text или text — берётся он
|
||||
- Если нода вернула объект провайдера:
|
||||
- OpenAI: choices[0].message.content
|
||||
- Gemini: candidates[0].content.parts[0].text
|
||||
- Claude: content[].text (склейка)
|
||||
- Если ничего из выше не подошло — выполняется глубокий поиск текстовых полей ("text"/"content")
|
||||
Формы доступа:
|
||||
- Полная форма: [[OUT:n1.result.choices.0.message.content]]
|
||||
(или фигурными скобками: {{ OUT.n1.result.choices.0.message.content }})
|
||||
- Короткая форма «просто текст»: [[OUT1]], [[OUT2]], ...
|
||||
Это эвристика: берётся самое вероятное «текстовое» поле из результата (см. [_best_text_from_outputs()](agentui/pipeline/templating.py:121)).
|
||||
|
||||
Реализация: [_best_text_from_outputs()](agentui/pipeline/executor.py:45) и подстановка коротких OUT: [render_template_simple()](agentui/pipeline/executor.py:155)
|
||||
Что возвращают встроенные ноды:
|
||||
- ProviderCall:
|
||||
- OUT.nX.result — сырой JSON ответа провайдера
|
||||
- OUT.nX.response_text — уже извлечённый «лучший текст» (строка)
|
||||
- RawForward:
|
||||
- OUT.nX.result — JSON, как пришёл от апстрима (или {"error": "...", "text": "..."} при не‑JSON ответе)
|
||||
|
||||
### 2) Полная форма (точный путь)
|
||||
- [[OUT:n1.result]] — целиком результат ноды n1
|
||||
- [[OUT:n1.result.candidates.0.content.parts.0.text]] — конкретный путь
|
||||
- Эквивалент через фигурные скобки: {{ OUT.n1.result.candidates.0.content.parts.0.text }}
|
||||
|
||||
Совет: используйте короткий [[OUTx]] если нужно «просто текст». Используйте полную форму, если нужен конкретный фрагмент/массив.
|
||||
Подсказка по короткой форме [[OUTx]]:
|
||||
- OpenAI: вернёт choices[0].message.content
|
||||
- Gemini: вернёт candidates[0].content.parts[0].text
|
||||
- Claude: склеит content[].text
|
||||
- Если явных полей нет — выполнит «глубокий поиск» по ключам "text"/"content"
|
||||
|
||||
---
|
||||
|
||||
## Единый фрагмент [[PROMPT]]
|
||||
## 3) Макросы подстановки и синтаксис
|
||||
|
||||
[[PROMPT]] — это уже собранный JSON‑фрагмент из ваших Prompt Blocks. Он зависит от выбранного провайдера ноды:
|
||||
- OpenAI → "messages": [...]
|
||||
- Gemini → "contents": [...], "systemInstruction": {...}
|
||||
- Claude → "system": "...", "messages": [...]
|
||||
В шаблонах доступны обе формы подстановки:
|
||||
|
||||
Как использовать внутри JSON‑шаблона:
|
||||
1) Квадратные скобки [[ ... ]] — простая подстановка
|
||||
- [[VAR:путь]] — взять значение из контекста по точечному пути
|
||||
Пример: [[VAR:incoming.json.max_tokens]]
|
||||
- [[OUT:путь]] — взять значение из OUT (см. раздел выше)
|
||||
Пример: [[OUT:n1.result.choices.0.message.content]]
|
||||
- [[OUT1]] / [[OUT2]] — короткая форма «просто текст»
|
||||
- [[PROMPT]] — специальный JSON‑фрагмент из Prompt Blocks (см. ниже)
|
||||
|
||||
{
|
||||
"model": "{{ model }}",
|
||||
[[PROMPT]],
|
||||
"temperature": {{ params.temperature|default(0.7) }}
|
||||
}
|
||||
|
||||
Вы также можете использовать сырьевые структуры:
|
||||
- {{ pm.messages }}
|
||||
- {{ pm.contents }}
|
||||
- {{ pm.systemInstruction }}
|
||||
- {{ pm.system_text }}
|
||||
|
||||
Но рекомендуемый путь — [[PROMPT]]: меньше шансов сломать JSON.
|
||||
2) Фигурные скобки {{ ... }} — «джинджа‑лайт»
|
||||
- {{ путь }} — взять значение по пути из контекста (или из OUT.* если начать с OUT.)
|
||||
Пример: {{ OUT.n1.result }}
|
||||
- Фильтр по умолчанию: {{ что-то|default(значение) }}
|
||||
Примеры:
|
||||
- {{ params.temperature|default(0.7) }}
|
||||
- {{ incoming.json.stop|default([]) }}
|
||||
- {{ anthropic_version|default('2023-06-01') }} — см. «Опциональные поля» ниже
|
||||
- Фигурные скобки удобны там, где нужно вставить внутрь JSON не строку, а ЧИСЛО/ОБЪЕКТ/МАССИВ без кавычек и/или задать дефолт.
|
||||
|
||||
---
|
||||
|
||||
## Примеры по провайдерам
|
||||
## 4) ProviderCall: Prompt Blocks, pm.* и [[PROMPT]]
|
||||
|
||||
### OpenAI (/v1/chat/completions)
|
||||
Узел ProviderCall собирает ваши Prompt Blocks (блоки вида: роль/текст/вкл‑выкл/порядок) в стандартные «сообщения» и превращает их в структуру для конкретного провайдера.
|
||||
|
||||
Внутри шаблонов этого узла доступны:
|
||||
- pm — «сырьевые» структуры из Prompt Blocks
|
||||
- Для OpenAI:
|
||||
- pm.messages — массив { role, content, name? }
|
||||
- pm.system_text — один большой текст из всех system‑блоков
|
||||
- Для Gemini:
|
||||
- pm.contents — массив { role: "user"|"model", parts: [{text}] }
|
||||
- pm.systemInstruction — объект вида { parts: [{text}] } или пустой {}
|
||||
- pm.system_text — строка
|
||||
- Для Claude:
|
||||
- pm.system_text — строка
|
||||
- pm.system — то же самое (удобно подставлять в поле "system")
|
||||
- pm.messages — массив { role: "user"|"assistant", content: [{type:"text", text:"..."}] }
|
||||
|
||||
- [[PROMPT]] — готовый JSON‑фрагмент на основе pm, безопасный для вставки внутрь шаблона:
|
||||
- OpenAI → подставит: "messages": [...]
|
||||
- Gemini → подставит: "contents": [...], "systemInstruction": {...}
|
||||
- Claude → подставит: "system": "...", "messages": [...]
|
||||
|
||||
Зачем это нужно?
|
||||
- Чтобы 1) удобно собирать промпт из визуальных блоков, 2) не «сломать» JSON руками.
|
||||
Вы можете вручную использовать {{ pm.* }}, но [[PROMPT]] — рекомендуемый и самый безопасный вариант.
|
||||
|
||||
---
|
||||
|
||||
## 5) Частые сценарии и примеры
|
||||
|
||||
Примеры ниже можно вклеивать в поле «template» ноды ProviderCall. Они уже используют [[PROMPT]] и аккуратные дефолты.
|
||||
|
||||
OpenAI (POST /v1/chat/completions):
|
||||
```
|
||||
{
|
||||
"model": "{{ model }}",
|
||||
[[PROMPT]],
|
||||
@@ -98,9 +151,10 @@
|
||||
"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=...)
|
||||
|
||||
Gemini (POST /v1beta/models/{model}:generateContent):
|
||||
```
|
||||
{
|
||||
"model": "{{ model }}",
|
||||
[[PROMPT]],
|
||||
@@ -112,71 +166,163 @@
|
||||
"stopSequences": {{ incoming.json.generationConfig.stopSequences|default(params.stop|default([])) }}
|
||||
}
|
||||
}
|
||||
```
|
||||
Подсказка: ключ Gemini удобно брать из строки запроса:
|
||||
в endpoint используйте …?key=[[VAR:incoming.api_keys.key]]
|
||||
|
||||
### Claude (/v1/messages)
|
||||
|
||||
Claude (POST /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)) }}
|
||||
"max_tokens": {{ incoming.json.max_tokens|default(params.max_tokens|default(256)) }},
|
||||
"system": {{ pm.system|default("") }}
|
||||
}
|
||||
```
|
||||
Подсказка: ключ Anthropic обычно передают в заголовке x-api-key.
|
||||
В UI‑пресете это поле уже есть в headers.
|
||||
|
||||
RawForward (прямой форвард входящего запроса):
|
||||
- Поля конфигурации base_url, override_path, extra_headers проходят через те же макросы, поэтому можно подставлять динамику:
|
||||
- base_url: https://generativelanguage.googleapis.com
|
||||
- override_path: [[VAR:incoming.path]] (или задать свой)
|
||||
- extra_headers (JSON): `{"X-Trace":"req-{{ incoming.query_params.session|default('no-session') }}"}`
|
||||
|
||||
---
|
||||
|
||||
## Частые кейсы
|
||||
## 6) Опциональные/редкие поля, о которых стоит знать
|
||||
|
||||
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]]
|
||||
- anthropic_version — используется как HTTP‑заголовок для Claude ("anthropic-version"). В тело запроса не вставляется.
|
||||
Если нужен дефолт, задавайте его в headers (например, в конфиге ноды/шаблоне заголовков). В шаблонах тела используйте [[PROMPT]]/pm.* без anthropic_version.
|
||||
|
||||
2) Переписать ответ предыдущей ноды «как текст»
|
||||
- [[OUT1]] — если предыдущая нода имеет id n1
|
||||
|
||||
3) Добавить ключ Gemini из query в endpoint
|
||||
- /v1beta/models/{{ model }}:generateContent?key=[[VAR:incoming.api_keys.key]]
|
||||
- stream — в MVP стриминг отключён, сервер принудительно не стримит ответ.
|
||||
В шаблонах можно встретить поля stream, но по умолчанию они не включены.
|
||||
|
||||
---
|
||||
|
||||
## Почему местами нужны {{ ... }}
|
||||
## 7) Когда использовать [[...]] и когда {{ ... }}
|
||||
|
||||
Внутри JSON нам важно вставлять объекты/массивы без кавычек и иметь дефолты:
|
||||
- {{ pm.contents }} — вставит массив как массив
|
||||
- {{ params.temperature|default(0.7) }} — если нет значения, подставится 0.7
|
||||
- Внутрь JSON как ОБЪЕКТ/МАССИВ/ЧИСЛО: используйте {{ ... }}
|
||||
(фигурные скобки вставляют «как есть», без кавычек, и умеют |default(...))
|
||||
- Для строк/URL/заголовков/простых значений: можно использовать [[...]]
|
||||
(квадратные скобки удобны и короче писать)
|
||||
|
||||
Квадратные [[...]] хорошо подходят для строк/простых значений и для URL/заголовков.
|
||||
Примеры:
|
||||
- {{ pm.contents }} — вставит массив как настоящий массив (без кавычек)
|
||||
- {{ params.temperature|default(0.7) }} — безопасный дефолт для числа
|
||||
- [[VAR:incoming.api_keys.authorization]] — быстро подставить строку Authorization
|
||||
|
||||
---
|
||||
|
||||
## Отладка
|
||||
## 8) Отладка и рекомендации
|
||||
|
||||
- Проверьте лог DEBUG в консоли: ProviderCallNode показывает провайдера, URL и первые 400 символов тела запроса.
|
||||
- ProviderCall печатает в консоль DEBUG сведения: выбранный провайдер, конечный URL, первые символы тела запроса — удобно для проверки корректности шаблона.
|
||||
- Если «ничего не подставилось»:
|
||||
- убедитесь, что не подаёте входной payload в ProviderCall (иначе шаблон игнорируется);
|
||||
- проверьте валидность JSON после подстановок;
|
||||
- проверьте, что макрос написан корректно (OUT против OUTn).
|
||||
1) Проверьте, что вы НЕ передаёте сырое входное тело напрямую в ProviderCall (узел строит тело из шаблона и Prompt Blocks).
|
||||
2) Убедитесь, что итоговый JSON валиден (закрывающие скобки, запятые).
|
||||
3) Проверьте точность путей в макросах (OUT vs OUTx, правильные id нод n1/n2/...).
|
||||
- Для ссылок на выходы предыдущих нод используйте [[OUT1]] как «просто текст», либо полные пути [[OUT:n1...]] для точного фрагмента.
|
||||
|
||||
---
|
||||
|
||||
## Мини‑FAQ
|
||||
## 9) Быстрая памятка по ключам доступа
|
||||
|
||||
В: Почему [[OUT1]] пустой?
|
||||
О: Возможно, нода n1 не вернула текстового поля, и глубокий поиск не нашёл текста. Уточните путь через полную форму [[OUT:n1....]].
|
||||
|
||||
В: Можно ли получить весь «сырой» ответ?
|
||||
О: [[OUT:n1.result]] — вернёт весь JSON результата ноды n1.
|
||||
|
||||
В: Почему фигурные скобки иногда обязательны?
|
||||
О: Они умеют |default(...) и корректно вставляют объекты/массивы внутрь JSON.
|
||||
- Gemini: [[VAR:incoming.api_keys.key]] — рекомендовано; ключ приходит в query (?key=...).
|
||||
- OpenAI: [[VAR:incoming.headers.authorization]] (или [[VAR:incoming.api_keys.authorization]]) — стандартный Bearer‑токен.
|
||||
- Anthropic: [[VAR:incoming.headers.x-api-key]] — ключ в заголовке.
|
||||
|
||||
---
|
||||
|
||||
## Ссылки на реализацию
|
||||
## 10) Ссылки на реализацию (для интересующихся деталями)
|
||||
|
||||
- Макросы/рендер: [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)
|
||||
- Контекст (переменные): [build_macro_context()](agentui/api/server.py:142)
|
||||
- Исполнение пайплайна, зависимости, снапшоты OUT: [PipelineExecutor.run()](agentui/pipeline/executor.py:136)
|
||||
- Узел провайдера (Prompt Blocks → провайдер): [ProviderCallNode.run()](agentui/pipeline/executor.py:650)
|
||||
- PM‑структуры для шаблонов: [ProviderCallNode._blocks_struct_for_template()](agentui/pipeline/executor.py:592)
|
||||
- Подстановка [[PROMPT]], макросы, дефолты: [render_template_simple()](agentui/pipeline/templating.py:187)
|
||||
- Короткая форма [[OUTx]] и поиск «лучшего текста»: [_best_text_from_outputs()](agentui/pipeline/templating.py:124)
|
||||
- Прямой форвард входящего запроса: [RawForwardNode.run()](agentui/pipeline/executor.py:833)
|
||||
- Детекция вендора по входному payload: [detect_vendor()](agentui/common/vendors.py:8)
|
||||
|
||||
Удачного редактирования!
|
||||
Удачного редактирования!
|
||||
---
|
||||
## Пользовательские переменные (SetVars) — «для людей»
|
||||
|
||||
Задача: в начале пайплайна положить свои значения и потом использовать их в шаблонах одной строкой — например [[MY_KEY]] или {{ MAX_TOKENS }}.
|
||||
|
||||
Где это в UI
|
||||
- В левой панели добавьте ноду SetVars и откройте её в инспекторе.
|
||||
- Жмите «Добавить переменную», у каждой переменной есть три поля:
|
||||
- name — имя переменной (латинские буквы/цифры/подчёркивание, не с цифры): MY_KEY, REGION, MAX_TOKENS
|
||||
- mode — режим обработки значения:
|
||||
- string — строка, в которой работают макросы ([[...]] и {{ ... }})
|
||||
- expr — «мини‑формула» без макросов (подробнее ниже)
|
||||
- value — собственно значение
|
||||
|
||||
Как потом вставлять переменные
|
||||
- Для строк (URL/заголовки/текст) — квадратные скобки: [[MY_KEY]]
|
||||
- Для чисел/массивов/объектов — фигурные скобки: {{ MAX_TOKENS }}, {{ GEN_CFG }}
|
||||
|
||||
Примеры «как надо»
|
||||
- Переменная-строка (mode=string):
|
||||
- name: AUTH
|
||||
- value: "Bearer [[VAR:incoming.headers.authorization]]"
|
||||
- Использование в заголовке: "Authorization": "[[AUTH]]"
|
||||
- Переменная-число (mode=expr):
|
||||
- name: MAX_TOKENS
|
||||
- value: 128 + 64
|
||||
- Использование в JSON: "max_tokens": {{ MAX_TOKENS }}
|
||||
- Переменная-объект (mode=expr):
|
||||
- name: GEN_CFG
|
||||
- value: {"temperature": 0.3, "topP": 0.9, "safe": true}
|
||||
- Использование: "generationConfig": {{ GEN_CFG }}
|
||||
|
||||
Важно про два режима
|
||||
- string — это «шаблон». Внутри работают все макросы ([[VAR:...]], [[OUT:...]], [[PROMPT]], {{ ... }}). Значение прогоняется через рендер [render_template_simple()](agentui/pipeline/templating.py:184).
|
||||
- expr — это «мини‑формула». Внутри НЕТ макросов и НЕТ доступа к контексту; только литералы и операции (см. ниже). Вычисляет значение безопасно — без eval, на белом списке AST (реализация: [SetVarsNode._safe_eval_expr()](agentui/pipeline/executor.py:291)).
|
||||
|
||||
Что умеет expr (мини‑формулы)
|
||||
- Числа и арифметика: 128 + 64, (5 * 60) + 30, 42 % 2, -5, 23 // 10
|
||||
- Строки: "eu" + "-central" → "eu-central" (строки склеиваем знаком +)
|
||||
- Булева логика: (2 < 3) and (10 % 2 == 0), 1 < 2 < 5
|
||||
- Коллекции: ["fast", "safe"], {"temperature": 0.3, "topP": 0.9, "safe": true}
|
||||
- JSON‑литералы: true/false/null, объекты и массивы — если выражение является чистым JSON, оно разбирается напрямую (без макросов), т.е. true→True, null→None и т.п.
|
||||
- Запрещено: функции (кроме специально разрешённых ниже), доступ к переменным/контексту, атрибуты/индексация/условные выражения.
|
||||
|
||||
Рандом в expr
|
||||
- В expr доступны три простые функции случайности:
|
||||
- rand() → число с плавающей точкой в диапазоне [0, 1)
|
||||
- randint(a, b) → целое число от a до b включительно
|
||||
- choice(list) → случайный элемент из списка/кортежа
|
||||
- Примеры:
|
||||
- name: RAND_F, mode: expr, value: rand()
|
||||
- "temperature": {{ RAND_F }}
|
||||
- name: DICE, mode: expr, value: randint(1, 6)
|
||||
- "dice_roll": {{ DICE }}
|
||||
- name: PICK_MODEL, mode: expr, value: choice(["gpt-4o-mini", "gpt-4o", "o3-mini"])
|
||||
- "model": "[[PICK_MODEL]]"
|
||||
- Зерна/seed нет — каждый запуск выдаёт новое значение.
|
||||
|
||||
«Почему в expr нельзя подставлять переменные/макросы?»
|
||||
- Для безопасности и предсказуемости: expr — это закрытый мини‑язык без окружения.
|
||||
- Если нужно использовать другие переменные/макросы — делайте это в режиме string (там всё рендерится шаблонизатором).
|
||||
- Технические детали: защита реализована в [SetVarsNode._safe_eval_expr()](agentui/pipeline/executor.py:291), а вставка string‑значений — через [render_template_simple()](agentui/pipeline/templating.py:184).
|
||||
|
||||
Как это работает внутри (если интересно)
|
||||
- SetVars исполняется как обычная нода пайплайна и отдаёт {"vars": {...}}.
|
||||
- Исполнитель добавляет эти значения в контекст для последующих нод как context.vars (см. [PipelineExecutor.run()](agentui/pipeline/executor.py:131)).
|
||||
- При рендере шаблонов:
|
||||
- [[NAME]] и {{ NAME }} подставляются с приоритетом из пользовательских переменных (см. обработку в [render_template_simple()](agentui/pipeline/templating.py:184)).
|
||||
- Сам SetVars считает переменные в порядке списка и возвращает их одним пакетом (внутри одной ноды значения не зависят друг от друга).
|
||||
|
||||
Частые вопросы
|
||||
- «Хочу собрать строку с частями из внешнего запроса»: делайте mode=string и пишите: "Bearer [[VAR:incoming.headers.authorization]]".
|
||||
- «Хочу массив случайных чисел»: mode=expr → [rand(), rand(), rand()], а в JSON: "numbers": {{ MY_LIST }}
|
||||
- «Почему мои значения не сохраняются?» — нажмите «Сохранить параметры» в инспекторе ноды, затем «Сохранить пайплайн» в шапке. UI синхронизирует данные в node.data и сохраняет в pipeline.json (см. [static/editor.html](static/editor.html)).
|
||||
|
||||
Ссылки на реализацию (для любопытных)
|
||||
- Нода переменных: [SetVarsNode](agentui/pipeline/executor.py:264), [SetVarsNode._safe_eval_expr()](agentui/pipeline/executor.py:291), [SetVarsNode.run()](agentui/pipeline/executor.py:354)
|
||||
- Исполнитель/контекст vars: [PipelineExecutor.run()](agentui/pipeline/executor.py:131)
|
||||
- Шаблоны и макросы (включая «голые» [[NAME]]/{{ NAME }}): [render_template_simple()](agentui/pipeline/templating.py:184)
|
||||
Reference in New Issue
Block a user