Package: gigaserve
GigaServe 🦜️🏓 = LangServe + GigaChatGigaServe — это python-библиотека, которая позволяет размещать цепочки и runnable-интерфейсы GigaChain с предоставлением к ним доступа через REST API.Библиотека GigaServe интегрирована сFastAPIи использует для валидации данныхPydantic.Особенности библиотекиБиблиотека дает следующие возможности:Автоматическое определение схем ввода и вывода основе объекта GigaChain. Схемы применяются для каждого запроса к API и обеспечивают подробные сообщения об ошибках.Страница API-документации с JSONSchema и Swagger.Эндпоинты с поддержкой множества одновременных запросов на одном сервере/invoke,/batchи/stream.Эндпоинт/stream_logдля потоковой передачи всех или выбранных промежуточных шагов работы цепочки/агента.Интерактивная песочница/playgroundс потоковым отображением и демонстрацией промежуточных шагов.Использование проверенных open-source библиотек Python таких, как FastAPI, Pydantic, uvloop и asyncio.Клиентский SDK, который позволяет обращаться к серверу GigaServe также как к локальному runnable-интерфейсу или напрямую с помощью HTTP API.ОграниченияКолбэки клиента не поддерживаются для событий, происходящих на сервере.OpenAPI-спецификация не генерируется, если вы используете Pydantic V2. Это связанно с тем, что Fast API не поддерживаетсмешивание пространств имен pydantic v1 и v2. Подробнее в разделе ниже.Установка {#ustanovka}Для одновременной установки клиента и сервера используйте команду:pipinstall"gigaserve[all]"Вы можете установить клиент и сервер по отдельности с помощью команд:# Команда установки клиентаpipinstall"gigaserve[client]"# Команда установки сервераpipgigaserve"langserve[server]"GigaChain CLI 🛠️GigaChain CLI — это утилита, которая поможет быстро настроить проект GigaServe. Для этого используйте следующую команду:gigachainappnew../path/to/directoryПри работе с GigaChain CLI всегда используйте последнюю версию утилиты. Вы можете установить ее с помощью команды:pipinstall-Ugigachain-cliПримерыДля быстрого старта GigaServe используйтешаблоны GigaChain.Больше примеров шаблонов вы найдете врепозитории.СерверПример ниже разворачивает чат-модели GigaChat и других LLM, а также цепочку, которая генерирует шутку по заданной теме (topic) с помощью модели Anthropic.#!/usr/bin/env pythonfromfastapiimportFastAPIfromlangchain.promptsimportChatPromptTemplatefromlangchain.chat_modelsimportGigaChat,ChatAnthropic,ChatOpenAIfromlangserveimportadd_routesapp=FastAPI(title="GigaChain Server",version="1.0",description="Простой API-сервер, использующий runnable-интерфейсы GigaChain",)add_routes(app,GigaChat(credentials=<авторизационныеданные>),path="/gigachat",)add_routes(app,ChatOpenAI(),path="/openai",)add_routes(app,ChatAnthropic(),path="/anthropic",)model=ChatAnthropic()prompt=ChatPromptTemplate.from_template("расскажи шутку о{topic}")add_routes(app,prompt|model,path="/joke",)if__name__=="__main__":importuvicornuvicorn.run(app,host="localhost",port=8000)ДокументацияСгенерированная OpenAPI-документация к серверу, развернутому с помощью предыдущего примера, доступна по адресу:curllocalhost:8000/docsПри этом, адресlocalhost:8000будет возвращать ошибку 404, пока вы не определите@app.get("/").[!NOTE]
При использовании pydantic v2документация не генерируетсядля эндпоинтов/invoke,/batch,/streamиstream_log.КлиентПример клиента на основе Python SDK:fromlangchain.schemaimportSystemMessage,HumanMessagefromlangchain.promptsimportChatPromptTemplatefromlangchain.schema.runnableimportRunnableMapfromlangserveimportRemoteRunnableopenai=RemoteRunnable("http://localhost:8000/openai/")anthropic=RemoteRunnable("http://localhost:8000/anthropic/")joke_chain=RemoteRunnable("http://localhost:8000/joke/")# Синхронный вызовjoke_chain.invoke({"topic":"попугаи"})# Асинхронный вызовawaitjoke_chain.ainvoke({"topic":"попугаи"})prompt=[SystemMessage(content='Веди себя как кошка или попугай.'),HumanMessage(content='Привет!')]# Поддержка astreamasyncformsginanthropic.astream(prompt):print(msg,end="",flush=True)prompt=ChatPromptTemplate.from_messages([("system","Расскажи мне длинную историю о{topic}")])# Определение собственных цепочекchain=prompt|RunnableMap({"openai":openai,"anthropic":anthropic,})chain.batch([{"topic":"попугаи"},{"topic":"кошки"}])Пример клиента на TypeScript (для работы клиента требуется LangChain.js версии 0.0.166 или выше):import{RemoteRunnable}from"langchain/runnables/remote";constchain=newRemoteRunnable({url:`http://localhost:8000/joke/`,});constresult=awaitchain.invoke({topic:"кошки",});Клиент, использующий Python-библиотекуrequests:importrequestsresponse=requests.post("http://localhost:8000/joke/invoke/",json={'input':{'topic':'кошки'}})response.json()Использование cURL:curl--location--requestPOST'http://localhost:8000/joke/invoke'\--header'Content-Type: application/json'\--data-raw'{"input": {"topic": "кошки"}}'ЭндпоинтыС помощью примера ниже вы можете добавить на сервер заранее подготовленные эндпоинты для работы с runnable-интерфейсами:...add_routes(app,runnable,path="/my_runnable",)Список эндпоинтов:POST /my_runnable/invoke— вызвать runnable-интерфейс для единичных входных данных;POST /my_runnable/batch— вызвать runnable-интерфейс для набора входных данных;POST /my_runnable/stream— вызвать для единичных входных данных с потоковым выводом;POST /my_runnable/stream_log— вызвать для единичных входных данных с потоковым выводом, включая вывод промежуточных шагов по ходу генерации;GET /my_runnable/input_schema— получить JSON-схему входных данных runnable-интерфейса;GET /my_runnable/output_schema— получить JSON-схему выходных данных runnable-интерфейса;GET /my_runnable/config_schema— получить JSON-схему параметров конфигурации runnable-интерфейса;[!NOTE]
Эндпоинты работают в соответствии сLangChain Expression Language interface (LCEL)— DSL для создания цепочек.ПесочницаСтраница песочницы доступна по адресу/my_runnable/playground.
На ней представлен простой интерфейс, который позволяет настроить параметры runnable-интерфейса и сделать запрос к нему с потоковым выводом и демонстрацией промежуточных шагов.ВиджетыПесочница поддерживаетвиджетыи может использоваться для тестирования ваших цепочек с разными входными данными.Кроме этого, если цепочка может настраиваться, песочница предоставляет задать параметры цепочки и поделиться ссылкой на полученную конфигурацию.Обмен конфигурацией цепочкиIn addition, for configurable runnables, the playground will allow you to configure the
runnable and share a link with the configuration:Работа с классическими цепочкамиGigaServe работает как с runnable-интерфейсами (написанным с помощьюLangChain Expression Language), так и с классическими цепочками (посредством наследования отChain).При работе с классическими цепочками учитывайте, что некоторые входные схемы для таких цепочек могут вызывать ошибки, т.к. могут быть некорректными или неполными.
Такие ошибки можно предотвратить, если обновить атрибутinput_schemaтаких цепочек в GigaChain.РазвертываниеНиже описаны способы развертывания на Google Cloud Platforms (GCP) и Azure.Развертывание на GCPДля развертывания на GCP Cloud Run используйте команду:gcloudrundeploy[your-service-name]--source.--port8001--allow-unauthenticated--regionus-central1--set-env-vars=GIGACHAT_API_KEY=your_keyРазвертывание на AzureВы можете развернуть сервер на Azure с помощью Azure Container Apps:azcontainerappup--name[container-app-name]--source.--resource-group[resource-group-name]--environment[environment-name]--ingressexternal--target-port8001--env-vars=OPENAI_API_KEY=your_keyПодробная информация вофициальной документации.Работа с PydanticGigaServe поддерживает Pydantic v2 с некоторыми ограничениями:При использовании Pydantic v2 документация OpenAPI не генерируется. Это связанно с тем, что Fast API не поддерживаетсмешивание пространств имен pydantic v1 и v2.GigaChain использует пространство имен версии v1 в Pydantic v2.За исключением указанных ограничений, эндпоинты API, страница песочницы и другие функции должны работать корректно.Дополнительные возможностиДобавление аутентификацииО том, как добавить аутентификацию на свой сервер GigaServe — в разделах документации FastAPI, посвященныхбезопасностиииспользованию связующего ПО.Работа с файламиОбработка файлов — это типичная задача для больших языковых моделей.
Существуют различные архитектурные подходы для решения этой задачи:Файл может быть загружен на сервер с помощью одного эндпоинта и обработан с помощью другого;Файл может быть представлен как в виде бинарного значения, так и в виде ссылки, например, на содержимое файла, размещенное в хранилище s3.Эндпоинт может быть блокирующим или неблокирующим.Сложную обработку можно выделить в отдельный пул процессов.Выбирайте подход в соответствии со своими задачами.[!NOTE]
GigaServe не поддерживает типmultipart/form-data.
Для загрузки бинарного значения файла в runnable-интерфейс используйте кодировку base64.Пример загрузки файла закодированного с помощью base64.Вы также можете загружать файлы с помощью ссылок (например, в хранилище s3) или загружать их на отдельный эндпоинт какmultipart/form-data.Настраиваемые типы входных и выходных данныхТипы входных и выходных данных определяются для всех runnable-интерфейсов. Они доступны в аттрибутахinput_schemaиoutput_schema. GigaServe использует эти типы для валидации данных и генерации документации.Вы можете переопределить наследованные типы с помощью методаwith_types.Общий пример работы с типами:fromtypingimportAnyfromfastapiimportFastAPIfromlangchain.schema.runnableimportRunnableLambdaapp=FastAPI()deffunc(x:Any)->int:"""Ошибочно заданная функция, которая принимает любые данные, хотя должна принимать int."""returnx+1runnable=RunnableLambda(func).with_types(input_schema=int,)add_routes(app,runnable)Пользовательские типыДля десериализации данных в pydantic-модель, а неdict, унаследуйтесь отCustomUserType.
При наследовании от этого типа сервер не будет преобразовывать данные вdict, а будет сохранять их как pydantic-модель.fromfastapiimportFastAPIfromlangchain.schema.runnableimportRunnableLambdafromlangserveimportadd_routesfromlangserve.schemaimportCustomUserTypeapp=FastAPI()classFoo(CustomUserType):bar:intdeffunc(foo:Foo)->int:"""Пример функции, которая ожидает тип Foo, представленный в виде моде pydantic model"""assertisinstance(foo,Foo)returnfoo.bar# Обратите внимание, что входные и выходные типы наследуются автоматически!# Вам не нужно их указывать# runnable = RunnableLambda(func).with_types( # <-- Не нужно в данном случае#     input_schema=Foo,#     output_schema=int,#add_routes(app,RunnableLambda(func),path="/foo")[!NOTE]
ТипCustomUserTypeподдерживается только на стороне сервера и определяет поведение при декодировании данных.Виджеты интерактивной страницыНа странице песочницы вы можете создавать различные виджеты, демонстрирующие работу runnable-интерфейсов вашего бекенда.Виджет задается на уровне поля и поставляется как часть JSON-схемы вводного типа.Виджет должен содержать ключtype, значением которого является один из известного списка виджетов.Другие ключи виджета будут связаны со значениями, описывающими пути в JSON-объекте.Общая схема:typeJsonPath=number|string|(number|string)[];typeNameSpacedPath={title:string;path:JsonPath};// title используется для имитации JSON-схемы, но можно использовать namespacetypeOneOfPath={oneOf:JsonPath[]};typeWidget={type:string// Какой-то хорошо известный тип, например, base64file, chat и др.[key:string]:JsonPath|NameSpacedPath|OneOfPath;};Виджет загрузки файлаВиджет позволяет загружать файлы в интерфейсе песочницы. Работает для файлов в виде base64-строки.Фрагмент примера:try:frompydantic.v1importFieldexceptImportError:frompydanticimportFieldfromlangserveimportCustomUserType# ВНИМАНИЕ: Наследуйтесь от CustomUserType, а не от BaseModel. В противном случае#            сервер декодирует данные в dict, а не модель pydantic.classFileProcessingRequest(CustomUserType):"""Request including a base64 encoded file."""# Дополнительное поле используется, чтобы задать виджет в интерфейсе интерактивной страницы.file:str=Field(...,extra={"widget":{"type":"base64file"}})num_chars:int=100[!NOTE]Подробный пример загрузки файла.Виджет чата {#vidzhet-chata}Пример виджета врепозитории.Чтобы задать виджет чата передайте"type": "chat":Полеinput— JSONPath к полю запроса, которое содержит новое входящее сообщение.Полеoutput— JSONPath к полю ответа, которое содержит одно или несколько сообщений.Не указывайте эти поля, если входящие и исходящие данные должны быть представлены в исходном виде.
Например, если нужно представить исходящие данные в виде списка сообщений.Пример:classChatHistory(CustomUserType):chat_history:List[Tuple[str,str]]=Field(...,examples=[[("human input","ai response")]],extra={"widget":{"type":"chat","input":"question","output":"answer"}},)question:strdef_format_to_messages(input:ChatHistory)->List[BaseMessage]:"""Представление вводда в виде списка собщений."""history=input.chat_historyuser_input=input.questionmessages=[]forhuman,aiinhistory:messages.append(HumanMessage(content=human))messages.append(AIMessage(content=ai))messages.append(HumanMessage(content=user_input))returnmessagesmodel=ChatOpenAI()chat_model=RunnableParallel({"answer":(RunnableLambda(_format_to_messages)|model)})add_routes(app,chat_model.with_types(input_type=ChatHistory),config_keys=["configurable"],path="/chat",)Включение и отключение эндпоинтов {#vklyuchenie-i-otklyuchenie-endpointov}Начиная с версии GigaServe 0.0.33, можно включать и отключать открытые эндпоинты.
Используйте атрибутenabled_endpoints, если вы хотите предотвратить перезапись эндпонтов при обновлении версии библиотеки.Пример ниже включает варианты эндпоинтовinvoke,batchиconfig_hash.add_routes(app,chain,enabled_endpoints=["invoke","batch","config_hashes"])Пример ниже отключает страницу песочницы для цепочки.add_routes(app,chain,disabled_endpoints=["playground"])БезопасностьВ версиях библиотеки 0.0.13—0.0.15 песочница, доступная по адресу/playground, позволяет получить доступ к произвольным файлам на сервере. Такое поведениеисправлено в версии библиотеки 0.0.16 и выше.