@langchain/google-common 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,535 @@
1
+ import { ChatGenerationChunk, } from "@langchain/core/outputs";
2
+ import { AIMessageChunk, } from "@langchain/core/messages";
3
+ export function getAnthropicAPI(config) {
4
+ function partToString(part) {
5
+ return "text" in part ? part.text : "";
6
+ }
7
+ function messageToString(message) {
8
+ const content = message?.content ?? [];
9
+ const ret = content.reduce((acc, part) => {
10
+ const str = partToString(part);
11
+ return acc + str;
12
+ }, "");
13
+ return ret;
14
+ }
15
+ function responseToString(response) {
16
+ const data = response.data;
17
+ switch (data?.type) {
18
+ case "message":
19
+ return messageToString(data);
20
+ default:
21
+ throw Error(`Unknown type: ${data?.type}`);
22
+ }
23
+ }
24
+ /**
25
+ * Normalize the AIMessageChunk.
26
+ * If the fields are just a string - use that as content.
27
+ * If the content is an array of just text fields, turn them into a string.
28
+ * @param fields
29
+ */
30
+ function newAIMessageChunk(fields) {
31
+ if (typeof fields === "string") {
32
+ return new AIMessageChunk(fields);
33
+ }
34
+ const ret = {
35
+ ...fields,
36
+ };
37
+ if (Array.isArray(fields?.content)) {
38
+ let str = "";
39
+ fields.content.forEach((val) => {
40
+ if (str !== undefined && val.type === "text") {
41
+ str = `${str}${val.text}`;
42
+ }
43
+ else {
44
+ str = undefined;
45
+ }
46
+ });
47
+ if (str) {
48
+ ret.content = str;
49
+ }
50
+ }
51
+ return new AIMessageChunk(ret);
52
+ }
53
+ function textContentToMessageFields(textContent) {
54
+ return {
55
+ content: [textContent],
56
+ };
57
+ }
58
+ function toolUseContentToMessageFields(toolUseContent) {
59
+ const tool = {
60
+ id: toolUseContent.id,
61
+ name: toolUseContent.name,
62
+ type: "tool_call",
63
+ args: toolUseContent.input,
64
+ };
65
+ return {
66
+ content: [],
67
+ tool_calls: [tool],
68
+ };
69
+ }
70
+ function anthropicContentToMessageFields(anthropicContent) {
71
+ const type = anthropicContent?.type;
72
+ switch (type) {
73
+ case "text":
74
+ return textContentToMessageFields(anthropicContent);
75
+ case "tool_use":
76
+ return toolUseContentToMessageFields(anthropicContent);
77
+ default:
78
+ return undefined;
79
+ }
80
+ }
81
+ function contentToMessage(anthropicContent) {
82
+ const complexContent = [];
83
+ const toolCalls = [];
84
+ anthropicContent.forEach((ac) => {
85
+ const messageFields = anthropicContentToMessageFields(ac);
86
+ if (messageFields?.content) {
87
+ complexContent.push(...messageFields.content);
88
+ }
89
+ if (messageFields?.tool_calls) {
90
+ toolCalls.push(...messageFields.tool_calls);
91
+ }
92
+ });
93
+ const ret = {
94
+ content: complexContent,
95
+ tool_calls: toolCalls,
96
+ };
97
+ return newAIMessageChunk(ret);
98
+ }
99
+ function messageToGenerationInfo(message) {
100
+ const usage = message?.usage;
101
+ const usageMetadata = {
102
+ input_tokens: usage?.input_tokens ?? 0,
103
+ output_tokens: usage?.output_tokens ?? 0,
104
+ total_tokens: (usage?.input_tokens ?? 0) + (usage?.output_tokens ?? 0),
105
+ };
106
+ return {
107
+ usage_metadata: usageMetadata,
108
+ finish_reason: message.stop_reason,
109
+ };
110
+ }
111
+ function messageToChatGeneration(responseMessage) {
112
+ const content = responseMessage?.content ?? [];
113
+ const text = messageToString(responseMessage);
114
+ const message = contentToMessage(content);
115
+ const generationInfo = messageToGenerationInfo(responseMessage);
116
+ return new ChatGenerationChunk({
117
+ text,
118
+ message,
119
+ generationInfo,
120
+ });
121
+ }
122
+ function messageStartToChatGeneration(event) {
123
+ const responseMessage = event.message;
124
+ return messageToChatGeneration(responseMessage);
125
+ }
126
+ function messageDeltaToChatGeneration(event) {
127
+ const responseMessage = event.delta;
128
+ return messageToChatGeneration(responseMessage);
129
+ }
130
+ function contentBlockStartTextToChatGeneration(event) {
131
+ const content = event.content_block;
132
+ const message = contentToMessage([content]);
133
+ if (!message) {
134
+ return null;
135
+ }
136
+ const text = "text" in content ? content.text : "";
137
+ return new ChatGenerationChunk({
138
+ message,
139
+ text,
140
+ });
141
+ }
142
+ function contentBlockStartToolUseToChatGeneration(event) {
143
+ const contentBlock = event.content_block;
144
+ const text = "";
145
+ const toolChunk = {
146
+ type: "tool_call_chunk",
147
+ index: event.index,
148
+ name: contentBlock.name,
149
+ id: contentBlock.id,
150
+ };
151
+ if (typeof contentBlock.input === "object" &&
152
+ Object.keys(contentBlock.input).length > 0) {
153
+ toolChunk.args = JSON.stringify(contentBlock.input);
154
+ }
155
+ const toolChunks = [toolChunk];
156
+ const content = [
157
+ {
158
+ index: event.index,
159
+ ...contentBlock,
160
+ },
161
+ ];
162
+ const messageFields = {
163
+ content,
164
+ tool_call_chunks: toolChunks,
165
+ };
166
+ const message = newAIMessageChunk(messageFields);
167
+ return new ChatGenerationChunk({
168
+ message,
169
+ text,
170
+ });
171
+ }
172
+ function contentBlockStartToChatGeneration(event) {
173
+ switch (event.content_block.type) {
174
+ case "text":
175
+ return contentBlockStartTextToChatGeneration(event);
176
+ case "tool_use":
177
+ return contentBlockStartToolUseToChatGeneration(event);
178
+ default:
179
+ console.warn(`Unexpected start content_block type: ${JSON.stringify(event)}`);
180
+ return null;
181
+ }
182
+ }
183
+ function contentBlockDeltaTextToChatGeneration(event) {
184
+ const delta = event.delta;
185
+ const text = delta?.text;
186
+ const message = newAIMessageChunk(text);
187
+ return new ChatGenerationChunk({
188
+ message,
189
+ text,
190
+ });
191
+ }
192
+ function contentBlockDeltaInputJsonDeltaToChatGeneration(event) {
193
+ const delta = event.delta;
194
+ const text = "";
195
+ const toolChunks = [
196
+ {
197
+ index: event.index,
198
+ args: delta.partial_json,
199
+ },
200
+ ];
201
+ const content = [
202
+ {
203
+ index: event.index,
204
+ ...delta,
205
+ },
206
+ ];
207
+ const messageFields = {
208
+ content,
209
+ tool_call_chunks: toolChunks,
210
+ };
211
+ const message = newAIMessageChunk(messageFields);
212
+ return new ChatGenerationChunk({
213
+ message,
214
+ text,
215
+ });
216
+ }
217
+ function contentBlockDeltaToChatGeneration(event) {
218
+ switch (event.delta.type) {
219
+ case "text_delta":
220
+ return contentBlockDeltaTextToChatGeneration(event);
221
+ case "input_json_delta":
222
+ return contentBlockDeltaInputJsonDeltaToChatGeneration(event);
223
+ default:
224
+ console.warn(`Unexpected delta content_block type: ${JSON.stringify(event)}`);
225
+ return null;
226
+ }
227
+ }
228
+ function responseToChatGeneration(response) {
229
+ const data = response.data;
230
+ switch (data.type) {
231
+ case "message":
232
+ return messageToChatGeneration(data);
233
+ case "message_start":
234
+ return messageStartToChatGeneration(data);
235
+ case "message_delta":
236
+ return messageDeltaToChatGeneration(data);
237
+ case "content_block_start":
238
+ return contentBlockStartToChatGeneration(data);
239
+ case "content_block_delta":
240
+ return contentBlockDeltaToChatGeneration(data);
241
+ case "ping":
242
+ case "message_stop":
243
+ case "content_block_stop":
244
+ // These are ignorable
245
+ return null;
246
+ case "error":
247
+ throw new Error(`Error while streaming results: ${JSON.stringify(data)}`);
248
+ default:
249
+ // We don't know what type this is, but Anthropic may have added
250
+ // new ones without telling us. Don't error, but don't use them.
251
+ console.warn("Unknown data for responseToChatGeneration", data);
252
+ // throw new Error(`Unknown response type: ${data.type}`);
253
+ return null;
254
+ }
255
+ }
256
+ function chunkToString(chunk) {
257
+ if (chunk === null) {
258
+ return "";
259
+ }
260
+ else if (typeof chunk.content === "string") {
261
+ return chunk.content;
262
+ }
263
+ else if (chunk.content.length === 0) {
264
+ return "";
265
+ }
266
+ else if (chunk.content[0].type === "text") {
267
+ return chunk.content[0].text;
268
+ }
269
+ else {
270
+ throw new Error(`Unexpected chunk: ${chunk}`);
271
+ }
272
+ }
273
+ function responseToBaseMessage(response) {
274
+ const data = response.data;
275
+ const content = data?.content ?? [];
276
+ return contentToMessage(content);
277
+ }
278
+ function responseToChatResult(response) {
279
+ const message = response.data;
280
+ const generations = [];
281
+ const gen = responseToChatGeneration(response);
282
+ if (gen) {
283
+ generations.push(gen);
284
+ }
285
+ const llmOutput = messageToGenerationInfo(message);
286
+ return {
287
+ generations,
288
+ llmOutput,
289
+ };
290
+ }
291
+ function formatAnthropicVersion() {
292
+ return config?.version ?? "vertex-2023-10-16";
293
+ }
294
+ function textContentToAnthropicContent(content) {
295
+ return content;
296
+ }
297
+ function extractMimeType(str) {
298
+ if (str.startsWith("data:")) {
299
+ return {
300
+ media_type: str.split(":")[1].split(";")[0],
301
+ data: str.split(",")[1],
302
+ };
303
+ }
304
+ return null;
305
+ }
306
+ function imageContentToAnthropicContent(content) {
307
+ const dataUrl = content.image_url;
308
+ const url = typeof dataUrl === "string" ? dataUrl : dataUrl?.url;
309
+ const urlInfo = extractMimeType(url);
310
+ if (!urlInfo) {
311
+ return undefined;
312
+ }
313
+ return {
314
+ type: "image",
315
+ source: {
316
+ type: "base64",
317
+ ...urlInfo,
318
+ },
319
+ };
320
+ }
321
+ function contentComplexToAnthropicContent(content) {
322
+ const type = content?.type;
323
+ switch (type) {
324
+ case "text":
325
+ return textContentToAnthropicContent(content);
326
+ case "image_url":
327
+ return imageContentToAnthropicContent(content);
328
+ default:
329
+ console.warn(`Unexpected content type: ${type}`);
330
+ return undefined;
331
+ }
332
+ }
333
+ function contentToAnthropicContent(content) {
334
+ const ret = [];
335
+ const ca = typeof content === "string" ? [{ type: "text", text: content }] : content;
336
+ ca.forEach((complex) => {
337
+ const ac = contentComplexToAnthropicContent(complex);
338
+ if (ac) {
339
+ ret.push(ac);
340
+ }
341
+ });
342
+ return ret;
343
+ }
344
+ function baseRoleToAnthropicMessage(base, role) {
345
+ const content = contentToAnthropicContent(base.content);
346
+ return {
347
+ role,
348
+ content,
349
+ };
350
+ }
351
+ function toolMessageToAnthropicMessage(base) {
352
+ const role = "user";
353
+ const toolUseId = base.tool_call_id;
354
+ const toolContent = contentToAnthropicContent(base.content);
355
+ const content = [
356
+ {
357
+ type: "tool_result",
358
+ tool_use_id: toolUseId,
359
+ content: toolContent,
360
+ },
361
+ ];
362
+ return {
363
+ role,
364
+ content,
365
+ };
366
+ }
367
+ function baseToAnthropicMessage(base) {
368
+ const type = base.getType();
369
+ switch (type) {
370
+ case "human":
371
+ return baseRoleToAnthropicMessage(base, "user");
372
+ case "ai":
373
+ return baseRoleToAnthropicMessage(base, "assistant");
374
+ case "tool":
375
+ return toolMessageToAnthropicMessage(base);
376
+ default:
377
+ return undefined;
378
+ }
379
+ }
380
+ function formatMessages(input) {
381
+ const ret = [];
382
+ input.forEach((baseMessage) => {
383
+ const anthropicMessage = baseToAnthropicMessage(baseMessage);
384
+ if (anthropicMessage) {
385
+ ret.push(anthropicMessage);
386
+ }
387
+ });
388
+ return ret;
389
+ }
390
+ function formatSettings(parameters) {
391
+ const ret = {
392
+ stream: parameters?.streaming ?? false,
393
+ max_tokens: parameters?.maxOutputTokens ?? 8192,
394
+ };
395
+ if (parameters.topP) {
396
+ ret.top_p = parameters.topP;
397
+ }
398
+ if (parameters.topK) {
399
+ ret.top_k = parameters.topK;
400
+ }
401
+ if (parameters.temperature) {
402
+ ret.temperature = parameters.temperature;
403
+ }
404
+ if (parameters.stopSequences) {
405
+ ret.stop_sequences = parameters.stopSequences;
406
+ }
407
+ return ret;
408
+ }
409
+ function contentComplexArrayToText(contentArray) {
410
+ let ret = "";
411
+ contentArray.forEach((content) => {
412
+ const contentType = content?.type;
413
+ if (contentType === "text") {
414
+ const textContent = content;
415
+ ret = `${ret}\n${textContent.text}`;
416
+ }
417
+ });
418
+ return ret;
419
+ }
420
+ function formatSystem(input) {
421
+ let ret = "";
422
+ input.forEach((message) => {
423
+ if (message._getType() === "system") {
424
+ const content = message?.content;
425
+ const contentString = typeof content === "string"
426
+ ? content
427
+ : contentComplexArrayToText(content);
428
+ ret = `${ret}\n${contentString}`;
429
+ }
430
+ });
431
+ return ret;
432
+ }
433
+ function formatGeminiTool(tool) {
434
+ if (Object.hasOwn(tool, "functionDeclarations")) {
435
+ const funcs = tool?.functionDeclarations ?? [];
436
+ return funcs.map((func) => {
437
+ const inputSchema = func.parameters;
438
+ return {
439
+ // type: "tool", // This may only be valid for models 20241022+
440
+ name: func.name,
441
+ description: func.description,
442
+ input_schema: inputSchema,
443
+ };
444
+ });
445
+ }
446
+ else {
447
+ console.warn(`Unable to format GeminiTool: ${JSON.stringify(tool, null, 1)}`);
448
+ return [];
449
+ }
450
+ }
451
+ function formatTool(tool) {
452
+ if (Object.hasOwn(tool, "name")) {
453
+ return [tool];
454
+ }
455
+ else {
456
+ return formatGeminiTool(tool);
457
+ }
458
+ }
459
+ function formatTools(parameters) {
460
+ const tools = parameters?.tools ?? [];
461
+ const ret = [];
462
+ tools.forEach((tool) => {
463
+ const anthropicTools = formatTool(tool);
464
+ anthropicTools.forEach((anthropicTool) => {
465
+ if (anthropicTool) {
466
+ ret.push(anthropicTool);
467
+ }
468
+ });
469
+ });
470
+ return ret;
471
+ }
472
+ function formatToolChoice(parameters) {
473
+ const choice = parameters?.tool_choice;
474
+ if (!choice) {
475
+ return undefined;
476
+ }
477
+ else if (typeof choice === "object") {
478
+ return choice;
479
+ }
480
+ else {
481
+ switch (choice) {
482
+ case "any":
483
+ case "auto":
484
+ return {
485
+ type: choice,
486
+ };
487
+ case "none":
488
+ return undefined;
489
+ default:
490
+ return {
491
+ type: "tool",
492
+ name: choice,
493
+ };
494
+ }
495
+ }
496
+ }
497
+ async function formatData(input, parameters) {
498
+ const typedInput = input;
499
+ const anthropicVersion = formatAnthropicVersion();
500
+ const messages = formatMessages(typedInput);
501
+ const settings = formatSettings(parameters);
502
+ const system = formatSystem(typedInput);
503
+ const tools = formatTools(parameters);
504
+ const toolChoice = formatToolChoice(parameters);
505
+ const ret = {
506
+ anthropic_version: anthropicVersion,
507
+ messages,
508
+ ...settings,
509
+ };
510
+ if (tools && tools.length && parameters?.tool_choice !== "none") {
511
+ ret.tools = tools;
512
+ }
513
+ if (toolChoice) {
514
+ ret.tool_choice = toolChoice;
515
+ }
516
+ if (system?.length) {
517
+ ret.system = system;
518
+ }
519
+ return ret;
520
+ }
521
+ return {
522
+ responseToString,
523
+ responseToChatGeneration,
524
+ chunkToString,
525
+ responseToBaseMessage,
526
+ responseToChatResult,
527
+ formatData,
528
+ };
529
+ }
530
+ export function validateClaudeParams(_params) {
531
+ // FIXME - validate the parameters
532
+ }
533
+ export function isModelClaude(modelName) {
534
+ return modelName.toLowerCase().startsWith("claude");
535
+ }
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.copyAndValidateModelParamsInto = exports.validateModelParams = exports.modelToFamily = exports.copyAIModelParamsInto = exports.convertToGeminiTools = exports.copyAIModelParams = void 0;
3
+ exports.copyAndValidateModelParamsInto = exports.validateModelParams = exports.modelToPublisher = exports.modelToFamily = exports.copyAIModelParamsInto = exports.convertToGeminiTools = exports.copyAIModelParams = void 0;
4
4
  const base_1 = require("@langchain/core/language_models/base");
5
5
  const function_calling_1 = require("@langchain/core/utils/function_calling");
6
6
  const gemini_js_1 = require("./gemini.cjs");
7
7
  const zod_to_gemini_parameters_js_1 = require("./zod_to_gemini_parameters.cjs");
8
+ const anthropic_js_1 = require("./anthropic.cjs");
8
9
  function copyAIModelParams(params, options) {
9
10
  return copyAIModelParamsInto(params, options, {});
10
11
  }
@@ -114,17 +115,35 @@ function modelToFamily(modelName) {
114
115
  else if ((0, gemini_js_1.isModelGemini)(modelName)) {
115
116
  return "gemini";
116
117
  }
118
+ else if ((0, anthropic_js_1.isModelClaude)(modelName)) {
119
+ return "claude";
120
+ }
117
121
  else {
118
122
  return null;
119
123
  }
120
124
  }
121
125
  exports.modelToFamily = modelToFamily;
126
+ function modelToPublisher(modelName) {
127
+ const family = modelToFamily(modelName);
128
+ switch (family) {
129
+ case "gemini":
130
+ case "palm":
131
+ return "google";
132
+ case "claude":
133
+ return "anthropic";
134
+ default:
135
+ return "unknown";
136
+ }
137
+ }
138
+ exports.modelToPublisher = modelToPublisher;
122
139
  function validateModelParams(params) {
123
140
  const testParams = params ?? {};
124
141
  const model = testParams.model ?? testParams.modelName;
125
142
  switch (modelToFamily(model)) {
126
143
  case "gemini":
127
144
  return (0, gemini_js_1.validateGeminiParams)(testParams);
145
+ case "claude":
146
+ return (0, anthropic_js_1.validateClaudeParams)(testParams);
128
147
  default:
129
148
  throw new Error(`Unable to verify model params: ${JSON.stringify(params)}`);
130
149
  }
@@ -1,7 +1,8 @@
1
- import type { GeminiTool, GoogleAIBaseLanguageModelCallOptions, GoogleAIModelParams, GoogleAIModelRequestParams, GoogleAIToolType, GoogleLLMModelFamily } from "../types.js";
1
+ import type { GeminiTool, GoogleAIBaseLanguageModelCallOptions, GoogleAIModelParams, GoogleAIModelRequestParams, GoogleAIToolType, VertexModelFamily } from "../types.js";
2
2
  export declare function copyAIModelParams(params: GoogleAIModelParams | undefined, options: GoogleAIBaseLanguageModelCallOptions | undefined): GoogleAIModelRequestParams;
3
3
  export declare function convertToGeminiTools(tools: GoogleAIToolType[]): GeminiTool[];
4
4
  export declare function copyAIModelParamsInto(params: GoogleAIModelParams | undefined, options: GoogleAIBaseLanguageModelCallOptions | undefined, target: GoogleAIModelParams): GoogleAIModelRequestParams;
5
- export declare function modelToFamily(modelName: string | undefined): GoogleLLMModelFamily;
5
+ export declare function modelToFamily(modelName: string | undefined): VertexModelFamily;
6
+ export declare function modelToPublisher(modelName: string | undefined): string;
6
7
  export declare function validateModelParams(params: GoogleAIModelParams | undefined): void;
7
8
  export declare function copyAndValidateModelParamsInto(params: GoogleAIModelParams | undefined, target: GoogleAIModelParams): GoogleAIModelParams;
@@ -2,6 +2,7 @@ import { isOpenAITool } from "@langchain/core/language_models/base";
2
2
  import { isLangChainTool } from "@langchain/core/utils/function_calling";
3
3
  import { isModelGemini, validateGeminiParams } from "./gemini.js";
4
4
  import { jsonSchemaToGeminiParameters, zodToGeminiParameters, } from "./zod_to_gemini_parameters.js";
5
+ import { isModelClaude, validateClaudeParams } from "./anthropic.js";
5
6
  export function copyAIModelParams(params, options) {
6
7
  return copyAIModelParamsInto(params, options, {});
7
8
  }
@@ -108,16 +109,33 @@ export function modelToFamily(modelName) {
108
109
  else if (isModelGemini(modelName)) {
109
110
  return "gemini";
110
111
  }
112
+ else if (isModelClaude(modelName)) {
113
+ return "claude";
114
+ }
111
115
  else {
112
116
  return null;
113
117
  }
114
118
  }
119
+ export function modelToPublisher(modelName) {
120
+ const family = modelToFamily(modelName);
121
+ switch (family) {
122
+ case "gemini":
123
+ case "palm":
124
+ return "google";
125
+ case "claude":
126
+ return "anthropic";
127
+ default:
128
+ return "unknown";
129
+ }
130
+ }
115
131
  export function validateModelParams(params) {
116
132
  const testParams = params ?? {};
117
133
  const model = testParams.model ?? testParams.modelName;
118
134
  switch (modelToFamily(model)) {
119
135
  case "gemini":
120
136
  return validateGeminiParams(testParams);
137
+ case "claude":
138
+ return validateClaudeParams(testParams);
121
139
  default:
122
140
  throw new Error(`Unable to verify model params: ${JSON.stringify(params)}`);
123
141
  }