Интеграция векторного магазина индекса ламы с агентами Langchain для приложений RAG

Я читал документацию весь день и, похоже, не могу понять, как я могу создать VectorStoreIndex с помощью llama_index и использовать созданные внедрения в качестве дополнительной информации для приложения/чат-бота RAG, который может общаться с пользователем. Я хочу использовать llama_index, потому что у них есть несколько интересных способов реализовать более продвинутые методы поиска, такие как поиск из окна предложений и поиск с автоматическим объединением (честно говоря, я не исследовал, поддерживает ли Langchain также эти типы методов векторного поиска). Я хочу использовать LangChain из-за его функциональности для разработки более сложных шаблонов подсказок (аналогично я не исследовал, поддерживает ли это llama_index).

Моя цель — в конечном итоге оценить, как эти различные методы поиска работают в контексте приложения/чат-бота. Я знаю, как оценить их с помощью отдельного файла оценочных вопросов, но мне бы хотелось сделать такие вещи, как сравнение скорости и человечности ответов, использования токенов и т. д.

Код минимального воспроизводимого примера будет следующим:

1) LangChain ChatBot initiation 
   from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
    from langchain.memory import ChatMessageHistory
    
    
    prompt = ChatPromptTemplate.from_messages(
        [
            (
                "system",
                """You are the world's greatest... \
                Use this document base to help you provide the best support possible to everyone you engage with. 
                """,
            ),
            MessagesPlaceholder(variable_name = "messages"),
        ]
    )
    
    chat = ChatOpenAI(model=llm_model, temperature=0.7)
    
    
    
    chain = prompt | chat
    
    
    chat_history = ChatMessageHistory()
    
    while True:
        user_input = input("You: ")
        chat_history.add_user_message(user_input)
        
        response = chain.invoke({"messages": chat_history.messages})
        
        if user_input.lower() == 'exit':
            break
        
        print("AI:", response)
        chat_history.add_ai_message(response)
  1. Получение окна индексного предложения ламы
from llama_index.core.node_parser import SentenceWindowNodeParser
        from llama_index.core.indices.postprocessor import MetadataReplacementPostProcessor
        from llama_index.core.postprocessor import LLMRerank
    
    class SentenceWindowUtils:
        def __init__(self, documents, llm, embed_model, sentence_window_size):
            self.documents = documents
            self.llm = llm
            self.embed_model = embed_model
            self.sentence_window_size = sentence_window_size
            # self.save_dir = save_dir
    
            self.node_parser = SentenceWindowNodeParser.from_defaults(
                window_size=self.sentence_window_size,
                window_metadata_key = "window",
                original_text_metadata_key = "original_text",
            )
    
            self.sentence_context = ServiceContext.from_defaults(
                llm=self.llm,
                embed_model=self.embed_model,
                node_parser=self.node_parser,
            )
    
        def build_sentence_window_index(self, save_dir):
            if not os.path.exists(save_dir):
                os.makedirs(save_dir)
                sentence_index = VectorStoreIndex.from_documents(
                    self.documents, service_context=self.sentence_context
                )
                sentence_index.storage_context.persist(persist_dir=save_dir)
            else:
                sentence_index = load_index_from_storage(
                    StorageContext.from_defaults(persist_dir=save_dir),
                    service_context=self.sentence_context,
                )
    
            return sentence_index
    
        def get_sentence_window_query_engine(self, sentence_index, similarity_top_k=6, rerank_top_n=3):
            postproc = MetadataReplacementPostProcessor(target_metadata_key = "window")
            rerank = LLMRerank(top_n=rerank_top_n, service_context=self.sentence_context)
    
            sentence_window_engine = sentence_index.as_query_engine(
                similarity_top_k=similarity_top_k, node_postprocessors=[postproc, rerank]
            )
    
            return sentence_window_engine
    
    
        sentence_window = SentenceWindowUtils(documents=documents, llm = llm, embed_model=embed_model, sentence_window_size=1)
        sentence_window_1 = sentence_window.build_sentence_window_index(save_dir='./indexes/sentence_window_index_1')
        sentence_window_engine_1 = sentence_window.get_sentence_window_query_engine(sentence_window_1)

Оба блока кода будут работать независимо. Но цель состоит в том, чтобы при выполнении запроса, требующего извлечения данных из существующей базы документов, я мог использовать встроенный механизм предложения_window_engine. Я предполагаю, что мог бы получить соответствующую информацию на основе запроса, а затем передать эту информацию в последующее приглашение для чат-бота, но я хотел бы попытаться избежать включения данных документа в приглашение.

Какие-либо предложения?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
869
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я так и не нашел точного способа получить информацию через llama_index, как я надеялся, но в основном я нашел обходной путь, сделав то, чего изначально хотел избежать, запросив мою базу документов и добавив ее в качестве контекстной информации в моего чат-бота как такового.

#### Conversation Prompt Chain #####
prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """You are the world's greatest...
            You have access to an extensive document base of information.
            Relevant Information to the user query is provided below. Use the information at your own discretion if it improves the quality of the response.
            A summary of the previous conversation is also provided to contextualize you on previous conversation.

            <<Relevant Information>>
            {relevant_information}


            << Previous Conversation Summary>>
            {previous_conversation}


            << Current Prompt >>
            {user_input}
            """,
        ),
        MessagesPlaceholder(variable_name = "messages"),
    ]
)

chat = ChatOpenAI(model=llm_model, temperature=0.0)



chain = prompt | chat


### Application Start ###


while True:
    # Some code....
    if route['destination'] == "data querying":
                formatted_response = query_and_format_sql(username, password, host, port, mydatabase, query_prompt, model = 'gpt-4', client_name = client_name, user_input=user_input)
                print(formatted_response)
                chat_history.add_ai_message(AIMessage(f'The previous query triggered a SQL agent response that was {formatted_response}'))
        else:
            # Search Document Base
            RAG_Context = sentence_window_engine_1.query(user_input)
    
            # Inject the retrieved information into the chatbot's context
            context_with_relevant_info = {
                "user_input": user_input,
                "messages": chat_history.messages,
                "previous_conversation": memory.load_memory_variables({}),
                "relevant_information": RAG_Context # ==> Inject relevant information from llama_index here
            }
            
            response = chain.invoke(context_with_relevant_info)

Я еще не сталкивался с проблемой токена, но могу себе представить, что если мое приложение будет расти и масштабироваться, у него могут возникнуть проблемы при попытке ввести соответствующую информацию, историю сообщений и приглашение. Я ограничиваю свою память с помощью ConversationBufferMemoryHistory, и пока это работает нормально.

Другие вопросы по теме