langchain / / 2024. 6. 5. 14:59

[langchain] openai 사용법

langchain을 사용하여 기본적인 openai를 사용하는 방법이다.

OpenAI API 키 발급

OpenAI API를 사용하기 위해서는 우선 API 키를 발급해야 한다. API 키를 발급하는 방법은 테디팀 사이트에 잘 정리되어 있으니 참고하기 바란다.
https://teddylee777.github.io/openai/openai-api-key/

환경 세팅

pipenv 사용

python에서는 가상환경을 사용하는 방법은 여러가지가 있는데 여기서는 가상환경을 위해 pipenv를 사용한다.
Pipenv 매뉴얼: https://pipenv.pypa.io/en/latest/

pipenv가 설치되지 않았다면 pip install pipenv를 통해 설치를 한다.

프로젝트 루트에 Pipfile 파일을 생성한다. (파일명: Pipfile)

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"
langchain-community = "==0.0.33"
python-dotenv = "==1.0.0"
black = "*"

[dev-packages]

[requires]
python_version = "3.12"

아래 명령어로 패키지를 설치한다.

pipenv install

openai api key 준비

api를 호출하기 전에 위에서 발급한 API를 .env 파일에 넣어준다. openai를 호출할 때 사용할 api key이다.

OPENAI_API_KEY=sk-xxx

기본 호출

langchain의 최소한 기능을 openai api를 호출해보자.

  • api key 로딩
  • ChatOpenAI() 생성
  • 프롬프트 생성
  • 응답 출력
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI

# api key 로딩
load_dotenv()

# open ai chat 생성
llm = ChatOpenAI()

# 질의 내용
question = "Java로 1부터 10까지 출력하는 함수 만들어줘"

# 실행
result = llm.invoke(question)
print(result)

실행 결과

content='Sure! 아래는 Java로 1부터 10까지 출력하는 함수의 예시입니다.\n\n```java\npublic class Main {\n    public static void printNumbers() {\n        for (int i = 1; i <= 10; i++) {\n            System.out.println(i);\n        }\n    }\n\n    public static void main(String[] args) {\n        printNumbers();\n    }\n}\n```\n\n위의 코드를 실행하면 1부터 10까지의 숫자가 한 줄씩 출력됩니다.' response_metadata={'token_usage': {'completion_tokens': 115, 'prompt_tokens': 26, 'total_tokens': 141}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-65c3871c-1bb5-423c-b3a5-b8912582fdab-0'

.env에 들어갈 api 키 이름은 정확히 OPENAI_API_KEY 이어야 하며 이름이 다르다면 아래와 같이 할 수도 있다.

import os

load_dotenv()

llm = ChatOpenAI(openai_api_key=os.environ["MY_KEY"])

이를 경우 MY_KEY 이름으로 api key를 가져오는 방식이다.

디버깅

호출되는 과정을 디버깅하려면 아래와 같이 debug=True로 하면 된다.

import langchain
langchain.debug=True

디버그를 활성화하고 실행하면 아래 디버그 코드가 표시된다.

[llm/start] [llm:ChatOpenAI] Entering LLM run with input:
{
  "prompts": [
    "Human: Java로 1부터 10까지 출력하는 함수 만들어줘"
  ]
}
[llm/end] [llm:ChatOpenAI] [2.45s] Exiting LLM run with output:
{
  "generations": [
    [
     ...
    ]
  ],
  "llm_output": {
    "token_usage": {
      "completion_tokens": 115,
      "prompt_tokens": 26,
      "total_tokens": 141
    },
    "model_name": "gpt-3.5-turbo",
    "system_fingerprint": null
  },
  "run": null
}

프롬프트의 내용, llm에서 사용된 토큰, 모델명 등이 표시된다.

PromptTemplate 사용

위의 question에서 질의 내용은 항상 동일(하드코딩)한데, 실제로 이렇게 사용하는 경우는 없을 것이다. 질의 내용을 변수처리를 해서 요청하고 싶을 때 PromptTemplate을 사용할 수 있다.

from dotenv import load_dotenv
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

load_dotenv()

llm = ChatOpenAI()

# 질의내용
template = "{language}로 1부터 10까지 출력하는 함수 만들어줘"

prompt = PromptTemplate.from_template(template=template)

chain = LLMChain(prompt=prompt, llm=llm)
result = chain.invoke({"language": "Java"})
print(result)

PromptTemplate은 template에서 지정한 변수({})를 문자열로 만드는데 사용되는 템플릿이다. 템플릿의 입력된 변수는 {}로 나타내고 {}안에 있는 문자가 변수(input_variables)로 정의된다.

template = "{language}로 1부터 10까지 출력하는 함수 만들어줘"
prompt = PromptTemplate.from_template(template=template)

위와 같이 template을 PromptTemplate으로 지정하면 아래와 같이 값이 지정이 된다.

input_variables=['language'] 
template='{language}로 1부터 10까지 출력하는 함수 만들어줘'

실행 결과

{
  "language": "Java",
  "text": "Sure! 아래는 Java로 1부터 10까지 출력하는 함수의 예시입니다.\n\n```java\npublic class PrintNumbers {\n    public static void printNumbers() {\n        for (int i = 1; i <= 10; i++) {\n            System.out.println(i);\n        }\n    }\n    \n    public static void main(String[] args) {\n        printNumbers();\n    }\n}\n```\n\n위 코드를 실행하면 1부터 10까지의 숫자가 한 줄씩 출력됩니다. 함수를 호출하면 됩니다."
}

또는 아래와 같이

template = "{language}로 1부터 10까지 출력하는 함수 만들어줘"

prompt_template = PromptTemplate.from_template(template)
prompt = prompt_template.format(language="Python")
llm = ChatOpenAI()
result = llm.invoke(prompt)
print(result)

여러 개의 값을 넘기는 경우

language 변수에 여러 개의 값을 넘기는 경우 아래와 같이 apply를 적용하면 된다.

from dotenv import load_dotenv
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

load_dotenv()

llm = ChatOpenAI()

# 질의내용
input_variables = [{"language": "Java"}, {"language": "python"}]
template = "{language}로 1부터 10까지 출력하는 함수 만들어줘"

prompt = PromptTemplate.from_template(template=template)
chain = LLMChain(prompt=prompt, llm=llm)
result = chain.apply(input_variables)
print(result)

실행결과

[
  {
    "text": "```java\npublic class Main {\n    public static void printNumbers() {\n        for (int i = 1; i <= 10; i++) {\n            System.out.println(i);\n        }\n    }\n\n    public static void main(String[] args) {\n        printNumbers();\n    }\n}\n```"
  },
  {
    "text": "Sure! 아래는 Python으로 1부터 10까지 출력하는 함수의 예시입니다.\n\n```python\ndef print_numbers():\n    for i in range(1, 11):\n        print(i)\n\nprint_numbers()\n```\n\n이 함수를 호출하면 1부터 10까지의 숫자가 한 줄에 하나씩 출력됩니다."
  }
]

변수를 2개 이상 지정하는 경우

만일 변수를 여러개 넣고 싶다면 아래와 같이 {}를 필요한 만큼 만들면 된다.

template = "{language}로 {task} 만들어줘"

prompt = PromptTemplate.from_template(template=template)
print(prompt)
chain = LLMChain(prompt=prompt, llm=llm)
result = chain.invoke(
    {"language": "Java", "task": "1부터 10까지 출력하는 함수 만들어줘"}
)
print(result)

streaming 사용

호출 결과를 한번에 받는 대신 스트림으로 받아 텍스트가 타이핑되는 것처럼 표시되게 하려면 아래와 같이 하면 된다.

ChatOpenAI를 생성할 때 streaming=True를 하고 StreamingStdOutCallbackHandler()를 callback으로 지정을 한다.

from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

load_dotenv()

llm = ChatOpenAI(
    streaming=True,
    callbacks=[StreamingStdOutCallbackHandler()],
)

# 질의내용
template = "{language}로 1부터 10까지 출력하는 함수 만들어줘"

prompt = PromptTemplate.from_template(template=template)
chain = LLMChain(prompt=prompt, llm=llm)
result = chain.invoke({"language": "Java"})
print(result)

참고

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