[10기 랭체인] LangChain 과제 수행

랭린이 과제 수행중 인상깊은 과제에 대한 설명입니다.


1. Multi Chain

Multi Chain을 사용하여 사용자가 입력한 속성을 기반으로 질문을 생성하는 과정을 보여줍니다.

# 필요 라이브러리 import
from operator import itemgetter

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser


# Load Model
OPENAI_KEY = 'Each-Key'
llm = ChatOpenAI(openai_api_key=OPENAI_KEY, model_name ='gpt-3.5-turbo')
model_parser = llm | StrOutputParser()


prompt1 = ChatPromptTemplate.from_template("generate a {attribute} color. Return the name of the color and nothing else:")
prompt2 = ChatPromptTemplate.from_template("what is a fruit of color: {color}. Return the name of the fruit and nothing else:")
prompt3 = ChatPromptTemplate.from_template("what is a country with a flag that has the color: {color}. Return the name of the country and nothing else:")
prompt4 = ChatPromptTemplate.from_template("What is the color of {fruit} and the flag of {country}?")


color_generator = (
    {"attribute": RunnablePassthrough()} | prompt1 | {"color": model_parser}
)
# prompt1 입력(RunnablePassthrough)된 속성에 해당하는 색상을 생성합니다.

color_to_fruit = (prompt2 | model_parser)
color_to_country = (prompt3 | model_parser)
# prompt1을 통해 생성된 색상에 해당하는 과일, 국가 생성

question_generator = (
    color_generator | {'fruit': color_to_fruit, 'country': color_to_country} | prompt4 
)
# prompt4를 사용하여 최종 질문 생성


prompt = question_generator.invoke({"attribute": "very cold"})
print(llm.invoke(prompt))

'''
content='The color of blueberries is typically a dark purple-blue, while the flag of Argentina consists of three horizontal stripes of light blue and white.' response_metadata={'token_usage': {'completion_tokens': 28, 'prompt_tokens': 20, 'total_tokens': 48}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_b28b39ffa8', 'finish_reason': 'stop', 'logprobs': None} id='run-53069ffb-2480-4587-ae8d-5b81d733a0d0-0'
'''


2. Branching and Merging

     Input
      / \
     /   \
 Branch1 Branch2
     \   /
      \ /
      Combine

하나의 Chain에서 출발하여 여러개의 체인으로 Banching 후 결과를 다시 Merging하여 결과를 생성하는 과제 입니다. (1번 과제와 비슷하다고 느꼈습니다.)


# 필요 라이브러리 import
from operator import itemgetter

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser


# Load Model
OPENAI_KEY = 'Each-Key'
llm = ChatOpenAI(openai_api_key=OPENAI_KEY, model_name ='gpt-3.5-turbo')
parser = StrOutputParser()


planner = (
    ChatPromptTemplate.from_template("Generate an argument about: {input}")
    | llm
    | parser
    | {'base_response': RunnablePassthrough()}
)
# planner 체인은 입력(RunnablePassthrough)에 대한 기본 응답(base response)을 생성

argument_for = (
    ChatPromptTemplate.from_template("List the pros or positive aspect of {base_response}")
    | llm
    | parser
)
argument_against = (
    ChatPromptTemplate.from_template("List the cons or negative aspect of {base_response}")
    | llm 
    | parser 
)
# Banching (planner chain의 결과 base_response를 받아 긍정, 부정 문장 생성)

final_responder = (
    ChatPromptTemplate.from_messages([
        ("system", "You are Morality teacher, Generate a final response given the cirtique"),
        ("human", "Pros:\n{result1}\n\nCons:\n{result2}"), # user
        ("ai", "{original_response}"),
    ])
    | llm
    | parser
)
# 생성된 긍정, 부장 문장을 받아 최종응답 생성 chain


chain = (
    planner
    | {
        'result1': argument_for,
        'result2': argument_against,
        'original_response': lambda x: x['base_response'], # itemgetter("base_response") key값을 가져오는 방법
    }
    | final_responder
)

print(chain.invoke({"input": "scrum"}))


3. Retrieval_augmented_chain

첫 과제설명…

  1. “harrison worked at kensho”라는 문장을 FAISS에 저장합니다.

  2. "where did harrison work?”라는 질문에 대한 답변을 출력합니다.

  3. 두번째 체인에서는 “where did harrison work?”이라는 질문에 대한 답변을 이탈리아어로 답변을 출력합니다.

# 필요 라이브러리 import
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.docstore.document import Document
from langchain_community.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate


# Load Model
OPENAI_KEY = 'Each-Key'
llm = ChatOpenAI(openai_api_key=OPENAI_KEY, model_name ='gpt-3.5-turbo')
embedding_model = OpenAIEmbeddings(openai_api_key=OPENAI_KEY)


# 1. “harrison worked at kensho”라는 문장을 FAISS에 저장합니다.
documents = []
documents.append(Document("harrison worked at kensho"))
vector_stores = FAISS.from_documents(documents=documents, embedding=embedding_model)
retriever = vector_stores.as_retriever()


# 2. "where did harrison work?”라는 질문에 대한 답변을 출력합니다.
query = "where did harrison work?"
text = retriever.invoke(query)

prompt = f"Based on the provided context, '{text[0].page_content}'"
print(prompt)


# 3. “where did harrison work?”이라는 질문에 대한 답변 입력 받은 언어(이탈리아어)로 답변을 출력합니다.
template = """
where did harrison work?'
{context}
Please answer in {language}
Answer: 
"""

rag_prompt = PromptTemplate.from_template(template)
rag_chain = {'context':retriever, 'language': RunnablePassthrough()} | rag_prompt | llm | StrOutputParser()
print(rag_chain.invoke('italian'))

느낀점

  • 추후 프로젝트 진행 시 단일 prompt, chain을 이용하지 않고 multi chain을 이용하여 서비스를 구성하면 좋을 것 같다.

  • ChromaDB말고 FAISS(좋다고 알려진?)를 사용해봤다. 추후 cloud db도 활용해서 프로젝트를 진행해보자.



과제 1,2 reference → https://python.langchain.com/docs/expression_language/cookbook/multiple_chains/

과제 3 reference →

5
2개의 답글

👉 이 게시글도 읽어보세요

모집 중인 AI 스터디