Model Bahasa Besar (LLM) ada di mana-mana, dari aplikasi sehari-hari kepada alat canggih. Menggunakannya mudah. Tetapi bagaimana jika anda perlu menjalankan model anda sendiri? Sama ada anda mempunyai satu yang disesuaikan dengan baik atau berurusan dengan data yang sensitif kepada privasi, kerumitan meningkat. Dalam post ini, kami akan berkongsi apa yang kami pelajari semasa membina sistem inferensi LLM kami sendiri. Kami akan meliputi penyimpanan dan pengenalan model, reka bentuk seni bina perkhidmatan, dan menyelesaikan isu-isu dunia sebenar seperti routing, streaming, dan menguruskan perkhidmatan mikro. Proses ini melibatkan cabaran, tetapi pada akhirnya, kami membina sistem yang boleh dipercayai dan mengumpulkan pelajaran yang layak dikongsi. Pengenalan LLM memberi kuasa kepada pelbagai aplikasi - dari chatbots dan agen aliran kerja kepada alat automasi pintar. manakala pengeluaran yang diperluaskan, panggilan alat, dan protokol multi-agent adalah penting, mereka beroperasi pada tahap di atas enjin teras: LLM asas. Ramai projek bergantung kepada pembekal luar, seperti daripada atau , yang mencukupi untuk kebanyakan kes penggunaan. Tetapi untuk aplikasi tertentu, ia dengan cepat menjadi masalah. Bagaimana jika pembekal berhenti? Bagaimana jika anda memerlukan kawalan penuh mengenai latency, harga, atau uptime? Yang paling penting - bagaimana jika anda peduli tentang privasi dan tidak mampu menghantar data pengguna kepada pihak ketiga? Pembukaan Gemini Antropologi Pembukaan Gemini Antropologi Itulah di mana self-hosting menjadi penting. Melayani model pra-latih atau disesuaikan dengan baik menyediakan kawalan, keselamatan, dan keupayaan untuk menyesuaikan model untuk keperluan perniagaan tertentu. Membina sistem sedemikian tidak memerlukan pasukan yang besar atau sumber-sumber yang meluas. Kami membina dengan bajet yang rendah, pasukan kecil, dan hanya beberapa nod. Pembatasan ini mempengaruhi keputusan arsitektur kami, memerlukan kami untuk memberi tumpuan kepada praktikaliti dan kecekapan. Gambaran keseluruhan Ini adalah komponen teras yang membentuk tulang belakang sistem. Format dan Encoding. Bahasa yang dikongsi di antara perkhidmatan adalah penting.Ini bermakna format permintaan / tindak balas yang konsisten, skim parameter pengeluaran, struktur sejarah dialog, dan serialisasi yang berfungsi di mana-mana - dari frontend hingga backend hingga model runner. Streaming dan Routing. Mengendalikan pelbagai model, jenis permintaan, dan keutamaan tuan rumah memerlukan keputusan routing yang bijaksana. kami akan membincangkan bagaimana permintaan pengguna yang masuk diarahkan melalui sistem - dari titik masuk permulaan ke nod pekerja yang sesuai - dan bagaimana jawapan dihantar semula. Penyimpanan dan penyebaran model.Di mana model hidup, dan bagaimana mereka disiapkan untuk digunakan dalam pengeluaran? Kami akan membincangkan ujian utama untuk dilakukan, termasuk memastikan kebolehpercayaan model. Observability.Bagaimana anda tahu perkara-perkara berfungsi?Kami akan menunjukkan apa metrik yang kami tonton, bagaimana kami memantau kegagalan, dan sond yang kami gunakan untuk memastikan kesihatan sistem dan kebolehpercayaan. Skema dan Data Encoding Memilih skim yang betul untuk pemindahan data adalah penting. Format yang dikongsi di antara perkhidmatan menyederhanakan integrasi, mengurangkan kesilapan, dan meningkatkan penyesuaian.Kami bertujuan untuk mewujudkan sistem untuk berfungsi dengan lancar dengan kedua-dua model yang dihoskan sendiri dan pembekal luaran - tanpa mendedahkan perbezaan kepada pengguna. Mengapa Reka Bentuk Reka Bentuk Penting There’s no universal standard for LLM data exchange. Many providers follow schemas similar to Sementara yang lain - seperti atau - memperkenalkan perbezaan halus tetapi penting.Banyak penyedia ini menawarkan SDK yang bersesuaian dengan OpenAI yang mengekalkan skim yang sama, walaupun sering dengan batasan atau set ciri yang dikurangkan (contohnya, daripada Projek-projek lain seperti bertujuan untuk menyatukan variasi ini dengan membungkusnya ke dalam antara muka yang bersesuaian dengan OpenAI. OpenAI’s Claude Gemini Anthropic’s OpenAI-compatible SDK Layar Kompatibiliti OpenAI Gemini OpenRouter Pembukaan Klod Gemini Antropic OpenAI-kompatibel SDK Layar Kompatibiliti OpenAI Gemini OpenRouter Mengekalkan skim pembekal yang ditakrifkan terlebih dahulu mempunyai kelebihan: Anda mendapat API yang stabil dan teruji. Anda boleh bergantung kepada SDK dan alat yang sedia ada. Tetapi terdapat juga kelemahan sebenar: Ia mewujudkan vendor lock-in, menjadikannya lebih sukar untuk menyokong pelbagai pembekal. Ia membatasi fleksibiliti untuk memperluaskan skim dengan ciri-ciri tersuai yang diperlukan untuk keperluan perniagaan atau keperluan pasukan sains data. Anda terdedah kepada perubahan yang melanggar atau deprecations di luar kawalan anda. Skim-skim ini sering membawa sekatan warisan yang mengehadkan kawalan gandum halus. Untuk menyelesaikan masalah ini, kami telah memilih untuk menentukan - skim yang direka kira-kira keperluan kita, yang kemudian kita boleh memaparkan kepada pelbagai format luaran apabila perlu. own internal data model Reka bentuk skim dalaman Sebelum menangani cabaran, mari kita mendefinisikan masalah dan merangkumi harapan kita untuk penyelesaian: Konversi mudah kepada format yang diperlukan oleh pembekal luar dan sebaliknya. Sokongan penuh untuk ciri-ciri khusus kepada pasukan perniagaan dan sains data kami. Pastikan skim mudah diperluaskan untuk memenuhi keperluan masa depan. Kami mula dengan meninjau skim LLM utama untuk memahami bagaimana pembekal struktur mesej, parameter, dan output. umum di kebanyakan sistem, termasuk: core domain entities Mesej (contohnya prompt, sejarah) Parameter pengeluaran (contohnya, suhu, top_p, beam_search) Terdapat beberapa parameter, seperti daripada atau , sebagai spesifik kepada konfigurasi dalaman penyedia dan logik perniagaan. Elemen-elemen ini terletak di luar domain teras LLM dan bukan sebahagian daripada skim yang dikongsi. Sebaliknya, mereka diperlakukan sebagai ekstensi opsional. Apabila ciri-ciri menjadi diterima secara meluas atau diperlukan untuk interoperabiliti yang lebih luas, kami menilai mengintegrasikannya ke dalam skim teras. service_tier usage_metadata reasoning_mode Pada tahap yang tinggi, skim input kami terstruktur dengan komponen utama ini: Model – Digunakan sebagai kunci laluan, bertindak sebagai pengenal laluan, membolehkan sistem untuk mengarahkan permintaan kepada nod pekerja yang sesuai. Parameter Generasi – tetapan model teras (contohnya, suhu, top_p, max_tokens). Mesej – Sejarah perbualan dan payloads segera. Alat – Definisi alat yang boleh digunakan oleh model. Ini membawa kita kepada skim berikut, yang diwakili dalam a Ia menggambarkan struktur dan niat reka bentuk, walaupun beberapa butiran pelaksanaan diabaikan untuk kesederhanaan. Pydantic-like Pidantik seperti class ChatCompletionRequest(BaseModel): model: str # Routing key to select the appropriate model or service messages: list[Message] # Prompt and dialogue history generation_parameters: GenerationParameters # Core generation settings tools: list[Tool] # Optional tool defenitions class GenerationParameters(BaseModel): temperature: float top_p: float max_tokens: int beam_search: BeamSearchParams # Optional, non-core fields specific to certain providers provider_extensions: dict[str, Any] = {} ... # Other parameters Kami sengaja memindahkan parameter pengeluaran ke dalam medan yang berasingan daripada meletakkannya di peringkat akar. parameter (contohnya, suhu, top-p, tetapan model) dan Banyak pasukan dalam ekosistem kami menyimpan parameter konstan ini dalam sistem konfigurasi luaran, menjadikan pemisahan ini praktikal dan perlu. constant variabel Kami memasukkan medan tambahan yang dipanggil Di dalam parameter ini berbeza secara signifikan di antara pembekal LLM yang berbeza, pengesahan dan interpretasi bidang ini adalah komponen yang tahu bagaimana untuk berkomunikasi dengan pembekal model tertentu. dengan itu, kami mengelakkan penyambung laluan yang tidak perlu yang disebabkan oleh pengesahan data yang berlebihan di pelbagai perkhidmatan. provider_extensions GenerationParameters delegated to the final module that handles model inference Untuk memastikan keserasian balik, ciri-ciri skim output baru diperkenalkan sebagai dalam skim permintaan. medan ini bertindak sebagai bendera ciri – pengguna mesti menetapkan mereka untuk memilih dalam tingkah laku tertentu. Pendekatan ini mengekalkan skim teras yang stabil sambil membolehkan evolusi bertambah. Sebagai contoh, jejak alasan hanya akan dimasukkan ke dalam output jika medan yang sesuai ditetapkan dalam permintaan. explicit, optional fields Skim ini dikekalkan dalam pustaka Python yang dikongsi dan digunakan di antara perkhidmatan untuk memastikan pemprosesan permintaan dan tindak balas yang konsisten. Bekerja dengan pembekal pihak ketiga Kami mula dengan menggambarkan bagaimana kami membina platform kami sendiri – jadi mengapa bimbang dengan keserasian di antara pembekal luaran? Pengeluaran data sintetik untuk prototipe dan eksperimen oleh pasukan sains data kami. Tugas-tujuan umum di mana sesetengah model proprietary melakukan lebih baik daripada kotak. Kes penggunaan yang tidak sensitif di mana privasi, latensi, atau kawalan infrastruktur kurang kritikal. Aliran komunikasi keseluruhan dengan pembekal luaran boleh disimpulkan seperti berikut: Proses ini melibatkan langkah-langkah berikut: Khidmat LLM-Gateway khas yang bertanggungjawab untuk komunikasi dengan pembekal menerima permintaan pengguna dalam format skim kami. Permintaan ditukar kepada format khusus pembekal, termasuk apa-apa penyampaian. Pembekal luar memproses permintaan dan mengembalikan jawapan. Perkhidmatan LLM-Gateway menerima jawapan dan memaparkannya kembali ke dalam skim tindak balas standard kami. Ini adalah skim peringkat tinggi yang merangkumi beberapa microservices individu. rincian tentang komponen tertentu dan format respons streaming akan dibahas dalam seksyen berikut. Format Streaming Jawapan LLM dihasilkan secara beransur-ansur - token oleh token - dan kemudian dikumpulkan ke dalam for efficient transmission. From the user’s perspective, whether through a browser, mobile app, or terminal, the experience must remain Ini memerlukan mekanisme pengangkutan yang menyokong . chunks fluid and responsive low-latency, real-time streaming Terdapat dua pilihan utama untuk mencapai ini: : A full-duplex communication channel that allows continuous two-way interaction between client and server. WebSockets : A unidirectional, HTTP-based streaming protocol that is widely used for real-time updates. Peristiwa yang dihantar oleh pelayan (SSE) WebSoket WebSoket Peristiwa yang dihantar oleh pelayan (SSE) Peristiwa yang dihantar oleh pelayan (SSE) Mengapa SSE di atas WebSockets? Walaupun kedua-dua pilihan ini boleh dilaksanakan, — terutamanya untuk OpenAI-kompatibel API dan sistem serupa. Ini disebabkan oleh beberapa kelebihan praktikal: SSE is the more commonly used solution for standard LLM inference Kesederhanaan: SSE berjalan di atas HTTP standard, tidak memerlukan kemas kini khas atau negosiasi. Kompatibiliti: Ia berfungsi secara semula jadi dalam semua pelayar utama tanpa pustaka tambahan. Aliran Unidirectional: Kebanyakan respons LLM hanya mengalir dari pelayan kepada pelanggan, yang selaras dengan reka bentuk SSE. Proxy-Friendliness: SSE bermain dengan baik dengan infrastruktur HTTP standard, termasuk proxy terbalik. upgrades or negotiation Oleh kerana manfaat ini, . SSE is typically chosen for text-only, prompt-response streaming use cases Walau bagaimanapun, sesetengah kes penggunaan yang muncul memerlukan komunikasi yang lebih kaya, latensi rendah, dua arah - seperti transkripsi masa nyata atau interaksi ucapan-ke-bicara. Menyelesaikan keperluan ini dengan menggunakan (for server-to-server). These protocols are better suited for continuous multimodal input and output. OpenAI’s Realtime API WebSockets API Realtime daripada OpenAI Oleh kerana sistem ini hanya memberi tumpuan kepada Kami berpegang dengan untuk kesederhanaannya, kompatibiliti, dan penyesuaian dengan model streaming kami. text-based interactions SSE Response Stream Kandungan dengan yang dipilih sebagai lapisan pengangkutan, langkah seterusnya ialah untuk menentukan Streaming yang berkesan memerlukan lebih daripada sekadar teks mentah - ia perlu menyediakan untuk menyokong pengguna latar belakang seperti antara muka pengguna dan alat automatik. aliran mesti mengandungi maklumat berikut: SSE what structure, metadata, and context Metadata Header-Level: Maklumat pengenalan asas seperti ID permintaan. Hasil teras – token atau string yang dihasilkan oleh model – disampaikan secara beransur-ansur apabila urutan (n) disiarkan kembali, chunk-by-chunk. Setiap generasi boleh terdiri daripada pelbagai urutan (contohnya, n = 2, n = 4) .Sejarah ini dihasilkan secara berasingan dan disiarkan secara bersamaan, masing-masing dibahagikan ke dalam set sendiri kepingan beransur-ansur. Metadata penggunaan dan Token-Level. Ini termasuk bilangan token yang dihasilkan, data masa, dan diagnostik opsional seperti logprobs atau jejak alasan. Ini boleh digunakan untuk pengiraan, debugging, atau penilaian model. Selepas mendefinisikan struktur respons yang disiarkan, kami juga mempertimbangkan beberapa keperluan bukan fungsional yang penting untuk kebolehpercayaan dan evolusi masa depan. Reka bentuk stream kami dimaksudkan untuk: Terstruktur – membezakan antara jenis kandungan dan sempadan peristiwa. Extensible - mampu membawa metadata opsional tanpa memecahkan klien sedia ada. Robust - tahan terhadap data yang rosak, terlambat, atau sebahagian. Dalam banyak aplikasi, seperti atau - berbilang siri (penyempurnaan) dihasilkan secara paralel sebagai sebahagian daripada permintaan generasi tunggal. side-by-side comparison diverse sampling The most comprehensive format for streaming responses is defined in the Menurut spesifikasi, satu generasi chunk boleh mengandungi pelbagai urutan dalam Rujukan : OpenAI API reference choices OpenAI API rujukan Pilihan Rangkaian Senarai pilihan penyelesaian perbualan. boleh mengandungi lebih daripada satu elemen jika n lebih besar daripada 1. choices Rangkaian A list of chat completion choices. Can contain more than one element if n is greater than 1. Can also be empty for the last chunk. Walaupun, dalam amalan, potongan-potongan individu biasanya mengandungi hanya satu delta, format ini membolehkan beberapa kemas kini siri per potongan.Ia adalah penting untuk mempertimbangkan ini, kerana kemas kini masa depan mungkin menggunakan lebih luas keupayaan ini. is designed to support this structure. official Python SDK Perkhidmatan Python SDK We chose to follow the same structure to ensure compatibility with a wide range of potential features. The diagram below illustrates an example from our implementation, where a single generation consists of three sequences, streamed in six chunks over time: This chunk marks the beginning of the entire generation. It doesn’t contain any actual content but includes shared metadata, such as the generation ID, timestamp, and role (e.g., assistant, etc.). Chunk 1 — Generation Start. Two sequences begin streaming in parallel. Each is tagged with a unique identifier to distinguish it from others. Chunk 2 — Sequence Start (Green & Purple). The third sequence starts (blue), while the first two sequences (green and purple) stream incremental content via delta events. Chunk 3 — Sequence Start (Blue) & Sequence Delta. The green and blue sequences continue streaming deltas. The purple sequence finishes — this includes a structured finish_reason (like stop, length, etc.). Chunk 4 — Midstream Updates & Finish (Purple). Chunk 5 – Remaining Sequence Finishes. Kedua-dua urutan hijau dan biru selesai. siklus hayat setiap urutan kini tertutup sepenuhnya antara penanda permulaan dan akhir masing-masing. This chunk closes the generation and may include global usage statistics, final token counts, latency info, or other diagnostics. Chunk 6 — Generation Finish. Seperti yang anda lihat, untuk menjadikan aliran yang kukuh dan lebih mudah untuk disemak, kami memilih untuk , bukannya bergantung kepada mekanisme tersirat seperti cek null, EOF, atau token ajaib. pendekatan terstruktur ini menyederhanakan penapisan ke bawah, terutamanya dalam persekitaran di mana beberapa penyelesaian ditayangkan secara bersamaan, dan juga meningkatkan penyelesaian dan pengasingan ralat semasa pembangunan dan pemeriksaan runtime. explicitly signal Start and Finish events for both the overall generation and each individual sequence Selain itu, kami memperkenalkan satu tambahan chunk that carries structured information about failures. Some errors — such as malformed requests or authorization issues — can be surfaced directly via standard HTTP response codes. However, if an error occurs , kami mempunyai dua pilihan: sama ada menghentikan aliran HTTP secara tiba-tiba atau menghantar kejadian kesilapan SSE yang terbentuk dengan baik. Kami memilih yang terakhir. Menutup sambungan secara tiba-tiba membuat ia sukar bagi pelanggan untuk membezakan antara masalah rangkaian dan kegagalan model / perkhidmatan sebenar. Dengan menggunakan bahagian kesilapan khusus, kami membolehkan pengesanan dan penyebaran masalah yang lebih boleh dipercayai semasa streaming. Error during the generation process Perkhidmatan backend dan aliran permintaan Di tengah-tengah sistem terdapat satu titik kemasukan: . It handles basic concerns like authentication, usage tracking and quota enforcement, request formatting, and routing based on the specified model. While it may look like the Gateway carries a lot of responsibility, each task is intentionally simple and modular. For external providers, it adapts requests to their APIs and maps responses back into a unified format. For self-hosted models, requests are routed directly to internal systems using our own unified schema. This design allows seamless support for both external and internal models through a consistent interface. LLM-Gateway Model yang Self-Hosted As mentioned earlier, sesuai untuk streaming respons kepada pengguna akhir, tetapi ia bukan pilihan praktikal untuk . When a request arrives, it must be routed to a suitable worker node for model inference, and the result streamed back. While some systems handle this using chained HTTP proxies and header-based routing, in our experience, this approach becomes difficult to manage and evolve as the logic grows in complexity. Server-Sent Events (SSE) internal backend communication Infrastruktur dalaman kami perlu menyokong: Jadual yang menyedari keutamaan – Permintaan mungkin mempunyai tahap kecemasan yang berbeza (contohnya, interaktif berbanding batch), dan tugas-tugas yang mempunyai keutamaan tinggi mesti ditangani terlebih dahulu. — Certain nodes run on higher-performance GPUs and should be preferred; others serve as overflow capacity. Hardware-aware routing Dispatching spesifik model – Setiap pekerja dikonfigurasi untuk menyokong hanya satu subset model, berdasarkan keserasian perkakasan dan sekatan sumber. Untuk memenuhi keperluan ini, kami menggunakan untuk memisahkan routing tugas daripada penghantaran hasil. Reka bentuk ini menyediakan fleksibiliti dan ketahanan yang lebih baik di bawah keadaan beban dan routing yang berbeza. for this purpose, though other brokers could also be viable depending on your latency, throughput, and operational preferences. RabbitMQ was a natural fit given its maturity and alignment with our existing tooling. message broker kelinci kelinci kelinci Sekarang mari kita lihat lebih dekat bagaimana sistem ini dilaksanakan dalam amalan: We use , allowing us to route requests based on model compatibility and node capabilities. The process is as follows: dedicated queues per model Perkhidmatan LLM-Gateway (diwakili sebagai pengguna) memulakan permintaan HTTP untuk memicu tugas pengeluaran teks. Task Routing melalui perkhidmatan Scheduler Permintaan dikendalikan oleh Scheduler, yang memilih barisan yang sesuai (ditandai dengan hijau pada imej) berdasarkan model yang diminta dan melampirkan mesej kepada ia. Pekerja Memilih Tugas. Pekerja Inference yang sesuai (satu pekerja sahaja dipaparkan untuk kesederhanaan, tetapi terdapat banyak) yang mendaftar ke barisan mengambil tugas dan memulakan pemprosesan. The worker streams the response chunk-by-chunk into the , to which the . Streaming the Response. Response Queue Scheduler replica handling the request is subscribed Receiving Response Chunks. The Scheduler mendengarkan baris jawapan dan menerima bahagian jawapan apabila mereka tiba. SSE Streaming. bahagian-bahagian ditukar kepada format SSE dan disiarkan ke klien. To handle , kita elakkan mengecewakan broker mesej: large payloads Alih-alih membenamkan data input atau output yang besar secara langsung ke dalam tugas, kami memuat naikkannya ke kedai bersesuaian S3 luaran. Rujukan (seperti URL atau ID sumber) disertakan dalam metadata tugas, dan pekerja mendapatkan kandungan sebenar apabila diperlukan. Menerapkan Reka Bentuk Dengan RabbitMQ Apabila ia datang kepada , each ialah RabbitMQ biasa , dikhususkan untuk menangani satu model jenis. kami memerlukan , which can be achieved using Dalam seting ini, mesej dengan nilai keutamaan yang lebih tinggi dihantar dan diproses sebelum yang lebih rendah. , di mana mesej hendaklah diarahkan kepada nod yang paling berkesan yang tersedia terlebih dahulu, Pengguna yang mempunyai keutamaan yang lebih tinggi menerima mesej selagi mereka aktif; Pengguna yang mempunyai keutamaan yang lebih rendah hanya menerima mesej apabila yang mempunyai keutamaan yang lebih tinggi disekat atau tidak tersedia. routing and publishing messages Request Queue queue priority-aware scheduling message priorities hardware-aware routing Prioriti Pengguna queue Pesan Prioriti Prioriti Pengguna Jika kehilangan mesej tidak boleh diterima, berikut mesti ada: Penerbit mengesahkan untuk memastikan broker telah menerima dan menyimpan mesej. Barisan yang berterusan dan mesej yang berterusan supaya data bertahan semula. for stronger durability through replication. These also support . Keterangan Quorum Mesej yang disederhanakan dan keutamaan pengguna daripada RabbitMQ 4.0 Publisher confirms Penerbit mengesahkan Quorum queues Keterangan Quorum Mesej yang disederhanakan dan keutamaan pengguna daripada RabbitMQ 4.0 Setakat ini, kami telah meliputi bagaimana tugas diterbitkan - tetapi bagaimana Langkah pertama ialah memahami bagaimana work in RabbitMQ. The broker supports a concept called , yang terikat kepada sambungan tunggal dan dipadamkan secara automatik apabila sambungan itu ditutup. streamed response temporary queues Penghantaran eksklusif Penghantaran eksklusif Penghantaran eksklusif Kami mewujudkan , ensuring it’s automatically cleaned up when the replica shuts down. However, this introduces a challenge: while each service replica has a single RabbitMQ queue, it must handle . one exclusive queue per Scheduler service replica many requests in parallel Untuk menangani masalah ini, kami memperlakukan baris RabbitMQ sebagai , routing jawapan kepada replika Scheduler yang betul. Setiap permintaan pengguna ditugaskan kepada , yang dimasukkan ke dalam setiap jawapan. dalam Kami mengekalkan tambahan dengan barisan dalam memori jangka pendek – satu per permintaan aktif. barisan masuk disatukan dengan barisan ini berdasarkan pengenal dan dihantar mengikutnya. barisan dalam memori ini dibuang apabila permintaan selesai, manakala barisan RabbitMQ berterusan sepanjang hayat replika perkhidmatan. transport layer unique identifier Scheduler in-memory routing layer Schematically this looks as follows: Dispatcher pusat dalam Scheduler menghantar keping ke baris dalam memori yang sesuai, masing-masing dikendalikan oleh pengendali yang berdedikasi. Inferensi There are several mature frameworks available for efficient LLM inference, such as and . These systems are designed to dan menjana token respons dalam masa nyata, sering dengan ciri-ciri seperti batching berterusan dan pengoptimuman memori GPU. sebagai enjin inferensi teras, dengan beberapa modifikasi tersuai: Merdeka Sengketa process multiple sequences in parallel vLLM Merdeka Merdeka Sengketa Sengketa — to better suit our generation logic and support structured constraints. Custom beam search implementation Sokongan untuk skim output terstruktur - membolehkan model untuk mengembalikan output yang selaras dengan format khusus perniagaan. Through experience, we’ve learned that even minor library updates can - sama ada dalam kualiti output, determinisme, atau tingkah laku bersamaan. Oleh kerana ini, kami telah menubuhkan paip ujian yang kukuh: significantly alter model behavior Ujian tekanan untuk mendedahkan masalah concurrency, kebocoran ingatan, atau regresi kestabilan. to ensure consistent outputs for fixed seeds and parameter sets. Determinism testing Ujian grid parameter untuk meliputi pelbagai tetapan pengeluaran, tanpa melampau. Penyimpanan dan Penyebaran Most modern systems run in — either in the cloud or within Kubernetes (K8s). While this setup works well for typical backend services, it introduces challenges around Model LLM boleh , dan model baking menimbang terus ke dalam imej Docker - dengan cepat menjadi bermasalah: containerized environments model weight storage tens or even hundreds of gigabytes in size Pembinaan lambat - Walaupun dengan pembinaan pelbagai peringkat dan caching, memindahkan fail model yang besar semasa fasa pembinaan boleh meningkatkan masa CI secara dramatik. Penyebaran lambat – Setiap penyebaran memerlukan tarikan imej besar, yang boleh mengambil masa beberapa minit dan menyebabkan ketidakhadiran atau penundaan. Resource inefficiency – Baik registers Docker maupun node Kubernetes tidak dioptimumkan untuk menangani imej yang sangat besar, yang mengakibatkan penggunaan storan yang membengkak dan ketegangan bandwidth. Untuk menyelesaikan masalah ini, kami membahagikan from the Docker image lifecycle. Our models are stored in an , dan diambil sebelum perkhidmatan inference memulakan. untuk meningkatkan masa memulakan dan mengelakkan muat turun berlebihan, kami juga menggunakan to cache model weights on each node. model storage external S3-compatible object storage Jumlah persisten tempatan (PVCs) Jumlah persisten tempatan (PVCs) Jumlah persisten tempatan (PVCs) Observability A system like this — built on — requires to ensure reliability and performance at scale. streaming, message queues, and real-time token generation robust observability In addition to standard service-level metrics (CPU, memory, error rates, etc.), we found it essential to monitor the following: Kedalaman barisan, backlog mesej, dan bilangan pengguna - memantau bilangan mesej yang menunggu, saiz barisan semasa, dan bilangan pengguna aktif membantu mendeteksi hambatan pengedaran tugas dan ketidakseimbangan dalam penggunaan pekerja. — tracking the number of tokens or response chunks generated per second helps identify latency or throughput regressions. Token/chunk throughput Penjejakan didistribusikan – untuk menentukan di mana permintaan gagal atau terjejas di antara komponen (gateway, broker, pekerja, dan lain-lain). Pemeriksaan kesihatan enjin inferensi – kerana proses inferensi boleh jatuh dalam keadaan yang jarang berlaku (contohnya, input yang buruk atau nilai parameter yang ekstrem), pemantauan proaktif keluaran dan ketersediaan adalah penting. Pengenalan Distributed Distributed tracing Further Improvements Walaupun sistem kami telah bersedia untuk pengeluaran, masih terdapat cabaran dan peluang yang penting untuk pengoptimuman: Menggunakan KV-cache yang didistribusikan untuk meningkatkan prestasi inferensi. Supporting to conserve compute when outputs are no longer needed. request cancellation Mencipta paip penghantaran model yang mudah untuk pasukan sains data. Kesimpulan While building a reliable and provider-independent LLM serving system can seem complex at first, it doesn’t require reinventing the wheel. Each component — streaming via SSE, task distribution through message brokers, and inference handled by runtimes like vLLM — serves a clear purpose and is grounded in existing, well-supported tools. With the right structure in place, it’s possible to create a maintainable and adaptable setup that meets production requirements without unnecessary complexity. Dalam post seterusnya, kami akan meneroka topik yang lebih maju seperti KV-caching terdistribusi, mengendalikan pelbagai model di seluruh replika, dan aliran kerja pemasangan yang sesuai untuk pasukan berorientasikan ML. Penulis Tochka , Stanislav Shimovolos Stanislav Shimovolos Stanislav Shimovolos Tochka , Maksim Afanasyev Maksim Afanasyev Maxim Afanasyev Pengiktirafan Kerja-kerja yang dilakukan di Tochka Dmitry Kryukov Dmitry Kryukov Dmitry Kryukov