Компоненты
GigaChain предоставляет стандартные расширяемые интерфейсы и внешние интеграции для различных компонентов, полезных при работе с LLM. Одни компоненты реализованы в GigaChain, для некоторых используются сторонние интеграции, а какие-то применяют и то, и другое.
Чат-модели
Языковые модели, которые используют последовательность сообщений в качестве входных данных и возвращают чат-сообщения в качестве выходных данных (в отличие от использования обычного текста). Такой подход характерен для более новых моделей. Более старые модели это, как правило, LLM. Чат-модели поддерживают назначение различных ролей для сообщений, что помогает различать сообщения от ИИ, пользователей и инструкции, такие как системные сообщения.
Хотя базовые модели работают по принципу «сообщение на входе, сообщение на выходе», обертки GigaChain также позволяют этим моделям принимать строку в качестве входных данных. Это позволяет использовать чат-модели вместо LLM.
Когда строка передается в качестве входных данных, она преобразуется в HumanMessage, который затем передается базовой модели.
GigaChain не предоставляет ChatModel, а использует интеграции со сторонними сервисами.
При создании экземпляра ChatModel используется стандартный параметр:
model
— имя модели.
Объекты ChatModel также принимают другие параметры, специфичные для выбранной интеграции.
Так, при работе с GigaChat, вы можете передать параметры credentials
и scope
, которые содержат ключ авторизации и версию API, к которой нужно обратиться.
Некоторые чат-модели подготовлены для вызова инструментов и предоставляют для этого специальный API. Такие модели рекомендуется использовать, если ваши задачи требуют вызова инструментов. Подробности — в разделе Вызов инструментов.
LLM
Те языковые модели, которые в качестве входных данных принимают строку, на выходе также возвращают строку.
Хотя базовые модели работают по принципу «строка на входе, строка на выходе», обертки GigaChain также позволяют этим моделям принимать сообщения в качестве входных данных. Это делает их взаимозаменяемыми с ChatModels. Когда сообщения передаются в качестве входных данных, они форматируются в строку перед передачей базовой модели.
Для работы с LLM GigaChain использует интеграции со сторонними сервисами.
Сообщения
Некоторые языковые модели принимают список сообщений в качестве входных данных и на выходе возвращают сообщение.
Существует несколько различных типов сообщений.
Все сообщения имеют свойства role
, content
и response_metadata
.
Свойство role
описывает автора сообщения.
GigaChain предоставляет разные классы сообщений для различных ролей.
Свойство content
описывает содержание сообщения.
Содержание может быть представлено:
- строковыми данными — большинство моделей работает именно с такими данными;
- списком словарей — используется для мультимодального ввода, где словарь содержит данные о типе ввода и месте, из которого он был получен.
HumanMessage
Сообщение от пользователя.
AIMessage
Сообщение от модели. Кроме content
, сообщения модели имеют свойства:
response_metadata
— дополнительные метаданные ответа. Эти данные, как правило, зависят от модели, которую вы используете. Например, данные могут содержать логарифм вероятности и информацию об использовании токенов.tool_calls
— данные о решении языковой модели вызвать инструмент. Они являются частью выводаAIMessage
и доступны с помощью свойства.tool_calls
.Это свойство возвращает список словарей. Каждый словарь содержит ключи:
name
— имя инструмента, который нужно вызвать;args
— аргументы вызываемого инструмента;id
— идентификатор вызова инструмента.
SystemMessage
Системное сообщение, которое сообщает модели, как себя вести. Некоторые модели могут не поддерживать системное сообщение.
FunctionMessage
Результат вызова функции. Кроме role
и content
, FunctionMessage содержит свойство name
.
Оно указывает имя функции, вызов которой привел к данному результату.
ToolMessage
Данное сообщение представляет результат вызова инструмента. Оно отличается от FunctionMessage тем, что соответствует типам сообщений OpenAI function
и tool
.
Кроме role
и content
, это сообщение содержит свойство tool_call_id
, которое передает идентификатор вызова инструмента,
Шаблоны промптов
Шаблоны промптов помогают преобразовывать ввод пользователя и параметры в инструкции для языковой модели. Их можно использовать для управления ответом модели, помогая ей понимать контекст задачи и поэтому генерировать более релевантный и связный текст.
Шаблоны принимают на вход словарь, где каждый ключ представляет переменную шаблона, которую нужно заполнить.
Шаблоны промптов возвращают значение промпта (PromptValue). Это значение можно передать в LLM или чат-модель, а также можно преобразовать в строку или список сообщений. PromptValue упрощает переключение между строковыми данными и сообщениями.
Существует несколько различных типов шаблонов промптов.
String PromptTemplates
Шаблоны промптов, которые используются для форматирования одной строки и, как правило, применяются для более простых входных данных.
Пример распространенного способа создания и использования PromptTemplate
:
from langchain_core.prompts import PromptTemplate
prompt_template = PromptTemplate.from_template("Расскажи мне шутку про {topic}")
prompt_template.invoke({"topic": "коты"})
ChatPromptTemplates
Шаблоны промптов, которые используются для форматирования списка сообщений. Эти «шаблоны» сами по себе состоят из списка шаблонов.
Пример распространенного способа создания и использования ChatPromptTemplate
:
from langchain_core.prompts import ChatPromptTemplate
prompt_template = ChatPromptTemplate.from_messages([
("system", "Ты полезный ассистент"),
("user", "Расскажи мне шутку про {topic}")
])
prompt_template.invoke({"topic": "коты"})
В примере ChatPromptTemplate
создаст два сообщения при вызове:
- первое — системное сообщение, которое не содержит переменных для форматирования;
- второе — сообщение от пользователя (HumanMessage). Оно может изменяться с помощью переменной
topic
, которую задает пользователь.
MessagesPlaceholder
Шаблон промптов, который отвечает за добавление списка сообщений в определенное место.
Так, пример работы с ChatPromptTemplate
показывает, как можно форматировать два сообщения, каждое из которых представляет собой строку.
В свою очередь MessagesPlaceholder
используется если нужно, чтобы пользователь передал список сообщений, которые требуется поместить в определенное место.
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage
prompt_template = ChatPromptTemplate.from_messages([
("system", "Ты полезный ассистент"),
MessagesPlaceholder("msgs")
])
prompt_template.invoke({"msgs": [HumanMessage(content="привет!")]})
При выполнении примера создается список из двух сообщений:
- первое — системное сообщение;
- второе — сообщение
HumanMessage
, которое передал пользователь.
Если передать пять сообщений, то в результате получится список из шести сообщений: системное сообщение и пять переданных. Это полезно, когда нужно поместить список сообщений в определенное место.
Того же результата можно достигнуть без MessagesPlaceholder
следующим образом:
prompt_template = ChatPromptTemplate.from_messages([
("system", "Вы полезный ассистент"),
("placeholder", "{msgs}") # <-- Измененный код
])
Селекторы образцов
Один из распространенных приемов для повышения качества работы модели — включение образцов желаемого результата в промпт. Так модели будет проще понять, как себя вести. Образцы можно прописать непосредственно в промпте, но для более сложных ситуаций может быть полезно выбирать их динамически. Селекторы образцов — это классы, ответственные за выбор и оформление образцов желаемого результата в промпты.
Парсеры вывода
Здесь описаны парсеры, которые получают текстовый вывод модели и пробуют преобразовать и представить его в более структурированном виде. Все больше моделей поддерживают вызов функций/инструментов, которые делают это автоматически. По возможности, вместо парсинга вывода рекомендуется использовать именно вызов функций/инструментов.
Парсеры отвечают за получение вывода модели и его преобразование в формат, более подходящий для дальнейших задач. Они полезны при использовании LLM для генерации структурированных данных или для нормализации вывода чат-моделей и LLM.
GigaChain поддерживает парсеры вывода различных типов. Список поддерживаемых парсеров представлен в таблице, которая содержит поля:
- Название — название парсера вывода.
- Поддержка потоковой передачи — поддерживает ли парсер потоковую передачу токенов.
- Инструкции по формату — есть ли у парсера инструкции по формату данных. Как правило, это доступно для всех парсеров, кроме случаев, когда требуемая схема не указана в промпте, а задается другими параметрами (например, при вызове функций OpenAI), или когда OutputParser оборачивает другой OutputParser.
- Вызов LLM — может ли парсер вывода самостоятельно вызывать LLM. Как правило, к вызову LLM обращаются только те парсеры, которые хотят исправить формат выходных данных.
- Тип выходных данных — ожидаемый тип входных данных. Большинство парсеров вывода работают как со строками, так и с сообщениями. Но некоторые, например, функции OpenAI, требуют сообщения с конкретными kwargs.
- Тип выходных данных — тип выходных данных объекта, возвращаемого парсером.
- Описание — комментарий, описывающий парсер и ситуации, когда он может быть полезен.
Название | Поддержка потоковой передачу | Инструкции по формату | Вызов LLM | Тип входных данных | Тип выходных данных | Описание |
---|---|---|---|---|---|---|
JSON | ✅ | ✅ | str | Message | Объект JSON | Возвращает JSON-объект. Можно указать модель Pydantic, в соответствии с которой парсер вернет JSON. Наиболее надежный парсер для получения структурированных данных, который не использует вызов функций | |
XML | ✅ | ✅ | str | Message | dict | Возвращает словарь тегов. Используйте, когда нужен XML-вывод. Используйте с моделями, которые хорошо работают с XML (например, Anthropic) | |
CSV | ✅ | ✅ | str | Message | List[str] | Возвращает список значений, разделенных запятыми | |
OutputFixing | ✅ | str | Message | Оборачивает другой парсер вывода. Если обернутый парсер вывода выдаст ошибку, то OutputFixing передаст сообщение об ошибке и неправильный вывод в LLM и попросит модель исправить вывод | |||
RetryWithError | ✅ | str | Message | Оборачивает другой парсер вывода. Если обернутый парсер вывода выдаст ошибку, то RetryWithError передаст оригинальные входные данные, неправильный вывод и сообщение об ошибке в LLM и попросит модель внести исправления. В отличие от OutputFixingParser, также передает исходные инструкции | |||
Pydantic | ✅ | str | Message | pydantic.BaseModel | Принимает пользовательскую модель Pydantic и возвращает данные, оформленные соответствующим образом | ||
YAML | ✅ | str | Message | pydantic.BaseModel | Принимает пользовательскую модель Pydantic и возвращает данные, оформленные соответствующим образом. Для кодирования использует YAML | ||
PandasDataFrame | ✅ | str | Message | dict | Полезен для выполнения операций с DataFrame библиотеки pandas | ||
Enum | ✅ | str | Message | Enum | Преобразует ответ в одно из заданных значений перечисления (enum) | ||
Datetime | ✅ | str | Message | datetime.datetime | Преобразует ответ в строку даты и времени (datetime) | ||
Structured | ✅ | str | Message | Dict[str, str] | Возвращает структурированную информацию. Менее развитый, чем другие парсеры вывода, так как позволяет полям быть только строками. Это может быть полезно при работе с небольшими LLM |
История чата
Большинство LLM-приложений имеют интерфейс для ведения диалога. Для них важно иметь возможность ссылаться на информацию, ранее представленную в беседе. В самом простом случае диалоговая система должна иметь возможность получать доступ к некоторому набору предыдущих сообщений.
Концепция ChatHistory
относится к классу в GigaChain, который можно использовать для обертывания произвольной цепочки.
Экземпляр ChatHistory
будет отслеживать входные и выходные данные основной цепочки и добавлять их в виде сообщений в базу данных сообщений.
Последующие обращения загружают эти сообщения и передают их в цепочку в качестве части входных данных.
Документы
Объект Document
в GigaChain содержит информацию о некоторых данных. Он имеет два атрибута:
page_content: str
— содержимое документа, представленное в виде строки;metadata: dict
— связанные с документом произвольные метаданные. Могут содержать идентификатор документа, имя файла и другие данные.
Загрузчики документов
Классы, которые загружают объекты Document
. GigaChain поддерживает интеграции с теми же сервисами, что и LangChain, например, Slack, Notion, Google Drive и другие. Подробнее об интеграциях с источниками данных — в официальной документации LangChain.
Каждый DocumentLoader
имеет свои специфические параметры, но любой из них можно вызвать одинаково с помощью метода .load
.
Пример использования:
from langchain_community.document_loaders.csv_loader import CSVLoader
loader = CSVLoader(
... # <-- Специфические параметры интеграции
)
data = loader.load()
Разделители текста
После загрузки документов часто возникает необходимость преобразовать их для более удобной обработки. Например, разбить длинный документ на более мелкие фрагменты, которые могут поместиться в окно контекста вашей модели. GigaChain предоставляет ряд встроенных преобразователей документов, которые позволяют разделять, объединять, фильтровать и выполнять другие манипуляции с документами.
Общее описание работы разделителей текста:
- Разделение текста на небольшие, семантически значимые части. Как правило, на предложения.
- Объединение этих небольших частей в более крупные до достижения определенного размера. Требуемый размер определяется собственной функцией.
- Чтобы сохранить контекст между разными фрагментам, после достижения нужного размера, создается отдельный фрагмент текста. Затем начинается создание нового фрагмента текста с некоторым перекрытием.
Таким образом, при настройке разделителя текста следует учитывать:
- Как текст делится.
- Как измеряется размер фрагмента.
Модели эмбеддингов
Класс Embeddings
предназначен для взаимодействия с моделями, которые создают векторное представление текста (эмбеддинги). При работе с GigaChat для эмбеддингов используется модель Embeddings. Вы также можете использовать подходящие модели других сервисов. Класс Embeddings
предоставляет стандартный интерфейс для работы с моделями разных сервисов.
Эмбеддинги позволяют работать с текстом в векторном пространстве и выполнять такие задачи, как семантический поиск, при котором ищутся текстовые фрагменты, наиболее схожие в векторном пространстве.
Базовый класс Embeddings
в GigaChain предоставляет два метода: один для эмбеддинга документов и один для эмбеддинга запроса. Первый принимает на вход несколько текстов, тогда как второй — один текст. Разделение на два метода обусловлено тем, что некоторые модели эмбеддингов имеют разные методы для эмбеддинга документов (для поиска) и запросов (сам поисковый запрос).
Векторные хранилища
Один из наиболее распространенных способов хранения и поиска по неструктурированным данным — это их векторное преобразование и сохранение полученного эмбеддинга. При выполнении запроса он преобразуется в набор векторов, после чего из ранее сохраненного эмбеддинга извлекаются векторы, которые наиболее схожи с векторами эмбеддинга запроса. Векторное хранилище позволяет хранить эмбеддинги и выполнять векторный поиск.
Векторные хранилища можно преобразовать в интерфейс ретривера следующим образом:
vectorstore = MyVectorStore()
retriever = vectorstore.as_retriever()
Ретриверы
Ретривер — это интерфейс, который возвращает документы по неструктурированному запросу. В отличие от векторных хранилищ, ретриверы применяются для решения задач более общего характера. Ретривер необязательно должен уметь хранить документы, его задача — возвращать (извлекать) их.
Ретриверы принимают строковый запрос на вход и возвращают список объектов Document
на выходе.
Инструменты
Инструменты — это интерфейсы, которые агент, цепочка или чат-модель/LLM могут использовать для взаимодействия с внешним миром.
Инструмент состоит из:
- названия;
- описания того, что делает инструмент;
- JSON-схемы входных данных инструмента;
- функции, которую вызывает инструмент;
- указания на то следует ли возвращать результат работы инструмента непосредственно пользователю. Это актуально только для агентов.
Название, описание и JSON-схема предоставляются в качестве контекста для LLM, позволяя модели правильно использовать инструмент. После получения списка доступных инструментов и промпта с инструкциями, LLM может запросить выполнение одного или нескольких инструментов с соответствующими аргументами.
tools = [...] # Определение списка инструментов
llm_with_tools = llm.bind_tools(tools)
ai_msg = llm_with_tools.invoke("Сделай 1, 2, 3...") # AIMessage(tool_calls=[ToolCall(...), ...], ...)
В общем случае, при разработке инструментов для использования в чат-моделях или LLM важно учитывать:
- Чат-модели, специально обученные для вызова инструментов, справляются с этим лучше.
- Неподготовленные модели могут в принципе не уметь работать с инструментами. Особенно, если инструменты сложные или требуют многократных вызовов.
- Модели будут работать лучше, если у инструментов тщательно подобраны названия, описания и JSON-схемы.
- Моделям легче работать с более простыми инструментами.
Наборы инструментов
Наборы инструментов — это коллекции инструментов, которые используются вместе в конкретных задачах. Наборы предоставляют удобные методы загрузки.
Все наборы инструментов реализуют метод get_tools
, который возвращает список инструментов:
# Инициализация набора инструментов
toolkit = ExampleToolkit(...)
# Получение списка инструментов
tools = toolkit.get_tools()
Агенты
Языковые модели не совершают действия сами — они просто генерируют текст. Одним из основных случаев использования GigaChain является создание агентов.
Агенты — это системы, которые используют LLM для рассуждений и определения, какие действия выполнить и какие входные данные для этих действий использовать. Результаты выполнения можно затем передать обратно агенту, который определит, нужно ли делать что-то еще или можно завершить работу.
GigaGraph — это расширение GigaChain, которое предназначено для создания управляемых и настраиваемых агентов. Подробнее о концепции агентов — в документации GigaGraph.
Для работы с агентами в GigaChain также существует класс AgentExecutor — среда выполнения для агентов.
В документации вы найдете раздел посвященный работе с AgentExecutor
, но для создания агентов рекомендуется использовать GigaGraph.
Колбэки
GigaChain предоставляет систему колбэков, которая позволяет вам подключаться к различным этапам работы вашего LLM-приложения. Это полезно для логирования, мониторинга, потоковой передачи и других задач. На эти события можно подписаться с помощью аргумента callbacks
, доступного в API.
Этот аргумент представляет список объектов-обработчиков, которые должны реализовать один или несколько методов, описанных ниже.
Обработчики колбэков
CallbackHandlers
— это объекты, которые реализуют интерфейс CallbackHandler
. Интерфейс содержит метод для каждого события, на которое можно подписаться.
При получении события объект CallbackManager
вызывает соответствующий метод каждого обработчика.
class BaseCallbackHandler:
"""Базовый обработчик колбэков, который можно использовать для обработки колбэков в gigachain."""
def on_llm_start(
self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any
) -> Any:
"""Выполняется при запуске LLM."""
def on_chat_model_start(
self, serialized: Dict[str, Any], messages: List[List[BaseMessage]], **kwargs: Any
) -> Any:
"""Выполняется при запуске чат-модели."""
def on_llm_new_token(self, token: str, **kwargs: Any) -> Any:
"""Выполняется при получении нового токена LLM. Доступно только при включенной потоковой передаче."""
def on_llm_end(self, response: LLMResult, **kwargs: Any) -> Any:
"""Выполняется при завершении работы LLM."""
def on_llm_error(
self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
) -> Any:
"""Выполняется при ошибке LLM."""
def on_chain_start(
self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any
) -> Any:
"""Выполняется при запуске цепочки."""
def on_chain_end(self, outputs: Dict[str, Any], **kwargs: Any) -> Any:
"""Выполняется при завершении работы цепочки."""
def on_chain_error(
self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
) -> Any:
"""Выполняется при ошибке цепочки."""
def on_tool_start(
self, serialized: Dict[str, Any], input_str: str, **kwargs: Any
) -> Any:
"""Выполняется при запуске инструмента."""
def on_tool_end(self, output: Any, **kwargs: Any) -> Any:
"""Выполняется при завершении работы инструмента."""
def on_tool_error(
self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
) -> Any:
"""Выполняется при ошибке инструмента."""
def on_text(self, text: str, **kwargs: Any) -> Any:
"""Выполняется при обработке произвольного текста."""
def on_agent_action(self, action: AgentAction, **kwargs: Any) -> Any:
"""Выполняется при действии агента."""
def on_agent_finish(self, finish: AgentFinish, **kwargs: Any) -> Any:
"""Выполняется при завершении работы агента."""
Передача колбэков
Свойство callbacks
доступно на большинстве объектов в API (моделях, инструментах, агентах и т.д.) в двух разных местах:
- Колбэки конструктора определяются в конструкторе, например,
ChatAnthropic(callbacks=[handler], tags=['a-tag'])
. В этом случае колбэки используются для всех вызовов, сделанных с этим объектом, и будут применяться только к этому объекту. Например, если вы инициализируете чат-модель с колбэками конструктора, а затем используете ее в цепочке, колбэки будут вызываться только при обращении к этой модели. - Колбэки запроса передаются в метод
invoke
, который используется для выполнения запроса. В этом случае колбэки используются только для этого конкретного запроса и всех подзапросов, которые он содержит. Например, вызов последовательности, которая вызывает модель, используя тот же обработчик, переданный в методеinvoke()
. В методеinvoke()
колбэки передаются в параметреconfig
.