Хотя экосистема LLM в основном ориентирована на Python, мы нашли Go исключительно подходящим для производственных развертываний. Наша инфраструктура на базе Go Хотя экосистема LLM в основном ориентирована на Python, мы нашли Go исключительно подходящим для производственных развертываний. Наша инфраструктура на базе Go

[Перевод] Масштабирование LLM с помощью Golang: как мы обслуживаем миллионы запросов LLM

Хотя экосистема LLM в основном ориентирована на Python, мы нашли Go исключительно подходящим для производственных развертываний. Наша инфраструктура на базе Go обрабатывает миллионы ежемесячных запросов LLM с минимальной настройкой производительности. Помимо хорошо документированных преимуществ Go (см. отличное изложение Роба Пайка о преимуществах Go), три возможности оказались особенно ценными для нагрузок LLM: статическая проверка типов для обработки выходных данных модели, горутины для управления параллельными вызовами API и интерфейсы для построения составных конвейеров ответов. Вот как мы реализовали каждую из них в нашем производственном стеке.

Типобезопасность и структурированные выходы

Одной из основных проблем с LLM является обработка их неструктурированных выходных данных. Поддержка структурированных выходных данных OpenAI стала значительным продвижением для нас, и система типов Go делает её особенно элегантной для реализации. Вместо написания отдельных определений схемы, мы можем использовать теги структур Go и рефлексию для генерации четко определенных схем. Вот пример, где мы автоматически конвертируем SupportResponse в формат JSON-схемы OpenAI с использованием библиотеки go-openai:

import ( "github.com/sashabaranov/go-openai" "github.com/sashabaranov/go-openai/jsonschema" ) type SupportResponse struct { Answer string `json:"answer"` RelatedDocs []string `json:"related_docs"` } func GetSupportResponse(messages []openai.ChatCompletionMessage) (*SupportResponse, error) { var supportResponse SupportResponse schema, err := jsonschema.GenerateSchemaForType(supportResponse) if err != nil { return nil, err } resp, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{ Messages: messages, ResponseFormat: &openai.ChatCompletionResponseFormat{ Type: openai.ChatCompletionResponseFormatTypeJSONSchema, JSONSchema: &openai.ChatCompletionResponseFormatJSONSchema{ Name: "support_response", Schema: schema, Strict: true, }, }, }) if err != nil { return nil, err } err = schema.Unmarshal(resp.Choices[0].Message.Content, &supportResponse) if err != nil { return nil, err } return &supportResponse, nil }

Вышеприведенный код предоставит нам Answer и RelatedDocs, заполненные непосредственно из вызова LLM. Теперь SupportResponse можно легко передать на наш фронтенд или сохранить в нашей базе данных.

Обратите внимание, что поскольку у Golang есть встроенная система типов, вам не нужно тратить дополнительное время на определение структуры объекта (как вы бы сделали в Python) - она уже доступна через рефлексию, и вы можете потратить больше времени на промптинг, входы и выходы LLM.

Параллельная обработка и задержка

Приложения LLM часто требуют параллельных вызовов API и сложной оркестрации. Горутины и каналы Go делают это удивительно просто.

Например, предположим, мы запускаем конвейер Retrieval Augmented Generation (RAG) и хотим выполнить гибридный поиск по трем различным поисковым бэкендам (см. нашу статью о Лучших результатах RAG с помощью Reciprocal Rank Fusion и гибридного поиска). Запуск этих поисков последовательно добавил бы их индивидуальные задержки, что привело бы к более медленным ответам. С Go мы можем относительно легко распараллелить поиски по нескольким бэкендам:

func ParallelSearch(query string) []SearchResult { ctx, cancel := context.WithTimeout(context.Background(), 750*time.Millisecond) defer cancel() resultsChan := make(chan []SearchResult, len(backends)) var wg sync.WaitGroup for _, backend := range backends { wg.Add(1) go func(backend func(string) ([]SearchResult, error)) { defer wg.Done() results, err := backend(query) if err != nil { return } select { case resultsChan <- results: case <-ctx.Done(): } }(backend) } wg.Wait() close(resultsChan) var combined []SearchResult for res := range resultsChan { combined = append(combined, res...) } return combined }

Этот паттерн снижает нашу общую задержку до задержки самого медленного бэкенда, с настраиваемым таймаутом для предотвращения блокировки всей системы одним медленным бэкендом. Результаты собираются через канал Go и объединяются после завершения всех горутин или истечения времени.

Конвейер обработки ответов

Выходные данные LLM часто нуждаются в нескольких преобразованиях перед тем, как они готовы для конечных пользователей. Например, если вы используете провайдера LLM с отличными способностями к рассуждению, но еще не имеющего структурированных выходных данных (например, Claude 3.5 Sonnet), вам, вероятно, захочется структурировать выходные данные в вашем промпте и разобрать выходные данные перед передачей конечному пользователю.

Мы построили составной конвейер, который делает эти преобразования как поддерживаемыми, так и тестируемыми:

type ResponseCleaner interface { Clean(context.Context, string) (string, []ResponseDetails, error) } type ResponseDetails struct { DetailType string `json:"detail_type"` Content interface{} `json:"content"` }

Каждый очиститель является дискретной единицей, которая обрабатывает одно конкретное преобразование. Это разделение ответственности делает тестирование простым и позволяет нам модифицировать индивидуальные преобразования без касания остальной части конвейера. Вот как мы обрабатываем цитирование источников:

type CitedSourceCleaner struct{} func (c CitedSourceCleaner) Clean(ctx context.Context, message string) (string, []ResponseDetails, error) { sourceRegex := regexp.MustCompile(`\[(Source|Ref):\s*([^\]]+)\]`) var citations []ResponseDetails matches := sourceRegex.FindAllStringSubmatch(message, -1) for i, match := range matches { citations = append(citations, ResponseDetails{ DetailType: "citation", Content: map[string]interface{}{ "number": i + 1, "source": match[2], }, }) message = strings.Replace(message, match[0], fmt.Sprintf("[%d]", i+1), 1) } return message, citations, nil }

Используя вышеприведенный очиститель, когда LLM отвечает:

Очиститель проанализирует источники и передаст их на фронтенд как детали ответа. Он также преобразует сырые выходные данные LLM в:

Дополнение Python

В то время как Go питает нашу производственную инфраструктуру, Python остается необходимым для экспериментов с ML и быстрого прототипирования. Экосистема Python превосходна в задачах вроде:

  • Кластеризация тикетов поддержки с scikit-learn (например, с AgglomerativeClustering)

  • Тонкая настройка LLM с transformers (особенно открытыми исходными моделями вроде Llama), особенно для кастомизации моделей на наших данных поддержки

  • Прототипирование RAG с sentence-transformers для тестирования моделей эмбеддингов и стратегий чанкинга

Эти задачи были бы значительно более сложными в Go, где ML-библиотеки либо не существуют, либо гораздо менее зрелые.

Чтобы преодолеть разрыв между Go и Python, мы поддерживаем легковесный Python-сервис, который наша Go-инфраструктура вызывает. Этот сервис обрабатывает вычислительно интенсивные ML-задачи (такие как генерация эмбеддингов или кластеризация), сохраняя нашу основную инфраструктуру на Go. На практике мы часто прототипируем фичи полностью на Python, затем постепенно портируем критически важные для производительности компоненты на Go после их доказательства. Этот подход позволяет нам поставлять улучшения инкрементально без ожидания полной Go-реализации.

Заключение

Сильные стороны Go в типобезопасности, параллелизме и построении интерфейсов сделали его отличным выбором для нашей LLM-инфраструктуры. В то время как Python остается нашим языком выбора для ML-разработки, Go предоставляет производительность и надежность, необходимые нам в продакшене. Комбинация обоих языков позволяет нам двигаться быстро, сохраняя надежную, масштабируемую систему.

Источник

Возможности рынка
Логотип Large Language Model
Large Language Model Курс (LLM)
$0.0003379
$0.0003379$0.0003379
-3.04%
USD
График цены Large Language Model (LLM) в реальном времени
Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу service@support.mexc.com для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.

Вам также может быть интересно

Botanix запускает stBTC для обеспечения нативной доходности Биткоина

Botanix запускает stBTC для обеспечения нативной доходности Биткоина

Пост Botanix запускает stBTC для обеспечения нативной доходности Биткоина появился на BitcoinEthereumNews.com. Botanix Labs запустила stBTC, токен для ликвидного стейкинга, разработанный для превращения Биткоина в актив, приносящий доходность, путем перераспределения сетевых комиссий за газ непосредственно пользователям. Протокол начнет накопление доходности позже на этой неделе, а его Genesis Vault планируется открыть 25 сентября с ограничением в 50 BTC. Эта инициатива является одной из первых попыток генерировать нативную доходность Биткоина без опоры на инфляционные модели токенов или централизованных хранителей. stBTC работает, позволяя пользователям депонировать Биткоин в смарт контракт Botanix без разрешений, получая токены stBTC, которые представляют их долю в стейкинг-хранилище. По мере совершения транзакций 50% сетевых комиссий за газ Botanix, оплачиваемых в BTC, возвращаются держателям stBTC. Со временем стоимость stBTC увеличивается относительно BTC, позволяя пользователям получать свой первоначальный депозит плюс доходность. Botanix оценивает, что ранняя доходность может достигать 20-50% годовых, прежде чем стабилизироваться на уровне около 6-8%, что аналогично стейкингу Ethereum, но полностью деноминировано в Биткоине. Botanix сообщает, что проверки безопасности были завершены компаниями Spearbit и Sigma Prime, а протокол построен на стандарте хранилища EIP-4626, который также лежит в основе продуктов для стейкинга на базе Ethereum. Архитектура Spiderchain компании, управляемая 16 независимыми организациями, включая Galaxy, Alchemy и Fireblocks, обеспечивает безопасность сети. Если внедрение будет расти, Botanix утверждает, что система может сделать Биткоин продуктивным, компонуемым активом для децентрализованных финансов, одновременно укрепляя консенсус сети. Это развивающаяся история. Эта статья была создана с помощью ИИ и проверена редактором Джеффри Альбусом перед публикацией. Получайте новости на свою электронную почту. Изучите информационные бюллетени Blockworks: Источник: https://blockworks.co/news/botanix-launches-stbtc
Поделиться
BitcoinEthereumNews2025/09/18 02:37
Торговая сделка ЕС с США не привела к увеличению расходов на импорт энергоносителей

Торговая сделка ЕС с США не привела к увеличению расходов на импорт энергоносителей

ЕС сообщил президенту Дональду Трампу, что потратит 750 миллиардов $ на американскую энергию в течение следующих трех лет. Это обязательство было четко заявлено обеими сторонами
Поделиться
Cryptopolitan2025/12/25 08:22
SEI удерживает поддержку $ 0,106: быки нацелены на потенциальный прорыв к $ 0,115

SEI удерживает поддержку $ 0,106: быки нацелены на потенциальный прорыв к $ 0,115

Circle, Tether, PayPal и Revolut создают новую капитальную структуру на блокчейне Sei Chain, переопределяют цифровую валюту, платежи и расчеты, и формируют будущее
Поделиться
Tronweekly2025/12/25 07:00