@mcp-abap-adt/sap-aicore-embedder 11.0.0 → 11.1.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 +34 -4
- package/dist/auth.d.ts +23 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +56 -0
- package/dist/auth.js.map +1 -0
- package/dist/decode-embedding.d.ts +7 -0
- package/dist/decode-embedding.d.ts.map +1 -0
- package/dist/decode-embedding.js +15 -0
- package/dist/decode-embedding.js.map +1 -0
- package/dist/deployments.d.ts +10 -0
- package/dist/deployments.d.ts.map +1 -0
- package/dist/deployments.js +27 -0
- package/dist/deployments.js.map +1 -0
- package/dist/foundation-embedder.d.ts +35 -0
- package/dist/foundation-embedder.d.ts.map +1 -0
- package/dist/foundation-embedder.js +114 -0
- package/dist/foundation-embedder.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/orchestration-embedder.d.ts +15 -0
- package/dist/orchestration-embedder.d.ts.map +1 -0
- package/dist/orchestration-embedder.js +38 -0
- package/dist/orchestration-embedder.js.map +1 -0
- package/dist/sap-ai-core-embedder.d.ts +25 -14
- package/dist/sap-ai-core-embedder.d.ts.map +1 -1
- package/dist/sap-ai-core-embedder.js +20 -49
- package/dist/sap-ai-core-embedder.js.map +1 -1
- package/dist/service-key.d.ts +10 -0
- package/dist/service-key.d.ts.map +1 -0
- package/dist/service-key.js +27 -0
- package/dist/service-key.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,14 +31,44 @@ console.log(results.map(r => r.vector));
|
|
|
31
31
|
|
|
32
32
|
## Configuration
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
```ts
|
|
35
|
+
interface SapAiCoreEmbedderConfig {
|
|
36
|
+
model: string;
|
|
37
|
+
resourceGroup?: string; // default: 'default'
|
|
38
|
+
scenario?: 'foundation-models' | 'orchestration'; // default: 'orchestration'
|
|
39
|
+
credentials?: FoundationModelsCredentials; // foundation-models only; falls back to AICORE_SERVICE_KEY
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Orchestration (default)
|
|
44
|
+
|
|
45
|
+
The default scenario — matches v11.0.0 behavior. Use this when the embedding model is deployed under the `orchestration` scenario. Authentication is handled automatically by the SAP AI SDK orchestration client using `AICORE_SERVICE_KEY`.
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { SapAiCoreEmbedder } from '@mcp-abap-adt/sap-aicore-embedder';
|
|
49
|
+
|
|
50
|
+
const embedder = new SapAiCoreEmbedder({ model: 'text-embedding-3-small' });
|
|
51
|
+
```
|
|
35
52
|
|
|
36
|
-
|
|
37
|
-
|
|
53
|
+
Existing v11.0.0 consumers require no config changes.
|
|
54
|
+
|
|
55
|
+
### Foundation-models
|
|
56
|
+
|
|
57
|
+
Opt-in path for tenants where embedding models (such as `gemini-embedding` or `text-embedding-3-small`) are deployed under the `foundation-models` scenario rather than the orchestration scenario. The embedder calls the AI Core REST inference API directly.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const embedder = new SapAiCoreEmbedder({
|
|
61
|
+
model: 'gemini-embedding',
|
|
62
|
+
scenario: 'foundation-models',
|
|
63
|
+
});
|
|
64
|
+
// Auth: process.env.AICORE_SERVICE_KEY (client_credentials flow)
|
|
65
|
+
```
|
|
38
66
|
|
|
39
67
|
## Authentication
|
|
40
68
|
|
|
41
|
-
|
|
69
|
+
For the `orchestration` scenario (default), authentication is handled automatically by the SAP AI SDK orchestration client using `AICORE_SERVICE_KEY`.
|
|
70
|
+
|
|
71
|
+
For the `foundation-models` scenario, authentication uses the `AICORE_SERVICE_KEY` environment variable directly (client credentials flow). You can also pass credentials explicitly via the `credentials` option.
|
|
42
72
|
|
|
43
73
|
## License
|
|
44
74
|
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface TokenProviderConfig {
|
|
2
|
+
clientId: string;
|
|
3
|
+
clientSecret: string;
|
|
4
|
+
tokenUrl: string;
|
|
5
|
+
}
|
|
6
|
+
export interface GetTokenOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Skip the local expiry cache. Note: if another `getToken()` call is already
|
|
9
|
+
* fetching a token, this flag coalesces into that in-flight request rather
|
|
10
|
+
* than starting a second one.
|
|
11
|
+
*/
|
|
12
|
+
forceRefresh?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class TokenProvider {
|
|
15
|
+
private readonly cfg;
|
|
16
|
+
private cachedToken;
|
|
17
|
+
private cachedExpiryMs;
|
|
18
|
+
private inFlight;
|
|
19
|
+
constructor(cfg: TokenProviderConfig);
|
|
20
|
+
getToken(options?: GetTokenOptions): Promise<string>;
|
|
21
|
+
private fetchToken;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAKD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAC1C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAgC;gBAEpC,GAAG,EAAE,mBAAmB;IAI9B,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;YAwB5C,UAAU;CA+BzB"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Refresh the token when less than this many ms remain on it. */
|
|
2
|
+
const REFRESH_WINDOW_MS = 60_000;
|
|
3
|
+
export class TokenProvider {
|
|
4
|
+
cfg;
|
|
5
|
+
cachedToken = null;
|
|
6
|
+
cachedExpiryMs = 0;
|
|
7
|
+
inFlight = null;
|
|
8
|
+
constructor(cfg) {
|
|
9
|
+
this.cfg = cfg;
|
|
10
|
+
}
|
|
11
|
+
async getToken(options) {
|
|
12
|
+
if (!options?.forceRefresh &&
|
|
13
|
+
this.cachedToken &&
|
|
14
|
+
Date.now() < this.cachedExpiryMs - REFRESH_WINDOW_MS) {
|
|
15
|
+
return this.cachedToken;
|
|
16
|
+
}
|
|
17
|
+
// Dedupe concurrent callers, including those with forceRefresh (see GetTokenOptions).
|
|
18
|
+
if (this.inFlight)
|
|
19
|
+
return this.inFlight;
|
|
20
|
+
this.inFlight = this.fetchToken()
|
|
21
|
+
.then((result) => {
|
|
22
|
+
this.cachedToken = result.token;
|
|
23
|
+
this.cachedExpiryMs = Date.now() + result.expiresInMs;
|
|
24
|
+
return result.token;
|
|
25
|
+
})
|
|
26
|
+
.finally(() => {
|
|
27
|
+
this.inFlight = null;
|
|
28
|
+
});
|
|
29
|
+
return this.inFlight;
|
|
30
|
+
}
|
|
31
|
+
async fetchToken() {
|
|
32
|
+
const basic = Buffer.from(`${this.cfg.clientId}:${this.cfg.clientSecret}`).toString('base64');
|
|
33
|
+
const res = await fetch(this.cfg.tokenUrl, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: {
|
|
36
|
+
Authorization: `Basic ${basic}`,
|
|
37
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
38
|
+
Accept: 'application/json',
|
|
39
|
+
},
|
|
40
|
+
body: 'grant_type=client_credentials',
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
const text = await res.text().catch(() => '');
|
|
44
|
+
throw new Error(`SAP AI Core token request failed: ${res.status} ${res.statusText} ${text}`);
|
|
45
|
+
}
|
|
46
|
+
const body = (await res.json());
|
|
47
|
+
if (!body.access_token) {
|
|
48
|
+
throw new Error('SAP AI Core token response missing access_token');
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
token: body.access_token,
|
|
52
|
+
expiresInMs: (body.expires_in ?? 3600) * 1000,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAeA,kEAAkE;AAClE,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAEjC,MAAM,OAAO,aAAa;IACP,GAAG,CAAsB;IAClC,WAAW,GAAkB,IAAI,CAAC;IAClC,cAAc,GAAG,CAAC,CAAC;IACnB,QAAQ,GAA2B,IAAI,CAAC;IAEhD,YAAY,GAAwB;QAClC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAyB;QACtC,IACE,CAAC,OAAO,EAAE,YAAY;YACtB,IAAI,CAAC,WAAW;YAChB,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,cAAc,GAAG,iBAAiB,EACpD,CAAC;YACD,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QACD,sFAAsF;QACtF,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC;QAExC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE;aAC9B,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;YAChC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;YACtD,OAAO,MAAM,CAAC,KAAK,CAAC;QACtB,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC,CAAC,CAAC;QAEL,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CACvB,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAChD,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,SAAS,KAAK,EAAE;gBAC/B,cAAc,EAAE,mCAAmC;gBACnD,MAAM,EAAE,kBAAkB;aAC3B;YACD,IAAI,EAAE,+BAA+B;SACtC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CACb,qCAAqC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,IAAI,IAAI,EAAE,CAC5E,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAG7B,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QACD,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,YAAY;YACxB,WAAW,EAAE,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,IAAI;SAC9C,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decode an embedding vector from either a `number[]` (JSON array) or a
|
|
3
|
+
* base64-encoded Float32 buffer string (compact on-wire form some SAP AI Core
|
|
4
|
+
* deployments return).
|
|
5
|
+
*/
|
|
6
|
+
export declare function decodeEmbedding(embedding: number[] | string): number[];
|
|
7
|
+
//# sourceMappingURL=decode-embedding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-embedding.d.ts","sourceRoot":"","sources":["../src/decode-embedding.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAWtE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// packages/sap-aicore-embedder/src/decode-embedding.ts
|
|
2
|
+
/**
|
|
3
|
+
* Decode an embedding vector from either a `number[]` (JSON array) or a
|
|
4
|
+
* base64-encoded Float32 buffer string (compact on-wire form some SAP AI Core
|
|
5
|
+
* deployments return).
|
|
6
|
+
*/
|
|
7
|
+
export function decodeEmbedding(embedding) {
|
|
8
|
+
if (typeof embedding === 'string') {
|
|
9
|
+
const buffer = Buffer.from(embedding, 'base64');
|
|
10
|
+
const float32 = new Float32Array(buffer.buffer, buffer.byteOffset, buffer.length / 4);
|
|
11
|
+
return Array.from(float32);
|
|
12
|
+
}
|
|
13
|
+
return embedding;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=decode-embedding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-embedding.js","sourceRoot":"","sources":["../src/decode-embedding.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,SAA4B;IAC1D,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,MAAM,GAAG,CAAC,CAClB,CAAC;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ResolveDeploymentOptions {
|
|
2
|
+
apiBaseUrl: string;
|
|
3
|
+
token: string;
|
|
4
|
+
resourceGroup: string;
|
|
5
|
+
model: string;
|
|
6
|
+
/** Scenario id. Default: 'foundation-models'. */
|
|
7
|
+
scenarioId?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveDeploymentId(options: ResolveDeploymentOptions): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=deployments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployments.d.ts","sourceRoot":"","sources":["../src/deployments.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAwBD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,CA2BjB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function extractModelName(resource) {
|
|
2
|
+
return (resource.details?.resources?.backend_details?.model?.name ??
|
|
3
|
+
resource.model?.name);
|
|
4
|
+
}
|
|
5
|
+
export async function resolveDeploymentId(options) {
|
|
6
|
+
const scenarioId = options.scenarioId ?? 'foundation-models';
|
|
7
|
+
const url = `${options.apiBaseUrl}/v2/lm/deployments?scenarioId=${encodeURIComponent(scenarioId)}&status=RUNNING`;
|
|
8
|
+
const res = await fetch(url, {
|
|
9
|
+
method: 'GET',
|
|
10
|
+
headers: {
|
|
11
|
+
Authorization: `Bearer ${options.token}`,
|
|
12
|
+
'AI-Resource-Group': options.resourceGroup,
|
|
13
|
+
Accept: 'application/json',
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
if (!res.ok) {
|
|
17
|
+
const text = await res.text().catch(() => '');
|
|
18
|
+
throw new Error(`SAP AI Core deployment list failed: ${res.status} ${res.statusText} ${text}`);
|
|
19
|
+
}
|
|
20
|
+
const body = (await res.json());
|
|
21
|
+
const match = (body.resources ?? []).find((r) => extractModelName(r) === options.model && typeof r.id === 'string');
|
|
22
|
+
if (!match?.id) {
|
|
23
|
+
throw new Error(`No RUNNING deployment found for model "${options.model}" in scenario "${scenarioId}"`);
|
|
24
|
+
}
|
|
25
|
+
return match.id;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=deployments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployments.js","sourceRoot":"","sources":["../src/deployments.ts"],"names":[],"mappings":"AAwBA,SAAS,gBAAgB,CAAC,QAA4B;IACpD,OAAO,CACL,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI;QACzD,QAAQ,CAAC,KAAK,EAAE,IAAI,CACrB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAiC;IAEjC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;IAC7D,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,UAAU,iCAAiC,kBAAkB,CAAC,UAAU,CAAC,iBAAiB,CAAC;IAClH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE;YACxC,mBAAmB,EAAE,OAAO,CAAC,aAAa;YAC1C,MAAM,EAAE,kBAAkB;SAC3B;KACF,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,uCAAuC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,IAAI,IAAI,EAAE,CAC9E,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2B,CAAC;IAC1D,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CACzE,CAAC;IACF,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,0CAA0C,OAAO,CAAC,KAAK,kBAAkB,UAAU,GAAG,CACvF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,EAAE,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { IEmbedderBatch, IEmbedResult } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import { type CallOptions } from '@mcp-abap-adt/llm-agent';
|
|
3
|
+
export interface FoundationModelsCredentials {
|
|
4
|
+
clientId: string;
|
|
5
|
+
clientSecret: string;
|
|
6
|
+
tokenUrl: string;
|
|
7
|
+
apiBaseUrl: string;
|
|
8
|
+
}
|
|
9
|
+
export interface FoundationModelsEmbedderConfig {
|
|
10
|
+
model: string;
|
|
11
|
+
resourceGroup?: string;
|
|
12
|
+
/** Explicit credentials. When omitted, `AICORE_SERVICE_KEY` env var is parsed. */
|
|
13
|
+
credentials?: FoundationModelsCredentials;
|
|
14
|
+
/**
|
|
15
|
+
* Azure OpenAI api-version query parameter for OpenAI-family deployments.
|
|
16
|
+
* Default: '2023-05-15'. Ignored for Gemini-family models.
|
|
17
|
+
*/
|
|
18
|
+
azureApiVersion?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class FoundationModelsEmbedder implements IEmbedderBatch {
|
|
21
|
+
private readonly model;
|
|
22
|
+
private readonly family;
|
|
23
|
+
private readonly azureApiVersion;
|
|
24
|
+
private readonly resourceGroup;
|
|
25
|
+
private readonly apiBaseUrl;
|
|
26
|
+
private readonly tokenProvider;
|
|
27
|
+
private deploymentIdPromise;
|
|
28
|
+
constructor(config: FoundationModelsEmbedderConfig);
|
|
29
|
+
embed(text: string, _options?: CallOptions): Promise<IEmbedResult>;
|
|
30
|
+
embedBatch(texts: string[], _options?: CallOptions): Promise<IEmbedResult[]>;
|
|
31
|
+
private requestEmbeddings;
|
|
32
|
+
private getDeploymentId;
|
|
33
|
+
private loadCredentialsFromEnv;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=foundation-embedder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foundation-embedder.d.ts","sourceRoot":"","sources":["../src/foundation-embedder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,yBAAyB,CAAC;AAMrE,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,WAAW,CAAC,EAAE,2BAA2B,CAAC;IAC1C;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAiBD,qBAAa,wBAAyB,YAAW,cAAc;IAC7D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,mBAAmB,CAAgC;gBAE/C,MAAM,EAAE,8BAA8B;IAc5C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAQlE,UAAU,CACd,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,YAAY,EAAE,CAAC;YAUZ,iBAAiB;IAoD/B,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,sBAAsB;CAS/B"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { RagError } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import { TokenProvider } from './auth.js';
|
|
3
|
+
import { decodeEmbedding } from './decode-embedding.js';
|
|
4
|
+
import { resolveDeploymentId } from './deployments.js';
|
|
5
|
+
import { parseServiceKey } from './service-key.js';
|
|
6
|
+
export class FoundationModelsEmbedder {
|
|
7
|
+
model;
|
|
8
|
+
family;
|
|
9
|
+
azureApiVersion;
|
|
10
|
+
resourceGroup;
|
|
11
|
+
apiBaseUrl;
|
|
12
|
+
tokenProvider;
|
|
13
|
+
deploymentIdPromise = null;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
const creds = config.credentials ?? this.loadCredentialsFromEnv();
|
|
16
|
+
this.model = config.model;
|
|
17
|
+
this.family = detectFamily(config.model);
|
|
18
|
+
this.azureApiVersion = config.azureApiVersion ?? '2023-05-15';
|
|
19
|
+
this.resourceGroup = config.resourceGroup ?? 'default';
|
|
20
|
+
this.apiBaseUrl = creds.apiBaseUrl;
|
|
21
|
+
this.tokenProvider = new TokenProvider({
|
|
22
|
+
clientId: creds.clientId,
|
|
23
|
+
clientSecret: creds.clientSecret,
|
|
24
|
+
tokenUrl: creds.tokenUrl,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async embed(text, _options) {
|
|
28
|
+
const items = await this.requestEmbeddings([text]);
|
|
29
|
+
if (items.length === 0) {
|
|
30
|
+
throw new RagError('No embeddings returned from SAP AI Core');
|
|
31
|
+
}
|
|
32
|
+
return { vector: decodeEmbedding(items[0].embedding) };
|
|
33
|
+
}
|
|
34
|
+
async embedBatch(texts, _options) {
|
|
35
|
+
if (texts.length === 0)
|
|
36
|
+
return [];
|
|
37
|
+
const items = await this.requestEmbeddings(texts);
|
|
38
|
+
if (items.length === 0) {
|
|
39
|
+
throw new RagError('No embeddings returned from SAP AI Core batch');
|
|
40
|
+
}
|
|
41
|
+
const sorted = [...items].sort((a, b) => a.index - b.index);
|
|
42
|
+
return sorted.map((item) => ({ vector: decodeEmbedding(item.embedding) }));
|
|
43
|
+
}
|
|
44
|
+
async requestEmbeddings(input) {
|
|
45
|
+
const token = await this.tokenProvider.getToken();
|
|
46
|
+
const deploymentId = await this.getDeploymentId(token);
|
|
47
|
+
const base = `${this.apiBaseUrl}/v2/inference/deployments/${deploymentId}`;
|
|
48
|
+
const headers = {
|
|
49
|
+
Authorization: `Bearer ${token}`,
|
|
50
|
+
'AI-Resource-Group': this.resourceGroup,
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
Accept: 'application/json',
|
|
53
|
+
};
|
|
54
|
+
if (this.family === 'gemini') {
|
|
55
|
+
const url = `${base}/models/${encodeURIComponent(this.model)}:predict`;
|
|
56
|
+
const body = {
|
|
57
|
+
instances: input.map((content) => ({ content })),
|
|
58
|
+
};
|
|
59
|
+
const res = await fetch(url, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers,
|
|
62
|
+
body: JSON.stringify(body),
|
|
63
|
+
});
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
const text = await res.text().catch(() => '');
|
|
66
|
+
throw new RagError(`SAP AI Core embeddings call failed: ${res.status} ${res.statusText} ${text}`);
|
|
67
|
+
}
|
|
68
|
+
const json = (await res.json());
|
|
69
|
+
return (json.predictions ?? []).map((p, i) => ({
|
|
70
|
+
embedding: p.embeddings?.values ?? [],
|
|
71
|
+
index: i,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
// azure-openai
|
|
75
|
+
const url = `${base}/embeddings?api-version=${encodeURIComponent(this.azureApiVersion)}`;
|
|
76
|
+
const body = { input: input.length === 1 ? input[0] : input };
|
|
77
|
+
const res = await fetch(url, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers,
|
|
80
|
+
body: JSON.stringify(body),
|
|
81
|
+
});
|
|
82
|
+
if (!res.ok) {
|
|
83
|
+
const text = await res.text().catch(() => '');
|
|
84
|
+
throw new RagError(`SAP AI Core embeddings call failed: ${res.status} ${res.statusText} ${text}`);
|
|
85
|
+
}
|
|
86
|
+
const json = (await res.json());
|
|
87
|
+
return json.data ?? [];
|
|
88
|
+
}
|
|
89
|
+
getDeploymentId(token) {
|
|
90
|
+
if (!this.deploymentIdPromise) {
|
|
91
|
+
this.deploymentIdPromise = resolveDeploymentId({
|
|
92
|
+
apiBaseUrl: this.apiBaseUrl,
|
|
93
|
+
token,
|
|
94
|
+
resourceGroup: this.resourceGroup,
|
|
95
|
+
model: this.model,
|
|
96
|
+
}).catch((err) => {
|
|
97
|
+
this.deploymentIdPromise = null;
|
|
98
|
+
throw err;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return this.deploymentIdPromise;
|
|
102
|
+
}
|
|
103
|
+
loadCredentialsFromEnv() {
|
|
104
|
+
const raw = process.env.AICORE_SERVICE_KEY;
|
|
105
|
+
if (!raw) {
|
|
106
|
+
throw new Error('SapAiCoreEmbedder (foundation-models): no credentials provided and AICORE_SERVICE_KEY env var is not set');
|
|
107
|
+
}
|
|
108
|
+
return parseServiceKey(raw);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function detectFamily(model) {
|
|
112
|
+
return /^gemini/i.test(model) ? 'gemini' : 'azure-openai';
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=foundation-embedder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foundation-embedder.js","sourceRoot":"","sources":["../src/foundation-embedder.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { SapAiCoreEmbedderConfig } from './sap-ai-core-embedder.js';
|
|
1
|
+
export type { FoundationModelsCredentials, SapAiCoreEmbedderConfig, SapAiCoreEmbedderScenario, } from './sap-ai-core-embedder.js';
|
|
2
2
|
export { SapAiCoreEmbedder } from './sap-ai-core-embedder.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,2BAA2B,EAC3B,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IEmbedderBatch, IEmbedResult } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import { type CallOptions } from '@mcp-abap-adt/llm-agent';
|
|
3
|
+
export interface OrchestrationScenarioEmbedderConfig {
|
|
4
|
+
model: string;
|
|
5
|
+
resourceGroup?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class OrchestrationScenarioEmbedder implements IEmbedderBatch {
|
|
8
|
+
private readonly model;
|
|
9
|
+
private readonly resourceGroup?;
|
|
10
|
+
constructor(config: OrchestrationScenarioEmbedderConfig);
|
|
11
|
+
embed(text: string, _options?: CallOptions): Promise<IEmbedResult>;
|
|
12
|
+
embedBatch(texts: string[], _options?: CallOptions): Promise<IEmbedResult[]>;
|
|
13
|
+
private createClient;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=orchestration-embedder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestration-embedder.d.ts","sourceRoot":"","sources":["../src/orchestration-embedder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,yBAAyB,CAAC;AAGrE,MAAM,WAAW,mCAAmC;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,6BAA8B,YAAW,cAAc;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAS;gBAE5B,MAAM,EAAE,mCAAmC;IAKjD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAUlE,UAAU,CACd,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,YAAY,EAAE,CAAC;YAYZ,YAAY;CAW3B"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { RagError } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import { decodeEmbedding } from './decode-embedding.js';
|
|
3
|
+
export class OrchestrationScenarioEmbedder {
|
|
4
|
+
model;
|
|
5
|
+
resourceGroup;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.model = config.model;
|
|
8
|
+
this.resourceGroup = config.resourceGroup;
|
|
9
|
+
}
|
|
10
|
+
async embed(text, _options) {
|
|
11
|
+
const client = await this.createClient();
|
|
12
|
+
const response = await client.embed({ input: text });
|
|
13
|
+
const embeddings = response.getEmbeddings();
|
|
14
|
+
if (!embeddings || embeddings.length === 0) {
|
|
15
|
+
throw new RagError('No embeddings returned from SAP AI Core');
|
|
16
|
+
}
|
|
17
|
+
return { vector: decodeEmbedding(embeddings[0].embedding) };
|
|
18
|
+
}
|
|
19
|
+
async embedBatch(texts, _options) {
|
|
20
|
+
if (texts.length === 0)
|
|
21
|
+
return [];
|
|
22
|
+
const client = await this.createClient();
|
|
23
|
+
const response = await client.embed({ input: texts });
|
|
24
|
+
const embeddings = response.getEmbeddings();
|
|
25
|
+
if (!embeddings || embeddings.length === 0) {
|
|
26
|
+
throw new RagError('No embeddings returned from SAP AI Core batch');
|
|
27
|
+
}
|
|
28
|
+
const sorted = [...embeddings].sort((a, b) => a.index - b.index);
|
|
29
|
+
return sorted.map((e) => ({ vector: decodeEmbedding(e.embedding) }));
|
|
30
|
+
}
|
|
31
|
+
async createClient() {
|
|
32
|
+
const { OrchestrationEmbeddingClient } = await import('@sap-ai-sdk/orchestration');
|
|
33
|
+
const modelName = this
|
|
34
|
+
.model;
|
|
35
|
+
return new OrchestrationEmbeddingClient({ embeddings: { model: { name: modelName } } }, this.resourceGroup ? { resourceGroup: this.resourceGroup } : undefined);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=orchestration-embedder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestration-embedder.js","sourceRoot":"","sources":["../src/orchestration-embedder.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAOxD,MAAM,OAAO,6BAA6B;IACvB,KAAK,CAAS;IACd,aAAa,CAAU;IAExC,YAAY,MAA2C;QACrD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAY,EAAE,QAAsB;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC5C,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,QAAQ,CAAC,yCAAyC,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,UAAU,CACd,KAAe,EACf,QAAsB;QAEtB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC5C,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,QAAQ,CAAC,+CAA+C,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACjE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACvE,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,MAAM,EAAE,4BAA4B,EAAE,GAAG,MAAM,MAAM,CACnD,2BAA2B,CAC5B,CAAC;QACF,MAAM,SAAS,GAAG,IAAI;aACnB,KAAsE,CAAC;QAC1E,OAAO,IAAI,4BAA4B,CACrC,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,EAC9C,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,SAAS,CACvE,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -1,22 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Generates text embeddings via SAP AI Core embedding model deployments.
|
|
5
|
-
* Authentication: reads AICORE_SERVICE_KEY env var automatically (same as LLM provider).
|
|
6
|
-
*/
|
|
7
|
-
import type { IEmbedderBatch, IEmbedResult } from '@mcp-abap-adt/llm-agent';
|
|
8
|
-
import { type CallOptions } from '@mcp-abap-adt/llm-agent';
|
|
1
|
+
import type { CallOptions, IEmbedderBatch, IEmbedResult } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import { type FoundationModelsCredentials } from './foundation-embedder.js';
|
|
3
|
+
export type SapAiCoreEmbedderScenario = 'foundation-models' | 'orchestration';
|
|
9
4
|
export interface SapAiCoreEmbedderConfig {
|
|
10
|
-
/** Embedding model name (e.g. 'text-embedding-3-small') */
|
|
5
|
+
/** Embedding model name (e.g. 'text-embedding-3-small', 'gemini-embedding') */
|
|
11
6
|
model: string;
|
|
12
|
-
/** SAP AI Core resource group
|
|
7
|
+
/** SAP AI Core resource group. Default: 'default'. */
|
|
13
8
|
resourceGroup?: string;
|
|
9
|
+
/**
|
|
10
|
+
* SAP AI Core scenario under which the embedding model is deployed.
|
|
11
|
+
* - `'orchestration'` (default): uses `OrchestrationEmbeddingClient` from `@sap-ai-sdk/orchestration`.
|
|
12
|
+
* Requires an orchestration-scenario deployment of the embedding model. This matches v11.0.0 behavior.
|
|
13
|
+
* - `'foundation-models'`: calls the AI Core REST inference API directly.
|
|
14
|
+
* Use this when your embedding models are deployed under the foundation-models scenario
|
|
15
|
+
* (common for tenants where SAP AI Core embedders such as `gemini-embedding` and `text-embedding-3-small`
|
|
16
|
+
* are deployed outside the orchestration scenario).
|
|
17
|
+
*/
|
|
18
|
+
scenario?: SapAiCoreEmbedderScenario;
|
|
19
|
+
/**
|
|
20
|
+
* Explicit credentials for the `foundation-models` scenario.
|
|
21
|
+
* When omitted, `AICORE_SERVICE_KEY` env var is parsed instead.
|
|
22
|
+
* Ignored for `scenario: 'orchestration'` (the SAP SDK handles auth there).
|
|
23
|
+
*/
|
|
24
|
+
credentials?: FoundationModelsCredentials;
|
|
14
25
|
}
|
|
26
|
+
export type { FoundationModelsCredentials };
|
|
15
27
|
export declare class SapAiCoreEmbedder implements IEmbedderBatch {
|
|
16
|
-
private readonly
|
|
17
|
-
private readonly resourceGroup?;
|
|
28
|
+
private readonly backend;
|
|
18
29
|
constructor(config: SapAiCoreEmbedderConfig);
|
|
19
|
-
embed(text: string,
|
|
20
|
-
embedBatch(texts: string[],
|
|
30
|
+
embed(text: string, options?: CallOptions): Promise<IEmbedResult>;
|
|
31
|
+
embedBatch(texts: string[], options?: CallOptions): Promise<IEmbedResult[]>;
|
|
21
32
|
}
|
|
22
33
|
//# sourceMappingURL=sap-ai-core-embedder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sap-ai-core-embedder.d.ts","sourceRoot":"","sources":["../src/sap-ai-core-embedder.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sap-ai-core-embedder.d.ts","sourceRoot":"","sources":["../src/sap-ai-core-embedder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACb,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,2BAA2B,EAEjC,MAAM,0BAA0B,CAAC;AAGlC,MAAM,MAAM,yBAAyB,GAAG,mBAAmB,GAAG,eAAe,CAAC;AAE9E,MAAM,WAAW,uBAAuB;IACtC,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,2BAA2B,CAAC;CAC3C;AAED,YAAY,EAAE,2BAA2B,EAAE,CAAC;AAE5C,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;gBAE7B,MAAM,EAAE,uBAAuB;IAgB3C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAIjE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAG5E"}
|
|
@@ -1,57 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Generates text embeddings via SAP AI Core embedding model deployments.
|
|
5
|
-
* Authentication: reads AICORE_SERVICE_KEY env var automatically (same as LLM provider).
|
|
6
|
-
*/
|
|
7
|
-
import { RagError } from '@mcp-abap-adt/llm-agent';
|
|
1
|
+
import { FoundationModelsEmbedder, } from './foundation-embedder.js';
|
|
2
|
+
import { OrchestrationScenarioEmbedder } from './orchestration-embedder.js';
|
|
8
3
|
export class SapAiCoreEmbedder {
|
|
9
|
-
|
|
10
|
-
resourceGroup;
|
|
4
|
+
backend;
|
|
11
5
|
constructor(config) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
.model;
|
|
19
|
-
const client = new OrchestrationEmbeddingClient({ embeddings: { model: { name: modelName } } }, this.resourceGroup ? { resourceGroup: this.resourceGroup } : undefined);
|
|
20
|
-
const response = await client.embed({ input: text });
|
|
21
|
-
const embeddings = response.getEmbeddings();
|
|
22
|
-
if (!embeddings || embeddings.length === 0) {
|
|
23
|
-
throw new RagError('No embeddings returned from SAP AI Core');
|
|
6
|
+
const scenario = config.scenario ?? 'orchestration';
|
|
7
|
+
if (scenario === 'orchestration') {
|
|
8
|
+
this.backend = new OrchestrationScenarioEmbedder({
|
|
9
|
+
model: config.model,
|
|
10
|
+
resourceGroup: config.resourceGroup,
|
|
11
|
+
});
|
|
24
12
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
13
|
+
else {
|
|
14
|
+
this.backend = new FoundationModelsEmbedder({
|
|
15
|
+
model: config.model,
|
|
16
|
+
resourceGroup: config.resourceGroup,
|
|
17
|
+
credentials: config.credentials,
|
|
18
|
+
});
|
|
31
19
|
}
|
|
32
|
-
return { vector: embedding };
|
|
33
20
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
.model;
|
|
40
|
-
const client = new OrchestrationEmbeddingClient({ embeddings: { model: { name: modelName } } }, this.resourceGroup ? { resourceGroup: this.resourceGroup } : undefined);
|
|
41
|
-
const response = await client.embed({ input: texts });
|
|
42
|
-
const embeddings = response.getEmbeddings();
|
|
43
|
-
if (!embeddings || embeddings.length === 0) {
|
|
44
|
-
throw new RagError('No embeddings returned from SAP AI Core batch');
|
|
45
|
-
}
|
|
46
|
-
const sorted = [...embeddings].sort((a, b) => a.index - b.index);
|
|
47
|
-
return sorted.map((e) => {
|
|
48
|
-
if (typeof e.embedding === 'string') {
|
|
49
|
-
const buffer = Buffer.from(e.embedding, 'base64');
|
|
50
|
-
const float32 = new Float32Array(buffer.buffer, buffer.byteOffset, buffer.length / 4);
|
|
51
|
-
return { vector: Array.from(float32) };
|
|
52
|
-
}
|
|
53
|
-
return { vector: e.embedding };
|
|
54
|
-
});
|
|
21
|
+
embed(text, options) {
|
|
22
|
+
return this.backend.embed(text, options);
|
|
23
|
+
}
|
|
24
|
+
embedBatch(texts, options) {
|
|
25
|
+
return this.backend.embedBatch(texts, options);
|
|
55
26
|
}
|
|
56
27
|
}
|
|
57
28
|
//# sourceMappingURL=sap-ai-core-embedder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sap-ai-core-embedder.js","sourceRoot":"","sources":["../src/sap-ai-core-embedder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sap-ai-core-embedder.js","sourceRoot":"","sources":["../src/sap-ai-core-embedder.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AA6B5E,MAAM,OAAO,iBAAiB;IACX,OAAO,CAAiB;IAEzC,YAAY,MAA+B;QACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,eAAe,CAAC;QACpD,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,GAAG,IAAI,6BAA6B,CAAC;gBAC/C,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,aAAa,EAAE,MAAM,CAAC,aAAa;aACpC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,IAAI,wBAAwB,CAAC;gBAC1C,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,WAAW,EAAE,MAAM,CAAC,WAAW;aAChC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAY,EAAE,OAAqB;QACvC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,UAAU,CAAC,KAAe,EAAE,OAAqB;QAC/C,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ParsedServiceKey {
|
|
2
|
+
clientId: string;
|
|
3
|
+
clientSecret: string;
|
|
4
|
+
/** Fully qualified token endpoint incl. `/oauth/token`. */
|
|
5
|
+
tokenUrl: string;
|
|
6
|
+
/** AI Core REST API base URL (no trailing slash). */
|
|
7
|
+
apiBaseUrl: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseServiceKey(raw: string): ParsedServiceKey;
|
|
10
|
+
//# sourceMappingURL=service-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-key.d.ts","sourceRoot":"","sources":["../src/service-key.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;CACpB;AASD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAgC7D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function parseServiceKey(raw) {
|
|
2
|
+
let obj;
|
|
3
|
+
try {
|
|
4
|
+
obj = JSON.parse(raw);
|
|
5
|
+
}
|
|
6
|
+
catch (err) {
|
|
7
|
+
throw new Error(`AICORE_SERVICE_KEY is not valid JSON: ${err.message}`);
|
|
8
|
+
}
|
|
9
|
+
const clientId = obj.clientid;
|
|
10
|
+
const clientSecret = obj.clientsecret;
|
|
11
|
+
const authUrl = obj.url;
|
|
12
|
+
const apiBaseUrl = obj.serviceurls?.AI_API_URL;
|
|
13
|
+
if (!clientId || !clientSecret || !authUrl || !apiBaseUrl) {
|
|
14
|
+
throw new Error('AICORE_SERVICE_KEY is missing required fields (clientid, clientsecret, url, serviceurls.AI_API_URL)');
|
|
15
|
+
}
|
|
16
|
+
const trimmedAuth = authUrl.replace(/\/+$/, '');
|
|
17
|
+
const tokenUrl = trimmedAuth.endsWith('/oauth/token')
|
|
18
|
+
? trimmedAuth
|
|
19
|
+
: `${trimmedAuth}/oauth/token`;
|
|
20
|
+
return {
|
|
21
|
+
clientId,
|
|
22
|
+
clientSecret,
|
|
23
|
+
tokenUrl,
|
|
24
|
+
apiBaseUrl: apiBaseUrl.replace(/\/+$/, ''),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=service-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-key.js","sourceRoot":"","sources":["../src/service-key.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,GAAkB,CAAC;IACvB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,yCAA0C,GAAa,CAAC,OAAO,EAAE,CAClE,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;IAC9B,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;IACtC,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC;IACxB,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC;IAE/C,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CACb,qGAAqG,CACtG,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC;QACnD,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,GAAG,WAAW,cAAc,CAAC;IAEjC,OAAO;QACL,QAAQ;QACR,YAAY;QACZ,QAAQ;QACR,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC"}
|