무제

[Langhchain] Refine 본문

Project/LLM

[Langhchain] Refine

mugan1 2024. 11. 21. 22:53

refine을 알아봤는데, Langchain 표현방식은 굉장히 다양한 것 같다. 어떤 방식으로 코드를 작성해야할지 고민이다

 

1번 방식

initial_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """
            You are a competent lawyer. Answer questions in Korean using only the following context.
            Use the following portion of a long document to see if any of the text is relevant to answer the question. 
            Answer the question based on the context provided. If there is no relevant information, return: 'No relevant information found.' 
            -------
            {context}
            """,
        ),
        ("human", "{question}"),
    ]
)

refine_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """
            You are a competent lawyer. Answer questions in Korean using only the following context.
            You are refining a previous answer based on additional context. Here is the current answer:
            ------
            Current Answer: {current_answer}
            ------
            And here is the new context:
            ------
            {context}
            ------
            Refine the answer by incorporating the new context. If the new context doesn't add relevant information, keep the current answer as is.
            """,
        ),
        ("human", "{question}"),
    ]
)

# Create chain for initial response generation
initial_llm = initial_prompt | llm
initial_chain = {
    "documents": retriever,
    "question": RunnablePassthrough(),
} | RunnableLambda(
    lambda inputs: [
        initial_llm.invoke({"context": doc.page_content, "question": inputs["question"]}).content
        for doc in inputs["documents"]
    ]
)

def refine_chain(inputs):
    initial_answers = inputs["initial_answers"]
    question = inputs["question"]
    
    refined_answer = initial_answers[0] if initial_answers else "No relevant information found."
    refine_llm = refine_prompt | llm
    for answer, doc in zip(initial_answers[1:], inputs["documents"][1:]):
        refined_answer = refine_llm.invoke(
            {
                "current_answer": refined_answer,
                "context": doc.page_content,
                "question": question,
            }
        ).content
    return refined_answer

refine_chain_fn = RunnableLambda(refine_chain)

chain = {
    "documents": retriever,
    "question": RunnablePassthrough(),
} | {"initial_answers": initial_chain, "question": RunnablePassthrough(), "documents": retriever} | refine_chain_fn

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

 

Output : 

무례한 표현만으로는 모욕죄가 성립하지 않습니다. 모욕죄는 상대방의 인격적 가치에 대한 사회적 평가를 저하시킬 만한 표현이어야 하며, 단순히 무례한 방법으로 표현되었다 하더라도 그것이 상대방의 사회적 평가를 저하시킬 수 없다면 모욕죄의 구성요건에 해당하지 않습니다. 

최근의 판례에서도 이러한 원칙이 확인되었습니다. 예를 들어, 한 사건에서 피고인이 아파트 관리소장에게 "야, 이따위로 일할래."라고 말하고, 관리소장이 "나이가 몇 살인데 반말을 하느냐"고 반응했으며, 피고인이 "나이 처먹은 게 무슨 자랑이냐."라고 응답한 경우, 이러한 발언은 무례하고 저속할 수 있지만, 객관적으로 상대방의 인격적 가치에 대한 사회적 평가를 저하시킬 만한 모욕적 언사로 보기는 어렵다는 판단이 내려졌습니다. 

따라서 표현의 내용과 맥락이 중요하며, 원심법원이 이러한 점을 간과하고 피고인의 발언이 모욕죄에 해당한다고 단정한 것은 법리를 오해한 잘못이 있다고 할 수 있습니다.

 

2번 방식

 

initial_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """
            You are a competent lawyer. Answer questions in Korean using only the following context.
            Use the following portion of a long document to see if any of the text is relevant to answer the question. 
            Answer the question based on the context provided. If there is no relevant information, return: 'No relevant information found.' 
            -------
            {context}
            """,
        ),
        ("human", "{question}"),
    ]
)

def refine_chain(inputs):
    documents = inputs["documents"]
    question = inputs["question"]
    
    # Initialize refined answer from the first document
    initial_context = documents[0].page_content
    inital_llm = initial_prompt | llm
    refined_answer = inital_llm.invoke({"context": initial_context, "question": question}).content
    
    for doc in documents[1:]:
        refine_context = doc.page_content
        refine_input = f"""
        Current Answer: {refined_answer}
        ------
        Additional Context: {refine_context}
        ------
        You are a competent lawyer. Answer questions in Korean using only the following context.
        Refine the answer to better address the question based on the new context. 
        If the new context doesn't add relevant information, keep the current answer as is.
        """
        refined_answer = llm.invoke([{"role": "system", "content": refine_input}]).content
    
    return refined_answer

chain = {
    "documents": retriever,
    "question": RunnablePassthrough(),
} | RunnableLambda(refine_chain)

# Invoke the chain with a sample question
response = chain.invoke("무례한 표현만으로 모욕죄가 될 수 있어?")
print(response)

 

Output :

무례한 표현만으로는 모욕죄가 성립되지 않습니다. 모욕죄는 상대방의 인격적 가치에 대한 사회적 평가를 저하시킬 만한 표현이어야 하며, 단순히 무례한 방법으로 표현되었다 하더라도 그 표현이 상대방의 사회적 평가를 저하시킬 수 없다면 모욕죄의 구성요건에 해당하지 않습니다. 

이번 사건에서 피고인이 공소외인에게 한 발언은 상대방을 불쾌하게 할 수 있는 무례하고 저속한 표현이지만, 객관적으로 공소외인의 인격적 가치에 대한 사회적 평가를 저하시킬 만한 모욕적 언사로 보기 어렵다는 점이 중요합니다. 원심법원이 이러한 기준을 충분히 고려하지 않고 피고인의 발언이 모욕죄에 해당한다고 단정한 것은 법리를 오해한 것으로, 따라서 사건을 다시 심리·판단하게 하기 위해 원심법원에 환송하는 것이 적절합니다.

 

개인적으로 1번 답변이 더 마음에 든다 ㅎㅎ 

 

3번 방식 추가요!

first_summary_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """
            You are a competent lawyer. Answer questions in Korean using only the following context.
            Use the following portion of a long document to see if any of the text is relevant to answer the question. 
            Answer the question based on the context provided. If there is no relevant information, return: 'No relevant information found.' 
            -------
            {context}
            """,
        ),
        ("human", "{question}"),
    ]
)

# Initial summary generation
def first_fn(inputs):
    docs = inputs["documents"]
    question = inputs["question"]
    first_summary_chain = first_summary_prompt | llm | StrOutputParser()

    # Generate summary for the first document
    summary = first_summary_chain.invoke(
        {"context": docs[0].page_content, "question": question}
    )
    return {"existing_summary": summary, "remaining_docs": docs[1:], "question": question}

refine_prompt = ChatPromptTemplate.from_template(
    """
    You are a competent lawyer.
    Your job is to produce a final summary in Korean.
    We have provided an existing summary up to a certain point: {existing_summary}
    We have the opportunity to refine the existing summary (only if needed) with some more context below.
    ------------
    {context}
    ------------
    Given the new context, refine the original summary.
    If the context isn't useful, RETURN the original summary.
    """
)

def refine_fn(inputs):
    existing_summary = inputs["existing_summary"]
    remaining_docs = inputs["remaining_docs"]
    question = inputs["question"]
    current_summary = existing_summary

    # Process each remaining document
    for doc in remaining_docs:
        context = doc.page_content
        refined_summary = refine_prompt | llm | StrOutputParser()
        current_summary = refined_summary.invoke(
            {
                "existing_summary": current_summary,
                "context": context,
                "question": question,
            }
        )
    return current_summary

refine_chain = (
    {"documents": retriever, "question": RunnablePassthrough()}
    | RunnableLambda(first_fn)
    | RunnableLambda(refine_fn)
)

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

 

Output :

 

무례한 표현만으로는 모욕죄가 성립되지 않습니다. 모욕죄는 사람의 사회적 평가를 저하시킬 만한 추상적 판단이나 경멸적 감정을 표현해야 하며, 단순히 무례한 방법으로 표현되었다 하더라도 상대방의 인격적 가치에 대한 사회적 평가를 저하시킬 만한 것이 아니라면 모욕죄의 구성요건에 해당하지 않습니다. 형법 제311조에 따르면, 모욕죄는 외부적 명예를 보호하는 범죄로, 사실을 적시하지 않고 사람의 사회적 평가를 저하시킬 만한 표현이 필요합니다. 이 사건에서 아파트 입주자대표회의 감사인 피고인이 관리소장과의 언쟁 중에 "야, 이따위로 일할래."라는 무례한 표현을 사용했으나, 그 발언이 상대방의 인격적 가치에 대한 사회적 평가를 저하시킬 만한 모욕적 언사로 판단되지 않았습니다. 피고인의 발언은 불쾌감을 줄 수 있는 저속한 표현이었지만, 객관적으로 공소외인의 인격적 가치에 대한 사회적 평가를 저하시킬 만한 모욕적 언사로 보기 어렵다는 점이 인정되었습니다. 따라서 원심은 이러한 사실을 간과하고 피고인의 발언이 형법 제311조의 모욕에 해당한다고 단정하였으므로, 이는 법리를 오해한 잘못이 있음을 지적하며, 나머지 상고이유에 대한 판단을 생략하고 원심판결을 파기하며 사건을 다시 심리·판단하기 위해 원심법원에 환송하기로 하였습니다.

 

-> refine 방식은 상당히 구체적이네 ...

 

다음에는 Map Re-rank 방식에 대해 공부해야겠다

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

[Langchain] Model Evaluation - 1  (0) 2024.11.24
[Langchain] Map Re-rank  (1) 2024.11.22
[Langchain] Map Reduce  (0) 2024.11.17
[Langchain] Retriever  (2) 2024.11.17
[Langchain] Qdrant Vector DB  (2) 2024.11.12
Comments