[8기 랭체인방] Langchain cookbook 클론코딩

8기 랭체인방 소속된 ‘신묘한힘’ 이준오 입니다!

서론

랭체인을 선택한 이유는 아부지 따라 갔던 오프라인 발표 때, 글 넣으면 mbti 알려주는 사례를 너무 재밌게 봤습니다.. 저에겐 아주 신선한 충격이었기에 그때부터 해보겠다고 다짐을 하게 되었습니다!🐣

죽이 되든, 밥이 되든 열심히 해보려고 합니다



Langchain이란,

언어모델을 사용하는 모든 작업에 사용할 수 있는 ‘frame work’로 이해하고 있습니다.

LLM에 집어넣는 prompt를 토큰화하고, 벡터화하는 전처리 과정 / LLM에서 나온 결과를 후처리하는 과정을 모두 지원하고, custom도 가능합니다. ‘Agent’는 아직 써보진 않았지만 주어진 문제 상황 속 문제 해결을 위한 다양한 문제 해결 방법을 부여할 수 있는 객체입니다.

Embedding vector

  • 기초적인 내용으로, 어떤 단어를 embedding vector로 만든 다는 것은 곧 내용과 의미를 구분할 수 있다는 의미입니다.

  • 비슷한 의미를 가지는 단어는 비슷한 vector들을 가지게 됩니다.


LLM이 답을 생성하는 과정

  • Labeled data → train model on data → call model 순으로 이루어집니다.

  • 부분 문장을 가지고 다음 단어를 예측하는 식으로 sequence training .

  • 단어를 Token별로 나누어서 학습을 합니다. 문자 하나하나를 가지고 학습하는 것이 아니기 때문에 lollipop이라는 단어를 거꾸로 표현해달라고 요청하여도 popillol이 아닌 pipoolll 이런 식으로 나타나게 됩니다. l / oll / ipo / p

Chat models vs LLMs

Language model이 베이스입니다. Chat message list를 입력으로 받을 수 있고, Chat message를 return 할 수 있습니다. LLM이 대화를 위해 특별히 tuned 된 것으로 이해할 수 있습니다


LLM은 Text string을 받고, text string을 return으로 내보냅니다. 단어 by 단어만 입력으로 받을 수 있습니다.


Prompt templates

  • Prompt templates는 우리가 모델의 설명 형식을 정해주는 것입니다.

  • Prompt templates에는 role이 없습니다.

from langchain.prompts import PromptTemplate  

  

invalid_prompt = PromptTemplate(  

input_variables=["adjective"],  

template="Tell me a {adjective} joke about {content}.",  

)

Chat prompt template

  • chat prompt template에서는 role을 지정해줄 수 있습니다

chat_template = ChatPromptTemplate.from_messages(  
[  
("system", "You are a helpful AI bot. Your name is {name}."),  
("human", "Hello, how are you doing?"),  
("ai", "I'm doing well, thanks!"),  
("human", "{user_input}"),  
]  
)  
  
messages = chat_template.format_messages(name="Bob", user_input="What is your name?")
  • System : sets tone / behavior of assistant

  • Assistant : LLM Response (AI)

  • User : prompts (human)


API 키 불러오기

api_key를 바로 붙이는 방법도 있겠지만, 보안에 문제가 생길 수 있기 때문에 공식 홈페이지에서도 이 방법을 지향하더라구요.

import os

from openai import OpenAI

from dotenv import load_dotenv, find_dotenv

# 환경 변수를 읽습니다.
_ = load_dotenv(find_dotenv('key.env'))

client = OpenAI(api_key=os.environ['API_KEY'])
  • 경로 내에 ‘key.env’라는 파일을 찾고, os.environ해서 넣으면 쉽게 api_key를 넣을 수 있습니다!


PromptTemplate + LLM

이후부터는 Langchain cookbook의 클론 코딩 내용입니다

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template("tell me a joke about {foo}")
model = ChatOpenAI(openai_api_key=os.environ['API_KEY'])
chain = prompt | model  

backspace | 는 prompt와 model을 엮는 문법입니다! ( chain 생성)

chain.invoke({"foo":"bears"})
"""AIMessage(content="Why don't bears wear shoes? \n\nBecause they already have bear feet!")""""

Attaching Stop Sequences

chain = prompt | model.bind(stop=["\n"]) 
# \n이 나오는 곳에서 멈추는 ! 
chain.invoke({"foo":"bears"})
"""AIMessage(content="Why don't bears wear shoes?")"""

Attaching Function Call information

  • 많은 경우에 각각의 모델에 대한 동작을 제어하고 싶을 수 있는데 그때 쓰는 것 같습니다

prompt = ChatPromptTemplate.from_template("tell me a advice about {foo}")
functions = [
    {
        "name" : "advice",
        "description" : "A advice",
        "parameters" : {
            "type" : "object",
            "properties" : {
                "setup" : {"type":"string","description":"The setup for the advice"},
                "punchline" : {
                    "type": "string",
                    "description": "The advice for the life",
                },
            },
            "required": ["setup","punchline"],
        },
    }
]#### functions 변수는 OpenAI 함수 형식을 따르는 custom 함수를 정의하고, 모델 실행 시 이 함수들을 호출할 수 있게 하는 역할
#### name, description,parameters 필드를 가지고 있음
#### joke 함수는 다음과 같은 형태(.json)의 출력을 생성
{
    "setup" : "setup"문자열,
    "punchline" : "punchline"문자열
}
chain = prompt | model.bind(function_call={"name":"advice"},functions=functions)
chain.invoke({"foo":"cars"},config={})

""" AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\n  "setup": "Always make sure to maintain your car regularly,",\n  "punchline": "It will help prevent costly repairs and ensure your safety on the road."\n}', 'name': 'advice'}}) """
  • prompt를 어떻게 주느냐가 가장 model의 답변에 큰 영향을 줬습니다. 당연하겠지만

  • model안의 functions들을 어떻게 바꾸느냐에 따라 어투가 많이 달라졌습니다.


PromptTemplate + LLM + OutputParser

  • output parser to easily tansform the raw LLM/ ChatModel output into a more workable format이라 써있는데 이해가 잘 안가고, 그냥 보기 쉽고, 만지기 쉽게 변경해준다는 것으로 이해했습니다.

from langchain.schema.output_parser import StrOutputParser

chain = prompt | model | StrOutputParser()
chain.invoke({"foo":"cars"}) 
““'One piece of advice about cars is to prioritize regular maintenance and servicing. Taking your car for routine check-ups and servicing can help prevent major issues from arising, prolong the lifespan of your vehicle, and ensure optimal performance and safety on the road. Additionally, staying on top of regular maintenance can help identify any potential problems early on, saving you from costly repairs down the line.'““
  • 자연스럽게 나온 것 같은..!


Functions Output parser

  • function 기능에 따라 message를 자를 수 있습니다.

from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser

chain = (
    prompt | model.bind(function_call={"name":"advice"},functions=functions)
    | JsonOutputFunctionsParser()
)
chain.invoke({"foo":"cars"})
“““{'setup': 'Taking care of your car is essential,', 'punchline': 'regular maintenance and timely repairs can save you from expensive breakdowns and ensure a longer lifespan for your vehicle.'}”””
  • key로 뽑아서 사용할 수도!

from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser

chain = (
    prompt | model.bind(function_call = {"name":"advice"},functions=functions)
    | JsonKeyOutputFunctionsParser(key_name="setup")
)
chain.invoke({"foo":"cars"})

"""'Always maintain your car regularly and follow the recommended service schedule.'"""

Simplifying input

  • 호출을 쉽게 하기 위해 프롬프트 입력 dic을 자동으로 생성하는

from langchain.schema.runnable import RunnableMap, RunnablePassthrough

map_ = RunnableMap(foo=RunnablePassthrough())
chain = (
    map_
    | prompt
    | model.bind(function_call={"name":"advice"},functions=functions)
    | JsonKeyOutputFunctionsParser(key_name='setup')
)
chain.invoke("bears") 
"""'Always carry bear spray when hiking in bear country.'"""
# 원래는 invoke에 dictionary 형태로 {"foo":"어떤 것"} 
# 써줘야 했는데  map_ 을 써서 안써도 되게 함! 간편 편리!!!! 


5
2개의 답글
지피터스 뉴스레터

이번 주 AI, 딱 쓸 것만

매주 월요일 오후,
읽고 바로 써먹을 AI 소식만