@providerprotocol/ai 0.0.15 → 0.0.17

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 CHANGED
@@ -57,16 +57,119 @@ const turn = await llm({
57
57
  console.log(turn.data); // { name: 'John', age: 30 }
58
58
  ```
59
59
 
60
+ ## Embeddings
61
+
62
+ Generate vector embeddings from text using the unified `embedding()` interface.
63
+
64
+ ```typescript
65
+ import { embedding } from '@providerprotocol/ai';
66
+ import { openai } from '@providerprotocol/ai/openai';
67
+ import { google } from '@providerprotocol/ai/google';
68
+ import { ollama } from '@providerprotocol/ai/ollama';
69
+ import { openrouter } from '@providerprotocol/ai/openrouter';
70
+
71
+ // Single text embedding
72
+ const embedder = embedding({ model: openai('text-embedding-3-small') });
73
+ const result = await embedder.embed('Hello world');
74
+ console.log(result.embeddings[0].vector); // [0.123, -0.456, ...]
75
+ console.log(result.embeddings[0].dimensions); // 1536
76
+
77
+ // Batch embedding
78
+ const batch = await embedder.embed(['doc1', 'doc2', 'doc3']);
79
+ console.log(batch.embeddings.length); // 3
80
+
81
+ // Custom dimensions (OpenAI text-embedding-3 models)
82
+ const smallEmbed = embedding({
83
+ model: openai('text-embedding-3-small'),
84
+ params: { dimensions: 256 },
85
+ });
86
+
87
+ // Google with task type optimization
88
+ const googleEmbed = embedding({
89
+ model: google('text-embedding-004'),
90
+ params: {
91
+ taskType: 'RETRIEVAL_DOCUMENT',
92
+ title: 'Important Document',
93
+ },
94
+ });
95
+
96
+ // Ollama local embeddings
97
+ const localEmbed = embedding({
98
+ model: ollama('qwen3-embedding:4b'),
99
+ });
100
+
101
+ // OpenRouter (access multiple providers)
102
+ const routerEmbed = embedding({
103
+ model: openrouter('openai/text-embedding-3-small'),
104
+ });
105
+ ```
106
+
107
+ ### Chunked Streaming
108
+
109
+ For large document sets, use chunked mode for progress tracking:
110
+
111
+ ```typescript
112
+ const embedder = embedding({ model: openai('text-embedding-3-small') });
113
+ const documents = Array.from({ length: 1000 }, (_, i) => `Document ${i}`);
114
+
115
+ const stream = embedder.embed(documents, {
116
+ chunked: true,
117
+ batchSize: 100,
118
+ concurrency: 2,
119
+ });
120
+
121
+ for await (const progress of stream) {
122
+ console.log(`${progress.percent.toFixed(1)}% complete`);
123
+ console.log(`Processed ${progress.completed} of ${progress.total}`);
124
+ }
125
+
126
+ const finalResult = await stream.result;
127
+ console.log(`Total embeddings: ${finalResult.embeddings.length}`);
128
+ ```
129
+
130
+ ### Provider-Specific Parameters
131
+
132
+ Each provider supports its native parameters passed through unchanged:
133
+
134
+ ```typescript
135
+ // OpenAI: dimensions, encoding_format, user
136
+ embedding({
137
+ model: openai('text-embedding-3-large'),
138
+ params: { dimensions: 1024, encoding_format: 'float' },
139
+ });
140
+
141
+ // Google: taskType, title, outputDimensionality
142
+ embedding({
143
+ model: google('text-embedding-004'),
144
+ params: {
145
+ taskType: 'SEMANTIC_SIMILARITY',
146
+ outputDimensionality: 256,
147
+ },
148
+ });
149
+
150
+ // Ollama: truncate, keep_alive, options
151
+ embedding({
152
+ model: ollama('nomic-embed-text'),
153
+ params: { truncate: true, keep_alive: '5m' },
154
+ });
155
+
156
+ // OpenRouter: dimensions, encoding_format, input_type
157
+ embedding({
158
+ model: openrouter('openai/text-embedding-3-small'),
159
+ params: { dimensions: 512 },
160
+ });
161
+ ```
162
+
60
163
  ## Providers
61
164
 
62
- | Provider | Import |
63
- |----------|--------|
64
- | Anthropic | `@providerprotocol/ai/anthropic` |
65
- | OpenAI | `@providerprotocol/ai/openai` |
66
- | Google | `@providerprotocol/ai/google` |
67
- | Ollama | `@providerprotocol/ai/ollama` |
68
- | OpenRouter | `@providerprotocol/ai/openrouter` |
69
- | xAI (Grok) | `@providerprotocol/ai/xai` |
165
+ | Provider | Import | LLM | Embedding |
166
+ |----------|--------|-----|-----------|
167
+ | Anthropic | `@providerprotocol/ai/anthropic` | Yes | - |
168
+ | OpenAI | `@providerprotocol/ai/openai` | Yes | Yes |
169
+ | Google | `@providerprotocol/ai/google` | Yes | Yes |
170
+ | Ollama | `@providerprotocol/ai/ollama` | Yes | Yes |
171
+ | OpenRouter | `@providerprotocol/ai/openrouter` | Yes | Yes |
172
+ | xAI (Grok) | `@providerprotocol/ai/xai` | Yes | - |
70
173
 
71
174
  ### xAI API Modes
72
175
 
@@ -1,4 +1,4 @@
1
- import { b as Provider } from '../provider-Bi0nyNhA.js';
1
+ import { d as Provider } from '../provider-D5MO3-pS.js';
2
2
 
3
3
  /**
4
4
  * @fileoverview Anthropic API type definitions.
@@ -1,4 +1,4 @@
1
- import { b as Provider } from '../provider-Bi0nyNhA.js';
1
+ import { d as Provider } from '../provider-D5MO3-pS.js';
2
2
 
3
3
  /**
4
4
  * Provider-specific parameters for Google Gemini API requests.
@@ -839,6 +839,33 @@ declare const cache: {
839
839
  delete: typeof deleteCache;
840
840
  };
841
841
 
842
+ /**
843
+ * @fileoverview Google Gemini Embeddings API Handler
844
+ *
845
+ * This module implements the embedding handler for Google's Gemini embeddings API.
846
+ * Supports gemini-embedding-001 and text-embedding-004 models.
847
+ *
848
+ * @see {@link https://ai.google.dev/gemini-api/docs/embeddings Google Embeddings API Reference}
849
+ * @module providers/google/embed
850
+ */
851
+
852
+ /**
853
+ * Google task types for embedding optimization.
854
+ */
855
+ type GoogleTaskType = 'RETRIEVAL_QUERY' | 'RETRIEVAL_DOCUMENT' | 'SEMANTIC_SIMILARITY' | 'CLASSIFICATION' | 'CLUSTERING' | 'QUESTION_ANSWERING' | 'FACT_VERIFICATION' | 'CODE_RETRIEVAL_QUERY' | 'TASK_TYPE_UNSPECIFIED';
856
+ /**
857
+ * Google embedding parameters.
858
+ * Passed through unchanged to the API.
859
+ */
860
+ interface GoogleEmbedParams {
861
+ /** Task type for optimization */
862
+ taskType?: GoogleTaskType;
863
+ /** Document title (for RETRIEVAL_DOCUMENT taskType) */
864
+ title?: string;
865
+ /** Output dimensionality */
866
+ outputDimensionality?: number;
867
+ }
868
+
842
869
  /**
843
870
  * Google Gemini provider for the Unified Provider Protocol (UPP).
844
871
  *
@@ -908,4 +935,4 @@ declare const google: Provider<unknown> & {
908
935
  };
909
936
  };
910
937
 
911
- export { type CacheCreateOptions, type CacheListOptions, type GoogleBuiltInTool, type GoogleCacheCreateRequest, type GoogleCacheListResponse, type GoogleCacheResponse, type GoogleCacheUpdateRequest, type GoogleCodeExecutionResult, type GoogleCodeExecutionTool, type GoogleFileSearchTool, type GoogleGroundingMetadata, type GoogleHeaders, type GoogleLLMParams, type GoogleMapsTool, type GoogleSearchTool, type GoogleToolConfig, type GoogleUrlContextTool, cache, google, tools };
938
+ export { type CacheCreateOptions, type CacheListOptions, type GoogleBuiltInTool, type GoogleCacheCreateRequest, type GoogleCacheListResponse, type GoogleCacheResponse, type GoogleCacheUpdateRequest, type GoogleCodeExecutionResult, type GoogleCodeExecutionTool, type GoogleEmbedParams, type GoogleFileSearchTool, type GoogleGroundingMetadata, type GoogleHeaders, type GoogleLLMParams, type GoogleMapsTool, type GoogleSearchTool, type GoogleTaskType, type GoogleToolConfig, type GoogleUrlContextTool, cache, google, tools };
@@ -520,6 +520,106 @@ function createLLMHandler() {
520
520
  };
521
521
  }
522
522
 
523
+ // src/providers/google/embed.ts
524
+ var GOOGLE_API_URL = "https://generativelanguage.googleapis.com/v1beta";
525
+ function createEmbeddingHandler() {
526
+ let providerRef = null;
527
+ return {
528
+ supportedInputs: ["text"],
529
+ _setProvider(provider) {
530
+ providerRef = provider;
531
+ },
532
+ bind(modelId) {
533
+ if (!providerRef) {
534
+ throw new UPPError(
535
+ "Provider reference not set. Handler must be used with createProvider().",
536
+ "INVALID_REQUEST",
537
+ "google",
538
+ "embedding"
539
+ );
540
+ }
541
+ const model = {
542
+ modelId,
543
+ maxBatchSize: 100,
544
+ maxInputLength: 2048,
545
+ dimensions: 3072,
546
+ get provider() {
547
+ return providerRef;
548
+ },
549
+ async embed(request) {
550
+ const apiKey = await resolveApiKey(
551
+ request.config,
552
+ "GOOGLE_API_KEY",
553
+ "google",
554
+ "embedding"
555
+ );
556
+ const baseUrl = request.config.baseUrl ?? GOOGLE_API_URL;
557
+ const requests = request.inputs.map((input) => {
558
+ const text = typeof input === "string" ? input : "text" in input ? input.text : "";
559
+ if (!text) {
560
+ throw new UPPError(
561
+ "Google embeddings only support text input",
562
+ "INVALID_REQUEST",
563
+ "google",
564
+ "embedding"
565
+ );
566
+ }
567
+ const embedRequest = {
568
+ model: `models/${modelId}`,
569
+ content: { parts: [{ text }] }
570
+ };
571
+ if (request.params?.taskType !== void 0) {
572
+ embedRequest.taskType = request.params.taskType;
573
+ }
574
+ if (request.params?.title !== void 0) {
575
+ embedRequest.title = request.params.title;
576
+ }
577
+ if (request.params?.outputDimensionality !== void 0) {
578
+ embedRequest.outputDimensionality = request.params.outputDimensionality;
579
+ }
580
+ return embedRequest;
581
+ });
582
+ const url = `${baseUrl}/models/${modelId}:batchEmbedContents?key=${apiKey}`;
583
+ const headers = {
584
+ "Content-Type": "application/json"
585
+ };
586
+ if (request.config.headers) {
587
+ for (const [key, value] of Object.entries(request.config.headers)) {
588
+ if (value !== void 0) {
589
+ headers[key] = value;
590
+ }
591
+ }
592
+ }
593
+ const response = await doFetch(url, {
594
+ method: "POST",
595
+ headers,
596
+ body: JSON.stringify({ requests }),
597
+ signal: request.signal
598
+ }, request.config, "google", "embedding");
599
+ const data = await response.json();
600
+ let totalTokens = 0;
601
+ for (const emb of data.embeddings) {
602
+ totalTokens += emb.statistics?.tokenCount ?? 0;
603
+ }
604
+ return {
605
+ embeddings: data.embeddings.map((e, index) => ({
606
+ vector: e.values,
607
+ index,
608
+ tokens: e.statistics?.tokenCount,
609
+ // Per-embedding metadata (NOT redacted)
610
+ metadata: e.statistics ? {
611
+ truncated: e.statistics.truncated
612
+ } : void 0
613
+ })),
614
+ usage: { totalTokens }
615
+ };
616
+ }
617
+ };
618
+ return model;
619
+ }
620
+ };
621
+ }
622
+
523
623
  // src/providers/google/cache.ts
524
624
  var CACHE_API_BASE = "https://generativelanguage.googleapis.com/v1beta/cachedContents";
525
625
  async function create(options) {
@@ -654,7 +754,8 @@ var baseProvider = createProvider({
654
754
  name: "google",
655
755
  version: "1.0.0",
656
756
  modalities: {
657
- llm: createLLMHandler()
757
+ llm: createLLMHandler(),
758
+ embedding: createEmbeddingHandler()
658
759
  }
659
760
  });
660
761
  var google = Object.assign(baseProvider, { cache });