В этой статье мы рассмотрим, как использовать Elasticsearch в качестве векторной базы данных в сочетании с технологией RAG (генерация поискового расширения) для получения опыта вопросов и ответов. Мы будем использовать LlamaIndex и локально работающую модель Mistral LLM.
Прежде чем начать, давайте разберемся в терминологии.
LlamaIndex Это ведущая платформа данных для создания приложений LLM (большая языковая модель). LlamaIndex предоставляет абстракции для различных этапов создания приложений RAG (Retrival Augmented Generation). Такие платформы, как LlamaIndex и LangChain, предоставляют уровни абстракции, чтобы приложения не были жестко привязаны к какому-либо конкретному API LLM.
Elasticsearch да Зависит отElasticоказанная услуга。ElasticдаElasticsearchЛидеры отрасли позади,Это механизм поиска и анализа, который поддерживает полнотекстовый поиск для точности, векторный поиск для семантического понимания и гибридный поиск для лучшего из обоих миров. Elasticsearch — полнофункциональная векторная база данных. Функция Elasticsearch, используемая в этой статье, доступна в Tencent Cloud Elasticsearch. Опыт работы в сервисе.
Поисковая дополненная генерация (RAG) да Что-то вродеAIтехнология/модель,Когда LLM предоставляет внешние знания для генерации ответов на Запрос пользователя. Это позволяет адаптировать ответы LLM к конкретным контекстам.,Это делает ответ более конкретным.
Mistral Предоставление оптимизированной модели корпоративного уровня с открытым исходным кодом LLM.В этом уроке,мы будемиспользоватьих модель с открытым исходным кодомmistral-7b,Он может работать на вашем ноутбуке. Если вы не хотите запускать модель локально,Вы также можете выбрать использование их облачной версии.,В этом случае вам необходимо изменить код в этой статье, чтобы использовать правильный ключ API и пакет.
Ollama Помогите запустить LLM на локальном ноутбуке. Мы будем использовать Ollama для локального запуска модели Mistral-7b с открытым исходным кодом.
Вложения Числовое представление значения текста/медиа. Они представляют собой низкоразмерные представления многомерной информации.
Сценарий:
У нас есть образец набора данных (в виде файла JSON) разговора в колл-центре вымышленной компании по страхованию жилья. Мы создадим простое Приложение RAG, которое сможет отвечать на такие вопросы, как:
Дайте мне обзор вопросов, связанных с водой.
насиспользоватьOllamaсуществовать Запустите Мистраль локально LLM。
Следующий,мы будемотJSONзагрузить в файл“диалог”какдокумент
ВходитьElasticsearchStore(этотдаодин Зависит отElasticsearchПоддерживаемое векторное хранилище)。существоватьнагрузкадокументв то же время,Наше использование локально запускает модель Mistral для создания вложений.,И сохраните его вместе с «разговором» в LlamaIndex Хранилища векторов Elasticsearch.
Мы настроили IngestionPipeline для LlamaIndex и предоставили локальный LLM, который мы использовали в этом случае: Mistral, работающий через Ollama.
Когда мы задаем вопрос типа «Дайте мне обзор проблем, связанных с водой», Elasticsearch выполняет семантический поиск и возвращает «беседы», связанные с проблемами воды. Эти «разговоры» вместе с исходными вопросами отправляются в локальный LLM для получения ответов.
Загрузите и установитеOllama。Установка завершенаOllamaназад,Выполните следующие команды для загрузки и запускаmistral:
ollama run mistral
Загрузка и первый запуск модели локально может занять несколько минут. Убедитесь, что мистраль работает правильно, задав вопросы типа «Напиши стихотворение об облаках» и убедитесь, что стихотворение вам нравится. Нам нужно, чтобы Ollama работала во время последующих взаимодействий с кодом.
Путем создания облачного развертывания(Руководство по установке)илисуществоватьdockerвбегая(Руководство по установке)чтобы встать и побежатьElasticsearch。Вы также можете начать сздесьНачните создавать самостоятельный хостинг производственного уровня.Elasticsearchразвертывать。
Предполагая, что вы используете облачное развертывание, следуйте инструкциям, чтобы получить ключ API и идентификатор облака. Мы будем использовать их в последующих шагах.
ссылкакод МожетсуществоватьРепозиторий на Гитхабенайден в。Клонировать репозиторийда Необязательныйиз,Потому что мы представим код шаг за шагом ниже.
В вашей любимой IDE создайте новое приложение Python и включите следующие 3 файла:
index.py
,и Индексные код, связанный с данными.query.py
,код, связанный с взаимодействием ЗапросиLLM..env
,Сохранить свойства конфигурации,Например, ключ API.Нам нужно установить несколько пакетов. Сначала создайте новый Python в корневом каталоге вашего приложения. виртуальная среда。
python3 -m venv .venv
Активируйте виртуальную среду и установите следующие необходимые пакеты.
source .venv/bin/activate
pip install llama-index
pip install llama-index-embeddings-ollama
pip install llama-index-llms-ollama
pip install llama-index-vector-stores-elasticsearch
pip install sentence-transformers
pip install python-dotenv
Настройте конечную точку Elasticsearch и ключ API.
скачатьconversations.jsonдокумент,Он содержит «разговор» между клиентом нашей вымышленной компании по страхованию жилья и агентом колл-центра. Поместите файл в корневой каталог приложения.,Вместе с двумя файлами Python и файлами .env, созданными ранее. Ниже приведен пример содержимого файла.
{
"conversation_id": 103,
"customer_name": "Sophia Jones",
"agent_name": "Emily Wilson",
"policy_number": "JKL0123",
"conversation": «Клиент: Привет, я София. Джонс. Моя дата рождения 15 ноября 1985 года, мой адрес 303. Cedar St, Miami, FL 33101, номер моего полиса JKL0123. \nАгент: Здравствуйте, София. Чем я могу помочь вам сегодня? \nКлиент: Здравствуйте, Эмили. У меня вопрос по поводу моей политики. \nКлиент: В моем доме произошла кража со взломом, и некоторые ценные вещи были потеряны. Эти предметы покрываются страховкой? \nАгент: Позвольте мне проверить покрытие, связанное с кражей, которое покрывает ваш полис. \nАгент: Да, кража личного имущества подпадает под действие вашего полиса. \nКлиент: Это действительно хорошие новости. Мне нужно подать претензию на украденные вещи. \nАгент: Мы поможем вам с процессом подачи претензии, София. Есть ли что-нибудь еще, чем я могу вам помочь? \nКлиент: Нет, на данный момент это все. Спасибо за помощь, Эмили. \nАгент: Пожалуйста, София. Если у вас есть какие-либо другие вопросы или проблемы, пожалуйста, свяжитесь со мной. \nКлиент: Я сделаю это. Хорошего дня! \nАгент: То же самое и с тобой, София. Береги себя. ",
"summary": «Клиент поинтересовался страховкой на украденные вещи после кражи со взломом, и агент подтвердил, что кража личного имущества подпадает под действие полиса. Агент оказал помощь в процессе рассмотрения претензий, а клиент выразил облегчение и благодарность».
}
нассуществоватьindex.py
определяет файл с именемget_documents_from_file
функция,он читаетjsonдокументисоздаватьодиндокументсписок。документобъектдаLlamaIndexбазовая единица обработки информации。
# index.py
import json, os
from llama_index.core import Document, Settings
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.ingestion import IngestionPipeline
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore
from dotenv import load_dotenv
def get_documents_from_file(file):
"""Прочитайте файл json и верните список документов"""
with open(file=file, mode='rt') as f:
conversations_dict = json.loads(f.read())
# использовать Создайте объект документа с интересующими полями.
documents = [Document(text=item['conversation'], metadata={"conversation_id": item['conversation_id']}) for item in conversations_dict]
return documents
первый,существовать.env
документдобавить тебя всуществоватьУстановите Elasticsearch
частично приобретенныйElasticsearch CloudIDиAPIключ。твой.env
документдолженнравиться Внизпоказано(использоватьистинная ценность)。
ELASTIC_CLOUD_ID=<Заменить натвойоблакоID>
ELASTIC_API_KEY=<Заменить натвойAPIключ>
LlamaIndexизПриемный конвейерпозволю тебеиспользовать Несколько компонентов для построения конвейера。Измените следующеекоддобавить вindex.py
документсередина。
# index.py
# Загрузите содержимое файла .env в env
# ELASTIC_CLOUD_IDиELASTIC_API_KEY ожидается в файле .env
load_dotenv('.env')
# ElasticsearchStore — это VectorStore, отвечающий за индекс ES и управление данными.
es_vector_store = ElasticsearchStore(index_name="calls", vector_field='conversation_vector', text_field='conversation', es_cloud_id=os.getenv("ELASTIC_CLOUD_ID"), es_api_key=os.getenv("ELASTIC_API_KEY"))
def main():
# Используйте модель внедрения Ollama для локального внедрения.
ollama_embedding = OllamaEmbedding("mistral")
# Конфигурация конвейера LlamaIndex обрабатывает фрагменты, внедрение и сохраняет внедрения в векторном хранилище.
pipeline = IngestionPipeline(transformations=[SentenceSplitter(chunk_size=350, chunk_overlap=50), ollama_embedding,], vector_store=es_vector_store)
# Загрузить данные из файла JSON в список документов LlamaIndex.
documents = get_documents_from_file(file="conversations.json")
pipeline.run(documents=documents)
print("....операция конвейера завершена....\n")
if __name__ == "__main__":
main()
Как упоминалось ранее, Приемный рейтинг LlamaIndex конвейер Может состоять из нескольких компонентов。нассуществоватьpipeline = IngestionPipeline(...)
Эта линиякоддобавлено в3компоненты。
get_documents_from_file()
изопределениепоказано,Каждый документ имеет текстовое поле.,Который содержит разговор в файле JSON. Это текстовое поле представляет собой длинный фрагмент текста. Чтобы семантический поиск работал хорошо,Его необходимо разбить на более мелкие фрагменты текста. Класс SentenceSplitter делает эту работу за нас. Эти блоки называются узлами в терминологии LlamaIndex. Узлы имеют метаданные, указывающие на документ, которому они принадлежат. или,Вы также можете выполнить фрагментацию с помощью Приемного конвейера Elasticsearch.,нравитьсяэтот篇блогпоказано。OllamaEmbedding("mistral")
。насиспользоватьSentenceSplitterразделениеиз Блоки отправляются черезOllamaсуществоватьна локальной машинебегатьизMistralМодель,Затем Mistral создает вложения для этих блоков.es_vector_store
Цитировать),наспредоставилнасхочусоздаватьизElasticsearchиндексизимя(существоватьнасизпример子серединадаcalls
),нас Хочу сохранить встроитьиз Поле(существоватьнасизпример子серединадаconversation_vector
),а такженасхочу存储文本из Поле(существоватьнасизпример子серединадаconversation
)。Суммируя,По нашей конфигурации,ElasticsearchStore
существоватьElasticsearchсерединасоздавать了один新изиндекс,вconversation_vector
иconversation
как Поле(Есть и другие автоматическиесоздаватьиз Поле)。объединить все это,нас Позвонивpipeline.run(documents=documents)
запустить трубопровод。
бегатьindex.py
скрипт для выполнения Приемный конвейер:
python index.py
После завершения запуска трубопровода,насдолженсуществоватьElasticsearchЯ увидел файл с именемcalls
из新индекс。использоватьDev В консоли запустите простой запрос Elasticsearch, и вы сможете увидеть загруженные данные, а также встраиваемые данные.
GET calls/_search?size=1
До сих пор мы создавали документы из файлов JSON, разбивали их на фрагменты, создавали внедрения для этих фрагментов и сохраняли внедрения (и текстовый диалог) в векторном хранилище (ElasticsearchStore).
llamaIndexизVectorStoreIndexпозволю тебе Поиск по темедокументи Запросданные。По умолчанию,VectorStoreIndexВстрою хранилищесуществовать内存серединаизодинSimpleVectorStore。Однако,ХОРОШОиспользоватьвнешнее векторное хранилище(нравитьсяElasticsearchStore)чтобы сделать встраивание постоянным。
Открытьquery.py
и вставьте следующеекод:
# query.py
from llama_index.core import VectorStoreIndex, QueryBundle, Response, Settings
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.llms.ollama import Ollama
from index import es_vector_store
# Local LLM используется для отправки пользователям Запроса
local_llm = Ollama(model="mistral")
Settings.embed_model = OllamaEmbedding("mistral")
index = VectorStoreIndex.from_vector_store(es_vector_store)
query_engine = index.as_query_engine(local_llm, similarity_top_k=10)
query="Дайте мне обзор проблем, связанных с водой"
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)
насопределение了один本地LLM(local_llm
),Указывает на модель Мистраля, работающую на Олламе. Следующий,насот之前создаватьизElasticsearchStoreвекторное хранилищесоздавать了одинVectorStoreIndex(index
),Затем из индекса получаем движок Запрос. При создании движка Запрос,Мы ссылались на местный LLM, который следует использовать для ответа.,насвозвращатьсяпредоставил(similarity_top_k=10
)для настройки, должен быть получен из векторного хранилища и отправлен вLLMчтобы получить ответиздокументколичество。
бегатьquery.py
скрипт для выполненияRAGпроцесс:
python query.py
насотправлять ЗапросДайте мне обзор проблем, связанных с водой.
(你Может自Зависит отсделанный на заказquery
),Ответ LLM должен быть примерно следующим.
В приведенном контексте мы видели, как несколько клиентов задавали вопросы о страховании от ущерба, причиненного водой. В двух случаях наводнение повредило подвал, а в другом случае проблемой стала протекающая крыша. Агент подтвердил, что оба типа ущерба от воды покрываются их полисом. Поэтому проблемы, связанные с водой, включая наводнение и протечки крыши, обычно покрываются полисами страхования жилья.
Эта статья в блоге представляет собой введение для начинающих в технологию RAG и Elasticsearch.,Поэтому настройка некоторых функций опущена.,Эти функции позволят вам перейти от этой отправной точки к производственному уровню. При создании сценариев использования в производственных целях,Вы можете рассмотреть более сложные аспекты,Сравниватьнравитьсяможетиспользоватьбезопасность на уровне документазащищатьтвойданные,какElasticsearch Приемный конвейеризвыполнено частичноданные Разбивка на части,или者甚至существоватьиспользуется дляGenAI/Chat/Q&Aвариант использованияизтакой жеданныеначальствобегатьдругойВакансии ML。
Вы также можете рассмотретьиспользоватьЭластичный соединительиз различных внешних источников(примернравитьсяAzure Blob Storage, Dropbox, Gmail и т. д.) для получения данных и создания вставок.
Elastic делает все вышеперечисленное и даже больше возможным, предоставляя комплексное решение корпоративного уровня для сценариев использования GenAI и не только.