@ragpipe/plugin-gemini 0.0.1
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/dist/index.cjs +162 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +134 -0
- package/package.json +60 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
geminiEmbedding: () => geminiEmbedding,
|
|
24
|
+
geminiGeneration: () => geminiGeneration
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/embedding.ts
|
|
29
|
+
function geminiEmbedding(options) {
|
|
30
|
+
const model = options.model ?? "gemini-embedding-001";
|
|
31
|
+
return {
|
|
32
|
+
name: "gemini",
|
|
33
|
+
dimensions: 3072,
|
|
34
|
+
rateLimit: { delayMs: 800 },
|
|
35
|
+
async embed(text) {
|
|
36
|
+
const res = await fetch(
|
|
37
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${model}:embedContent?key=${options.apiKey}`,
|
|
38
|
+
{
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "Content-Type": "application/json" },
|
|
41
|
+
body: JSON.stringify({ content: { parts: [{ text }] } })
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Gemini embedding error: ${res.status} ${await res.text()}`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const data = await res.json();
|
|
50
|
+
return data.embedding.values;
|
|
51
|
+
},
|
|
52
|
+
async embedMany(texts) {
|
|
53
|
+
const requests = texts.map((text) => ({
|
|
54
|
+
model: `models/${model}`,
|
|
55
|
+
content: { parts: [{ text }] }
|
|
56
|
+
}));
|
|
57
|
+
const res = await fetch(
|
|
58
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${model}:batchEmbedContents?key=${options.apiKey}`,
|
|
59
|
+
{
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: { "Content-Type": "application/json" },
|
|
62
|
+
body: JSON.stringify({ requests })
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
if (!res.ok) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Gemini batch embedding error: ${res.status} ${await res.text()}`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const data = await res.json();
|
|
71
|
+
return data.embeddings.map((e) => e.values);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/generation.ts
|
|
77
|
+
function geminiGeneration(options) {
|
|
78
|
+
const model = options.model ?? "gemini-2.5-flash";
|
|
79
|
+
function buildBody(question, context, opts) {
|
|
80
|
+
const systemPrompt = opts?.systemPrompt ?? options.systemPrompt ?? "Answer based on the provided context.";
|
|
81
|
+
let userPrompt = `Context:
|
|
82
|
+
${context}
|
|
83
|
+
|
|
84
|
+
Question: ${question}`;
|
|
85
|
+
if (opts?.history) {
|
|
86
|
+
userPrompt = `Conversation history:
|
|
87
|
+
${opts.history}
|
|
88
|
+
|
|
89
|
+
${userPrompt}`;
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
contents: [{ parts: [{ text: userPrompt }] }],
|
|
93
|
+
systemInstruction: { parts: [{ text: systemPrompt }] }
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
name: "gemini",
|
|
98
|
+
async generate(question, context, opts) {
|
|
99
|
+
const body = buildBody(question, context, opts);
|
|
100
|
+
const res = await fetch(
|
|
101
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${options.apiKey}`,
|
|
102
|
+
{
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: { "Content-Type": "application/json" },
|
|
105
|
+
body: JSON.stringify(body)
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
if (!res.ok) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Gemini generation error: ${res.status} ${await res.text()}`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const data = await res.json();
|
|
114
|
+
return data.candidates[0].content.parts[0].text;
|
|
115
|
+
},
|
|
116
|
+
async *generateStream(question, context, opts) {
|
|
117
|
+
const body = buildBody(question, context, opts);
|
|
118
|
+
const res = await fetch(
|
|
119
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse&key=${options.apiKey}`,
|
|
120
|
+
{
|
|
121
|
+
method: "POST",
|
|
122
|
+
headers: { "Content-Type": "application/json" },
|
|
123
|
+
body: JSON.stringify(body)
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
if (!res.ok) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Gemini generation stream error: ${res.status} ${await res.text()}`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
const reader = res.body?.getReader();
|
|
132
|
+
if (!reader) throw new Error("No response body");
|
|
133
|
+
const decoder = new TextDecoder();
|
|
134
|
+
let buffer = "";
|
|
135
|
+
try {
|
|
136
|
+
for (; ; ) {
|
|
137
|
+
const { done, value } = await reader.read();
|
|
138
|
+
if (done) break;
|
|
139
|
+
buffer += decoder.decode(value, { stream: true });
|
|
140
|
+
const lines = buffer.split("\n");
|
|
141
|
+
buffer = lines.pop() ?? "";
|
|
142
|
+
for (const line of lines) {
|
|
143
|
+
if (!line.startsWith("data: ")) continue;
|
|
144
|
+
try {
|
|
145
|
+
const data = JSON.parse(line.slice(6));
|
|
146
|
+
const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
147
|
+
if (text) yield text;
|
|
148
|
+
} catch {
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} finally {
|
|
153
|
+
reader.releaseLock();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
159
|
+
0 && (module.exports = {
|
|
160
|
+
geminiEmbedding,
|
|
161
|
+
geminiGeneration
|
|
162
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EmbeddingPlugin, GenerationPlugin } from 'ragpipe';
|
|
2
|
+
|
|
3
|
+
interface GeminiEmbeddingOptions {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
model?: string;
|
|
6
|
+
}
|
|
7
|
+
declare function geminiEmbedding(options: GeminiEmbeddingOptions): EmbeddingPlugin;
|
|
8
|
+
|
|
9
|
+
interface GeminiGenerationOptions {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
model?: string;
|
|
12
|
+
systemPrompt?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function geminiGeneration(options: GeminiGenerationOptions): GenerationPlugin;
|
|
15
|
+
|
|
16
|
+
export { type GeminiEmbeddingOptions, type GeminiGenerationOptions, geminiEmbedding, geminiGeneration };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EmbeddingPlugin, GenerationPlugin } from 'ragpipe';
|
|
2
|
+
|
|
3
|
+
interface GeminiEmbeddingOptions {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
model?: string;
|
|
6
|
+
}
|
|
7
|
+
declare function geminiEmbedding(options: GeminiEmbeddingOptions): EmbeddingPlugin;
|
|
8
|
+
|
|
9
|
+
interface GeminiGenerationOptions {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
model?: string;
|
|
12
|
+
systemPrompt?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function geminiGeneration(options: GeminiGenerationOptions): GenerationPlugin;
|
|
15
|
+
|
|
16
|
+
export { type GeminiEmbeddingOptions, type GeminiGenerationOptions, geminiEmbedding, geminiGeneration };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// src/embedding.ts
|
|
2
|
+
function geminiEmbedding(options) {
|
|
3
|
+
const model = options.model ?? "gemini-embedding-001";
|
|
4
|
+
return {
|
|
5
|
+
name: "gemini",
|
|
6
|
+
dimensions: 3072,
|
|
7
|
+
rateLimit: { delayMs: 800 },
|
|
8
|
+
async embed(text) {
|
|
9
|
+
const res = await fetch(
|
|
10
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${model}:embedContent?key=${options.apiKey}`,
|
|
11
|
+
{
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: { "Content-Type": "application/json" },
|
|
14
|
+
body: JSON.stringify({ content: { parts: [{ text }] } })
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
if (!res.ok) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Gemini embedding error: ${res.status} ${await res.text()}`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const data = await res.json();
|
|
23
|
+
return data.embedding.values;
|
|
24
|
+
},
|
|
25
|
+
async embedMany(texts) {
|
|
26
|
+
const requests = texts.map((text) => ({
|
|
27
|
+
model: `models/${model}`,
|
|
28
|
+
content: { parts: [{ text }] }
|
|
29
|
+
}));
|
|
30
|
+
const res = await fetch(
|
|
31
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${model}:batchEmbedContents?key=${options.apiKey}`,
|
|
32
|
+
{
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "Content-Type": "application/json" },
|
|
35
|
+
body: JSON.stringify({ requests })
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Gemini batch embedding error: ${res.status} ${await res.text()}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const data = await res.json();
|
|
44
|
+
return data.embeddings.map((e) => e.values);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/generation.ts
|
|
50
|
+
function geminiGeneration(options) {
|
|
51
|
+
const model = options.model ?? "gemini-2.5-flash";
|
|
52
|
+
function buildBody(question, context, opts) {
|
|
53
|
+
const systemPrompt = opts?.systemPrompt ?? options.systemPrompt ?? "Answer based on the provided context.";
|
|
54
|
+
let userPrompt = `Context:
|
|
55
|
+
${context}
|
|
56
|
+
|
|
57
|
+
Question: ${question}`;
|
|
58
|
+
if (opts?.history) {
|
|
59
|
+
userPrompt = `Conversation history:
|
|
60
|
+
${opts.history}
|
|
61
|
+
|
|
62
|
+
${userPrompt}`;
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
contents: [{ parts: [{ text: userPrompt }] }],
|
|
66
|
+
systemInstruction: { parts: [{ text: systemPrompt }] }
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
name: "gemini",
|
|
71
|
+
async generate(question, context, opts) {
|
|
72
|
+
const body = buildBody(question, context, opts);
|
|
73
|
+
const res = await fetch(
|
|
74
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${options.apiKey}`,
|
|
75
|
+
{
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: { "Content-Type": "application/json" },
|
|
78
|
+
body: JSON.stringify(body)
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Gemini generation error: ${res.status} ${await res.text()}`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
const data = await res.json();
|
|
87
|
+
return data.candidates[0].content.parts[0].text;
|
|
88
|
+
},
|
|
89
|
+
async *generateStream(question, context, opts) {
|
|
90
|
+
const body = buildBody(question, context, opts);
|
|
91
|
+
const res = await fetch(
|
|
92
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse&key=${options.apiKey}`,
|
|
93
|
+
{
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers: { "Content-Type": "application/json" },
|
|
96
|
+
body: JSON.stringify(body)
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
if (!res.ok) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Gemini generation stream error: ${res.status} ${await res.text()}`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
const reader = res.body?.getReader();
|
|
105
|
+
if (!reader) throw new Error("No response body");
|
|
106
|
+
const decoder = new TextDecoder();
|
|
107
|
+
let buffer = "";
|
|
108
|
+
try {
|
|
109
|
+
for (; ; ) {
|
|
110
|
+
const { done, value } = await reader.read();
|
|
111
|
+
if (done) break;
|
|
112
|
+
buffer += decoder.decode(value, { stream: true });
|
|
113
|
+
const lines = buffer.split("\n");
|
|
114
|
+
buffer = lines.pop() ?? "";
|
|
115
|
+
for (const line of lines) {
|
|
116
|
+
if (!line.startsWith("data: ")) continue;
|
|
117
|
+
try {
|
|
118
|
+
const data = JSON.parse(line.slice(6));
|
|
119
|
+
const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
120
|
+
if (text) yield text;
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} finally {
|
|
126
|
+
reader.releaseLock();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
geminiEmbedding,
|
|
133
|
+
geminiGeneration
|
|
134
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ragpipe/plugin-gemini",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Gemini embedding and generation plugin for ragpipe",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "yungblud",
|
|
9
|
+
"url": "https://github.com/yungblud"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/yungblud/ragpipe",
|
|
14
|
+
"directory": "packages/plugin-gemini"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/yungblud/ragpipe/issues"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/yungblud/ragpipe#readme",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js",
|
|
27
|
+
"require": "./dist/index.cjs"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"main": "./dist/index.cjs",
|
|
31
|
+
"module": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"files": ["dist"],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsup",
|
|
36
|
+
"dev": "tsup --watch",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"test:watch": "vitest",
|
|
40
|
+
"test:coverage": "vitest run --coverage"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"ragpipe",
|
|
44
|
+
"rag",
|
|
45
|
+
"gemini",
|
|
46
|
+
"google-ai",
|
|
47
|
+
"embedding",
|
|
48
|
+
"generation",
|
|
49
|
+
"plugin"
|
|
50
|
+
],
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"ragpipe": ">=0.0.1"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"ragpipe": "workspace:*",
|
|
56
|
+
"tsup": "^8.4.0",
|
|
57
|
+
"typescript": "^5.8.3",
|
|
58
|
+
"vitest": "^3.1.1"
|
|
59
|
+
}
|
|
60
|
+
}
|