Доступ к переменным LangChain LCEL из предыдущих этапов цепочки

Я пытаюсь сесть на поезд LCEL и Langserve, но у меня возникли небольшие проблемы с пониманием некоторой «магии», связанной с доступом к переменным, установленным в словаре конвейера.

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

class ChatResponse(BaseModel):
    answer: str
    sources: List[Document]

store = FAISS.from_texts(
    ["harrison worked at kensho"], embedding=OpenAIEmbeddings()
)
retriever = store.as_retriever()
template = """Answer the question based only on the following context:
{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
llm = ChatOpenAI()

def format_response(answer):
    sources = [] # TODO lookup source documents (key: 'context')
    return ChatResponse(answer=answer, sources=sources)

retrieval_chain = (
        {"context": retriever, "question": RunnablePassthrough()}
        | prompt
        | llm
        | StrOutputParser()
        | RunnableLambda(format_response)
)
app = FastAPI()
add_routes(app, retrieval_chain, path = "/chat", input_type=str, output_type=ChatResponse)

В format_response я оставил TODO для поиска исходных документов. Я хотел бы получить исходные документы из ключа context конвейера. Как мне получить доступ к этому ключу, который был установлен на первом этапе цепочки?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
126
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

из документации по адресу https://python.langchain.com/docs/use_cases/question_answering/sources/

from langchain_core.runnables import RunnableParallel

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

rag_chain_from_docs = (
    RunnablePassthrough.assign(context=(lambda x: format_docs(x["context"])))
    | prompt
    | llm
    | StrOutputParser()
)

rag_chain_with_source = RunnableParallel(
    {"context": retriever, "question": RunnablePassthrough()}
).assign(answer=rag_chain_from_docs)

тогда это:

rag_chain_with_source.invoke("where did harrison work ?")

возвращает:

{'context': [Document(page_content='harrison worked at kensho')],
 'question': 'where did harrison work ?',
 'answer': 'Harrison worked at Kensho.'}

Я думаю, что мой пример был слишком упрощен. Возможность RunnableParallel возвращать объединенный словарь определенно решает мой пример, но не отвечает на более широкий вопрос о том, как мы можем разрешить эти переменные аналогично тому, как работают PromptTemplates для более сложных требований.

Mike Cantrell 25.04.2024 17:01

Думаю, я увлекся размышлениями об этом немного в стороне. Глядя на пример цитат, я вижу, как, создав несколько цепочек и используя RunnableParallel для их объединения, вы можете решить некоторые более сложные требования: python.langchain.com/docs/use_cases/question_answering/…

Mike Cantrell 25.04.2024 17:50

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

Похожие вопросы

Я получаю пустой массив из векторного поиска в mongoDB с помощью langchain
Ошибка импорта: не удалось импортировать пакет Python chromadb. Пожалуйста, установите его с помощью `pip install chromadb`
Milvus.py: pymilvus.Exceptions.MilvusException: <MilvusException: (код=1, сообщение=полная_длина поля отсутствует в объекте обращения)>
Как изменить функцию расстояния в langchainпохожий_поиск
Как интегрировать комментарии к столбцам Oracle в LangChain для расширенной генерации SQL-запросов (NL2SQL)?
Как заставить диалоговую поисковую цепочку включать метаданные в приглашение, используя langchain с chromadb, чтобы LLM знал о метаданных?
Почему db.get_usable_table_names() не возвращает все таблицы в моей базе данных PostgreSQL с помощью Langchain?
Langchain: Как просмотреть контекст, который мой ретривер использовал при вызове
Как разрешить AttributeError и BadRequestError в Python с помощью LangChain и AzureOpenAI?
Возникла проблема с импортом TextLoader из langchain.document_loaders