@langchain/core
Version:
Core LangChain.js abstractions and schemas
1 lines • 8.83 kB
Source Map (JSON)
{"version":3,"file":"google.cjs","names":["_isString","iife","_isContentBlock","_isObject"],"sources":["../../../src/messages/block_translators/google.ts"],"sourcesContent":["import { AIMessage } from \"../ai.js\";\nimport { ContentBlock } from \"../content/index.js\";\nimport type { StandardContentBlockTranslator } from \"./index.js\";\nimport { iife, _isContentBlock, _isObject, _isString } from \"./utils.js\";\n\nconst GEMINI_REFUSAL_FINISH_REASONS = new Set([\n \"SAFETY\",\n \"PROHIBITED_CONTENT\",\n \"BLOCKLIST\",\n]);\n\n/**\n * Builds a refusal block from a Gemini finish reason.\n *\n * A blocked prompt has no message: `@langchain/google` throws\n * `PromptBlockedError` for it instead.\n */\nfunction refusalFromMetadata(\n message: AIMessage\n): ContentBlock.Refusal | undefined {\n const metadata = message.response_metadata;\n const kwargs = message.additional_kwargs;\n // `invoke` sets `finish_reason`, stream events set `finishReason`, and\n // streamed chunks keep both fields only in `additional_kwargs`.\n const finishReason =\n metadata.finishReason ?? metadata.finish_reason ?? kwargs.finishReason;\n if (\n !_isString(finishReason) ||\n !GEMINI_REFUSAL_FINISH_REASONS.has(finishReason)\n ) {\n return undefined;\n }\n const finishMessage = metadata.finishMessage ?? kwargs.finishMessage;\n return {\n type: \"refusal\",\n refusal: _isString(finishMessage) ? finishMessage : \"\",\n extras: { finishReason },\n };\n}\n\nfunction convertToV1FromChatGoogleMessage(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n const content = iife(() => {\n if (typeof message.content === \"string\") {\n if (message.additional_kwargs.originalTextContentBlock) {\n return [\n {\n ...message.additional_kwargs.originalTextContentBlock,\n type: \"text\",\n },\n ];\n } else {\n return [{ type: \"text\", text: message.content }];\n }\n } else {\n const originalBlock = message.additional_kwargs\n ?.originalTextContentBlock as Record<string, unknown> | undefined;\n if (originalBlock?.thoughtSignature) {\n // During streaming with thinking models, thoughtSignature arrives in\n // a metadata-only chunk and is stored in originalTextContentBlock.\n // When content is an array (due to thinking parts), this signature\n // isn't carried into the content array by mergeContent().\n // Merge it into the last non-thinking text block.\n const hasSignatureInContent = message.content.some(\n (b: Record<string, unknown>) => \"thoughtSignature\" in b\n );\n if (!hasSignatureInContent) {\n const result = [...message.content];\n for (let i = result.length - 1; i >= 0; i--) {\n const block = result[i] as Record<string, unknown>;\n if (block.type === \"text\" && !block.thought) {\n block.thoughtSignature = originalBlock.thoughtSignature;\n return result;\n }\n }\n }\n }\n return message.content;\n }\n });\n for (const block of content) {\n const contentBlockBase: ContentBlock.Standard = iife(() => {\n if (_isContentBlock(block, \"text\") && _isString(block.text)) {\n return {\n type: \"text\",\n text: block.text,\n };\n } else if (\n _isContentBlock(block, \"inlineData\") &&\n _isObject(block.inlineData) &&\n _isString(block.inlineData.mimeType) &&\n _isString(block.inlineData.data)\n ) {\n return {\n type: \"file\",\n mimeType: block.inlineData.mimeType,\n data: block.inlineData.data,\n };\n } else if (\n _isContentBlock(block, \"functionCall\") &&\n _isObject(block.functionCall) &&\n _isString(block.functionCall.name) &&\n _isObject(block.functionCall.args)\n ) {\n return {\n type: \"tool_call\",\n id: message.id,\n name: block.functionCall.name,\n args: block.functionCall.args,\n };\n } else if (_isContentBlock(block, \"functionResponse\")) {\n return { type: \"non_standard\", value: block };\n } else if (\n _isContentBlock(block, \"fileData\") &&\n _isObject(block.fileData) &&\n _isString(block.fileData.mimeType) &&\n _isString(block.fileData.fileUri)\n ) {\n return {\n type: \"file\",\n mimeType: block.fileData.mimeType,\n fileId: block.fileData.fileUri,\n };\n } else if (_isContentBlock(block, \"executableCode\")) {\n return { type: \"non_standard\", value: block };\n } else if (_isContentBlock(block, \"codeExecutionResult\")) {\n return { type: \"non_standard\", value: block };\n }\n return { type: \"non_standard\", value: block };\n });\n const contentBlock: ContentBlock.Standard = iife(() => {\n if (\"thought\" in block && block.thought) {\n const reasoning: string =\n contentBlockBase.type === \"text\" ? contentBlockBase.text : \"\";\n return {\n type: \"reasoning\",\n reasoning,\n reasoningContentBlock: contentBlockBase,\n };\n } else {\n return contentBlockBase;\n }\n });\n\n const ret: ContentBlock.Standard = {\n thought: block.thought,\n thoughtSignature: block.thoughtSignature,\n partMetadata: block.partMetadata,\n ...contentBlock,\n };\n for (const attribute in ret) {\n if (ret[attribute] === undefined) {\n delete ret[attribute];\n }\n }\n\n yield ret;\n continue;\n }\n }\n const blocks = Array.from(iterateContent());\n const refusal = refusalFromMetadata(message);\n if (refusal) blocks.push(refusal);\n return blocks;\n}\n\nexport const ChatGoogleTranslator: StandardContentBlockTranslator = {\n translateContent: convertToV1FromChatGoogleMessage,\n translateContentChunk: convertToV1FromChatGoogleMessage,\n};\n"],"mappings":"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"}