123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- import { parsePartialJson } from "../utils/json.js";
- import { BaseMessage, BaseMessageChunk, mergeContent, _mergeDicts, _mergeLists, } from "./base.js";
- import { defaultToolCallParser, } from "./tool.js";
- /**
- * Represents an AI message in a conversation.
- */
- export class AIMessage extends BaseMessage {
- get lc_aliases() {
- // exclude snake case conversion to pascal case
- return {
- ...super.lc_aliases,
- tool_calls: "tool_calls",
- invalid_tool_calls: "invalid_tool_calls",
- };
- }
- constructor(fields,
- /** @deprecated */
- kwargs) {
- let initParams;
- if (typeof fields === "string") {
- initParams = {
- content: fields,
- tool_calls: [],
- invalid_tool_calls: [],
- additional_kwargs: kwargs ?? {},
- };
- }
- else {
- initParams = fields;
- const rawToolCalls = initParams.additional_kwargs?.tool_calls;
- const toolCalls = initParams.tool_calls;
- if (!(rawToolCalls == null) &&
- rawToolCalls.length > 0 &&
- (toolCalls === undefined || toolCalls.length === 0)) {
- console.warn([
- "New LangChain packages are available that more efficiently handle",
- "tool calling.\n\nPlease upgrade your packages to versions that set",
- "message tool calls. e.g., `yarn add @langchain/anthropic`,",
- "yarn add @langchain/openai`, etc.",
- ].join(" "));
- }
- try {
- if (!(rawToolCalls == null) && toolCalls === undefined) {
- const [toolCalls, invalidToolCalls] = defaultToolCallParser(rawToolCalls);
- initParams.tool_calls = toolCalls ?? [];
- initParams.invalid_tool_calls = invalidToolCalls ?? [];
- }
- else {
- initParams.tool_calls = initParams.tool_calls ?? [];
- initParams.invalid_tool_calls = initParams.invalid_tool_calls ?? [];
- }
- }
- catch (e) {
- // Do nothing if parsing fails
- initParams.tool_calls = [];
- initParams.invalid_tool_calls = [];
- }
- }
- // Sadly, TypeScript only allows super() calls at root if the class has
- // properties with initializers, so we have to check types twice.
- super(initParams);
- // These are typed as optional to avoid breaking changes and allow for casting
- // from BaseMessage.
- Object.defineProperty(this, "tool_calls", {
- enumerable: true,
- configurable: true,
- writable: true,
- value: []
- });
- Object.defineProperty(this, "invalid_tool_calls", {
- enumerable: true,
- configurable: true,
- writable: true,
- value: []
- });
- /**
- * If provided, token usage information associated with the message.
- */
- Object.defineProperty(this, "usage_metadata", {
- enumerable: true,
- configurable: true,
- writable: true,
- value: void 0
- });
- if (typeof initParams !== "string") {
- this.tool_calls = initParams.tool_calls ?? this.tool_calls;
- this.invalid_tool_calls =
- initParams.invalid_tool_calls ?? this.invalid_tool_calls;
- }
- this.usage_metadata = initParams.usage_metadata;
- }
- static lc_name() {
- return "AIMessage";
- }
- _getType() {
- return "ai";
- }
- get _printableFields() {
- return {
- ...super._printableFields,
- tool_calls: this.tool_calls,
- invalid_tool_calls: this.invalid_tool_calls,
- usage_metadata: this.usage_metadata,
- };
- }
- }
- export function isAIMessage(x) {
- return x._getType() === "ai";
- }
- export function isAIMessageChunk(x) {
- return x._getType() === "ai";
- }
- /**
- * Represents a chunk of an AI message, which can be concatenated with
- * other AI message chunks.
- */
- export class AIMessageChunk extends BaseMessageChunk {
- constructor(fields) {
- let initParams;
- if (typeof fields === "string") {
- initParams = {
- content: fields,
- tool_calls: [],
- invalid_tool_calls: [],
- tool_call_chunks: [],
- };
- }
- else if (fields.tool_call_chunks === undefined) {
- initParams = {
- ...fields,
- tool_calls: fields.tool_calls ?? [],
- invalid_tool_calls: [],
- tool_call_chunks: [],
- usage_metadata: fields.usage_metadata !== undefined
- ? fields.usage_metadata
- : undefined,
- };
- }
- else {
- const toolCalls = [];
- const invalidToolCalls = [];
- for (const toolCallChunk of fields.tool_call_chunks) {
- let parsedArgs = {};
- try {
- parsedArgs = parsePartialJson(toolCallChunk.args || "{}");
- if (parsedArgs === null ||
- typeof parsedArgs !== "object" ||
- Array.isArray(parsedArgs)) {
- throw new Error("Malformed tool call chunk args.");
- }
- toolCalls.push({
- name: toolCallChunk.name ?? "",
- args: parsedArgs,
- id: toolCallChunk.id,
- type: "tool_call",
- });
- }
- catch (e) {
- invalidToolCalls.push({
- name: toolCallChunk.name,
- args: toolCallChunk.args,
- id: toolCallChunk.id,
- error: "Malformed args.",
- type: "invalid_tool_call",
- });
- }
- }
- initParams = {
- ...fields,
- tool_calls: toolCalls,
- invalid_tool_calls: invalidToolCalls,
- usage_metadata: fields.usage_metadata !== undefined
- ? fields.usage_metadata
- : undefined,
- };
- }
- // Sadly, TypeScript only allows super() calls at root if the class has
- // properties with initializers, so we have to check types twice.
- super(initParams);
- // Must redeclare tool call fields since there is no multiple inheritance in JS.
- // These are typed as optional to avoid breaking changes and allow for casting
- // from BaseMessage.
- Object.defineProperty(this, "tool_calls", {
- enumerable: true,
- configurable: true,
- writable: true,
- value: []
- });
- Object.defineProperty(this, "invalid_tool_calls", {
- enumerable: true,
- configurable: true,
- writable: true,
- value: []
- });
- Object.defineProperty(this, "tool_call_chunks", {
- enumerable: true,
- configurable: true,
- writable: true,
- value: []
- });
- /**
- * If provided, token usage information associated with the message.
- */
- Object.defineProperty(this, "usage_metadata", {
- enumerable: true,
- configurable: true,
- writable: true,
- value: void 0
- });
- this.tool_call_chunks =
- initParams.tool_call_chunks ?? this.tool_call_chunks;
- this.tool_calls = initParams.tool_calls ?? this.tool_calls;
- this.invalid_tool_calls =
- initParams.invalid_tool_calls ?? this.invalid_tool_calls;
- this.usage_metadata = initParams.usage_metadata;
- }
- get lc_aliases() {
- // exclude snake case conversion to pascal case
- return {
- ...super.lc_aliases,
- tool_calls: "tool_calls",
- invalid_tool_calls: "invalid_tool_calls",
- tool_call_chunks: "tool_call_chunks",
- };
- }
- static lc_name() {
- return "AIMessageChunk";
- }
- _getType() {
- return "ai";
- }
- get _printableFields() {
- return {
- ...super._printableFields,
- tool_calls: this.tool_calls,
- tool_call_chunks: this.tool_call_chunks,
- invalid_tool_calls: this.invalid_tool_calls,
- usage_metadata: this.usage_metadata,
- };
- }
- concat(chunk) {
- const combinedFields = {
- content: mergeContent(this.content, chunk.content),
- additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs),
- response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata),
- tool_call_chunks: [],
- id: this.id ?? chunk.id,
- };
- if (this.tool_call_chunks !== undefined ||
- chunk.tool_call_chunks !== undefined) {
- const rawToolCalls = _mergeLists(this.tool_call_chunks, chunk.tool_call_chunks);
- if (rawToolCalls !== undefined && rawToolCalls.length > 0) {
- combinedFields.tool_call_chunks = rawToolCalls;
- }
- }
- if (this.usage_metadata !== undefined ||
- chunk.usage_metadata !== undefined) {
- const inputTokenDetails = {
- ...((this.usage_metadata?.input_token_details?.audio !== undefined ||
- chunk.usage_metadata?.input_token_details?.audio !== undefined) && {
- audio: (this.usage_metadata?.input_token_details?.audio ?? 0) +
- (chunk.usage_metadata?.input_token_details?.audio ?? 0),
- }),
- ...((this.usage_metadata?.input_token_details?.cache_read !==
- undefined ||
- chunk.usage_metadata?.input_token_details?.cache_read !==
- undefined) && {
- cache_read: (this.usage_metadata?.input_token_details?.cache_read ?? 0) +
- (chunk.usage_metadata?.input_token_details?.cache_read ?? 0),
- }),
- ...((this.usage_metadata?.input_token_details?.cache_creation !==
- undefined ||
- chunk.usage_metadata?.input_token_details?.cache_creation !==
- undefined) && {
- cache_creation: (this.usage_metadata?.input_token_details?.cache_creation ?? 0) +
- (chunk.usage_metadata?.input_token_details?.cache_creation ?? 0),
- }),
- };
- const outputTokenDetails = {
- ...((this.usage_metadata?.output_token_details?.audio !== undefined ||
- chunk.usage_metadata?.output_token_details?.audio !== undefined) && {
- audio: (this.usage_metadata?.output_token_details?.audio ?? 0) +
- (chunk.usage_metadata?.output_token_details?.audio ?? 0),
- }),
- ...((this.usage_metadata?.output_token_details?.reasoning !==
- undefined ||
- chunk.usage_metadata?.output_token_details?.reasoning !==
- undefined) && {
- reasoning: (this.usage_metadata?.output_token_details?.reasoning ?? 0) +
- (chunk.usage_metadata?.output_token_details?.reasoning ?? 0),
- }),
- };
- const left = this.usage_metadata ?? {
- input_tokens: 0,
- output_tokens: 0,
- total_tokens: 0,
- };
- const right = chunk.usage_metadata ?? {
- input_tokens: 0,
- output_tokens: 0,
- total_tokens: 0,
- };
- const usage_metadata = {
- input_tokens: left.input_tokens + right.input_tokens,
- output_tokens: left.output_tokens + right.output_tokens,
- total_tokens: left.total_tokens + right.total_tokens,
- // Do not include `input_token_details` / `output_token_details` keys in combined fields
- // unless their values are defined.
- ...(Object.keys(inputTokenDetails).length > 0 && {
- input_token_details: inputTokenDetails,
- }),
- ...(Object.keys(outputTokenDetails).length > 0 && {
- output_token_details: outputTokenDetails,
- }),
- };
- combinedFields.usage_metadata = usage_metadata;
- }
- return new AIMessageChunk(combinedFields);
- }
- }
|