История чата LangChain

Я пытаюсь передать контекст в диалоговую цепочку тряпок при использовании RunnableWithMessageHistory.

У меня есть следующая функция запроса:

def query(query_text, prompt, session_id, metadata_context):
# History retrieval test
contextualize_q_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", contextualize_q_system_prompt),
        ("system", "{context}"),
        ("system", prompt),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}"),
    ]
)
history_aware_retriever = create_history_aware_retriever(
    llm, retriever, contextualize_q_prompt
)

qa_prompt = ChatPromptTemplate.from_messages(
    [   
        ("system", PROMPT_TEMPLATE),
        ("system", "{context}"),
        ("system", prompt),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}"),
    ]
)

question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)

conversational_rag_chain = RunnableWithMessageHistory(
    rag_chain,
    get_session_history,
    input_messages_key = "input",
    history_messages_key = "chat_history",
    output_messages_key = "answer",
)
try:
    logger.info(f"Model: {LLM_MODEL} assigned. Generation of response has started.")
    response = conversational_rag_chain.invoke({"input": query_text, "context": metadata_context}, config = {"configurable": {"session_id": f"{session_id}"}},)
    logger.info(f"Response generated.")
except Exception as e:
    return ({'Generation of response failed: ': str(e)})
return response["answer"]

Я хочу передать свой собственный «контекст», подготовленный и проанализированный из ретривера. Я не хочу, чтобы ретривер вызывался снова, но, судя по тому, что я прочитал, получение происходит само по себе, еслиchat_history не содержит ответа.

создается переменная подсказки:

prompt_template = ChatPromptTemplate.from_template(PROMPT_TEMPLATE)
prompt = prompt_template.format(context=metadata_context, input=query_text)

Как видите, я пытаюсь везде разместить контекст, но безуспешно.

«Контекст», который я вижу при звонке

conversational_rag_chain.invoke({"input": query_text, "context": metadata_context}, config = {"configurable": {"session_id": f"{session_id}"}},)
        logger.info(f"Response generated.")

является результатом ретривера:

Document(metadata = {'number_of_reviews': '16', 'price': 18999, 'product_name': 'product', 'rating': '4')

Код, который я использую, выглядит следующим образом:

chroma_client = chromadb.HttpClient(host=DB_HOST, port=DB_PORT)
chroma_collection = chroma_client.get_collection(os.getenv("DB_COLLECTION"))

vectorstore = VStoreChroma(DB_COLLECTION, embedding_function, client=client)


llm = ChatOpenAI(model = "gpt-4o-mini",temperature=0)

retriever = SelfQueryRetriever.from_llm(
    llm,
    vectorstore,
    document_content_description,
    metadata_field_info,
    search_kwargs = {"k": 10}
)

def self_query(query_text):
    model = llm
    logger.info("Data retrieval has started.")
    try:
        result = retriever.invoke(query_text)
        logger.info("Data retrieved from database.")
        if len(result) == 0:
            logger.info(f"Unable to find matching results.")
    except Exception as e:
        return ({'Retrieval failed: ': str(e)})
    return result

С извлечением все в порядке, я получаю правильные результаты. Проблема в том, что контекст я готовлю из метаданных, анализируя его с помощью функции, подобной той, которую вы упомянули в своем фрагменте. Это строка, и я не понимаю, куда ее можно передать, чтобы контекст использовался правильно. Остальное, как я уже говорил.

Вы пробовали использовать «из langchain.memory импортировать ChatMessageHistory»?

Derek Roberts 05.08.2024 22:03

Пробовал использовать следующую цепочку = ( {"context": restarter | format_metadata, "question": RunnablePassthrough()} | Prompt_template | llm | StrOutputParser()). Но ответы были ужасными и не могли загрузить историю...

vloubes 05.08.2024 22:09
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы можете передать свой контекст или свой вопрос по своему усмотрению, но я думаю, что по сути ваш контекст должен быть отделен от вопроса.

Вы также можете легко передать свой контекст, используя этот шаблон, который я предоставил.

    chat_template = """
                Answer the following questions{question} \n
                Based on the data and context provided {context} \n
                Question: {question} \n
            """

    # get the chat prompt template
    prompt = ChatPromptTemplate.from_template(chat_template)

Что-то вроде этого ниже.

from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
from langchain_core.output_parsers import StrOutputParser
from operator import itemgetter

prompt = ChatPromptTemplate.from_template(chat_template)

# Initialize the LLM
llm = ChatOpenAI(temperature=0.5, max_tokens=4096)

# Initialize the output parser
output_parser = StrOutputParser()

# Create the LLMChain
final_rag = LLMChain(prompt=prompt, llm=llm, output_parser=output_parser)

# Invoke the chain with the input
question = "Your question here"  # Replace this with your actual question
response = final_rag.invoke({"input": question, "context": itemgetter(metadata_context)})

print(response)

Я использую self_query в качестве средства извлечения, и у меня есть специальная функция для форматирования результата поиска из базы данных def format_metadata(result), которая возвращает контекст, который я хочу передать. Идеальная статистика заключается в том, что каждый раз, когда вызывается ретривер, я могу отформатировать выходные данные и внедрить их в качестве контекста.

vloubes 06.08.2024 09:37

Большое спасибо за предложения. К сожалению, это не то, что я пытаюсь сделать. Когда ответ = разговорный_rag_chain.invoke( {"input": query_text, "prompt": Prompt, "context":metadata_context}, config = {"configurable": {"session_id": f"{session_id}"}},) при запуске появляются следующие значения в ответе: 'input': "query_text", "prompt": "prompt value", "context": "Document(metadata = {values}". Есть ли у вас какие-либо идеи, как принять мои собственную строку контекста, которую я создаю? Я попробовал эту rag_chain | {"context": извлекать} внутри RunnableWithMessageHistory, но ответа нет...

vloubes 06.08.2024 15:53

Спасибо, я поделился кодом. Я использую chromadb, поиск работает хорошо, и я получаю правильные результаты. Проблема в передаче контекста в цепочку с историей...

vloubes 06.08.2024 18:56

теперь я получаю контекст, который вы хотите передать, это из извлекаемой_цепочки? («система», «{контекст}») — это тот, который вы хотите передать в диалоговую_раг_цепочку

Derek Roberts 06.08.2024 19:28

Спасибо за помощь. Я пытаюсь Final_rag = ( {"context": itemgetter("context")} | Prompt | llm | StrOutputParser()), но он кричит: неподдерживаемые типы операндов для |: 'dict' и 'str'. Это внутри моей функции def query(), где я создаю тряпку. Все, что касается контекста, приглашения, session_id, я передаю - result = self_query(query_text) Metadata_context = format_metadata(result) session_id = "123" Prompt_template = ChatPromptTemplate.from_template(PROMPT_TEMPLATE) query(query_text, Prompt_template, session_id)).

vloubes 06.08.2024 20:34

очень странно, в любом случае у меня есть информация о том, как передавать контекст, дайте мне знать, если это работает @vloubes

Derek Roberts 06.08.2024 20:58

Это работает. ответ = Final_rag.invoke({"input": вопрос, "контекст": itemgetter(metadata_context)}) выполнил работу.

vloubes 06.08.2024 21:11

о, так ты хотел itemgetter(metadata_context)}) ? Я обновил код. можешь отметить как ответивший? @vloubes

Derek Roberts 06.08.2024 21:21

Не совсем. Вся проблема заключается в обработке истории, поэтому мне следует просто добавить Final_rag = LLMChain(prompt=prompt_template, llm=llm, output_parser=output_parser) в RunnableWithMessageHistory? Теперь я немного не понимаю, как собрать все это воедино, чтобы можно было следить за историей разговоров, например config = {"configurable": {"session_id": f"{session_id}"}}.

vloubes 06.08.2024 21:24

@vloubes Я считаю, что вам придется попробовать что-то самостоятельно, ваш вопрос заключался в том, чтобы помочь передать контекст, что и было сделано. если вы хотите получить историю разговоров, вам придется прочитать это langchain_conversation_docs

Derek Roberts 06.08.2024 21:29

Да, спасибо, чувак!

vloubes 06.08.2024 21:31

@vloubes, чтобы немного помочь, поместите похожие вещи в функцию, например: 1. ваш вектор_дб должен быть в функции 2. ваше приглашение должно быть в функции 3. ваш ретривер должен быть в функции, а затем соединить их вместе. Вы можете поместить их в класс и создать функцию __call__().

Derek Roberts 06.08.2024 21:32

Я понимаю. Чего я не понимаю, так это того, что когда я теперь вызываюconversal_rag_chain.invoke(), это RunnableWithMessageHistory. Когда я вызываю его с помощью разговорного_rag_chain.invoke({"input": вопрос, "контекст": itemgetter(metadata_context)}, config = {"configurable": {"session_id": f"{session_id}"}},) Он имеет никакого влияния на контекст вообще :D

vloubes 06.08.2024 21:46

вы хотите увидеть контекст? или вы хотите, чтобы фильм сделал из этого вывод?

Derek Roberts 06.08.2024 22:24

@vloubes, можете ли вы предоставить информацию об этом контексте метаданных?

Derek Roberts 06.08.2024 23:15

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