SiCore TokenWorks
LLM APIAPI Gateway

Практичний досвід інженера token8341: створення прототипу розумної служби підтримки за тиждень і записи про підводні камені при порівнянні API різних моделей

SiCore TokenWorks Team·2026-10-05

Минулого тижня я взяв завдання — створити прототип розумної служби підтримки для команди, яка розробляє SaaS-систему тікетів, потрібно було запустити його за тиждень і ще й порівняти якість відповідей чотирьох моделей: GPT-4o, DeepSeek-V3, Qwen-Max і Doubao. Звучить нескладно, але коли почав працювати, виявилося, що всі підводні камені уніфікованої інтеграції кількох моделей ховаються в дрібницях. У цій статті я записав процес, щоб заощадити час колегам, які теж робитимуть порівняння кількох моделей.

Керування Key: 5 платформ, 5 наборів бекенду — спершу розберіться з обліком

Найбільша проблема на початку була не в написанні коду, а в керуванні Key. Чотири моделі з чотирьох платформ, плюс одна запасна — п'ять бекендів, п'ять консолей, і в кожної свій формат Key, спосіб перегляду квоти та правила обмеження швидкості. На деяких платформах Key показується відкритим текстом, на інших потрібно створити суб-акаунт і потім розподіляти. На етапі прототипу, щоб було швидше, я запхав усі Key в один файл .env, і наступного дня, коли обсяг тестування зріс, один з Key був обмежений, і в повідомленні про помилку взагалі не було видно, з якою платформою проблема.

Пізніше я перейшов на шар конфігураційного мапінгу: прив'язав кожен Key до псевдоніма та тегу призначення, і в логах виводив лише псевдонім. Ще простіший варіант — використовувати платформу агрегації AI API, де один Key керує всіма моделями. Під час порівняння ми пробували token8341 — його модельний шлюз уніфікує автентифікацію кількох вітчизняних великих моделей, і для перемикання моделі достатньо змінити назву моделі в конфігурації, Key чіпати не потрібно. Для етапу прототипу це означає менше підтримки чотирьох наборів логіки автентифікації — і тижня вистачить.

Сумісність SDK: в кожної платформи інтерфейс виглядає по-різному

Встановлення SDK відбило половину терпіння. Екосистема SDK від OpenAI найзріліша, багато постачальників заявляють про сумісність, але коли підключаєш насправді, виявляється, що назви параметрів не збігаються. Наприклад, на одній платформі temperature називається temperature, на іншій пишуть top_p і змішують використання, а ще десь max_tokens змінили на max_output_tokens. Перемикач потокової передачі теж не уніфікований: десь stream=True, а десь треба окремо передавати stream_options.

Мій підхід — абстрагувати шар адаптера, назовні виставляти лише уніфіковану функцію виклику, а всередині розгалужувати за постачальником. Так бізнес-код не відчуває відмінностей. Якщо не хочеться писати цей шар самостійно, рішення, сумісне з OpenAI SDK, може заощадити чимало зусиль: змінюєш один рядок base_url і перемикаєш модель, а складність уніфікованої інтеграції кількох моделей переміщується з рівня коду на рівень конфігурації. На етапі перевірки прототипу цей компроміс дуже вартий.

Потокове виведення: реалізація протоколу SSE в кожної платформи різна

Розумна служба підтримки обов'язково має працювати з потоковою передачею, інакше користувач чекає три секунди, поки з'явиться текст, і досвід одразу руйнується. Проблема в тому, що деталі реалізації протоколу SSE в різних платформ відрізняються. На одній платформі кожен chunk містить повну структуру event, на іншій передається лише поле data; ознака завершення десь [DONE], десь встановлюється поле finish_reason; а ще десь посередині вставляються heartbeat-пакети, які фронтенд при парсингу легко помилково сприймає за вміст.

Спочатку я написав парсер за форматом OpenAI, і при підключенні другої платформи все перетворилося на абракадабру. Рішення — написати уніфіковане проміжне ПЗ для парсингу SSE, яке нормалізує chunk від кожної платформи в одну структуру подій, і фронтенд розуміє лише її. Підводний камінь, на який я наступив: не вірте написаному в документації "повністю сумісно", обов'язково беріть реальні відповіді та дивіться через перехоплення трафіку — документація й реалізація часто розходяться.

Обробка винятків: якщо в однієї платформи таймаут, як автоматично перемкнутися

Після запуску порівняльних тестів найдратівливішим був таймаут окремої платформи. Одного разу під час навантажувального тесту відповідь Qwen-Max раптом сповільнилася, весь ланцюжок служби підтримки застряг, а фронтенд безкінечно крутив індикатор. На етапі прототипу не було механізму деградації — впала одна, впали всі.

Пізніше я додав шар маршрутизації моделей: для кожного запиту встановлюється поріг таймауту, при перевищенні автоматично перемикаємось на запасну модель і одночасно записуємо лог перемикання. Тут важливо: перемикання не можна робити бездумним повторенням — потрібно розрізняти мережевий таймаут і блокування модерацією вмісту; перший можна перемикати, другий — марно. Цінність маршрутизації великих моделей саме в цьому: перетворити доступність з однієї точки на багато точок. У нашому проєкті ми використовували подібну перевірку з плануванням SiliconFlow, автоматично обираючи модель за типом завдання, і ланцюжок деградації за таймаутом працював досить стабільно.

Моніторинг витрат: як агрегувати споживання Token

Найнесподіванішою витратою за тиждень виявилися Token. Чотири моделі паралельно проганялися в тестах, щоденний обсяг викликів був невеликий, але через відсутність агрегації при звірці в кінці місяця виявилося, що споживання однієї платформи втричі перевищує оцінку. Причина в тому, що при потоковому виведенні на багатьох платформах поле usage у відповіді порожнє, і доводиться самому оцінювати за символами, а оцінка неточна.

Мій підхід — уніфікований облік на рівні шлюзу: кожен виклик записує назву моделі, вхідні та вихідні Token, час виконання, чи була деградація — все в одну таблицю. За моделі оплати за обсягом цей облік потрібно вести самостійно, не можна повністю покладатися на бекенд платформи. При порівнянні цін API також слід звертати увагу: якщо в моделі з низькою ціною складні правила тарифікації вихідних Token, фактична вартість може виявитися вищою.

Одним реченням: суть прототипу для порівняння кількох моделей не в тому, щоб налагодити якусь одну модель, а в тому, щоб зробити інтеграцію, потокову передачу, деградацію та облік — ці чотири речі — уніфікованим шаром. Якщо хочете глибше розібратися у виборі модельного шлюзу, можете ще переглянути матеріали щодо агрегації API.

Автор: Чжоу Мінчже

Дата публікації: 6 жовтня 2026 року