langchain / / 2024. 5. 22. 09:58

[LangChain] 체인(Chain)은 무엇인가?

ChatGPT and LangChain: The Complete Developer's Masterclass 강좌의 일부를 요약한 내용이다.

샘플 프로그램

만들어볼 프로그램은 아래와 같다.

위의 시나리오는 CLI로 task와 language를 input으로 받고 파싱을 한 다음 prompt를 생성한 다음 OpenAI에 요청을 한다. 그리고 우리가 원하는 결과(프로그램)를 받는 것이다. 또한 OpenAI의 응답을 Bard에게 프로그램에 버그가 있는지 확인요청을 다시 하고 그 결과를 받는다.

LangChain의 두 가지 목표가 있다.

  1. 텍스트 생성 파이프라인의 단계를 자동화하는 도구를 제공
  2. 도구를 연결하기 쉽게 한다

OpenAI는 Llama나 Claude로 변경할 수도 있어야 한다. 즉, 다른 LLM으로 쉽게 바꿀 수 있어야 한다는 뜻이다.

Chain은 무엇인가?

  • Chain은 LangChain에서 제공되는 python 클래스이다.
  • 재사용 가능한 텍스트 생성 파이프라인을 만들기 위해 Chain을 사용한다.
  • Chain은 복잡한 파이프라인을 만들기 위해 결합될 수 있다.
  • Chain은 PromptTemplate과 LLM을 연결한다.

PromptTemplate

  • LLM에 보내질 최종 prompt를 만든다.
  • prompt를 만들 때 필요한 변수를 선언해야 한다.
  • 이 경우는 languagetask가 필요한 변수이다.

Language Model

  • 텍스트 생성 파이프라인에 필요한 LLM이다.
  • ChatGPT, Bard와 같이 텍스트를 만드는 어떤 것도 될 수 있다.

위의 시나리오에서는 아래 그림과 같이 2개의 체인이 연결되는 형태를 띄게 된다.

Chain A의 Output에 출력되는 language, code 변수값은 Chain B의 Input으로 대입을 해준다.

첫 번째 체인 생성

코드를 작성해보자. 우선 Pipfile에 아래 내용을 추가한다.

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
langchain = "==0.1.16"
openai = "==1.21.2"
langchain-openai = "==0.1.3"

[dev-packages]

[requires]
python_version = "3.12"

그리고 pipenv install을 통해 패키지를 설치하자.

main.py를 만들어 코드를 작성하자.

from langchain_openai import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
api_key = "sk-xxx" # api key

llm = OpenAI(
    openai_api_key=api_key,
)

# code template을 만든다.
code_prompt = PromptTemplate(
    # task, language는 변수로 사용되고 매개변수의 값으로 치환이 된다.
    template="Write a very short {language} function that will {task}",
    # input_variables로 변수를 나타낸다.
    input_variables=["language", "task"],
)

# chain을 만드는 데 code_prompt를 사용한다.
code_chain = LLMChain(
    llm=llm,
    prompt=code_prompt
)

result = code_chain.invoke({
    "language": "python",
    "task": "return a list of numbers"
})

print(result)

이렇게 하고 실행해보면 아래와 같이 출력된다.

{
  'language': 'python', 
  'task': 'return a list of numbers', 
  'text': '\n\ndef get_numbers():\n    return [1, 2, 3, 4, 5]'
}

language와 task는 input 값이고 출력값은 text로 나타내어 진다.

매개변수 주입

위의 코드에서 language와 task의 input 값은 소스코드에 하드코딩해서 넣었다. 이를 주입받을 수 있도록 해보자.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--task", default="Return a list of numbers")
parser.add_argument("--language", default="python")
args = parser.parse_args()

...

result = code_chain.invoke({
    "language": args.language,
    "task": args.task
})

print(result['text'])

매개변수를 받기 위해서는 argparse를 사용한다. task와 language를 주입받게 하고 chain을 실행할 때 arg.language, arg.task로 변경하자.

그리고 실행할 때 매개변수를 넘기자.

python main.py --language javascript --task 'print hello'

실행 결과는 아래와 같이 출력된다.

function sayHello() {
  console.log("Hello");
}

만일 매개변수를 넘기지 않으면 default로 지정된 문자열이 동작한다. 즉, python에 Return a list of numbers 의 task가 실행된다.

API Key 안전하게 보관

위의 소스코드에는 api_key = "sk-xxx"가 코드 내에 하드코딩이 되어 있다. 이를 git에 커밋을 하는 경우 보안상 문제가 될 수 있다. 그래서 api key를 안전하게 보관하는 방법을 알아본다.

위의 OpenAI() 함수에서는 OPENAI_API_KEY라는 이름의 변수를 우선 찾는다. 그래서 변수로 선언하고 사용하게 할 것이다.

환경변수를 읽어오는 방법은 여러가지가 있지만 여기서는 dotenv를 사용한다.

.env 파일을 만들고 OPENAI_API_KEY를 추가하자. (.env 파일을 git에 추가하면 절대로 안된다)

OPENAI_API_KEY=sk-xxx

또한 dotenv를 설치하자.

pipenv install python-dotenv를 실행한다.

그리고 main.py에 아래 로직을 추가한다.

from dotenv import load_dotenv

load_dotenv()

llm = OpenAI() # 기존의 api_key을 지운다.

두 번째 체인 생성

이 시나리오에서는 체인을 2개 만든다. 하나는 코드 생성 체인, 다른 하나는 코드 검증 체인이다. 위에서 코드 생성 체인을 만들었고 이제 코드 검증 체인을 만들어보자. 코드 검증 체인은 첫 번째와 동일한데 코드 생성 체인에서 나온 결과(output)를 코드 검증 체인의 Input으로 넣어준다. 즉 코드 생성 체인의 Output인 language, code를 코드 검증 체인의 Input으로 넣어준다는 것이다.

code_chain = LLMChain(
    llm=llm,
    prompt=code_prompt
)
...
print(result['text'])

위에서 code_chain의 실행 결과가 text로 넘어왔다. 여기서 두번째 체인에 넘겨줄 값을 code로 변경을 해야 하므로 Output의 key값을 변경을 해보자. 변경하는 방법은 간단한다.

code_chain = LLMChain(
    llm=llm,
    prompt=code_prompt,
    output_key="code"
)
...
print(result['code'])

output_key를 넣어주면 해당 키로 output을 넘겨준다.

이제 검증 체인을 만들어보자.

test_prompt = PromptTemplate(
    input_variables=["language", "code"],
    template="Write a test for the following {language} function:\n{code}"
)
...
test_chain = LLMChain(
    llm=llm,
    prompt=test_prompt,
    output_key="test"
)

첫 번째 체인과 동일하게 PromptTemplate을 만들고, LLMChain을 만든다.

첫 번째 체인의 Output을 두 번째 체인의 Input으로 넘겨준다. 이를 Sequential Action이라고 한다. 여러 개의 체인을 순차적으로 실행한다는 것을 나타낸다.

SequentialChain을 사용하는 방법은 아래와 같다.

from langchain.chains import LLMChain, SequentialChain # SequentialChain 추가
...

chain = SequentialChain(
    chains=[code_chain, test_chain],
    input_variables=["task", "language"],
    output_variables=["test", "code"]
)

result = chain.invoke({
    "language": args.language,
    "task": args.task
})

print(result)

참고

ChatGPT and LangChain: The Complete Developer's Masterclass

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유