koishi-plugin-chatluna-google-gemini-adapter 1.1.0-beta.2 → 1.1.0-beta.4
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.
- package/lib/index.cjs +57 -43
- package/lib/index.mjs +58 -44
- package/package.json +2 -3
package/lib/index.cjs
CHANGED
|
@@ -56,7 +56,6 @@ var import_error2 = require("koishi-plugin-chatluna/utils/error");
|
|
|
56
56
|
// src/requester.ts
|
|
57
57
|
var import_messages2 = require("@langchain/core/messages");
|
|
58
58
|
var import_outputs = require("@langchain/core/outputs");
|
|
59
|
-
var import_json = require("@streamparser/json");
|
|
60
59
|
var import_api = require("koishi-plugin-chatluna/llm-core/platform/api");
|
|
61
60
|
var import_error = require("koishi-plugin-chatluna/utils/error");
|
|
62
61
|
var import_sse = require("koishi-plugin-chatluna/utils/sse");
|
|
@@ -243,14 +242,27 @@ function formatToolsToGeminiAITools(tools, config, model) {
|
|
|
243
242
|
}
|
|
244
243
|
const functions = tools.map(formatToolToGeminiAITool);
|
|
245
244
|
const result = [];
|
|
246
|
-
|
|
245
|
+
const unsupportedModels = [
|
|
246
|
+
"gemini-1.0",
|
|
247
|
+
"gemini-2.0-flash-lite",
|
|
248
|
+
"gemini-1.5-flash"
|
|
249
|
+
];
|
|
250
|
+
let googleSearch = config.googleSearch;
|
|
251
|
+
if (functions.length > 0 && !googleSearch) {
|
|
247
252
|
result.push({
|
|
248
253
|
functionDeclarations: functions
|
|
249
254
|
});
|
|
250
|
-
} else if (functions.length > 0 &&
|
|
255
|
+
} else if (functions.length > 0 && googleSearch) {
|
|
251
256
|
logger.warn("Google search is enabled, tool calling will be disable.");
|
|
257
|
+
} else if (unsupportedModels.some(
|
|
258
|
+
(unsupportedModel) => model.includes(unsupportedModel)
|
|
259
|
+
) && googleSearch) {
|
|
260
|
+
logger.warn(
|
|
261
|
+
`The model ${model} does not support google search. google search will be disable.`
|
|
262
|
+
);
|
|
263
|
+
googleSearch = false;
|
|
252
264
|
}
|
|
253
|
-
if (
|
|
265
|
+
if (googleSearch) {
|
|
254
266
|
if (model.includes("gemini-2")) {
|
|
255
267
|
result.push({
|
|
256
268
|
google_search: {}
|
|
@@ -336,7 +348,7 @@ var GeminiRequester = class extends import_api.ModelRequester {
|
|
|
336
348
|
async *completionStream(params) {
|
|
337
349
|
try {
|
|
338
350
|
const response = await this._post(
|
|
339
|
-
`models/${params.model}:streamGenerateContent`,
|
|
351
|
+
`models/${params.model}:streamGenerateContent?alt=sse`,
|
|
340
352
|
{
|
|
341
353
|
contents: await langchainMessageToGeminiMessage(
|
|
342
354
|
params.input,
|
|
@@ -345,23 +357,23 @@ var GeminiRequester = class extends import_api.ModelRequester {
|
|
|
345
357
|
safetySettings: [
|
|
346
358
|
{
|
|
347
359
|
category: "HARM_CATEGORY_HARASSMENT",
|
|
348
|
-
threshold: "BLOCK_NONE"
|
|
360
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
349
361
|
},
|
|
350
362
|
{
|
|
351
363
|
category: "HARM_CATEGORY_HATE_SPEECH",
|
|
352
|
-
threshold: "BLOCK_NONE"
|
|
364
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
353
365
|
},
|
|
354
366
|
{
|
|
355
367
|
category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
|
356
|
-
threshold: "BLOCK_NONE"
|
|
368
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
357
369
|
},
|
|
358
370
|
{
|
|
359
371
|
category: "HARM_CATEGORY_DANGEROUS_CONTENT",
|
|
360
|
-
threshold: "BLOCK_NONE"
|
|
372
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
361
373
|
},
|
|
362
374
|
{
|
|
363
375
|
category: "HARM_CATEGORY_CIVIC_INTEGRITY",
|
|
364
|
-
threshold: "BLOCK_NONE"
|
|
376
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
365
377
|
}
|
|
366
378
|
],
|
|
367
379
|
generationConfig: {
|
|
@@ -382,44 +394,41 @@ var GeminiRequester = class extends import_api.ModelRequester {
|
|
|
382
394
|
}
|
|
383
395
|
);
|
|
384
396
|
let errorCount = 0;
|
|
385
|
-
const stream = new TransformStream();
|
|
386
|
-
const iterable = (0, import_stream.readableStreamToAsyncIterable)(
|
|
387
|
-
stream.readable
|
|
388
|
-
);
|
|
389
|
-
const jsonParser = new import_json.JSONParser();
|
|
390
|
-
const writable = stream.writable.getWriter();
|
|
391
397
|
let groundingContent = "";
|
|
392
398
|
let currentGroudingIndex = 0;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
if (!transformValue.candidates) {
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
for (const candidate of transformValue.candidates) {
|
|
402
|
-
const parts = candidate.content?.parts;
|
|
403
|
-
if (parts == null || parts.length < 1) {
|
|
404
|
-
throw new Error(JSON.stringify(value));
|
|
399
|
+
await (0, import_sse.checkResponse)(response);
|
|
400
|
+
const readableStream = new ReadableStream({
|
|
401
|
+
async start(controller) {
|
|
402
|
+
for await (const chunk of (0, import_sse.sseIterable)(response)) {
|
|
403
|
+
controller.enqueue(chunk.data);
|
|
405
404
|
}
|
|
406
|
-
|
|
407
|
-
|
|
405
|
+
controller.close();
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
const transformToChatPartStream = new TransformStream({
|
|
409
|
+
async transform(chunk, controller) {
|
|
410
|
+
const parsedValue = JSON.parse(chunk);
|
|
411
|
+
const transformValue = parsedValue;
|
|
412
|
+
if (!transformValue.candidates) {
|
|
413
|
+
return;
|
|
408
414
|
}
|
|
409
|
-
for (const
|
|
410
|
-
|
|
415
|
+
for (const candidate of transformValue.candidates) {
|
|
416
|
+
const parts = candidate.content?.parts;
|
|
417
|
+
if (parts == null || parts.length < 1) {
|
|
418
|
+
throw new Error(chunk);
|
|
419
|
+
}
|
|
420
|
+
for (const part of parts) {
|
|
421
|
+
controller.enqueue(part);
|
|
422
|
+
}
|
|
423
|
+
for (const source of candidate.groundingMetadata?.groundingChunks ?? []) {
|
|
424
|
+
groundingContent += `[^${currentGroudingIndex++}]: [${source.web.title}](${source.web.uri})
|
|
411
425
|
`;
|
|
426
|
+
}
|
|
412
427
|
}
|
|
413
428
|
}
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
response,
|
|
418
|
-
async (rawData) => {
|
|
419
|
-
jsonParser.write(rawData);
|
|
420
|
-
return true;
|
|
421
|
-
},
|
|
422
|
-
0
|
|
429
|
+
});
|
|
430
|
+
const iterable = (0, import_stream.readableStreamToAsyncIterable)(
|
|
431
|
+
readableStream.pipeThrough(transformToChatPartStream)
|
|
423
432
|
);
|
|
424
433
|
let reasoningContent = "";
|
|
425
434
|
let content = "";
|
|
@@ -602,10 +611,15 @@ ${groundingContent}`
|
|
|
602
611
|
}
|
|
603
612
|
_concatUrl(url) {
|
|
604
613
|
const apiEndPoint = this._config.apiEndpoint;
|
|
614
|
+
let baseURL;
|
|
605
615
|
if (apiEndPoint.endsWith("/")) {
|
|
606
|
-
|
|
616
|
+
baseURL = new URL(apiEndPoint + url);
|
|
617
|
+
} else {
|
|
618
|
+
baseURL = new URL(apiEndPoint + "/" + url);
|
|
607
619
|
}
|
|
608
|
-
|
|
620
|
+
const searchParams = baseURL.searchParams;
|
|
621
|
+
searchParams.set("key", this._config.apiKey);
|
|
622
|
+
return baseURL.toString();
|
|
609
623
|
}
|
|
610
624
|
_buildHeaders() {
|
|
611
625
|
return {
|
package/lib/index.mjs
CHANGED
|
@@ -40,7 +40,6 @@ import {
|
|
|
40
40
|
// src/requester.ts
|
|
41
41
|
import { AIMessageChunk as AIMessageChunk2 } from "@langchain/core/messages";
|
|
42
42
|
import { ChatGenerationChunk } from "@langchain/core/outputs";
|
|
43
|
-
import { JSONParser } from "@streamparser/json";
|
|
44
43
|
import {
|
|
45
44
|
ModelRequester
|
|
46
45
|
} from "koishi-plugin-chatluna/llm-core/platform/api";
|
|
@@ -48,7 +47,7 @@ import {
|
|
|
48
47
|
ChatLunaError,
|
|
49
48
|
ChatLunaErrorCode
|
|
50
49
|
} from "koishi-plugin-chatluna/utils/error";
|
|
51
|
-
import { checkResponse,
|
|
50
|
+
import { checkResponse, sseIterable } from "koishi-plugin-chatluna/utils/sse";
|
|
52
51
|
import { readableStreamToAsyncIterable } from "koishi-plugin-chatluna/utils/stream";
|
|
53
52
|
|
|
54
53
|
// src/utils.ts
|
|
@@ -237,14 +236,27 @@ function formatToolsToGeminiAITools(tools, config, model) {
|
|
|
237
236
|
}
|
|
238
237
|
const functions = tools.map(formatToolToGeminiAITool);
|
|
239
238
|
const result = [];
|
|
240
|
-
|
|
239
|
+
const unsupportedModels = [
|
|
240
|
+
"gemini-1.0",
|
|
241
|
+
"gemini-2.0-flash-lite",
|
|
242
|
+
"gemini-1.5-flash"
|
|
243
|
+
];
|
|
244
|
+
let googleSearch = config.googleSearch;
|
|
245
|
+
if (functions.length > 0 && !googleSearch) {
|
|
241
246
|
result.push({
|
|
242
247
|
functionDeclarations: functions
|
|
243
248
|
});
|
|
244
|
-
} else if (functions.length > 0 &&
|
|
249
|
+
} else if (functions.length > 0 && googleSearch) {
|
|
245
250
|
logger.warn("Google search is enabled, tool calling will be disable.");
|
|
251
|
+
} else if (unsupportedModels.some(
|
|
252
|
+
(unsupportedModel) => model.includes(unsupportedModel)
|
|
253
|
+
) && googleSearch) {
|
|
254
|
+
logger.warn(
|
|
255
|
+
`The model ${model} does not support google search. google search will be disable.`
|
|
256
|
+
);
|
|
257
|
+
googleSearch = false;
|
|
246
258
|
}
|
|
247
|
-
if (
|
|
259
|
+
if (googleSearch) {
|
|
248
260
|
if (model.includes("gemini-2")) {
|
|
249
261
|
result.push({
|
|
250
262
|
google_search: {}
|
|
@@ -330,7 +342,7 @@ var GeminiRequester = class extends ModelRequester {
|
|
|
330
342
|
async *completionStream(params) {
|
|
331
343
|
try {
|
|
332
344
|
const response = await this._post(
|
|
333
|
-
`models/${params.model}:streamGenerateContent`,
|
|
345
|
+
`models/${params.model}:streamGenerateContent?alt=sse`,
|
|
334
346
|
{
|
|
335
347
|
contents: await langchainMessageToGeminiMessage(
|
|
336
348
|
params.input,
|
|
@@ -339,23 +351,23 @@ var GeminiRequester = class extends ModelRequester {
|
|
|
339
351
|
safetySettings: [
|
|
340
352
|
{
|
|
341
353
|
category: "HARM_CATEGORY_HARASSMENT",
|
|
342
|
-
threshold: "BLOCK_NONE"
|
|
354
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
343
355
|
},
|
|
344
356
|
{
|
|
345
357
|
category: "HARM_CATEGORY_HATE_SPEECH",
|
|
346
|
-
threshold: "BLOCK_NONE"
|
|
358
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
347
359
|
},
|
|
348
360
|
{
|
|
349
361
|
category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
|
350
|
-
threshold: "BLOCK_NONE"
|
|
362
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
351
363
|
},
|
|
352
364
|
{
|
|
353
365
|
category: "HARM_CATEGORY_DANGEROUS_CONTENT",
|
|
354
|
-
threshold: "BLOCK_NONE"
|
|
366
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
355
367
|
},
|
|
356
368
|
{
|
|
357
369
|
category: "HARM_CATEGORY_CIVIC_INTEGRITY",
|
|
358
|
-
threshold: "BLOCK_NONE"
|
|
370
|
+
threshold: params.model.includes("gemini-2.0") ? "OFF" : "BLOCK_NONE"
|
|
359
371
|
}
|
|
360
372
|
],
|
|
361
373
|
generationConfig: {
|
|
@@ -376,44 +388,41 @@ var GeminiRequester = class extends ModelRequester {
|
|
|
376
388
|
}
|
|
377
389
|
);
|
|
378
390
|
let errorCount = 0;
|
|
379
|
-
const stream = new TransformStream();
|
|
380
|
-
const iterable = readableStreamToAsyncIterable(
|
|
381
|
-
stream.readable
|
|
382
|
-
);
|
|
383
|
-
const jsonParser = new JSONParser();
|
|
384
|
-
const writable = stream.writable.getWriter();
|
|
385
391
|
let groundingContent = "";
|
|
386
392
|
let currentGroudingIndex = 0;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
if (!transformValue.candidates) {
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
for (const candidate of transformValue.candidates) {
|
|
396
|
-
const parts = candidate.content?.parts;
|
|
397
|
-
if (parts == null || parts.length < 1) {
|
|
398
|
-
throw new Error(JSON.stringify(value));
|
|
393
|
+
await checkResponse(response);
|
|
394
|
+
const readableStream = new ReadableStream({
|
|
395
|
+
async start(controller) {
|
|
396
|
+
for await (const chunk of sseIterable(response)) {
|
|
397
|
+
controller.enqueue(chunk.data);
|
|
399
398
|
}
|
|
400
|
-
|
|
401
|
-
|
|
399
|
+
controller.close();
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
const transformToChatPartStream = new TransformStream({
|
|
403
|
+
async transform(chunk, controller) {
|
|
404
|
+
const parsedValue = JSON.parse(chunk);
|
|
405
|
+
const transformValue = parsedValue;
|
|
406
|
+
if (!transformValue.candidates) {
|
|
407
|
+
return;
|
|
402
408
|
}
|
|
403
|
-
for (const
|
|
404
|
-
|
|
409
|
+
for (const candidate of transformValue.candidates) {
|
|
410
|
+
const parts = candidate.content?.parts;
|
|
411
|
+
if (parts == null || parts.length < 1) {
|
|
412
|
+
throw new Error(chunk);
|
|
413
|
+
}
|
|
414
|
+
for (const part of parts) {
|
|
415
|
+
controller.enqueue(part);
|
|
416
|
+
}
|
|
417
|
+
for (const source of candidate.groundingMetadata?.groundingChunks ?? []) {
|
|
418
|
+
groundingContent += `[^${currentGroudingIndex++}]: [${source.web.title}](${source.web.uri})
|
|
405
419
|
`;
|
|
420
|
+
}
|
|
406
421
|
}
|
|
407
422
|
}
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
response,
|
|
412
|
-
async (rawData) => {
|
|
413
|
-
jsonParser.write(rawData);
|
|
414
|
-
return true;
|
|
415
|
-
},
|
|
416
|
-
0
|
|
423
|
+
});
|
|
424
|
+
const iterable = readableStreamToAsyncIterable(
|
|
425
|
+
readableStream.pipeThrough(transformToChatPartStream)
|
|
417
426
|
);
|
|
418
427
|
let reasoningContent = "";
|
|
419
428
|
let content = "";
|
|
@@ -596,10 +605,15 @@ ${groundingContent}`
|
|
|
596
605
|
}
|
|
597
606
|
_concatUrl(url) {
|
|
598
607
|
const apiEndPoint = this._config.apiEndpoint;
|
|
608
|
+
let baseURL;
|
|
599
609
|
if (apiEndPoint.endsWith("/")) {
|
|
600
|
-
|
|
610
|
+
baseURL = new URL(apiEndPoint + url);
|
|
611
|
+
} else {
|
|
612
|
+
baseURL = new URL(apiEndPoint + "/" + url);
|
|
601
613
|
}
|
|
602
|
-
|
|
614
|
+
const searchParams = baseURL.searchParams;
|
|
615
|
+
searchParams.set("key", this._config.apiKey);
|
|
616
|
+
return baseURL.toString();
|
|
603
617
|
}
|
|
604
618
|
_buildHeaders() {
|
|
605
619
|
return {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-chatluna-google-gemini-adapter",
|
|
3
3
|
"description": "google-gemini adapter for chatluna",
|
|
4
|
-
"version": "1.1.0-beta.
|
|
4
|
+
"version": "1.1.0-beta.4",
|
|
5
5
|
"main": "lib/index.cjs",
|
|
6
6
|
"module": "lib/index.mjs",
|
|
7
7
|
"typings": "lib/index.d.ts",
|
|
@@ -63,7 +63,6 @@
|
|
|
63
63
|
],
|
|
64
64
|
"dependencies": {
|
|
65
65
|
"@langchain/core": "^0.3.18",
|
|
66
|
-
"@streamparser/json": "^0.0.21",
|
|
67
66
|
"zod": "^3.24.0-canary.20241107T043915",
|
|
68
67
|
"zod-to-json-schema": "^3.23.5"
|
|
69
68
|
},
|
|
@@ -73,7 +72,7 @@
|
|
|
73
72
|
},
|
|
74
73
|
"peerDependencies": {
|
|
75
74
|
"koishi": "^4.18.4",
|
|
76
|
-
"koishi-plugin-chatluna": "^1.1.0-beta.
|
|
75
|
+
"koishi-plugin-chatluna": "^1.1.0-beta.16"
|
|
77
76
|
},
|
|
78
77
|
"koishi": {
|
|
79
78
|
"description": {
|