모델
모델 (Models)
LLM은 사람처럼 텍스트를 해석하고 생성할 수 있는 강력한 AI 도구예요. 콘텐츠 작성, 번역, 요약, 질문 응답까지 — 각 작업마다 특별히 훈련하지 않아도 해낼 수 있을 만큼 범용적이죠. 에이전트의 "추론 엔진"이 바로 이 모델이고, 어떤 도구를 호출할지, 결과를 어떻게 해석할지, 언제 최종 답을 낼지 결정하는 의사 결정 과정을 이끌어요.
모델이 할 수 있는 일
텍스트 생성 외에도 많은 모델이 지원하는 기능이 있어요.
- 도구 호출 (Tool calling) — 데이터베이스 질의나 API 호출 같은 외부 도구를 호출하고 그 결과를 응답에 활용합니다.
- 구조화된 출력 (Structured output) — 모델 응답이 정의된 형식을 따르도록 제약합니다.
- 멀티모달 (Multimodality) — 이미지, 오디오, 비디오처럼 텍스트가 아닌 데이터를 처리하고 반환합니다.
- 추론 (Reasoning) — 결론에 도달하기 위해 여러 단계의 추론을 수행합니다.
선택한 모델의 품질과 능력은 에이전트의 기본적인 신뢰성과 성능에 직접 영향을 줘요. 모델마다 잘하는 작업이 다릅니다 — 어떤 건 복잡한 지시를 잘 따르고, 어떤 건 구조화된 추론에 강하며, 어떤 건 더 많은 정보를 처리할 수 있는 큰 컨텍스트 윈도우를 지원하죠.
LangChain의 표준 모델 인터페이스 덕분에 많은 프로바이더 통합을 쉽게 오가며 실험할 수 있어요. 프로바이더별 통합 정보와 기능은 해당 프로바이더의 chat model 페이지를 참고하세요. LangSmith는 각 모델 호출을 추적해 프로바이더를 비교하고, 도구 라우팅을 살펴보고, 실패를 디버깅할 수 있게 해줍니다. LangSmith Engine을 함께 설정하면 트레이스를 모니터링하면서 문제를 감지하고 수정안을 제안받을 수 있어요.
기본 사용법 (Basic usage)
모델은 두 가지 방식으로 사용할 수 있어요.
- 에이전트와 함께 — 에이전트를 만들 때 모델을 동적으로 지정합니다.
- 독립 실행 (Standalone) — 에이전트 프레임워크 없이, 텍스트 생성·분류·추출 같은 작업을 위해 (에이전트 루프 밖에서) 직접 호출합니다.
같은 모델 인터페이스가 두 맥락 모두에서 동작해서, 단순하게 시작했다가 필요에 따라 더 복잡한 에이전트 기반 워크플로로 확장하기 좋아요.
모델 초기화 (Initialize a model)
LangChain에서 독립 모델을 시작하는 가장 쉬운 방법은 init_chat_model을 쓰는 거예요. OpenAI, Anthropic, Azure, Google Gemini, AWS Bedrock, HuggingFace, OpenRouter 중 원하는 채팅 모델 프로바이더를 고르면 됩니다.
pip install -U "langchain[openai]"
import os
from langchain.chat_models import init_chat_model
os.environ["OPENAI_API_KEY"] = "sk-..."
model = init_chat_model("gpt-5.5")
import os
from langchain_openai import ChatOpenAI
os.environ["OPENAI_API_KEY"] = "sk-..."
model = ChatOpenAI(model="gpt-5.5")
response = model.invoke("Why do parrots talk?")
init_chat_model에 대한 더 자세한 내용(모델 파라미터를 넘기는 방법 포함)은 init_chat_model 문서를 참고하세요.
주요 메서드 (Key methods)
| 메서드 | 설명 |
|---|---|
invoke |
모델이 완전한 응답을 생성한 뒤 메시지를 입력받고 메시지를 출력합니다. |
stream |
모델을 호출하되, 생성되는 대로 실시간으로 출력을 스트리밍합니다. |
batch |
여러 요청을 배치로 보내 더 효율적으로 처리합니다. |
채팅 모델 외에도 LangChain은 임베딩 모델, 벡터 스토어 같은 인접 기술을 지원합니다. 자세한 내용은 통합 페이지를 참고하세요.
파라미터 (Parameters)
채팅 모델은 동작을 설정하는 파라미터를 받아요. 지원되는 파라미터 전체 집합은 모델과 프로바이더마다 다르지만, 표준적인 것들은 다음과 같습니다.
| 파라미터 | 타입 | 설명 |
|---|---|---|
model |
string (필수) | 프로바이더와 함께 쓰려는 특정 모델의 이름이나 식별자. openai:o1처럼 : 형식으로 모델과 프로바이더를 하나의 인자로 지정할 수도 있어요. |
api_key |
string | 모델의 프로바이더와 인증하기 위한 키. 보통 가입 시 발급되며 환경 변수로 설정해 두는 경우가 많아요. |
temperature |
number | 모델 출력의 무작위성을 조절합니다. 클수록 창의적, 작을수록 결정적이에요. |
max_tokens |
number | 응답의 총 토큰 수를 제한해 출력 길이를 조절합니다. |
timeout |
number | 응답을 기다리는 최대 시간(초). 초과하면 요청을 취소해요. |
max_retries |
number (기본 "6") |
네트워크 타임아웃·요율 제한 같은 실패 시 요청을 재전송하는 최대 횟수. 지수 백오프 + 지터(jitter)를 사용합니다. |
init_chat_model로 파라미터를 넘기는 예시:
model = init_chat_model(
"claude-sonnet-4-6",
# Kwargs passed to the model:
temperature=0.7,
timeout=30,
max_tokens=1000,
max_retries=6, # Default; increase for unreliable networks
)
연결 복원력 (Connection resilience)
LangChain 채팅 모델은 실패한 API 요청을 지수 백오프로 자동 재시도해요. 기본적으로 네트워크 오류·요율 제한(429)·서버 오류(5xx)에 대해 최대 6회 재시도하며, 401(권한 없음)이나 404 같은 클라이언트 오류는 재시도하지 않습니다.
모델을 만들 때 max_retries와 timeout을 조정할 수 있고, 그 인스턴스를 create_agent, create_deep_agent에 넘기거나 독립적으로 호출할 수 있어요.
from langchain.chat_models import init_chat_model
model = init_chat_model(
"google_genai:gemini-3.6-flash",
max_retries=10, # Increase for unreliable networks (default: 6)
timeout=120, # Seconds; increase for slow connections
)
불안정한 네트워크에서 오래 실행되는 에이전트 그래프라면 더 높은 max_retries(예: 10–15)와 함께 체크포인터를 써서 실패해도 진행 상태가 보존되게 하는 게 좋아요.
각 채팅 모델 통합은 프로바이더 고유 기능을 제어하는 추가 파라미터를 가질 수 있어요. 예를 들어 ChatOpenAI는 OpenAI Responses API를 쓸지 Completions API를 쓸지 정하는 use_responses_api가 있습니다. 특정 채팅 모델이 지원하는 모든 파라미터는 채팅 모델 통합 페이지에서 확인하세요.
호출 (Invocation)
채팅 모델은 출력을 생성하기 위해 호출(invoke)되어야 해요. 상황에 따라 쓰이는 세 가지 주요 호출 메서드가 있습니다.
invoke
모델을 호출하는 가장 직관적인 방법으로, 단일 메시지 또는 메시지 리스트를 인자로 받아요.
response = model.invoke("Why do parrots have colorful feathers?")
print(response)
채팅 모델에는 대화 기록을 나타내는 메시지 리스트를 줄 수 있어요. 각 메시지는 역할(role)을 가지며, 모델이 대화에서 누가 보낸 메시지인지 알 수 있게 합니다.
딕셔너리 형식:
conversation = [
{"role": "system", "content": "You are a helpful assistant that translates English to French."},
{"role": "user", "content": "Translate: I love programming."},
{"role": "assistant", "content": "J'adore la programmation."},
{"role": "user", "content": "Translate: I love building applications."}
]
response = model.invoke(conversation)
print(response) # AIMessage("J'adore créer des applications.")
메시지 객체 형식:
from langchain.messages import HumanMessage, AIMessage, SystemMessage
conversation = [
SystemMessage("You are a helpful assistant that translates English to French."),
HumanMessage("Translate: I love programming."),
AIMessage("J'adore la programmation."),
HumanMessage("Translate: I love building applications.")
]
response = model.invoke(conversation)
print(response) # AIMessage("J'adore créer des applications.")
호출의 반환 타입이 문자열이라면, LLM이 아니라 채팅 모델을 쓰고 있는지 확인하세요. 레거시 텍스트 완성 LLM은 문자열을 직접 반환합니다. LangChain 채팅 모델은 Chat 접두사가 붙어요. 예: ChatOpenAI.
stream
대부분의 모델은 출력을 생성하면서 스트리밍할 수 있어요. 긴 응답일수록 점진적으로 표시되는 스트리밍이 사용자 경험을 크게 개선합니다.
stream()을 호출하면 생성되는 대로 출력 청크를 내놓는 이터레이터를 반환합니다.
for chunk in model.stream("Why do parrots have colorful feathers?"):
print(chunk.text, end="|", flush=True)
invoke()가 전체 응답을 다 생성한 뒤 단일 AIMessage를 반환하는 것과 달리, stream()은 각각 출력 텍스트의 일부를 담은 여러 AIMessageChunk 객체를 반환해요. 특히 스트림의 각 청크는 합산을 통해 하나의 완전한 메시지로 모으도록 설계되었습니다.
full = None # None | AIMessageChunk
for chunk in model.stream("What color is the sky?"):
full = chunk if full is None else full + chunk
print(full.text)
# The
# The sky
# The sky is
# The sky is typically
# The sky is typically blue
# ...
print(full.content_blocks)
# [{"type": "text", "text": "The sky is typically blue..."}]
스트리밍은 프로그램의 모든 단계가 청크 스트림을 처리하는 방법을 안다고 전제해요. 예를 들어 처리 전에 전체 출력을 메모리에 저장해야 하는 애플리케이션은 스트리밍을 지원하지 않는 경우입니다.
batch
독립적인 요청 모음을 배치로 처리하면 병렬 처리가 가능해져 성능이 크게 개선되고 비용이 줄어들 수 있어요.
responses = model.batch([
"Why do parrots have colorful feathers?",
"How do airplanes fly?",
"What is quantum computing?"
])
for response in responses:
print(response)
주의할 점: 여기서 설명하는 batch()는 클라이언트 측에서 모델 호출을 병렬화하는 메서드입니다. OpenAI나 Anthropic 같은 추론 프로바이더가 지원하는 batch API와는 다릅니다.
기본적으로 batch()는 배치 전체의 최종 출력만 반환합니다. 각 입력의 출력이 생성되는 대로 받고 싶다면 batch_as_completed()로 스트리밍하면 돼요.
for response in model.batch_as_completed([
"Why do parrots have colorful feathers?",
"How do airplanes fly?",
"What is quantum computing?"
]):
print(response)
batch_as_completed()를 쓰면 결과가 순서대로 오지 않을 수 있어요. 각 결과에는 입력 인덱스가 포함되므로 필요하면 원래 순서를 재구성할 수 있습니다.
많은 입력을 batch()나 batch_as_completed()로 처리할 때 병렬 호출의 최대 수를 제한하고 싶다면, RunnableConfig 딕셔너리에 max_concurrency 속성을 설정하면 돼요.
model.batch(
list_of_inputs,
config={
'max_concurrency': 5, # Limit to 5 parallel calls
}
)
도구 호출 (Tool calling)
모델은 데이터베이스에서 데이터를 가져오거나, 웹을 검색하거나, 코드를 실행하는 도구를 호출하도록 요청할 수 있어요. 도구는 다음의 짝으로 이루어집니다:
- 스키마 — 도구 이름, 설명, 인자 정의(보통 JSON 스키마)
- 실행할 함수 또는 코루틴
"function calling"이라는 용어를 들을 수도 있는데, 우리는 "tool calling"과 같은 뜻으로 씁니다. 직접 정의한 도구를 모델이 사용할 수 있게 하려면 bind_tools로 바인딩해야 해요. 이후 호출에서 모델은 바인딩된 도구 중 필요에 따라 아무거나 호출할 수 있습니다.
일부 모델 프로바이더는 모델 또는 호출 파라미터로 활성화할 수 있는 내장 도구를 제공하기도 해요(예: ChatOpenAI, ChatAnthropic). 자세한 내용은 해당 프로바이더 레퍼런스를 확인하세요.
from langchain.tools import tool
@tool
def get_weather(location: str) -> str:
"""Get the weather at a location."""
return f"It's sunny in {location}."
model_with_tools = model.bind_tools([get_weather])
response = model_with_tools.invoke("What's the weather like in Boston?")
for tool_call in response.tool_calls:
# View tool calls made by the model
print(f"Tool: {tool_call['name']}")
print(f"Args: {tool_call['args']}")
사용자 정의 도구를 바인딩하면 모델 응답에 도구 실행 요청이 포함됩니다. 모델을 에이전트와 분리해서 쓸 때는 요청된 도구를 직접 실행하고 그 결과를 모델에 돌려줘야 해요(후속 추론에 쓰이도록). 에이전트를 쓸 때는 에이전트 루프가 도구 실행 루프를 대신 처리해줍니다.
구조화된 출력 (Structured output)
모델이 주어진 스키마에 맞는 형식으로 응답하도록 요청할 수 있어요. 출력을 쉽게 파싱하고 후속 처리에 사용하는 데 유용하죠. LangChain은 여러 스키마 타입과 구조화된 출력을 강제하는 방법을 지원합니다. 자세한 내용은 "Structured output" 문서를 참고하세요.
Pydantic 모델은 필드 검증, 설명, 중첩 구조를 갖춘 가장 풍부한 기능 집합을 제공합니다.
from pydantic import BaseModel, Field
class Movie(BaseModel):
"""A movie with details."""
title: str = Field(description="The title of the movie")
year: int = Field(description="The year the movie was released")
director: str = Field(description="The director of the movie")
rating: float = Field(description="The movie's rating out of 10")
model_with_structure = model.with_structured_output(Movie)
response = model_with_structure.invoke("Provide details about the movie Inception")
print(response) # Movie(title="Inception", year=2010, director="Christopher Nolan", rating=8.8)
구조화된 출력의 주요 고려사항:
- Method 파라미터: 프로바이더에 따라 구조화된 출력 방식이 달라요.
'json_schema'(프로바이더의 전용 구조화 출력 기능),'function_calling'(주어진 스키마를 따르는 도구 호출을 강제),'json_mode'(json_schema의 전신, 유효한 JSON을 생성하지만 스키마를 프롬프트로 설명해야 함). - include_raw:
include_raw=True로 설정하면 파싱된 출력과 원본 AI 메시지를 모두 얻을 수 있어요. Pydantic은 자동 검증을 제공하지만, TypedDict와 JSON Schema는 수동 검증이 필요합니다.
고급 주제 (Advanced topics)
모델 프로파일 (Model profiles)
모델 프로파일은 langchain>=1.1이 필요해요. LangChain 채팅 모델은 profile 속성을 통해 지원되는 기능과 능력의 딕셔너리를 노출할 수 있습니다.
model.profile
# {
# "max_input_tokens": 400000,
# "image_inputs": True,
# "reasoning_output": True,
# "tool_calling": True,
# ...
# }
모델 프로파일 데이터의 많은 부분은 모델 능력 데이터를 제공하는 오픈소스 프로젝트 models.dev에서 제공되며, LangChain 용도에 맞는 추가 필드로 보강됩니다. 이 데이터를 활용하면:
- 요약 미들웨어가 모델의 컨텍스트 윈도우 크기에 따라 요약을 트리거하고
create_agent의 구조화된 출력 전략이 자동으로 추론되며- 지원되는 모달리티와 최대 입력 토큰에 따라 모델 입력이 게이트(gate)됩니다.
모델 프로파일은 베타 기능입니다. 프로파일 형식은 변경될 수 있어요.
멀티모달 (Multimodal)
일부 모델은 이미지, 오디오, 비디오 같은 비텍스트 데이터를 처리하고 반환할 수 있어요. 콘텐츠 블록(content blocks)을 제공해 비텍스트 데이터를 모델에 전달할 수 있습니다. 멀티모달 능력이 있는 모든 LangChain 채팅 모델은 교차 프로바이더 표준 형식, OpenAI chat completions 형식, 해당 프로바이더 고유 형식을 지원해요.
일부 모델은 응답의 일부로 멀티모달 데이터를 반환할 수 있어요. 호출되면 결과 AIMessage에 멀티모달 타입의 콘텐츠 블록이 담겨 있습니다.
response = model.invoke("Create a picture of a cat")
print(response.content_blocks)
# [
# {"type": "text", "text": "Here's a picture of a cat"},
# {"type": "image", "base64": "...", "mime_type": "image/jpeg"},
# ]
추론 (Reasoning)
많은 모델이 결론에 도달하기 위해 다단계 추론을 수행할 수 있어요. 복잡한 문제를 더 작고 다루기 쉬운 단계로 쪼개는 방식이죠. 기반 모델이 지원한다면 이 추론 과정을 표면화해서 모델이 최종 답에 어떻게 도달했는지 이해할 수 있습니다.
for chunk in model.stream("Why do parrots have colorful feathers?"):
reasoning_steps = [r for r in chunk.content_blocks if r["type"] == "reasoning"]
print(reasoning_steps if reasoning_steps else chunk.text)
모델에 따라 추론에 들이는 "노력"의 수준을 지정할 수도 있고, 추론을 아예 끄도록 요청할 수도 있어요. 범주형 "tier"(예: 'low'나 'high') 또는 정수 토큰 예산의 형태일 수 있어요. ChatOpenAI, ChatAnthropic, ChatFireworks, ChatXAI, ChatGoogleGenerativeAI, ChatBedrockConverse는 표준 reasoning_effort 파라미터를 지원합니다. 각 프로바이더는 이를 자체 API 형식으로 번역하죠.
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(model="claude-sonnet-4-6")
response = model.invoke(
"Why do parrots have colorful feathers?",
reasoning_effort="high",
)
지원되는 effort 수준과 프로바이더의 문서상 기본값은 모델마다 달라요. 모델 프로파일에서 지원 수준과 기본값을 확인할 수 있습니다.
로컬 모델 (Local models)
LangChain은 자체 하드웨어에서 로컬로 모델을 실행하는 것을 지원해요. 데이터 프라이버시가 중요한 경우, 커스텀 모델을 호출하고 싶을 때, 또는 클라우드 모델 사용 비용을 피하고 싶을 때 유용합니다. Ollama는 채팅·임베딩 모델을 로컬에서 실행하는 가장 쉬운 방법 중 하나예요.
프롬프트 캐싱 (Prompt caching)
많은 프로바이더가 같은 토큰을 반복 처리할 때 지연 시간과 비용을 줄이는 프롬프트 캐싱 기능을 제공해요. 캐싱은 세 수준에서 작동합니다.
- 암시적 프로바이더 캐싱: 요청이 캐시에 걸리면 별도 설정 없이 프로바이더가 비용 절감을 자동으로 넘겨줍니다(예: OpenAI, Gemini).
- 프로바이더 레벨 명시적 제어: 수동으로 캐시 지점을 표시해 제어를 강화하거나 비용 절감을 보장합니다(예:
ChatOpenAI의prompt_cache_key, Anthropic의 content-blockcache_control, AWS BedrockcachePoint블록). - LangChain 미들웨어: 에이전트에 대해 미들웨어가 안정적인 시스템 프롬프트·도구 콘텐츠의 캐싱을 최적화하게 합니다(예: Anthropic의
AnthropicPromptCachingMiddleware, AWS Bedrock의BedrockPromptCachingMiddleware).
프롬프트 캐싱은 종종 최소 입력 토큰 임계값 이상에서만 사용됩니다. 프로바이더별 상세는 해당 페이지를 참고하세요.
서버 측 도구 사용 (Server-side tool use)
일부 프로바이더는 서버 측 도구 호출 루프를 지원해요. 모델이 웹 검색, 코드 인터프리터 등의 도구와 상호작용하고 그 결과를 단일 대화 턴 안에서 분석할 수 있게 합니다. 모델이 서버 측에서 도구를 호출하면, 응답 메시지의 콘텐츠에 도구의 호출과 결과를 나타내는 콘텐츠가 포함됩니다. 프로바이더에 구애받지 않는 형식으로 서버 측 도구 호출과 결과를 반환받을 수 있죠.
from langchain.chat_models import init_chat_model
model = init_chat_model("gpt-5.4-mini")
tool = {"type": "web_search"}
model_with_tools = model.bind_tools([tool])
response = model_with_tools.invoke("What was a positive news story from today?")
print(response.content_blocks)
이는 단일 대화 턴을 나타내며, 클라이언트 측 도구 호출처럼 넘겨야 하는 관련 ToolMessage 객체가 없어요.
모델 예외 (Model exceptions)
주요 통합 패키지는 인증 오류, 요율 제한, 타임아웃 같은 일반적인 모델 실패에 대해 langchain_core.exceptions의 표준 예외 타입을 던져요. 이 예외들은 LangChain 기본 타입과 프로바이더 SDK의 자체 예외 타입에서 모두 상속받으므로, 둘 중 아무거나 잡을 수 있습니다.
from langchain.chat_models import init_chat_model
from langchain_core.exceptions import ModelTimeoutError
model = init_chat_model("openai:gpt-5.6-luna", timeout=0.0001)
try:
response = model.invoke("Hello")
except ModelTimeoutError:
print("caught")
각 타입은 재시도 미들웨어가 기본적으로 존중하는 is_retryable 속성을 갖습니다.
요율 제한 (Rate limiting)
많은 채팅 모델 프로바이더가 주어진 시간 동안 만들 수 있는 호출 수를 제한해요. 요율 제한에 걸리면 보통 프로바이더로부터 rate limit 오류 응답을 받고, 더 요청하기 전에 기다려야 합니다. 이를 관리하기 위해 채팅 모델 통합은 초기화 시 rate_limiter 파라미터를 받아 요청 생성 속도를 제어할 수 있게 해줍니다.
Base URL과 프록시 설정
OpenAI Chat Completions API를 구현하는 프로바이더에 대해 커스텀 base URL을 구성할 수 있어요. model_provider="openai"(또는 직접 ChatOpenAI 사용)는 공식 OpenAI API 스펙을 대상으로 합니다. 라우터와 프록시의 프로바이더별 필드는 추출되거나 보존되지 않을 수 있어요. OpenRouter와 LiteLLM은 전용 통합을 선호합니다: ChatOpenRouter(langchain-openrouter), ChatLiteLLM/ChatLiteLLMRouter(langchain-litellm).
로그 확률 (Log probabilities)
일부 모델은 초기화 시 logprobs 파라미터를 설정해 토큰 수준의 로그 확률을 반환하도록 구성할 수 있어요.
model = init_chat_model(
model="gpt-5.5",
model_provider="openai"
).bind(logprobs=True)
response = model.invoke("Why do parrots talk?")
print(response.response_metadata["logprobs"])
토큰 사용량 (Token usage)
많은 모델 프로바이더가 호출 응답의 일부로 토큰 사용량 정보를 반환해요. 사용 가능할 때 이 정보는 해당 모델이 만든 AIMessage 객체에 포함됩니다. OpenAI와 Azure OpenAI chat completions 같은 일부 프로바이더 API는 스트리밍 상황에서 토큰 사용량 데이터를 받으려면 옵트인이 필요해요.
콜백이나 컨텍스트 매니저로 애플리케이션 전체의 모델 간 집계 토큰 수를 추적할 수 있어요.
from langchain.chat_models import init_chat_model
from langchain_core.callbacks import UsageMetadataCallbackHandler
model_1 = init_chat_model(model="gpt-5.4-mini")
model_2 = init_chat_model(model="claude-haiku-4-5-20251001")
callback = UsageMetadataCallbackHandler()
result_1 = model_1.invoke("Hello", config={"callbacks": [callback]})
result_2 = model_2.invoke("Hello", config={"callbacks": [callback]})
print(callback.usage_metadata)
# {
# 'gpt-5.4-mini': {
# 'input_tokens': 8, 'output_tokens': 10, 'total_tokens': 18,
# 'input_token_details': {'audio': 0, 'cache_read': 0},
# 'output_token_details': {'audio': 0, 'reasoning': 0}
# },
# 'claude-haiku-4-5-20251001': {
# 'input_tokens': 8, 'output_tokens': 21, 'total_tokens': 29,
# 'input_token_details': {'cache_read': 0, 'cache_creation': 0}
# }
# }
호출 설정 (Invocation config)
모델을 호출할 때 RunnableConfig 딕셔너리를 사용해 config 파라미터로 추가 설정을 넘길 수 있어요. 실행 동작, 콜백, 메타데이터 추적을 런타임에 제어할 수 있죠.
response = model.invoke(
"Tell me a joke",
config={
"run_name": "joke_generation", # Custom name for this run
"tags": ["humor", "demo"], # Tags for categorization
"metadata": {"user_id": "123"}, # Custom metadata
"callbacks": [my_callback_handler], # Callback handlers
}
)
이 설정 값들은 LangSmith 트레이싱으로 디버깅할 때, 커스텀 로깅·모니터링을 구현할 때, 프로덕션에서 리소스 사용을 제어할 때, 복잡한 파이프라인에서 호출을 추적할 때 특히 유용해요.
설정 가능한 모델 (Configurable models)
configurable_fields를 지정해 런타임에 설정 가능한 모델을 만들 수도 있어요. 모델 값을 지정하지 않으면 기본적으로 model과 model_provider가 설정 가능해집니다.
from langchain.chat_models import init_chat_model
configurable_model = init_chat_model(temperature=0)
configurable_model.invoke(
"what's your name",
config={"configurable": {"model": "gpt-5-nano"}}, # Run with GPT-5-Nano
)
configurable_model.invoke(
"what's your name",
config={"configurable": {"model": "claude-sonnet-4-6"}}, # Run with Claude
)
동적 모델 선택 (Dynamic model selection)
동적 모델은 현재 상태와 컨텍스트에 따라 런타임에 선택됩니다. 정교한 라우팅 로직과 비용 최적화를 가능하게 하죠. 동적 모델을 쓰려면 @wrap_model_call 데코레이터로 미들웨어를 만들어 요청의 모델을 수정하면 돼요.
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
basic_model = ChatOpenAI(model="gpt-5.4-mini")
advanced_model = ChatOpenAI(model="gpt-5.5")
@wrap_model_call
def dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse:
"""Choose model based on conversation complexity."""
message_count = len(request.state["messages"])
if message_count > 10:
# Use an advanced model for longer conversations
model = advanced_model
else:
model = basic_model
return handler(request.override(model=model))
agent = create_agent(
model=basic_model, # Default model
tools=[],
middleware=[dynamic_model_selection]
)
구조화된 출력을 쓸 때는 미리 바인딩된 모델(이미 bind_tools가 호출된 모델)이 지원되지 않아요. 구조화된 출력과 함께 동적 모델 선택이 필요하다면, 미들웨어에 넘기는 모델이 사전 바인딩되지 않도록 하세요.