ChatAnthropic 통합

ChatAnthropic 통합 (ChatAnthropic integration)

LangChain JavaScript로 ChatAnthropic 채팅 모델과 통합하세요.

Anthropic은 AI 안전과 연구 회사입니다. Claude의 창시자입니다.

이 문서는 ChatAnthropic 채팅 모델을 시작하는 데 도움이 됩니다. 모든 ChatAnthropic 기능과 구성에 대한 자세한 문서는 API reference를 참조하세요.

개요 (Overview)

통합 세부 사항 (Integration details)

클래스 패키지 직렬화 가능 PY 지원 다운로드 버전
ChatAnthropic @langchain/anthropic NPM - Downloads NPM - Version

모델 기능 (Model features)

특정 기능을 사용하는 방법에 대한 가이드는 아래 표 머리글의 링크를 참조하세요.

도구 호출 구조화된 출력 이미지 입력 오디오 입력 비디오 입력 토큰 수준 스트리밍 토큰 사용량 Logprobs

설정 (Setup)

가입하고 Anthropic API 키를 얻고, @langchain/anthropic 통합 패키지를 설치해야 합니다.

자격 증명 (Credentials)

Anthropic 웹사이트로 가서 Anthropic에 가입하고 API 키를 생성하세요. 완료한 뒤 ANTHROPIC_API_KEY 환경 변수를 설정하세요:

export ANTHROPIC_API_KEY="your-api-key"

모델 호출의 자동 추적을 원한다면 아래 주석을 해제해 LangSmith API 키도 설정할 수 있습니다:

# export LANGSMITH_TRACING="true"
# export LANGSMITH_API_KEY="your-api-key"

설치 (Installation)

LangChain ChatAnthropic 통합은 @langchain/anthropic 패키지에 있습니다:

```bash npm theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}} npm install @langchain/anthropic @langchain/core ```
yarn add @langchain/anthropic @langchain/core
pnpm add @langchain/anthropic @langchain/core

인스턴스화 (Instantiation)

이제 모델 객체를 인스턴스화하고 채팅 완성을 생성할 수 있습니다:

import { ChatAnthropic } from "@langchain/anthropic"

const llm = new ChatAnthropic({
    model: "claude-haiku-4-5-20251001",
    // temperature: 0, // Non-default values are rejected on newer Claude models; see Sampling parameters
    maxTokens: undefined,
    maxRetries: 2,
    // other params...
});

샘플링 파라미터 (Sampling parameters)

최신 Claude 모델은 기본이 아닌 샘플링 파라미터를 거부합니다. claude-opus-5, claude-fable-5, claude-opus-4-8, claude-opus-4-7, 또는 claude-sonnet-5에서 temperature, topP, 또는 topK를 기본이 아닌 값으로 설정하면 400 오류를 반환합니다:

const model = new ChatAnthropic({ model: "claude-opus-5", temperature: 0 });
await model.invoke("Hello!");
// BadRequestError: 400
// {"type":"error","error":{"type":"invalid_request_error",
//  "message":"`temperature` is deprecated for this model."}}

모델별 지원:

모델 temperature / topP / topK
claude-opus-5, claude-fable-5, claude-opus-4-8, claude-opus-4-7, claude-sonnet-5 기본이 아닌 값 거부(400). 파라미터를 생략하거나 기본값만 전달하세요(예: temperature: 1).
claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 및 이전 허용
**모델 문자열을 업그레이드하고 있나요?**

new ChatAnthropic({ model, temperature: 0 })로 작성된 코드는 모델을 위의 최신 모델 중 하나로 업그레이드하면 깨집니다. 값을 조정하는 대신 샘플링 파라미터를 제거하세요. 이 모델들에서는 프롬프팅으로 출력 스타일을 조정하세요. 자세한 내용은 Anthropic 마이그레이션 가이드를 참조하세요.

호출 (Invocation)

const aiMsg = await llm.invoke([
    [
        "system",
        "You are a helpful assistant that translates English to French. Translate the user sentence.",
    ],
    ["human", "I love programming."],
])
aiMsg
AIMessage {
  "id": "msg_013WBXXiggy6gMbAUY6NpsuU",
  "content": "Voici la traduction en français :\n\nJ'adore la programmation.",
  "additional_kwargs": {
    "id": "msg_013WBXXiggy6gMbAUY6NpsuU",
    "type": "message",
    "role": "assistant",
    "model": "claude-haiku-4-5-20251001",
    "stop_reason": "end_turn",
    "stop_sequence": null,
    "usage": {
      "input_tokens": 29,
      "output_tokens": 20
    }
  },
  "response_metadata": {
    "id": "msg_013WBXXiggy6gMbAUY6NpsuU",
    "model": "claude-haiku-4-5-20251001",
    "stop_reason": "end_turn",
    "stop_sequence": null,
    "usage": {
      "input_tokens": 29,
      "output_tokens": 20
    },
    "type": "message",
    "role": "assistant"
  },
  "tool_calls": [],
  "invalid_tool_calls": [],
  "usage_metadata": {
    "input_tokens": 29,
    "output_tokens": 20,
    "total_tokens": 49
  }
}
console.log(aiMsg.content)
Voici la traduction en français :

J'adore la programmation.

콘텐츠 블록 (Content blocks)

Anthropic 모델과 대부분의 다른 모델 사이의 한 가지 핵심 차이는 단일 Anthropic AIMessage의 콘텐츠가 단일 문자열이거나 콘텐츠 블록 목록일 수 있다는 것입니다. 예를 들어 Anthropic 모델이 도구를 호출하면 도구 호출은 메시지 콘텐츠의 일부입니다(표준화된 AIMessage.tool_calls 필드에도 노출됩니다):

import { ChatAnthropic } from "@langchain/anthropic";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import * as z from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";

const calculatorSchema = z.object({
  operation: z
    .enum(["add", "subtract", "multiply", "divide"])
    .describe("The type of operation to execute."),
  number1: z.number().describe("The first number to operate on."),
  number2: z.number().describe("The second number to operate on."),
});

const calculatorTool = {
  name: "calculator",
  description: "A simple calculator tool",
  input_schema: zodToJsonSchema(calculatorSchema),
};

const toolCallingLlm = new ChatAnthropic({
  model: "claude-haiku-4-5-20251001",
}).bindTools([calculatorTool]);

const toolPrompt = ChatPromptTemplate.fromMessages([
  [
    "system",
    "You are a helpful assistant who always needs to use a calculator.",
  ],
  ["human", "{input}"],
]);

// Chain your prompt and model together
const toolCallChain = toolPrompt.pipe(toolCallingLlm);

await toolCallChain.invoke({
  input: "What is 2 + 2?",
});
AIMessage {
  "id": "msg_01DZGs9DyuashaYxJ4WWpWUP",
  "content": [
    {
      "type": "text",
      "text": "Here is the calculation for 2 + 2:"
    },
    {
      "type": "tool_use",
      "id": "toolu_01SQXBamkBr6K6NdHE7GWwF8",
      "name": "calculator",
      "input": {
        "number1": 2,
        "number2": 2,
        "operation": "add"
      }
    }
  ],
  "additional_kwargs": {
    "id": "msg_01DZGs9DyuashaYxJ4WWpWUP",
    "type": "message",
    "role": "assistant",
    "model": "claude-haiku-4-5-20251001",
    "stop_reason": "tool_use",
    "stop_sequence": null,
    "usage": {
      "input_tokens": 449,
      "output_tokens": 100
    }
  },
  "response_metadata": {
    "id": "msg_01DZGs9DyuashaYxJ4WWpWUP",
    "model": "claude-haiku-4-5-20251001",
    "stop_reason": "tool_use",
    "stop_sequence": null,
    "usage": {
      "input_tokens": 449,
      "output_tokens": 100
    },
    "type": "message",
    "role": "assistant"
  },
  "tool_calls": [
    {
      "name": "calculator",
      "args": {
        "number1": 2,
        "number2": 2,
        "operation": "add"
      },
      "id": "toolu_01SQXBamkBr6K6NdHE7GWwF8",
      "type": "tool_call"
    }
  ],
  "invalid_tool_calls": [],
  "usage_metadata": {
    "input_tokens": 449,
    "output_tokens": 100,
    "total_tokens": 549
  }
}

커스텀 헤더 (Custom headers)

요청에 커스텀 헤더를 다음과 같이 전달할 수 있습니다:

import { ChatAnthropic } from "@langchain/anthropic";

const llmWithCustomHeaders = new ChatAnthropic({
  model: "claude-sonnet-4-6",
  maxTokens: 1024,
  clientOptions: {
    defaultHeaders: {
      "X-Api-Key": process.env.ANTHROPIC_API_KEY,
    },
  },
});

await llmWithCustomHeaders.invoke("Why is the sky blue?");
AIMessage {
  "id": "msg_019z4nWpShzsrbSHTWXWQh6z",
  "content": "The sky appears blue due to a phenomenon called Rayleigh scattering. Here's a brief explanation:\n\n1) Sunlight is made up of different wavelengths of visible light, including all the colors of the rainbow.\n\n2) As sunlight passes through the atmosphere, the gases (mostly nitrogen and oxygen) cause the shorter wavelengths of light, such as violet and blue, to be scattered more easily than the longer wavelengths like red and orange.\n\n3) This scattering of the shorter blue wavelengths occurs in all directions by the gas molecules in the atmosphere.\n\n4) Our eyes are more sensitive to the scattered blue light than the scattered violet light, so we perceive the sky as having a blue color.\n\n5) The scattering is more pronounced for light traveling over longer distances through the atmosphere. This is why the sky appears even darker blue when looking towards the horizon.\n\nSo in essence, the selective scattering of the shorter blue wavelengths of sunlight by the gases in the atmosphere is what causes the sky to appear blue to our eyes during the daytime.",
  "additional_kwargs": {
    "id": "msg_019z4nWpShzsrbSHTWXWQh6z",
    "type": "message",
    "role": "assistant",
    "model": "claude-3-sonnet-20240229",
    "stop_reason": "end_turn",
    "stop_sequence": null,
    "usage": {
      "input_tokens": 13,
      "output_tokens": 236
    }
  },
  "response_metadata": {
    "id": "msg_019z4nWpShzsrbSHTWXWQh6z",
    "model": "claude-3-sonnet-20240229",
    "stop_reason": "end_turn",
    "stop_sequence": null,
    "usage": {
      "input_tokens": 13,
      "output_tokens": 236
    },
    "type": "message",
    "role": "assistant"
  },
  "tool_calls": [],
  "invalid_tool_calls": [],
  "usage_metadata": {
    "input_tokens": 13,
    "output_tokens": 236,
    "total_tokens": 249
  }
}

프롬프트 캐싱 (Prompt caching)

Anthropic은 긴 컨텍스트가 필요한 사용 사례의 비용을 줄이기 위해 프롬프트의 일부를 캐싱하는 것을 지원합니다. 도구와 전체 메시지, 개별 블록을 모두 캐시할 수 있습니다.

하나 이상의 블록 또는 "cache_control": { "type": "ephemeral" } 필드가 있는 도구 정의를 포함한 초기 요청은 프롬프트의 그 부분을 자동으로 캐시합니다. 이 초기 캐싱 단계는 추가 비용이 들지만, 후속 요청은 할인된 요금으로 청구됩니다. 캐시 수명은 5분이며, 캐시가 적중될 때마다 갱신됩니다. 더 긴 캐싱을 원하면 cache_control 필드에 "ttl": "1h"를 지정하세요.

캐시할 수 있는 최소 프롬프트 길이가 있으며, 모델에 따라 다릅니다. 자세한 내용은 프롬프트 캐싱 세부 사항을 참조하세요.

다음은 LangChain 개념 문서를 포함하는 시스템 메시지의 일부를 캐싱하는 예시입니다:

let CACHED_TEXT = "...";
// @lc-docs-hide-cell

CACHED_TEXT = `## Components

LangChain provides standard, extendable interfaces and external integrations for various components useful for building with LLMs.
Some components LangChain implements, some components we rely on third-party integrations for, and others are a mix.

### Chat models

<span data-heading-keywords="chat model,chat models"></span>

Language models that use a sequence of messages as inputs and return chat messages as outputs (as opposed to using plain text).
These are generally newer models (older models are generally \`LLMs\`, see below).
Chat models support the assignment of distinct roles to conversation messages, helping to distinguish messages from the AI, users, and instructions such as system messages.

Although the underlying models are messages in, message out, the LangChain wrappers also allow these models to take a string as input.
This gives them the same interface as LLMs (and simpler to use).
When a string is passed in as input, it will be converted to a \`HumanMessage\` under the hood before being passed to the underlying model.

LangChain does not host any Chat Models, rather we rely on third party integrations.

We have some standardized parameters when constructing ChatModels:

- \`model\`: the name of the model

Chat Models also accept other parameters that are specific to that integration.

<Warning>
**Some chat models have been fine-tuned for **tool calling** and provide a dedicated API for it.**

Generally, such models are better at tool calling than non-fine-tuned models, and are recommended for use cases that require tool calling.
Please see the [tool calling section](/oss/javascript/langchain/tools) for more information.
</Warning>

For specifics on how to use chat models, see the [relevant how-to guides here](/oss/javascript/langchain/models).

#### Multimodality

Some chat models are multimodal, accepting images, audio and even video as inputs.
These are still less common, meaning model providers haven't standardized on the "best" way to define the API.
Multimodal outputs are even less common. As such, we've kept our multimodal abstractions fairly light weight
and plan to further solidify the multimodal APIs and interaction patterns as the field matures.

In LangChain, most chat models that support multimodal inputs also accept those values in OpenAI's content blocks format.
So far this is restricted to image inputs. For models like Gemini which support video and other bytes input, the APIs also support the native, model-specific representations.

For specifics on how to use multimodal models, see the [relevant how-to guides here](/oss/javascript/how-to/#multimodal).

### LLMs

<span data-heading-keywords="llm,llms"></span>

<Warning>
**Pure text-in/text-out LLMs tend to be older or lower-level. Many popular models are best used as [chat completion models](/oss/javascript/langchain/models),**

even for non-chat use cases.

You are probably looking for [the section above instead](/oss/javascript/langchain/models).
</Warning>

Language models that takes a string as input and returns a string.
These are traditionally older models (newer models generally are [Chat Models](/oss/javascript/langchain/models), see above).

Although the underlying models are string in, string out, the LangChain wrappers also allow these models to take messages as input.
This gives them the same interface as [Chat Models](/oss/javascript/langchain/models).
When messages are passed in as input, they will be formatted into a string under the hood before being passed to the underlying model.

LangChain does not host any LLMs, rather we rely on third party integrations.

For specifics on how to use LLMs, see the [relevant how-to guides here](/oss/javascript/langchain/models).

### Message types

Some language models take an array of messages as input and return a message.
There are a few different types of messages.
All messages have a \`role\`, \`content\`, and \`response_metadata\` property.

The \`role\` describes WHO is saying the message.
LangChain has different message classes for different roles.

The \`content\` property describes the content of the message.
This can be a few different things:

- A string (most models deal this type of content)
- A List of objects (this is used for multi-modal input, where the object contains information about that input type and that input location)

#### HumanMessage

This represents a message from the user.

#### AIMessage

This represents a message from the model. In addition to the \`content\` property, these messages also have:

**\`response_metadata\`**

The \`response_metadata\` property contains additional metadata about the response. The data here is often specific to each model provider.
This is where information like log-probs and token usage may be stored.

**\`tool_calls\`**

These represent a decision from a language model to call a tool. They are included as part of an \`AIMessage\` output.
They can be accessed from there with the \`.tool_calls\` property.

This property returns a list of \`ToolCall\`s. A \`ToolCall\` is an object with the following arguments:

- \`name\`: The name of the tool that should be called.
- \`args\`: The arguments to that tool.
- \`id\`: The id of that tool call.

#### SystemMessage

This represents a system message, which tells the model how to behave. Not every model provider supports this.

#### ToolMessage

This represents the result of a tool call. In addition to \`role\` and \`content\`, this message has:

- a \`tool_call_id\` field which conveys the id of the call to the tool that was called to produce this result.
- an \`artifact\` field which can be used to pass along arbitrary artifacts of the tool execution which are useful to track but which should not be sent to the model.

#### (Legacy) FunctionMessage

This is a legacy message type, corresponding to OpenAI's legacy function-calling API. \`ToolMessage\` should be used instead to correspond to the updated tool-calling API.

This represents the result of a function call. In addition to \`role\` and \`content\`, this message has a \`name\` parameter which conveys the name of the function that was called to produce this result.

### Prompt templates

<span data-heading-keywords="prompt,prompttemplate,chatprompttemplate"></span>

Prompt templates help to translate user input and parameters into instructions for a language model.
This can be used to guide a model's response, helping it understand the context and generate relevant and coherent language-based output.

Prompt Templates take as input an object, where each key represents a variable in the prompt template to fill in.

Prompt Templates output a PromptValue. This PromptValue can be passed to an LLM or a ChatModel, and can also be cast to a string or an array of messages.
The reason this PromptValue exists is to make it easy to switch between strings and messages.

There are a few different types of prompt templates:

#### String PromptTemplates

These prompt templates are used to format a single string, and generally are used for simpler inputs.
For example, a common way to construct and use a PromptTemplate is as follows:

\`\`\`typescript
import { PromptTemplate } from "@langchain/core/prompts";

const promptTemplate = PromptTemplate.fromTemplate(
  "Tell me a joke about {topic}"
);

await promptTemplate.invoke({ topic: "cats" });
\`\`\`

#### ChatPromptTemplates

These prompt templates are used to format an array of messages. These "templates" consist of an array of templates themselves.
For example, a common way to construct and use a ChatPromptTemplate is as follows:

\`\`\`typescript
import { ChatPromptTemplate } from "@langchain/core/prompts";

const promptTemplate = ChatPromptTemplate.fromMessages([
  ["system", "You are a helpful assistant"],
  ["user", "Tell me a joke about {topic}"],
]);

await promptTemplate.invoke({ topic: "cats" });
\`\`\`

In the above example, this ChatPromptTemplate will construct two messages when called.
The first is a system message, that has no variables to format.
The second is a HumanMessage, and will be formatted by the \`topic\` variable the user passes in.

#### MessagesPlaceholder

<span data-heading-keywords="messagesplaceholder"></span>

This prompt template is responsible for adding an array of messages in a particular place.
In the above ChatPromptTemplate, we saw how we could format two messages, each one a string.
But what if we wanted the user to pass in an array of messages that we would slot into a particular spot?
This is how you use MessagesPlaceholder.

\`\`\`typescript
import {
  ChatPromptTemplate,
  MessagesPlaceholder,
} from "@langchain/core/prompts";
import { HumanMessage } from "@langchain/core/messages";

const promptTemplate = ChatPromptTemplate.fromMessages([
  ["system", "You are a helpful assistant"],
  new MessagesPlaceholder("msgs"),
]);

promptTemplate.invoke({ msgs: [new HumanMessage({ content: "hi!" })] });
\`\`\`

This will produce an array of two messages, the first one being a system message, and the second one being the HumanMessage we passed in.
If we had passed in 5 messages, then it would have produced 6 messages in total (the system message plus the 5 passed in).
This is useful for letting an array of messages be slotted into a particular spot.

An alternative way to accomplish the same thing without using the \`MessagesPlaceholder\` class explicitly is:

\`\`\`typescript
const promptTemplate = ChatPromptTemplate.fromMessages([
  ["system", "You are a helpful assistant"],
  ["placeholder", "{msgs}"], // <-- This is the changed part
]);
\`\`\`

For specifics on how to use prompt templates, see the [relevant how-to guides here](/oss/javascript/how-to/#prompt-templates).

### Example Selectors

One common prompting technique for achieving better performance is to include examples as part of the prompt.
This gives the language model concrete examples of how it should behave.
Sometimes these examples are hardcoded into the prompt, but for more advanced situations it may be nice to dynamically select them.
Example Selectors are classes responsible for selecting and then formatting examples into prompts.

For specifics on how to use example selectors, see the [relevant how-to guides here](/oss/javascript/how-to/#example-selectors).

### Output parsers

<span data-heading-keywords="output parser"></span>

<Note>
**The information here refers to parsers that take a text output from a model try to parse it into a more structured representation.**

More and more models are supporting function (or tool) calling, which handles this automatically.
It is recommended to use function/tool calling rather than output parsing.
See the [LangChain tools documentation](/oss/javascript/langchain/tools).

</Note>

Responsible for taking the output of a model and transforming it to a more suitable format for downstream tasks.
Useful when you are using LLMs to generate structured data, or to normalize output from chat models and LLMs.

There are two main methods an output parser must implement:

- "Get format instructions": A method which returns a string containing instructions for how the output of a language model should be formatted.
- "Parse": A method which takes in a string (assumed to be the response from a language model) and parses it into some structure.

And then one optional one:

- "Parse with prompt": A method which takes in a string (assumed to be the response from a language model) and a prompt (assumed to be the prompt that generated such a response) and parses it into some structure. The prompt is largely provided in the event the OutputParser wants to retry or fix the output in some way, and needs information from the prompt to do so.

Output parsers accept a string or \`BaseMessage\` as input and can return an arbitrary type.

LangChain has many different types of output parsers. This is a list of output parsers LangChain supports. The table below has various pieces of information:

**Name**: The name of the output parser

**Supports Streaming**: Whether the output parser supports streaming.

**Input Type**: Expected input type. Most output parsers work on both strings and messages, but some (like OpenAI Functions) need a message with specific arguments.

**Output Type**: The output type of the object returned by the parser.

**Description**: Our commentary on this output parser and when to use it.

The current date is ${new Date().toISOString()}`;

// Noop statement to hide output
void 0;
import { ChatAnthropic } from "@langchain/anthropic";

const modelWithCaching = new ChatAnthropic({
  model: "claude-sonnet-4-6",
});

const LONG_TEXT = `You are a pirate. Always respond in pirate dialect.

Use the following as context when answering questions:

${CACHED_TEXT}`;

const messages = [
  {
    role: "system",
    content: [
      {
        type: "text",
        text: LONG_TEXT,
        // Tell Anthropic to cache this block
        cache_control: { type: "ephemeral" },
      },
    ],
  },
  {
    role: "user",
    content: "What types of messages are supported in LangChain?",
  },
];

const res = await modelWithCaching.invoke(messages);

console.log("USAGE:", res.response_metadata.usage);
USAGE: {
  input_tokens: 18,
  cache_creation_input_tokens: 2960,
  cache_read_input_tokens: 0,
  cache_creation: { ephemeral_5m_input_tokens: 2960, ephemeral_1h_input_tokens: 0 },
  output_tokens: 433,
  service_tier: 'standard',
  inference_geo: 'global'
}

Anthropic이 반환한 원시 usage 필드에 cache_creation_input_tokens라는 새 필드가 생긴 것을 볼 수 있습니다.

같은 메시지를 다시 사용하면 긴 텍스트의 입력 토큰이 캐시에서 읽히는 것을 볼 수 있습니다:

const res2 = await modelWithCaching.invoke(messages);

console.log("USAGE:", res2.response_metadata.usage);
USAGE: {
  input_tokens: 18,
  cache_creation_input_tokens: 0,
  cache_read_input_tokens: 2960,
  cache_creation: { ephemeral_5m_input_tokens: 0, ephemeral_1h_input_tokens: 0 },
  output_tokens: 393,
  service_tier: 'standard',
  inference_geo: 'global'
}

도구 캐싱 (Tool caching)

도구 정의 안에 같은 "cache_control": { "type": "ephemeral" }을 설정해 도구도 캐시할 수 있습니다. 이것은 현재 Anthropic의 원시 도구 형식으로 도구를 바인딩해야 합니다. 예시는 다음과 같습니다:

const SOME_LONG_DESCRIPTION = "...";

// Tool in Anthropic format
const anthropicTools = [{
  name: "get_weather",
  description: SOME_LONG_DESCRIPTION,
  input_schema: {
    type: "object",
    properties: {
      location: {
        type: "string",
        description: "Location to get the weather for",
      },
      unit: {
        type: "string",
        description: "Temperature unit to return",
      },
    },
    required: ["location"],
  },
  // Tell Anthropic to cache this tool
  cache_control: { type: "ephemeral" },
}]

const modelWithCachedTools = modelWithCaching.bindTools(anthropicTools);

await modelWithCachedTools.invoke("what is the weather in SF?");

프롬프트 캐싱이 어떻게 작동하는지 더 자세히 알아보려면 Anthropic 문서를 참조하세요.

커스텀 클라이언트 (Custom clients)

Anthropic 모델은 Gemini Enterprise Agent Platform 같은 클라우드 서비스에 호스팅될 수 있으며, 기본 Anthropic 클라이언트와 같은 인터페이스의 다른 기본 클라이언트에 의존합니다. 초기화된 Anthropic 클라이언트 인스턴스를 반환하는 createClient 메서드를 제공해 이러한 서비스에 접근할 수 있습니다. 예시:

import { AnthropicVertex } from "@anthropic-ai/vertex-sdk";

const customClient = new AnthropicVertex();

const modelWithCustomClient = new ChatAnthropic({
  modelName: "claude-sonnet-4-6",
  maxRetries: 0,
  createClient: () => customClient,
});

await modelWithCustomClient.invoke([{ role: "user", content: "Hello!" }]);

인용 (Citations)

Anthropic은 사용자가 제공한 원본 자료를 기반으로 Claude가 답변에 컨텍스트를 첨부할 수 있게 하는 citations 기능을 지원합니다. 이 원본 자료는 전체 문서를 설명하는 문서 콘텐츠 블록으로 제공하거나, 검색 시스템에서 반환된 관련 구절이나 스니펫을 설명하는 검색 결과로 제공할 수 있습니다. 쿼리에 "citations": { "enabled": true }를 포함하면 Claude는 응답에서 제공된 자료에 대한 직접 인용을 생성할 수 있습니다.

문서 예시 (Document example)

이 예시에서 일반 텍스트 문서를 전달합니다. 백그라운드에서 Claude는 입력 텍스트를 자동으로 문장으로 청크하며, 이것은 인용 생성에 사용됩니다.

import { ChatAnthropic } from "@langchain/anthropic";

const citationsModel = new ChatAnthropic({
  model: "claude-haiku-4-5-20251001",
});

const messagesWithCitations = [
  {
    role: "user",
    content: [
      {
        type: "document",
        source: {
          type: "text",
          media_type: "text/plain",
          data: "The grass is green. The sky is blue.",
        },
        title: "My Document",
        context: "This is a trustworthy document.",
        citations: {
          enabled: true,
        },
      },
      {
        type: "text",
        text: "What color is the grass and sky?",
      },
    ],
  }
];

const responseWithCitations = await citationsModel.invoke(messagesWithCitations);

console.log(JSON.stringify(responseWithCitations.content, null, 2));
[
  {
    "type": "text",
    "text": "Based on the document, I can tell you that:\n\n- "
  },
  {
    "type": "text",
    "text": "The grass is green",
    "citations": [
      {
        "type": "char_location",
        "cited_text": "The grass is green. ",
        "document_index": 0,
        "document_title": "My Document",
        "start_char_index": 0,
        "end_char_index": 20
      }
    ]
  },
  {
    "type": "text",
    "text": "\n- "
  },
  {
    "type": "text",
    "text": "The sky is blue",
    "citations": [
      {
        "type": "char_location",
        "cited_text": "The sky is blue.",
        "document_index": 0,
        "document_title": "My Document",
        "start_char_index": 20,
        "end_char_index": 36
      }
    ]
  }
]

검색 결과 예시 (Search results example)

이 예시에서 메시지 콘텐츠의 일부로 검색 결과를 전달합니다. 이렇게 하면 Claude가 응답에서 여러분의 검색 시스템의 특정 구절이나 스니펫을 인용할 수 있습니다.

이 접근 방식은 Claude가 특정 지식 집합의 정보를 인용하길 원하지만, 모델이 자동으로 검색하거나 검색하지 않고 직접 사전에 가져온/캐시된 콘텐츠를 가져오길 원할 때 유용합니다.

import { ChatAnthropic } from "@langchain/anthropic";

const citationsModel = new ChatAnthropic({
  model: "claude-haiku-4-5-20251001",
});

const messagesWithCitations = [
  {
    type: "user",
    content: [
      {
        type: "search_result",
        title: "History of France",
        source: "https://some-uri.com",
        citations: { enabled: true },
        content: [
          {
            type: "text",
            text: "The capital of France is Paris.",
          },
          {
            type: "text",
            text: "The old capital of France was Lyon.",
          },
        ],
      },
      {
        type: "text",
        text: "What is the capital of France?",
      },
    ],
  },
];

const responseWithCitations = await citationsModel.invoke(messagesWithCitations);

console.log(JSON.stringify(responseWithCitations.content, null, 2));

도구의 검색 결과 (Search results from a tool)

도구를 사용해 모델이 응답에서 인용할 수 있는 검색 결과를 제공할 수도 있습니다. 이것은 Claude가 언제, 어디서 정보를 검색할지 결정할 수 있는 RAG(또는 Retrieval-Augmented Generation) 워크플로에 잘 맞습니다. 이 정보를 검색 결과로 반환하면 Claude가 도구에서 반환된 자료로 인용을 만들 수 있습니다.

Anthropic의 citations API가 기대하는 형식으로 검색 결과를 반환하는 도구를 만드는 방법은 다음과 같습니다:

import { ChatAnthropic } from "@langchain/anthropic";
import { tool } from "@langchain/core/tools";

// Create a tool that returns search results
const ragTool = tool(
  () => [
    {
      type: "search_result",
      title: "History of France",
      source: "https://some-uri.com",
      citations: { enabled: true },
      content: [
        {
          type: "text",
          text: "The capital of France is Paris.",
        },
        {
          type: "text",
          text: "The old capital of France was Lyon.",
        },
      ],
    },
    {
      type: "search_result",
      title: "Geography of France",
      source: "https://some-uri.com",
      citations: { enabled: true },
      content: [
        {
          type: "text",
          text: "France is a country in Europe.",
        },
        {
          type: "text",
          text: "The capital of France is Paris.",
        },
      ],
    },
  ],
  {
    name: "my_rag_tool",
    description: "Retrieval system that accesses my knowledge base.",
    schema: z.object({
      query: z.string().describe("query to search in the knowledge base"),
    }),
  }
);

// Create model with search results beta header
const model = new ChatAnthropic({
  model: "claude-haiku-4-5-20251001",
}).bindTools([ragTool]);

const result = await model.invoke([
  {
    role: "user",
    content: "What is the capital of France?",
  },
]);

console.log(JSON.stringify(result.content, null, 2));

LangChain에서 RAG가 어떻게 작동하는지 더 알아보세요.

도구 호출에 대해 더 알아보기

텍스트 스플리터와 함께 사용 (Using with text splitters)

Anthropic은 커스텀 문서 유형으로 자체 분할을 지정할 수도 있습니다. LangChain 텍스트 스플리터를 사용해 이 목적에 맞는 의미 있는 분할을 생성할 수 있습니다. LangChain.js README(마크다운 문서)를 분할해 컨텍스트로 Claude에 전달하는 아래 예시를 참조하세요:

import { ChatAnthropic } from "@langchain/anthropic";
import { MarkdownTextSplitter } from "@langchain/classic/text_splitter";

function formatToAnthropicDocuments(documents: string[]) {
  return {
    type: "document",
    source: {
      type: "content",
      content: documents.map((document) => ({ type: "text", text: document })),
    },
    citations: { enabled: true },
  };
}

// Pull readme
const readmeResponse = await fetch(
  "https://raw.githubusercontent.com/langchain-ai/langchainjs/master/README.md"
);

const readme = await readmeResponse.text();

// Split into chunks
const splitter = new MarkdownTextSplitter({
  chunkOverlap: 0,
  chunkSize: 50,
});
const documents = await splitter.splitText(readme);

// Construct message
const messageWithSplitDocuments = {
  role: "user",
  content: [
    formatToAnthropicDocuments(documents),
    { type: "text", text: "Give me a link to LangChain's tutorials. Cite your sources" },
  ],
};

// Query LLM
const citationsModelWithSplits = new ChatAnthropic({
  model: "claude-sonnet-4-6",
});
const resWithSplits = await citationsModelWithSplits.invoke([messageWithSplitDocuments]);

console.log(JSON.stringify(resWithSplits.content, null, 2));
[
  {
    "type": "text",
    "text": "Based on the documentation, I can provide you with a link to LangChain's tutorials:\n\n"
  },
  {
    "type": "text",
    "text": "The tutorials can be found at: https://js.langchain.com/docs/tutorials/",
    "citations": [
      {
        "type": "content_block_location",
        "cited_text": "[Tutorial](https://js.langchain.com/docs/tutorials/) walkthroughs",
        "document_index": 0,
        "document_title": null,
        "start_block_index": 191,
        "end_block_index": 194
      }
    ]
  }
]

컨텍스트 관리 (Context management)

Anthropic은 모델의 컨텍스트 창을 자동으로 관리하는(예: 도구 결과 지우기) 컨텍스트 편집 기능을 지원합니다.

세부 사항과 구성 옵션은 Anthropic 문서를 참조하세요.

**컨텍스트 관리는 `@langchain/[email protected]` 이후부터 지원됩니다.**
import { ChatAnthropic } from "@langchain/anthropic";

const llm = new ChatAnthropic({
  model: "claude-sonnet-4-6",
  clientOptions: {
    defaultHeaders: {
      "anthropic-beta": "context-management-2025-06-27",
    },
  },
  contextManagement: { edits: [{ type: "clear_tool_uses_20250919" }] },
)
const llmWithTools = llm.bindTools([{ type: "web_search_20250305", name: "web_search" }]);
const response = await llmWithTools.invoke("Search for recent developments in AI");

API reference

모든 ChatAnthropic 기능과 구성에 대한 자세한 문서는 API reference를 참조하세요.


더 알아보기