isbondarev/giga3.1-github-issues
075
1{#--------TOOL RENDERING FUNCTIONS---------#}2 3{#---------------------------------------------------------------4 Converts JSON Schema (dict) to a TypeScript type definition5----------------------------------------------------------------#}6{%- macro json_schema_to_typescript(schema, indent="") -%}7 {%- set ADDITIONAL_JSON_KEYS = ['format', 'maxItems', 'maximum', 'minItems', 'minimum', 'pattern'] -%}8 {%- set ty = schema.get("type") -%}9 10 {# ---------------- OBJECT ---------------- #}11 {%- if ty == "object" -%}12 {{- "{\n" -}}13 14 {# Start building property list #}15 {%- set props = schema.get("properties", {}) -%}16 {%- set required = schema.get("required", []) -%}17 {%- set has_additional_props = schema.get("additionalProperties") is defined -%}18 {%- set additional_props_type = none -%}19 {%- if has_additional_props -%}20 {%- if schema.additionalProperties == true -%}21 {%- set additional_props_type = {'type': 'any'} -%}22 {%- elif schema.additionalProperties is mapping -%}23 {%- set additional_props_type = schema.additionalProperties -%}24 {%- endif -%}25 {%- endif -%}26 27 {%- for key, val in props.items() -%}28 {# ---------- Description Comments ---------- #}29 {%- if "description" in val -%}30 {%- for line in val['description'].split('\n') -%}31 {%- if line.strip() -%}32 {{- indent + '// ' + line + '\n' -}}33 {%- endif -%}34 {%- endfor -%}35 {%- endif -%}36 37 {# ---------- Additional JSON Keys ---------- #}38 {%- for add_key, add_val in val.items() -%}39 {%- if add_key in ADDITIONAL_JSON_KEYS -%}40 {%- if add_val is string -%}41 {{- indent + '// ' + add_key + ': "' + add_val + '"' + '\n' -}}42 {%- else -%}43 {{- indent + '// ' + add_key + ': ' ~ add_val ~ '\n' -}}44 {%- endif -%}45 {%- endif -%}46 {%- endfor -%}47 48 {# ---------- Property Definition ---------- #}49 {%- set type_str = json_schema_to_typescript(50 val, 51 indent + " "52 ) -%}53 54 {{- indent + key + ('' if key in required else '?') + ': ' + type_str + ',' -}}55 56 {%- if "default" in val or "defalut_value" in val -%}57 {%- set default = val.get("default", val.get("defalut_value")) -%}58 {%- if default is string -%}59 {{- ' // default: "' + default + '"' -}}60 {%- else -%}61 {{- ' // default: ' ~ default -}}62 {%- endif -%}63 {%- endif -%}64 65 {{- "\n" -}}66 {%- endfor -%}67 68 {# Handle additionalProperties as index signature #}69 {%- if has_additional_props and additional_props_type is not none -%}70 {%- set additional_type_str = json_schema_to_typescript(71 additional_props_type,72 indent + " "73 ) -%}74 {{- indent + '[key: string]: ' + additional_type_str + '\n' -}}75 {%- endif -%}76 77 {{- indent[: (indent|length - " "|length) ] + '}' -}}78 79 {# ---------------- STRING ---------------- #}80 {%- elif ty == "string" -%}81 {%- if schema.get("enum") -%}82 {%- set ns = namespace(enum = []) -%}83 {%- for en in schema['enum'] -%}84 {%- set ns.enum = ns.enum + ['"' ~ en ~ '"'] -%}85 {%- endfor -%}86 {{- ns.enum | join(' | ') -}}87 {%- elif schema.get("format", "none") in ['date-time', 'date'] -%}88 {{- 'Date' -}}89 {%- else -%}90 {{- 'string' -}}91 {%- endif -%}92 93 {# ---------------- NUMBER / INTEGER ---------------- #}94 {%- elif ty in ["number", "integer"] -%}95 {%- if schema.get("enum") -%}96 {{- schema.enum | join(' | ') -}}97 {%- else -%}98 {{- 'number' -}}99 {%- endif -%}100 101 {# ---------------- BOOLEAN ---------------- #}102 {%- elif ty == "boolean" -%}103 {{- 'boolean' -}}104 105 {# ---------------- ARRAY ---------------- #}106 {%- elif ty == "array" -%}107 {%- if "items" in schema -%}108 {{- json_schema_to_typescript(schema['items'], indent) + '[]' -}}109 {%- else -%}110 {{- 'Array<any>' -}}111 {%- endif -%}112 113 {# ---------------- FALLBACK ---------------- #}114 {%- else -%}115 {{- 'any' -}}116 {%- endif -%}117{%- endmacro -%}118 119{#---------------------------------------------------------------120 Renders a namespace and its tool definitions in TypeScript style121----------------------------------------------------------------#}122 123{%- macro render_tool_namespace(namespace_name, tools) -%}124 {%- set ns = namespace(sections = ['namespace ' ~ namespace_name ~ ' {']) -%}125 126 {%- for tool in tools -%}127 {%- if tool.function -%}128 {%- set tool = tool.function -%}129 {%- endif -%}130 131 {%- set ns_tool = namespace(content_lines=[]) -%}132 133 {# ---------- TOOL DESCRIPTION ---------- #}134 {%- if tool.get('description') -%}135 {%- for line in tool['description'].split('\n') -%}136 {%- if line.strip() -%}137 {%- set ns_tool.content_lines = ns_tool.content_lines + ['// ' ~ line] -%}138 {%- endif -%}139 {%- endfor -%}140 {%- endif -%}141 142 {# ---------- TOOL SIGNATURE ---------- #}143 {%- set main_body = "" -%}144 {%- set params = tool.get("parameters") -%}145 {%- if params and params.get("properties") -%}146 {%- set param_type = json_schema_to_typescript(params, " ") -%}147 {%- set main_body = 'type ' ~ tool.name ~ ' = (_: ' ~ param_type ~ ') => ' -%}148 {%- else -%}149 {%- set main_body = 'type ' ~ tool.name ~ ' = () => ' -%}150 {%- endif -%}151 152 {# ---------- RETURN TYPE ---------- #}153 {%- set return_params = tool.get("return_parameters") -%}154 {%- if return_params and return_params.get("properties") -%}155 {%- set return_type = json_schema_to_typescript(return_params, " ") -%}156 {%- set main_body = main_body ~ return_type -%}157 {%- else -%}158 {%- set main_body = main_body ~ 'any' -%}159 {%- endif -%}160 161 {%- set main_body = main_body ~ ';\n' -%}162 163 {%- set ns_tool.content_lines = ns_tool.content_lines + [main_body] -%}164 165 {# ---------- ADD TOOL TO SECTIONS ---------- #}166 {%- set ns.sections = ns.sections + [ns_tool.content_lines | join('\n')] -%}167 {%- endfor -%}168 169 {%- set ns.sections = ns.sections + ['} // namespace ' ~ namespace_name] -%}170 171 {{- ns.sections | join('\n') -}}172{%- endmacro -%}173 174 175{# ----------- MESSAGE RENDERING HELPER FUNCTIONS ------------ #}176 177{%- macro render_function_call(call) -%}178 {%- if call.function -%}179 {%- set call = call.function -%}180 {%- endif -%}181 182 {%- set arguments = call['arguments'] -%}183 {%- if arguments is not string -%}184 {%- set arguments = arguments| tojson(ensure_ascii=False) -%}185 {%- endif -%}186 187 {{- '{"name": "' ~ call['name'] ~ '", "arguments": ' ~ arguments ~ '}' -}}188{%- endmacro -%}189 190 191{%- macro render_role_message(message, role=None) -%}192 {%- if not role -%}193 {%- set role = message["role"] -%}194 {%- endif -%}195 196 {%- set message_content = message['content'] or '' -%}197 {%- if message_content is not string -%}198 {%- set message_content = message_content | tojson(ensure_ascii=False) -%}199 {%- endif -%}200 201 {{- role + add_tokens.role_sep + message_content -}}202 203 {%- if message.tool_calls is defined and message.tool_calls -%}204 {{- add_tokens.function_call + render_function_call(message.tool_calls[0]) -}}205 {%- endif -%}206 207 {{- add_tokens.message_sep -}}208 209{%- endmacro -%}210 211 212 213{# ----- SPECIAL TOKENS ----- #}214 215{%- set add_tokens = namespace(216 role_sep="<|role_sep|>\n", 217 message_sep="<|message_sep|>\n\n",218 function_call="<|function_call|>"219) -%}220 221{# ----- DEFAULT DEVSYSTEM ----- #}222 223{%- set DEVSYSTEM -%}224<role_description>225Описание доступных в диалоге ролей.226 227`developer system`228Сообщение, добавленное Сбером до основного диалога. Имеет самый высокий приоритет и определяет глобальные, неотменяемые условия (например, правила ведения диалога, политику безопасности, общий стиль ответов ассистента и пр.).229 230`system`231Системная инструкция, добавляемая разработчиками или пользователем, но с приоритетом ниже, чем `developer system`. Обычно описывает инструкции ассистента, конкретный стиль ответа и другие условия для данного конкретного диалога.232 233`user`234Сообщение или запрос от пользователя. Ассистент следует ему, если это не противоречит инструкциям более высокого приоритета (см. <instruction_priority>).235 236`user memory`237Последовательность наиболее актуальных долговременных фактов о пользователе на момент его запроса, представленная в виде JSON‑списка строк. Факты в ней перечислены в хронологическом порядке, то есть более новые факты дописываются в конец последовательности. При этом при изменении или удалении фактов записи о предыдущих фактах остаются в последовательности. Ассистент сохраняет факты с помощью функции и использует их в соответствии с указаниями из блока <memory_guidelines> ниже.238 239`added files`240Метаинформация о файлах, доступных для использования в диалоге, представленная в формате JSON. Содержит следующие ключи: id (уникальный идентификатор файла), name (имя файла), type (тип файла).241 242`assistant`243Ответ ассистента на запрос пользователя. Если системная инструкция или пользователь не задаёт дополнительных правил для `assistant`, то такая реплика должна соответствовать указаниям из блока <assistant_guidelines> ниже. Список доступных для вызова функций содержится в последней реплике роли `available functions`. Название необходимой для вызова функции и аргументы будут сгенерированы после специального токена вызова функции. В своих репликах ассистент следует инструкциям в соответствии с <instruction_priority>.244Вызов функции осуществляется в строгом соответствии с инструкцией из блока <function_usage>.245 246`function descriptions`247Описания функций в формате TypeScript. Функция — это специальный инструмент (или набор инструкций), который ассистент может вызвать для выполнения конкретных действий, вычислений или получения данных, необходимых для решения задачи пользователя. Каждое описание функции содержит блоки с именем, описанием, аргументами. Иногда описание содержит отдельные блоки с возвращаемыми параметрами и примерами применения, иллюстрирующими правильный вызов и аргументы.248 249`available functions`250Список, который содержит названия функций, доступных для вызова. Если список не содержит элементов, то в следующем сообщении функции, доступные для вызова, отсутствуют.251 252`function result`253Результат последнего вызова функции.254</role_description>255 256 257<available_modalities>258Ассистент умеет работать со следующими модальностями: текст, доступные функции.259</available_modalities>260 261 262<instruction_priority>263В случае противоречия инструкций разных ролей в контексте диалога соблюдай приоритеты:264`developer system` > `system` > `user` > `function descriptions` > `function result` > `user memory`265</instruction_priority>266 267 268<function_usage>269Базовые инструкции для работы с функциями.270 271Можно вызывать только те функции, которые доступны исходя из последнего сообщения `available functions`.272 273Вызывай доступные функции в случае, если согласно их описанию такой вызов поможет дать более полный и/или точный ответ на запрос пользователя. Заполняй аргументы функций, используя информацию из контекста диалога. Если функция может помочь ответить на запрос, но для её обязательного аргумента отсутствует информация в контексте, уточни у пользователя недостающие данные перед вызовом функции. При недоступности необходимой функции или ошибке — кратко сообщи об этом пользователю и по возможности предложи альтернативу.274</function_usage>275 276 277<memory_guidelines>278Правила использования фактов в долговременной памяти:279 280Если в диалоге нет сообщения под ролью `user memory`, то это равносильно отсутствию долговременных фактов о пользователе в памяти. В таком случае информация о пользователе ограничена текущим диалогом, и новые факты не должны сохраняться.281</memory_guidelines>282 283 284<assistant_guidelines>285GigaChat — нейросетевая модель искусственного интеллекта, созданная компанией Сбер в России.286 287GigaChat старается отвечать на языке, на котором пользователь задал запрос. Если из запроса пользователя и контекста диалога язык определить невозможно, GigaChat использует русский.288GigaChat предоставляет подробные ответы на более сложные и открытые вопросы.289GigaChat в ответе не использует названия доступных функций.290GigaChat отвечает безопасно, в соответствии с действующим законодательством Российской Федерации, стараясь помочь пользователю решить задачу или поддержать беседу.291 292Ты — GigaChat.293</assistant_guidelines>294 295 296Ниже будет приведён диалог.297В диалоге могут быть разнообразные роли, описанные в блоке <role_description>.298Каждая реплика начинается с названия роли и специального токена, обозначающего конец полного наименования роли, а заканчивается специальным токеном конца реплики.299Твоя задача — продолжить диалог от последней указанной роли в соответствии с контекстом диалога.300{%- endset -%}301 302 303{#- ---------------------- RENDERING STARTS HERE ---------------------- -#}304 305 306{# ----- RENDER BOS TOKEN ----- #}307{{- bos_token -}}308 309 310{# ----- RENDER DEVSYSTEM ----- #}311{{- render_role_message({"role": "developer system", "content": DEVSYSTEM}) -}}312 313{# ----- RENDER SYSTEM IF PRESENT ----- #}314{%- if messages and messages[0]['role'] == 'system' -%}315 {{- render_role_message(messages[0]) -}}316 {%- set messages = messages[1:] -%}317{%- else -%}318 {{- render_role_message({"role": "system", "content": ""}) -}}319{%- endif -%}320 321{# ----- RENDER TOOLS ----- #}322{%- if tools -%}323 {%- set tools_content = (324 render_tool_namespace('functions', tools) 325 + "\n\n"326 ) -%}327 {{- render_role_message({'role': 'function descriptions', 'content': tools_content}) -}}328{%- endif -%}329 330{# ----- MAIN MESSAGE LOOP ----- #}331{%- for message in messages -%}332 333 {# ----- TOOL MESSAGE -------#}334 {%- if message['role'] == 'tool' -%}335 {{- render_role_message(message, 'function result') -}}336 337 {# ----- OTHER MESSAGES ----- #}338 {%- else -%}339 {{- render_role_message(message) -}}340 {%- endif -%}341 342 {# ----- ADDING GENERATION PROMPT ----- #}343 344 {%- if loop.last and add_generation_prompt and message['role'] != 'assistant' -%}345 {{- 'assistant' + add_tokens.role_sep -}}346 {%- endif -%}347 348{%- endfor -%}