LangChain 챗봇2장 · 개발 환경 준비10 / 20← 이전목차다음 →MetaContents

2장. 개발 환경 준비

ChatOpenAI 로 첫 호출

1장에서 연습용 모형 칼로 썰기 연습을 했다고 해 봅시다. 진짜 칼로 바꿔 쥐어도 쥐는 법과 써는 동작은 똑같습니다. 바뀌는 것은 칼 하나뿐입니다. LangChain 의 ChatOpenAI 가 그 진짜 칼입니다. 1장의 가짜 모델 FakeListChatModel 과 꽂는 모양이 같아서, 모델을 만드는 한 줄만 바꾸면 나머지 코드는 그대로 돌아갑니다.

가짜 모델 FakeListChatModel 과 진짜 모델 ChatOpenAI 가 모두 invoke 로 불러 AIMessage 를 돌려준다는 것을 나란히 놓은 비교 그림

왼쪽 파랑 상자가 1장의 가짜 모델, 오른쪽 보라 상자가 이 장의 진짜 모델입니다. 둘 다 invoke 로 부르고 AIMessage 를 돌려줍니다. 다른 것은 가운데 줄 하나, 정해 둔 답을 돌려주느냐 질문을 읽고 답을 쓰느냐입니다. 여기서 모형 칼이 FakeListChatModel, 진짜 칼이 ChatOpenAI, 써는 동작이 invoke 입니다. 비유와 다른 점은, 진짜 칼은 공짜지만 진짜 모델은 부를 때마다 토큰만큼 요금이 붙는다는 것입니다.

OpenAI SDK 와 ChatOpenAI 견주기

견줄 것OpenAI SDKLangChain 의 ChatOpenAI
만들기client = OpenAI()model = ChatOpenAI(model=MODEL, temperature=0)
보내기client.chat.completions.create(model=…, messages=[사전…])model.invoke([SystemMessage(…), HumanMessage(…)])
답의 글response.choices[0].message.contentreply.content
토큰 수response.usage.prompt_tokens 등reply.usage_metadata["input_tokens"] 등
모델 이름, 끝난 까닭response.model, choices[0].finish_reasonreply.response_metadata["model_name"], ["finish_reason"]
좋은 점OpenAI 의 기능을 바로 쓴다다른 회사 모델로 바꿔도 코드가 같고, 3장의 체인에 바로 잇는다

이 과정은 3장부터 ChatOpenAI 를 씁니다. OpenAI SDK 는 LangChain 이 안에서 대신 불러 주는 부품이라고 보면 됩니다.

응답 객체 AIMessage 읽기

속성원래 말담긴 것
content내용답의 글
usage_metadatausage(사용량) + metadata(데이터에 대한 데이터)input_tokens(보낸 토큰), output_tokens(받은 토큰), total_tokens(합)
response_metadataresponse(응답) + metadatamodel_name(답한 모델), finish_reason(끝난 까닭) 등 서버가 알려 준 정보

finish_reason 이 stop 이면 모델이 스스로 답을 끝낸 것이고, length 면 길이 제한에 걸려 중간에 잘린 것입니다.

짧은 예시

모델을 부르지 않고 세 가지를 봅니다. ChatOpenAI 를 자리표시 키로 만들기만 하고, 같은 질문 함수에 가짜 모델을 넣어 돌리고, 응답과 같은 꼴의 AIMessage 를 직접 만들어 읽습니다. 토큰 수는 연습용으로 지어낸 것입니다.

Python
from langchain_core.language_models.fake_chat_models import FakeListChatModel
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI


def ask(model, question):
    """모델의 종류와 상관없이 같은 꼴로 묻는다."""
    reply = model.invoke([SystemMessage("너는 구름다리여행의 여행 비서다."), HumanMessage(question)])
    return reply.content


# 1) 진짜 모델은 만들기만 한다. 만드는 것만으로는 서버에 아무것도 보내지 않는다
real = ChatOpenAI(model="gpt-4.1-mini", temperature=0, api_key="발급받은_인증키")
print("만든 모델:", real.model_name, "/ 온도:", real.temperature)

# 2) 같은 ask 함수에 1차시의 가짜 모델을 넣는다. 키가 있으면 real 을 넣어도 똑같이 돈다
fake = FakeListChatModel(responses=["성산일출봉을 추천합니다."])
print("가짜 모델의 답:", ask(fake, "제주도에서 해돋이를 볼 곳은?"))

# 3) 진짜 모델이 돌려줄 AIMessage 와 같은 꼴을 직접 만들어 읽는다
reply = AIMessage(
    content="성산일출봉을 추천합니다.",
    usage_metadata={"input_tokens": 30, "output_tokens": 10, "total_tokens": 40},
    response_metadata={"model_name": "gpt-4.1-mini", "finish_reason": "stop"},
)
print("보낸 토큰:", reply.usage_metadata["input_tokens"], "/ 받은 토큰:", reply.usage_metadata["output_tokens"])
print("끝난 까닭:", reply.response_metadata["finish_reason"])
출력
만든 모델: gpt-4.1-mini / 온도: 0.0
가짜 모델의 답: 성산일출봉을 추천합니다.
보낸 토큰: 30 / 받은 토큰: 10
끝난 까닭: stop

ask 함수는 모델이 가짜인지 진짜인지 모릅니다. invoke 로 부르고 content 를 꺼낼 뿐입니다. 키를 받은 뒤 ask(real, …) 로 바꾸면 진짜 답이 돌아옵니다. 실습 4에서 그렇게 합니다.

코드가 의미하는 것

이 코드는 진짜 칼을 쥐어 보기만 하고, 써는 동작은 모형 칼로 해 보고, 썬 결과의 모양은 견본으로 익히는 일입니다. 세 가지 동작이 차례로 나옵니다.

코드하는 일챗봇에서 뜻하는 것
ask(model, question)모델을 받아 invoke 로 묻고 content 를 돌려준다챗봇의 나머지 코드는 이 함수처럼 모델의 종류를 모른 채 씁니다. 모델만 갈아 끼우면 됩니다
ChatOpenAI(model="gpt-4.1-mini", temperature=0, api_key=...)진짜 모델 객체를 만든다이 장부터 쓰는 진짜 칼입니다. 만들기만 해서는 서버에 요청이 가지 않습니다
FakeListChatModel(responses=[...])정해 둔 답을 돌려주는 가짜 모델을 만든다1장의 모형 칼입니다. 키 없이 ask 가 도는지 시험합니다
AIMessage(content=..., usage_metadata=..., response_metadata=...)응답과 같은 꼴의 메시지를 직접 만든다진짜 모델이 돌려줄 상자의 칸 이름을 미리 익힙니다

결과에서 읽을 것은 세 가지입니다.

  • 온도는 0.0 으로 담깁니다. temperature=0 으로 넣었는데 0.0 으로 찍혔습니다. 실수로 바꿔 담은 것이고 뜻은 같습니다.
  • 같은 함수, 다른 모델입니다. ask(fake, …) 는 정해 둔 답 "성산일출봉을 추천합니다."를 돌려줬습니다. 같은 자리에 real 을 넣으면 질문을 읽고 쓴 답이 옵니다.
  • 칸 이름으로 읽습니다. 토큰 30 / 10 과 stop 은 지어낸 값이지만, usage_metadata["input_tokens"] 와 response_metadata 의 finish_reason 을 읽는 법은 실습 4에서도 같습니다.

주의할 점

  • ChatOpenAI 도 키가 없으면 만드는 자리에서 OpenAIError("Missing credentials")가 납니다. 예시에서 자리표시 키를 넣은 까닭입니다.
  • 온도는 1장에서 본 것처럼 0 에 가까울수록 답이 덜 흔들립니다. GPT-5 계열처럼 온도를 기본값(1)만 받는 모델도 있으니, 교수자가 그런 모델을 정했다면 temperature=0 을 지웁니다.
  • 옛 예제의 from langchain.chat_models import ChatOpenAI 는 지금 판에서 오류가 납니다. from langchain_openai import ChatOpenAI 로 부릅니다.
← 이전 절2장 · OpenAI 라이브러리로 첫 호출다음 절 →2장 · 자주 나는 오류