@vivantel/virage-embedder-openai 0.2.0

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/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # @vivantel/virage-embedder-openai
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@vivantel/virage-embedder-openai.svg)](https://www.npmjs.com/package/@vivantel/virage-embedder-openai)
4
+
5
+ OpenAI-compatible embedding provider for `@vivantel/virage-core`. Works with OpenAI, Azure OpenAI, GitHub Models, Ollama, LM Studio, and any OpenAI-compatible endpoint.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @vivantel/virage-embedder-openai
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### OpenAI
16
+
17
+ ```typescript
18
+ import { OpenAICompatibleEmbedder } from "@vivantel/virage-embedder-openai";
19
+
20
+ const embedder = new OpenAICompatibleEmbedder({
21
+ apiKey: process.env.OPENAI_API_KEY!,
22
+ model: "text-embedding-3-small",
23
+ dimensions: 1536,
24
+ });
25
+ ```
26
+
27
+ ### GitHub Models (preset)
28
+
29
+ ```typescript
30
+ import { createGitHubModelsEmbedder } from "@vivantel/virage-embedder-openai";
31
+
32
+ const embedder = createGitHubModelsEmbedder({
33
+ token: process.env.GITHUB_TOKEN!,
34
+ model: "openai/text-embedding-3-small", // optional, this is the default
35
+ });
36
+ ```
37
+
38
+ ### Azure OpenAI (preset)
39
+
40
+ ```typescript
41
+ import { createAzureOpenAIEmbedder } from "@vivantel/virage-embedder-openai";
42
+
43
+ const embedder = createAzureOpenAIEmbedder({
44
+ apiKey: process.env.AZURE_OPENAI_KEY!,
45
+ endpoint: "https://my-resource.openai.azure.com",
46
+ model: "text-embedding-3-small",
47
+ });
48
+ ```
49
+
50
+ ### Ollama (preset)
51
+
52
+ ```typescript
53
+ import { createOllamaEmbedder } from "@vivantel/virage-embedder-openai";
54
+
55
+ const embedder = createOllamaEmbedder({
56
+ model: "nomic-embed-text",
57
+ dimensions: 768,
58
+ baseURL: "http://localhost:11434", // optional, this is the default
59
+ });
60
+ ```
61
+
62
+ ## JSON config
63
+
64
+ ```json
65
+ {
66
+ "embedder": {
67
+ "package": "@vivantel/virage-embedder-openai",
68
+ "config": {
69
+ "apiKey": "${GITHUB_TOKEN}",
70
+ "baseURL": "https://models.github.ai/inference",
71
+ "model": "openai/text-embedding-3-small",
72
+ "dimensions": 1536
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ ## Options
79
+
80
+ | Option | Type | Required | Description |
81
+ | --- | --- | --- | --- |
82
+ | `apiKey` | `string` | ✓ | API key |
83
+ | `model` | `string` | ✓ | Model identifier |
84
+ | `dimensions` | `number` | — | Output dimensions (default: 1536) |
85
+ | `baseURL` | `string` | — | API base URL (default: OpenAI) |
86
+ | `organizationId` | `string` | — | OpenAI organization ID |
87
+ | `maxRetries` | `number` | — | Retry attempts (default: 3) |
88
+
89
+ ## License
90
+
91
+ MIT
@@ -0,0 +1,32 @@
1
+ import type { EmbeddingProvider, EmbeddingMetrics, Logger } from "@vivantel/virage-core";
2
+ import { type SemanticCacheConfig } from "./semantic-cache.js";
3
+ export interface OpenAICompatibleEmbedderOptions {
4
+ apiKey: string;
5
+ model: string;
6
+ dimensions?: number;
7
+ /** Defaults to https://api.openai.com/v1 */
8
+ baseURL?: string;
9
+ organizationId?: string;
10
+ maxRetries?: number;
11
+ /** Optional semantic or exact embedding cache. */
12
+ cache?: SemanticCacheConfig;
13
+ }
14
+ export declare class OpenAICompatibleEmbedder implements EmbeddingProvider {
15
+ readonly name: string;
16
+ readonly dimensions: number;
17
+ readonly model: string;
18
+ readonly preferredBatchSize = 100;
19
+ private readonly client;
20
+ private readonly cache;
21
+ private readonly baseURL;
22
+ private logger;
23
+ constructor(options: OpenAICompatibleEmbedderOptions);
24
+ setLogger(logger: Logger): void;
25
+ embed(text: string): Promise<number[]>;
26
+ private embedDirect;
27
+ embedBatch(texts: string[]): Promise<number[][]>;
28
+ private embedBatchDirect;
29
+ healthCheck(): Promise<boolean>;
30
+ getMetrics(embeddings: number[][]): Promise<EmbeddingMetrics>;
31
+ }
32
+ //# sourceMappingURL=embedder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedder.d.ts","sourceRoot":"","sources":["../src/embedder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,MAAM,EACP,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE9E,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,KAAK,CAAC,EAAE,mBAAmB,CAAC;CAC7B;AAED,qBAAa,wBAAyB,YAAW,iBAAiB;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,kBAAkB,OAAO;IAElC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,EAAE,+BAA+B;IAkBpD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIzB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAU9B,WAAW;IAanB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YA8BxC,gBAAgB;IAaxB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAGpE"}
@@ -0,0 +1,96 @@
1
+ import OpenAI from "openai";
2
+ import { computeEmbeddingMetrics } from "./embedding-metrics.js";
3
+ import { SemanticCache } from "./semantic-cache.js";
4
+ export class OpenAICompatibleEmbedder {
5
+ name;
6
+ dimensions;
7
+ model;
8
+ preferredBatchSize = 100;
9
+ client;
10
+ cache;
11
+ baseURL;
12
+ logger = null;
13
+ constructor(options) {
14
+ this.model = options.model;
15
+ this.dimensions = options.dimensions ?? 1536;
16
+ this.baseURL = options.baseURL;
17
+ this.name = options.baseURL
18
+ ? `openai-compatible:${new URL(options.baseURL).hostname}`
19
+ : "openai";
20
+ this.client = new OpenAI({
21
+ apiKey: options.apiKey,
22
+ baseURL: options.baseURL,
23
+ organization: options.organizationId,
24
+ maxRetries: options.maxRetries ?? 3,
25
+ });
26
+ this.cache = options.cache ? new SemanticCache(options.cache) : null;
27
+ }
28
+ setLogger(logger) {
29
+ this.logger = logger.withTag("openai");
30
+ }
31
+ async embed(text) {
32
+ if (this.cache) {
33
+ const hit = await this.cache.get(text, (t) => this.embedDirect(t));
34
+ if (hit)
35
+ return hit;
36
+ }
37
+ const embedding = await this.embedDirect(text);
38
+ if (this.cache)
39
+ await this.cache.set(text, embedding);
40
+ return embedding;
41
+ }
42
+ async embedDirect(text) {
43
+ const start = Date.now();
44
+ const res = await this.client.embeddings.create({
45
+ model: this.model,
46
+ input: text,
47
+ dimensions: this.dimensions !== 1536 ? this.dimensions : undefined,
48
+ });
49
+ this.logger?.debug(`Embed call: ${Date.now() - start}ms, ${text.length} chars`);
50
+ return res.data[0].embedding;
51
+ }
52
+ async embedBatch(texts) {
53
+ this.logger?.verbose(`Batch ${texts.length} texts to ${this.baseURL ?? "https://api.openai.com/v1"}`);
54
+ this.logger?.trace(`Text lengths: ${texts.map((t) => t.length).join(", ")}`);
55
+ if (this.cache) {
56
+ // Try cache for each text; fall back to batch API for misses
57
+ const results = await Promise.all(texts.map((t) => this.cache.get(t, (x) => this.embedDirect(x))));
58
+ const missIndices = results
59
+ .map((r, i) => (r === null ? i : -1))
60
+ .filter((i) => i >= 0);
61
+ if (missIndices.length === 0)
62
+ return results;
63
+ const missTexts = missIndices.map((i) => texts[i]);
64
+ const missEmbeddings = await this.embedBatchDirect(missTexts);
65
+ for (let k = 0; k < missIndices.length; k++) {
66
+ results[missIndices[k]] = missEmbeddings[k];
67
+ await this.cache.set(missTexts[k], missEmbeddings[k]);
68
+ }
69
+ return results;
70
+ }
71
+ return this.embedBatchDirect(texts);
72
+ }
73
+ async embedBatchDirect(texts) {
74
+ const start = Date.now();
75
+ const res = await this.client.embeddings.create({
76
+ model: this.model,
77
+ input: texts,
78
+ dimensions: this.dimensions !== 1536 ? this.dimensions : undefined,
79
+ });
80
+ this.logger?.debug(`Batch call: ${Date.now() - start}ms, ${texts.length} texts`);
81
+ return res.data.map((d) => d.embedding);
82
+ }
83
+ async healthCheck() {
84
+ try {
85
+ await this.embed("health check");
86
+ return true;
87
+ }
88
+ catch {
89
+ return false;
90
+ }
91
+ }
92
+ async getMetrics(embeddings) {
93
+ return computeEmbeddingMetrics(embeddings);
94
+ }
95
+ }
96
+ //# sourceMappingURL=embedder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedder.js","sourceRoot":"","sources":["../src/embedder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Pure embedding quality metric functions.
3
+ * No I/O, no external dependencies.
4
+ */
5
+ import type { EmbeddingMetrics } from "@vivantel/virage-core";
6
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
7
+ /**
8
+ * TWO-NN intrinsic dimension estimator.
9
+ * For each point, computes r1/r2 (ratio of distances to 1st and 2nd
10
+ * nearest neighbours). ID = -1 / mean(ln(r1/r2)).
11
+ * Reference: Facco et al. (2017).
12
+ */
13
+ export declare function computeIntrinsicDimension(embeddings: number[][]): number;
14
+ /**
15
+ * Mean cosine similarity between randomly sampled pairs.
16
+ * Close to 0 is ideal (well-spread embedding space).
17
+ */
18
+ export declare function computeAvgCosineSimRandomPairs(embeddings: number[][], sampleSize?: number): number;
19
+ /**
20
+ * Fraction of embeddings whose L2-norm z-score exceeds 2.5.
21
+ */
22
+ export declare function detectOutliers(embeddings: number[][]): number;
23
+ export declare function computeEmbeddingMetrics(embeddings: number[][]): Promise<EmbeddingMetrics>;
24
+ //# sourceMappingURL=embedding-metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-metrics.d.ts","sourceRoot":"","sources":["../src/embedding-metrics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAWjE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAoCxE;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,MAAM,EAAE,EAAE,EACtB,UAAU,SAAM,GACf,MAAM,CAeR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAe7D;AAED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAAE,EAAE,GACrB,OAAO,CAAC,gBAAgB,CAAC,CAM3B"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Pure embedding quality metric functions.
3
+ * No I/O, no external dependencies.
4
+ */
5
+ export function cosineSimilarity(a, b) {
6
+ let dot = 0;
7
+ let normA = 0;
8
+ let normB = 0;
9
+ for (let i = 0; i < a.length; i++) {
10
+ dot += a[i] * b[i];
11
+ normA += a[i] * a[i];
12
+ normB += b[i] * b[i];
13
+ }
14
+ if (normA === 0 || normB === 0)
15
+ return 0;
16
+ return dot / (Math.sqrt(normA) * Math.sqrt(normB));
17
+ }
18
+ /**
19
+ * TWO-NN intrinsic dimension estimator.
20
+ * For each point, computes r1/r2 (ratio of distances to 1st and 2nd
21
+ * nearest neighbours). ID = -1 / mean(ln(r1/r2)).
22
+ * Reference: Facco et al. (2017).
23
+ */
24
+ export function computeIntrinsicDimension(embeddings) {
25
+ const n = embeddings.length;
26
+ if (n < 3)
27
+ return embeddings[0]?.length ?? 0;
28
+ const l2sq = (a, b) => {
29
+ let s = 0;
30
+ for (let i = 0; i < a.length; i++)
31
+ s += (a[i] - b[i]) ** 2;
32
+ return s;
33
+ };
34
+ let sumLn = 0;
35
+ let count = 0;
36
+ for (let i = 0; i < n; i++) {
37
+ let d1 = Infinity;
38
+ let d2 = Infinity;
39
+ for (let j = 0; j < n; j++) {
40
+ if (i === j)
41
+ continue;
42
+ const d = l2sq(embeddings[i], embeddings[j]);
43
+ if (d < d1) {
44
+ d2 = d1;
45
+ d1 = d;
46
+ }
47
+ else if (d < d2) {
48
+ d2 = d;
49
+ }
50
+ }
51
+ if (d1 > 0 && d2 > 0 && d1 < d2) {
52
+ sumLn += Math.log(Math.sqrt(d1) / Math.sqrt(d2));
53
+ count++;
54
+ }
55
+ }
56
+ if (count === 0)
57
+ return embeddings[0]?.length ?? 0;
58
+ return -count / sumLn;
59
+ }
60
+ /**
61
+ * Mean cosine similarity between randomly sampled pairs.
62
+ * Close to 0 is ideal (well-spread embedding space).
63
+ */
64
+ export function computeAvgCosineSimRandomPairs(embeddings, sampleSize = 500) {
65
+ const n = embeddings.length;
66
+ if (n < 2)
67
+ return 0;
68
+ const pairs = Math.min(sampleSize, (n * (n - 1)) / 2);
69
+ let sum = 0;
70
+ for (let i = 0; i < pairs; i++) {
71
+ const a = Math.floor(Math.random() * n);
72
+ let b = Math.floor(Math.random() * (n - 1));
73
+ if (b >= a)
74
+ b++;
75
+ sum += cosineSimilarity(embeddings[a], embeddings[b]);
76
+ }
77
+ return sum / pairs;
78
+ }
79
+ /**
80
+ * Fraction of embeddings whose L2-norm z-score exceeds 2.5.
81
+ */
82
+ export function detectOutliers(embeddings) {
83
+ if (embeddings.length < 2)
84
+ return 0;
85
+ const norms = embeddings.map((e) => Math.sqrt(e.reduce((s, v) => s + v * v, 0)));
86
+ const mean = norms.reduce((s, v) => s + v, 0) / norms.length;
87
+ const variance = norms.reduce((s, v) => s + (v - mean) ** 2, 0) / norms.length;
88
+ const std = Math.sqrt(variance);
89
+ if (std === 0)
90
+ return 0;
91
+ const outliers = norms.filter((n) => Math.abs(n - mean) / std > 2.5).length;
92
+ return outliers / norms.length;
93
+ }
94
+ export async function computeEmbeddingMetrics(embeddings) {
95
+ return {
96
+ intrinsicDimension: computeIntrinsicDimension(embeddings),
97
+ avgCosineSimRandomPairs: computeAvgCosineSimRandomPairs(embeddings),
98
+ outlierFraction: detectOutliers(embeddings),
99
+ };
100
+ }
101
+ //# sourceMappingURL=embedding-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-metrics.js","sourceRoot":"","sources":["../src/embedding-metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { OpenAICompatibleEmbedder, type OpenAICompatibleEmbedderOptions, } from "./embedder.js";
2
+ export { computeEmbeddingMetrics, cosineSimilarity, computeIntrinsicDimension, computeAvgCosineSimRandomPairs, detectOutliers, } from "./embedding-metrics.js";
3
+ export { OpenAIJudge, type OpenAIJudgeOptions } from "./judge.js";
4
+ export { SemanticCache, type SemanticCacheConfig } from "./semantic-cache.js";
5
+ export { createGitHubModelsEmbedder, createAzureOpenAIEmbedder, createOllamaEmbedder, type GitHubModelsPresetOptions, type AzureOpenAIPresetOptions, type OllamaPresetOptions, } from "./presets.js";
6
+ import type { EmbeddingProvider } from "@vivantel/virage-core";
7
+ /** Factory used by the JSON config loader. */
8
+ export declare function createEmbedder(config: Record<string, unknown>): EmbeddingProvider;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,KAAK,+BAA+B,GACrC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,yBAAyB,EACzB,8BAA8B,EAC9B,cAAc,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM/D,8CAA8C;AAC9C,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,iBAAiB,CA6BnB"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ export { OpenAICompatibleEmbedder, } from "./embedder.js";
2
+ export { computeEmbeddingMetrics, cosineSimilarity, computeIntrinsicDimension, computeAvgCosineSimRandomPairs, detectOutliers, } from "./embedding-metrics.js";
3
+ export { OpenAIJudge } from "./judge.js";
4
+ export { SemanticCache } from "./semantic-cache.js";
5
+ export { createGitHubModelsEmbedder, createAzureOpenAIEmbedder, createOllamaEmbedder, } from "./presets.js";
6
+ import { OpenAICompatibleEmbedder, } from "./embedder.js";
7
+ /** Factory used by the JSON config loader. */
8
+ export function createEmbedder(config) {
9
+ const apiKey = config.apiKey;
10
+ if (typeof apiKey !== "string" || !apiKey) {
11
+ throw new Error("@vivantel/virage-embedder-openai: config.apiKey is required");
12
+ }
13
+ const model = config.model;
14
+ if (typeof model !== "string" || !model) {
15
+ throw new Error("@vivantel/virage-embedder-openai: config.model is required");
16
+ }
17
+ const opts = {
18
+ apiKey,
19
+ model,
20
+ dimensions: typeof config.dimensions === "number" ? config.dimensions : undefined,
21
+ baseURL: typeof config.baseURL === "string" ? config.baseURL : undefined,
22
+ organizationId: typeof config.organizationId === "string"
23
+ ? config.organizationId
24
+ : undefined,
25
+ maxRetries: typeof config.maxRetries === "number" ? config.maxRetries : undefined,
26
+ };
27
+ return new OpenAICompatibleEmbedder(opts);
28
+ }
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,GAEzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,yBAAyB,EACzB,8BAA8B,EAC9B,cAAc,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAA2B,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,aAAa,EAA4B,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,GAIrB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,wBAAwB,GAEzB,MAAM,eAAe,CAAC;AAEvB,8CAA8C;AAC9C,MAAM,UAAU,cAAc,CAC5B,MAA+B;IAE/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAoC;QAC5C,MAAM;QACN,KAAK;QACL,UAAU,EACR,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;QACvE,OAAO,EAAE,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QACxE,cAAc,EACZ,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ;YACvC,CAAC,CAAC,MAAM,CAAC,cAAc;YACvB,CAAC,CAAC,SAAS;QACf,UAAU,EACR,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;KACxE,CAAC;IAEF,OAAO,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { LLMJudge } from "@vivantel/virage-core";
2
+ export interface OpenAIJudgeOptions {
3
+ apiKey: string;
4
+ /** Defaults to "gpt-4o-mini" */
5
+ model?: string;
6
+ baseURL?: string;
7
+ maxRetries?: number;
8
+ }
9
+ export declare class OpenAIJudge implements LLMJudge {
10
+ readonly name: string;
11
+ private readonly client;
12
+ private readonly model;
13
+ constructor(options: OpenAIJudgeOptions);
14
+ evaluate(query: string, contexts: string[], groundTruth: string): Promise<{
15
+ faithfulness: number;
16
+ answerRelevance: number;
17
+ contextRecall: number;
18
+ }>;
19
+ private score;
20
+ }
21
+ //# sourceMappingURL=judge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judge.d.ts","sourceRoot":"","sources":["../src/judge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA4CD,qBAAa,WAAY,YAAW,QAAQ;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,EAAE,kBAAkB;IAUjC,QAAQ,CACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;YAWY,KAAK;CAkBpB"}
package/dist/judge.js ADDED
@@ -0,0 +1,73 @@
1
+ import OpenAI from "openai";
2
+ // RAGAS-style prompt templates
3
+ // Reference: https://docs.ragas.io/en/stable/concepts/metrics/
4
+ const FAITHFULNESS_PROMPT = (contexts, answer) => `You are evaluating RAG faithfulness. Given the retrieved context and an answer, score from 0.0 to 1.0 how much the answer is grounded in the context (1.0 = fully grounded, 0.0 = completely hallucinated).
5
+
6
+ CONTEXT:
7
+ ${contexts.map((c, i) => `[${i + 1}] ${c}`).join("\n\n")}
8
+
9
+ ANSWER:
10
+ ${answer}
11
+
12
+ Respond with ONLY a JSON object: {"score": <number>}`;
13
+ const ANSWER_RELEVANCE_PROMPT = (query, answer) => `You are evaluating RAG answer relevance. Given the query and the answer, score from 0.0 to 1.0 how well the answer addresses the question (1.0 = perfectly on-topic, 0.0 = completely irrelevant).
14
+
15
+ QUERY:
16
+ ${query}
17
+
18
+ ANSWER:
19
+ ${answer}
20
+
21
+ Respond with ONLY a JSON object: {"score": <number>}`;
22
+ const CONTEXT_RECALL_PROMPT = (groundTruth, contexts) => `You are evaluating RAG context recall. Given the expected answer and the retrieved contexts, score from 0.0 to 1.0 how much information from the expected answer is covered by the contexts (1.0 = fully covered, 0.0 = not covered at all).
23
+
24
+ EXPECTED ANSWER:
25
+ ${groundTruth}
26
+
27
+ RETRIEVED CONTEXTS:
28
+ ${contexts.map((c, i) => `[${i + 1}] ${c}`).join("\n\n")}
29
+
30
+ Respond with ONLY a JSON object: {"score": <number>}`;
31
+ export class OpenAIJudge {
32
+ name;
33
+ client;
34
+ model;
35
+ constructor(options) {
36
+ this.model = options.model ?? "gpt-4o-mini";
37
+ this.name = `openai-judge:${this.model}`;
38
+ this.client = new OpenAI({
39
+ apiKey: options.apiKey,
40
+ baseURL: options.baseURL,
41
+ maxRetries: options.maxRetries ?? 3,
42
+ });
43
+ }
44
+ async evaluate(query, contexts, groundTruth) {
45
+ // Use ground truth as the "answer" for faithfulness and relevance evaluation
46
+ const [faithfulness, answerRelevance, contextRecall] = await Promise.all([
47
+ this.score(FAITHFULNESS_PROMPT(contexts, groundTruth)),
48
+ this.score(ANSWER_RELEVANCE_PROMPT(query, groundTruth)),
49
+ this.score(CONTEXT_RECALL_PROMPT(groundTruth, contexts)),
50
+ ]);
51
+ return { faithfulness, answerRelevance, contextRecall };
52
+ }
53
+ async score(prompt) {
54
+ const response = await this.client.chat.completions.create({
55
+ model: this.model,
56
+ messages: [{ role: "user", content: prompt }],
57
+ response_format: { type: "json_object" },
58
+ temperature: 0,
59
+ });
60
+ const content = response.choices[0]?.message?.content ?? "{}";
61
+ try {
62
+ const parsed = JSON.parse(content);
63
+ const score = parsed.score;
64
+ if (typeof score !== "number")
65
+ return 0;
66
+ return Math.max(0, Math.min(1, score));
67
+ }
68
+ catch {
69
+ return 0;
70
+ }
71
+ }
72
+ }
73
+ //# sourceMappingURL=judge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judge.js","sourceRoot":"","sources":["../src/judge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { OpenAICompatibleEmbedder } from "./embedder.js";
2
+ export interface GitHubModelsPresetOptions {
3
+ token: string;
4
+ model?: string;
5
+ dimensions?: number;
6
+ }
7
+ export interface AzureOpenAIPresetOptions {
8
+ apiKey: string;
9
+ endpoint: string;
10
+ model?: string;
11
+ dimensions?: number;
12
+ }
13
+ export interface OllamaPresetOptions {
14
+ model: string;
15
+ dimensions: number;
16
+ baseURL?: string;
17
+ }
18
+ /** Pre-configured embedder for GitHub Models (OpenAI-compatible endpoint). */
19
+ export declare function createGitHubModelsEmbedder(options: GitHubModelsPresetOptions): OpenAICompatibleEmbedder;
20
+ /** Pre-configured embedder for Azure OpenAI. */
21
+ export declare function createAzureOpenAIEmbedder(options: AzureOpenAIPresetOptions): OpenAICompatibleEmbedder;
22
+ /** Pre-configured embedder for a local Ollama server. */
23
+ export declare function createOllamaEmbedder(options: OllamaPresetOptions): OpenAICompatibleEmbedder;
24
+ //# sourceMappingURL=presets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EAEzB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8EAA8E;AAC9E,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,yBAAyB,GACjC,wBAAwB,CAO1B;AAED,gDAAgD;AAChD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAO1B;AAED,yDAAyD;AACzD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,mBAAmB,GAC3B,wBAAwB,CAO1B"}
@@ -0,0 +1,29 @@
1
+ import { OpenAICompatibleEmbedder, } from "./embedder.js";
2
+ /** Pre-configured embedder for GitHub Models (OpenAI-compatible endpoint). */
3
+ export function createGitHubModelsEmbedder(options) {
4
+ return new OpenAICompatibleEmbedder({
5
+ apiKey: options.token,
6
+ baseURL: "https://models.github.ai/inference",
7
+ model: options.model ?? "openai/text-embedding-3-small",
8
+ dimensions: options.dimensions ?? 1536,
9
+ });
10
+ }
11
+ /** Pre-configured embedder for Azure OpenAI. */
12
+ export function createAzureOpenAIEmbedder(options) {
13
+ return new OpenAICompatibleEmbedder({
14
+ apiKey: options.apiKey,
15
+ baseURL: `${options.endpoint.replace(/\/$/, "")}/openai`,
16
+ model: options.model ?? "text-embedding-3-small",
17
+ dimensions: options.dimensions ?? 1536,
18
+ });
19
+ }
20
+ /** Pre-configured embedder for a local Ollama server. */
21
+ export function createOllamaEmbedder(options) {
22
+ return new OpenAICompatibleEmbedder({
23
+ apiKey: "ollama",
24
+ baseURL: (options.baseURL ?? "http://localhost:11434") + "/v1",
25
+ model: options.model,
26
+ dimensions: options.dimensions,
27
+ });
28
+ }
29
+ //# sourceMappingURL=presets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,GAEzB,MAAM,eAAe,CAAC;AAqBvB,8EAA8E;AAC9E,MAAM,UAAU,0BAA0B,CACxC,OAAkC;IAElC,OAAO,IAAI,wBAAwB,CAAC;QAClC,MAAM,EAAE,OAAO,CAAC,KAAK;QACrB,OAAO,EAAE,oCAAoC;QAC7C,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,+BAA+B;QACvD,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;KACvC,CAAC,CAAC;AACL,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,yBAAyB,CACvC,OAAiC;IAEjC,OAAO,IAAI,wBAAwB,CAAC;QAClC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS;QACxD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,wBAAwB;QAChD,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;KACvC,CAAC,CAAC;AACL,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,oBAAoB,CAClC,OAA4B;IAE5B,OAAO,IAAI,wBAAwB,CAAC;QAClC,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,CAAC,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC,GAAG,KAAK;QAC9D,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,UAAU,EAAE,OAAO,CAAC,UAAU;KACI,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,28 @@
1
+ export interface SemanticCacheConfig {
2
+ strategy: "exact" | "semantic";
3
+ /** Cosine similarity threshold for semantic cache hits. Defaults to 0.95. */
4
+ similarityThreshold?: number;
5
+ /** Max cache size in MB (in-memory LRU). Defaults to 500. */
6
+ maxSizeMB?: number;
7
+ /** Persistence backend. Defaults to "memory". */
8
+ persistence?: "memory" | "sqlite";
9
+ /** Path to SQLite database file. Defaults to ".rag-embedding-cache.db". */
10
+ sqlitePath?: string;
11
+ }
12
+ export declare class SemanticCache {
13
+ private readonly config;
14
+ /** In-memory LRU store: key → embedding */
15
+ private readonly lru;
16
+ /** Semantic store: [embedding, originalKey][] for cosine comparison */
17
+ private semantic;
18
+ private db;
19
+ private dbReady;
20
+ constructor(config: SemanticCacheConfig);
21
+ get(text: string, embed: (t: string) => Promise<number[]>): Promise<number[] | null>;
22
+ set(text: string, embedding: number[]): Promise<void>;
23
+ private lruPut;
24
+ private initDb;
25
+ private dbGet;
26
+ private dbSet;
27
+ }
28
+ //# sourceMappingURL=semantic-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-cache.d.ts","sourceRoot":"","sources":["../src/semantic-cache.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,GAAG,UAAU,CAAC;IAC/B,6EAA6E;IAC7E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAClC,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAgCD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,2CAA2C;IAC3C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA+B;IACnD,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,mBAAmB;IAUjC,GAAG,CACP,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GACtC,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;IAsCrB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAa3D,OAAO,CAAC,MAAM;YAcA,MAAM;YA0BN,KAAK;YAcL,KAAK;CAYpB"}
@@ -0,0 +1,141 @@
1
+ function cosineSimilarity(a, b) {
2
+ let dot = 0, normA = 0, normB = 0;
3
+ for (let i = 0; i < a.length; i++) {
4
+ dot += a[i] * b[i];
5
+ normA += a[i] * a[i];
6
+ normB += b[i] * b[i];
7
+ }
8
+ if (normA === 0 || normB === 0)
9
+ return 0;
10
+ return dot / (Math.sqrt(normA) * Math.sqrt(normB));
11
+ }
12
+ /** Simple SHA-256-free hash for exact cache key (djb2). */
13
+ function hashText(text) {
14
+ let h = 5381;
15
+ for (let i = 0; i < text.length; i++) {
16
+ h = ((h << 5) + h) ^ text.charCodeAt(i);
17
+ }
18
+ return (h >>> 0).toString(36);
19
+ }
20
+ export class SemanticCache {
21
+ config;
22
+ /** In-memory LRU store: key → embedding */
23
+ lru = new Map();
24
+ /** Semantic store: [embedding, originalKey][] for cosine comparison */
25
+ semantic = [];
26
+ db = null;
27
+ dbReady = false;
28
+ constructor(config) {
29
+ this.config = {
30
+ strategy: config.strategy,
31
+ similarityThreshold: config.similarityThreshold ?? 0.95,
32
+ maxSizeMB: config.maxSizeMB ?? 500,
33
+ persistence: config.persistence ?? "memory",
34
+ sqlitePath: config.sqlitePath ?? ".rag-embedding-cache.db",
35
+ };
36
+ }
37
+ async get(text, embed) {
38
+ const key = hashText(text);
39
+ // 1. Exact in-memory hit
40
+ const memHit = this.lru.get(key);
41
+ if (memHit)
42
+ return memHit;
43
+ // 2. SQLite exact hit
44
+ if (this.config.persistence === "sqlite") {
45
+ const dbHit = await this.dbGet(key);
46
+ if (dbHit) {
47
+ this.lruPut(key, dbHit);
48
+ return dbHit;
49
+ }
50
+ }
51
+ // 3. Semantic hit (needs query embedding)
52
+ if (this.config.strategy === "semantic" && this.semantic.length > 0) {
53
+ const queryEmb = await embed(text);
54
+ let bestSim = -1;
55
+ let bestEmb = null;
56
+ for (const [emb] of this.semantic) {
57
+ const sim = cosineSimilarity(queryEmb, emb);
58
+ if (sim > bestSim) {
59
+ bestSim = sim;
60
+ bestEmb = emb;
61
+ }
62
+ }
63
+ if (bestSim >= this.config.similarityThreshold && bestEmb) {
64
+ return bestEmb;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ async set(text, embedding) {
70
+ const key = hashText(text);
71
+ this.lruPut(key, embedding);
72
+ if (this.config.strategy === "semantic") {
73
+ this.semantic.push([embedding, key]);
74
+ }
75
+ if (this.config.persistence === "sqlite") {
76
+ await this.dbSet(key, embedding);
77
+ }
78
+ }
79
+ lruPut(key, embedding) {
80
+ // Evict oldest entry if we're over size (rough approximation)
81
+ const maxEntries = Math.floor((this.config.maxSizeMB * 1024 * 1024) /
82
+ (embedding.length * 4 + key.length * 2));
83
+ if (this.lru.size >= maxEntries) {
84
+ const firstKey = this.lru.keys().next().value;
85
+ if (firstKey !== undefined)
86
+ this.lru.delete(firstKey);
87
+ }
88
+ this.lru.delete(key); // move to end (LRU update)
89
+ this.lru.set(key, embedding);
90
+ }
91
+ async initDb() {
92
+ if (this.dbReady)
93
+ return this.db;
94
+ try {
95
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
96
+ // @ts-ignore — better-sqlite3 is an optional peer dependency
97
+ const { default: Database } = (await import("better-sqlite3"));
98
+ const db = new Database(this.config.sqlitePath);
99
+ db.exec(`CREATE TABLE IF NOT EXISTS embeddings (
100
+ key TEXT PRIMARY KEY,
101
+ embedding BLOB NOT NULL
102
+ )`);
103
+ this.db = db;
104
+ this.dbReady = true;
105
+ }
106
+ catch {
107
+ console.warn("[rag-embedder-openai] better-sqlite3 not available — cache will use memory only.");
108
+ this.dbReady = true; // prevent repeated attempts
109
+ }
110
+ return this.db;
111
+ }
112
+ async dbGet(key) {
113
+ const db = await this.initDb();
114
+ if (!db)
115
+ return null;
116
+ try {
117
+ const row = db
118
+ .prepare("SELECT embedding FROM embeddings WHERE key = ?")
119
+ .get(key);
120
+ if (!row)
121
+ return null;
122
+ return Array.from(new Float32Array(row.embedding.buffer));
123
+ }
124
+ catch {
125
+ return null;
126
+ }
127
+ }
128
+ async dbSet(key, embedding) {
129
+ const db = await this.initDb();
130
+ if (!db)
131
+ return;
132
+ try {
133
+ const buf = Buffer.from(new Float32Array(embedding).buffer);
134
+ db.prepare("INSERT OR REPLACE INTO embeddings (key, embedding) VALUES (?, ?)").run(key, buf);
135
+ }
136
+ catch {
137
+ // Non-fatal
138
+ }
139
+ }
140
+ }
141
+ //# sourceMappingURL=semantic-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-cache.js","sourceRoot":"","sources":["../src/semantic-cache.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@vivantel/virage-embedder-openai",
3
+ "version": "0.2.0",
4
+ "description": "OpenAI-compatible embedding provider for @vivantel/rag-core",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "sideEffects": false,
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "type-check": "tsc --noEmit",
25
+ "test": "vitest run",
26
+ "prepublishOnly": "npm run build",
27
+ "lint": "eslint src/",
28
+ "lint:fix": "eslint src/ --fix",
29
+ "format": "prettier --write \"src/**/*.ts\"",
30
+ "fix": "npm run lint:fix && npm run format"
31
+ },
32
+ "keywords": [
33
+ "rag",
34
+ "embeddings",
35
+ "openai",
36
+ "azure",
37
+ "github-models"
38
+ ],
39
+ "author": "Vivantel",
40
+ "license": "MIT",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/vivantel/virage",
44
+ "directory": "packages/virage-embedder-openai"
45
+ },
46
+ "dependencies": {
47
+ "openai": "^6.41.0"
48
+ },
49
+ "peerDependencies": {
50
+ "@vivantel/virage-core": "*"
51
+ },
52
+ "devDependencies": {
53
+ "@vivantel/virage-core": "0.2.0",
54
+ "@types/node": "^25.9.1",
55
+ "typescript": "^6.0.3",
56
+ "vitest": "^4.1.8"
57
+ },
58
+ "engines": {
59
+ "node": ">=18.0.0"
60
+ }
61
+ }