무제

[Langchain] Map Reduce 본문

Project/LLM

[Langchain] Map Reduce

mugan1 2024. 11. 17. 17:34

분할된 문서들을 처리하는 방법은 

Stuff, Refine, Map Reduce, Map Re-rank 방식이 있으며, 이를 잘 정리한 블로그 링크를 첨부하겠다.

https://pkgpl.org/2023/10/10/langchain-%EA%B8%B4-%EB%AC%B8%EC%84%9C-%EB%8B%A4%EB%A3%A8%EA%B8%B0/

 

LangChain 긴 문서 다루기: Stuff, Refine, Map Reduce, Map Re-rank

LangChain에서 document loader를 이용해 문서를 읽어들인 후 text splitter를 이용해 긴 문서를 chunk들로 나누었습니다. 그 다음엔 분할한 문서들로 요약이나 질의응답(QA)과 같은 LLM 작업을 수행해야겠죠?

pkgpl.org

 

이중 doc chunk마다 llm에서 각각 요약한 내용을 context에 합쳐 마지막 요약을 하는 방식의 map reduce를 공부해보았다.

llm = ChatOpenAI(temperature=0.1, model="gpt-4o-mini")
retriever = vectorstore.as_retriever()

map_doc_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """
            Use the following portion of a long document to see if any of the text is relevant to answer the question. Return any relevant text verbatim. If there is no relevant text, return : ''
            -------
            {context}
            """,
        ),
        ("human", "{question}"),
    ]
)

map_doc_chain = map_doc_prompt | llm

def map_docs(inputs):
    documents = inputs["documents"]
    question = inputs["question"]
    return "\n\n".join(
        map_doc_chain.invoke(
            {"context": doc.page_content, "question": question}
        ).content
        for doc in documents
    )
    # for doc in documents:
    #     result = map_doc_chain.invoke({"context": doc.page_content, "question": question}).content
    #     print(result)
    # return 

map_chain = {
    "documents": retriever,
    "question": RunnablePassthrough(),
} | RunnableLambda(map_docs)

final_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """
            You are a competent lawyer. Answer questions in Korean using only the following context.
            Given the following extracted parts of a long document and a question, create a final answer. 
            If you don't know the answer, just say that you don't know. Don't try to make up an answer.
            ------
            {context}
            """,
        ),
        ("human", "{question}"),
    ]
)

chain = {"context": map_chain, "question": RunnablePassthrough()} | final_prompt | llm

chain.invoke("무례한 표현만으로 모욕죄가 될 수 있어?")

 

파이프라인의 흐름은 다음과 같다.

1) query가 map_chain으로 전달된다

2) retriever와 query가 각각 document, question으로 RunnableLambda를 통해 map_docs 함수로 전달된다

3) documents를 순회하며 map_doc_chain에서 query와 관련된 답안을 뱉어내고 이를 하나의 String으로 return 한다

4) return된 결과는 final_prompt에 context로 저장된다

 

stuff방식은 긴 문서일 경우 효율적으로 모든 정보를 담을 수 없지만, map reduce 방식을 사용하며 api 호출은 많아지지만 각 chunk별 관련 정보를 효율적으로 담아 요약할 수 있다....근데 사용 방법이 어렵네...ㅠㅠ

 

 

'Project > LLM' 카테고리의 다른 글

[Langchain] Map Re-rank  (1) 2024.11.22
[Langhchain] Refine  (0) 2024.11.21
[Langchain] Retriever  (2) 2024.11.17
[Langchain] Qdrant Vector DB  (2) 2024.11.12
[Langchain] Splitter / Vector DB  (0) 2024.11.10
Comments