@genbounty/ailp 0.1.0 → 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 +82 -92
- package/dist/ailp.d.ts +28 -0
- package/dist/ailp.d.ts.map +1 -0
- package/dist/ailp.js +34 -0
- package/dist/ailp.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +5 -5
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +14 -7
- package/dist/react.js.map +1 -1
- package/dist/types.d.ts +22 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/wrap.d.ts +27 -37
- package/dist/wrap.d.ts.map +1 -1
- package/dist/wrap.js +16 -35
- package/dist/wrap.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,118 +1,114 @@
|
|
|
1
|
-
# ailp
|
|
1
|
+
# @genbounty/ailp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**LLM compliance risk assessment — drop one line into any AI call.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Sends your LLM interactions to the [Genbounty AILP](https://github.com/genbounty/ailp) server for automated compliance scoring against frameworks like EU AI Act, OWASP LLM Top 10, NIST AI RMF, and more. Works with any LLM provider. No runtime dependencies — uses native `fetch`.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install ailp
|
|
11
|
-
# peer dep only needed for React hook:
|
|
12
|
-
npm install react
|
|
10
|
+
npm install @genbounty/ailp
|
|
13
11
|
```
|
|
14
12
|
|
|
15
13
|
## Quick start
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
import { AilpClient } from "ailp";
|
|
15
|
+
Configure once:
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
```typescript
|
|
18
|
+
import { createAilp } from "@genbounty/ailp";
|
|
21
19
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
input: {
|
|
27
|
-
messages: [{ role: "user", content: "hello how are you" }],
|
|
28
|
-
endpoint: "/api/chat",
|
|
29
|
-
},
|
|
30
|
-
output: "Hello! I'm here to help.",
|
|
31
|
-
promptTokens: 11,
|
|
32
|
-
completionTokens: 14,
|
|
33
|
-
totalTokens: 25,
|
|
34
|
-
responseTime: 830,
|
|
35
|
-
endpoint: "/api/chat",
|
|
36
|
-
status: "success",
|
|
37
|
-
genbounty: {
|
|
38
|
-
apiKey: "your-genbounty-key",
|
|
39
|
-
programId: "your-program-id",
|
|
40
|
-
frameworks: ["eu-ai-act", "owasp-llm"],
|
|
41
|
-
},
|
|
20
|
+
const ailp = createAilp({
|
|
21
|
+
baseUrl: "http://localhost:8000",
|
|
22
|
+
programId: "your-program-id",
|
|
23
|
+
frameworks: ["eu-ai-act", "owasp-llm"],
|
|
42
24
|
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Drop in after **any LLM call**:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
const res = await ailp(messages, llmOutput);
|
|
43
31
|
|
|
44
|
-
console.log(
|
|
45
|
-
console.log(
|
|
46
|
-
console.log(
|
|
47
|
-
console.log(
|
|
32
|
+
console.log(res.risk_level); // "compliant"
|
|
33
|
+
console.log(res.frameworks); // ["EU AI Act", "OWASP LLM & Agent"]
|
|
34
|
+
console.log(res.experts); // [{ framework, risk_level, reasoning }, ...]
|
|
35
|
+
console.log(res.judge_reasoning); // "The interaction is benign and poses no risk..."
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Pass an optional model hint:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
const res = await ailp(messages, llmOutput, { model: "gpt-4o-mini" });
|
|
48
42
|
```
|
|
49
43
|
|
|
50
44
|
---
|
|
51
45
|
|
|
52
|
-
##
|
|
46
|
+
## Works with any LLM provider
|
|
47
|
+
|
|
48
|
+
### OpenAI
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
const response = await openai.chat.completions.create({ model, messages });
|
|
52
|
+
const res = await ailp(messages, response.choices[0].message.content ?? "");
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Anthropic
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const response = await anthropic.messages.create({ model, messages, max_tokens: 256 });
|
|
59
|
+
const res = await ailp(messages, response.content[0]?.text ?? "");
|
|
60
|
+
```
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
counts are captured automatically. Assessment runs **fire-and-forget** in the
|
|
56
|
-
background — your LLM call is never blocked or delayed.
|
|
62
|
+
### Any other provider
|
|
57
63
|
|
|
58
64
|
```typescript
|
|
59
|
-
|
|
60
|
-
|
|
65
|
+
const output = await myLlm(messages);
|
|
66
|
+
const res = await ailp(messages, output);
|
|
67
|
+
```
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Fire-and-forget wrapper (OpenAI)
|
|
64
72
|
|
|
65
|
-
|
|
73
|
+
Assessment runs in the background — your LLM response is never blocked or delayed:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { wrapOpenAI, AilpClient } from "@genbounty/ailp";
|
|
77
|
+
|
|
78
|
+
const client = new AilpClient({ baseUrl: "http://localhost:8000" });
|
|
66
79
|
|
|
67
80
|
const response = await wrapOpenAI(
|
|
68
|
-
(
|
|
81
|
+
(p) => openai.chat.completions.create(p),
|
|
69
82
|
{ model: "gpt-4o-mini", messages },
|
|
70
83
|
{
|
|
71
|
-
client
|
|
84
|
+
client,
|
|
85
|
+
programId: "your-program-id",
|
|
72
86
|
frameworks: ["eu-ai-act", "owasp-llm"],
|
|
73
|
-
|
|
74
|
-
endpoint: "/api/chat",
|
|
75
|
-
genbounty: {
|
|
76
|
-
apiKey: "your-genbounty-key",
|
|
77
|
-
programId: "your-program-id",
|
|
78
|
-
},
|
|
79
|
-
onAssess: (result, entry) => {
|
|
80
|
-
console.log("Risk:", result.risk_level);
|
|
81
|
-
},
|
|
82
|
-
onAssessError: (err) => {
|
|
83
|
-
console.warn("AILP assess failed:", err);
|
|
84
|
-
},
|
|
87
|
+
onAssess: (result) => console.log("Risk:", result.risk_level),
|
|
85
88
|
},
|
|
86
89
|
);
|
|
87
|
-
|
|
88
|
-
console.log(response.choices[0].message.content);
|
|
89
90
|
```
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
## Generic LLM wrapper
|
|
92
|
+
## Generic fire-and-forget wrapper
|
|
94
93
|
|
|
95
|
-
Use `wrapLlmCall` for any async LLM function
|
|
96
|
-
You supply an `extractOutput` mapper to pull the text and token counts from
|
|
97
|
-
whatever response shape your LLM returns.
|
|
94
|
+
Use `wrapLlmCall` for any async LLM function:
|
|
98
95
|
|
|
99
96
|
```typescript
|
|
100
|
-
import { wrapLlmCall } from "ailp";
|
|
97
|
+
import { wrapLlmCall, AilpClient } from "@genbounty/ailp";
|
|
98
|
+
|
|
99
|
+
const client = new AilpClient({ baseUrl: "http://localhost:8000" });
|
|
101
100
|
|
|
102
101
|
const response = await wrapLlmCall(
|
|
103
|
-
(
|
|
102
|
+
(p) => anthropic.messages.create(p),
|
|
104
103
|
{ model: "claude-3-haiku-20240307", max_tokens: 256, messages },
|
|
105
104
|
{
|
|
106
|
-
client
|
|
105
|
+
client,
|
|
106
|
+
programId: "your-program-id",
|
|
107
107
|
frameworks: ["nist-ai-rmf"],
|
|
108
108
|
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
109
|
-
functionName: "chat",
|
|
110
109
|
extractOutput: (res) => ({
|
|
111
110
|
output: res.content[0]?.text ?? "",
|
|
112
111
|
model: res.model,
|
|
113
|
-
promptTokens: res.usage?.input_tokens,
|
|
114
|
-
completionTokens: res.usage?.output_tokens,
|
|
115
|
-
totalTokens: (res.usage?.input_tokens ?? 0) + (res.usage?.output_tokens ?? 0),
|
|
116
112
|
}),
|
|
117
113
|
},
|
|
118
114
|
);
|
|
@@ -122,26 +118,26 @@ const response = await wrapLlmCall(
|
|
|
122
118
|
|
|
123
119
|
## React hook
|
|
124
120
|
|
|
125
|
-
Import from
|
|
121
|
+
Import from `@genbounty/ailp/react` to keep React out of the core bundle:
|
|
126
122
|
|
|
127
123
|
```tsx
|
|
128
|
-
import {
|
|
129
|
-
import { useAssess } from "ailp/react";
|
|
124
|
+
import { createAilp } from "@genbounty/ailp";
|
|
125
|
+
import { useAssess } from "@genbounty/ailp/react";
|
|
130
126
|
|
|
131
|
-
const
|
|
127
|
+
const ailp = createAilp({
|
|
128
|
+
baseUrl: "http://localhost:8000",
|
|
129
|
+
programId: "your-program-id",
|
|
130
|
+
frameworks: ["eu-ai-act"],
|
|
131
|
+
});
|
|
132
132
|
|
|
133
133
|
function ChatWidget() {
|
|
134
|
-
const { assess, result, loading, error
|
|
134
|
+
const { assess, result, loading, error } = useAssess(ailp);
|
|
135
135
|
|
|
136
136
|
async function handleSend(userMessage: string, llmOutput: string) {
|
|
137
|
-
await assess(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
output: llmOutput,
|
|
142
|
-
status: "success",
|
|
143
|
-
genbounty: { frameworks: ["eu-ai-act"] },
|
|
144
|
-
});
|
|
137
|
+
await assess(
|
|
138
|
+
[{ role: "user", content: userMessage }],
|
|
139
|
+
llmOutput,
|
|
140
|
+
);
|
|
145
141
|
}
|
|
146
142
|
|
|
147
143
|
return (
|
|
@@ -163,8 +159,6 @@ function ChatWidget() {
|
|
|
163
159
|
|
|
164
160
|
## Framework slugs
|
|
165
161
|
|
|
166
|
-
Pass any of these as `frameworks` (hyphen or underscore):
|
|
167
|
-
|
|
168
162
|
| Slug | Framework |
|
|
169
163
|
|------|-----------|
|
|
170
164
|
| `eu_ai_act` / `eu-ai-act` | EU AI Act |
|
|
@@ -184,10 +178,6 @@ Pass any of these as `frameworks` (hyphen or underscore):
|
|
|
184
178
|
|
|
185
179
|
---
|
|
186
180
|
|
|
187
|
-
##
|
|
181
|
+
## License
|
|
188
182
|
|
|
189
|
-
|
|
190
|
-
npm install
|
|
191
|
-
npm run build # outputs to dist/
|
|
192
|
-
npm run dev # watch mode
|
|
193
|
-
```
|
|
183
|
+
MIT
|
package/dist/ailp.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AilpAssessResponse, AilpCallOptions, AilpMessage, AilpOptions } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* A pre-configured assess function returned by createAilp().
|
|
4
|
+
* Call it after any LLM interaction — vendor agnostic.
|
|
5
|
+
*
|
|
6
|
+
* @param messages The conversation messages sent to the LLM.
|
|
7
|
+
* @param output The raw text response from the LLM.
|
|
8
|
+
* @param options Optional per-call overrides (model, endpoint).
|
|
9
|
+
*/
|
|
10
|
+
export type AilpFn = (messages: AilpMessage[], output: string, options?: AilpCallOptions) => Promise<AilpAssessResponse>;
|
|
11
|
+
/**
|
|
12
|
+
* Create a pre-configured AILP assess function.
|
|
13
|
+
* Call createAilp() once at startup, then drop the returned function
|
|
14
|
+
* in after any LLM call.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const ailp = createAilp({
|
|
18
|
+
* baseUrl: "http://localhost:8000",
|
|
19
|
+
* programId: "my-program",
|
|
20
|
+
* frameworks: ["eu-ai-act", "owasp-llm"],
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // after any LLM call:
|
|
24
|
+
* const res = await ailp(messages, llmOutput);
|
|
25
|
+
* console.log(res.risk_level);
|
|
26
|
+
*/
|
|
27
|
+
export declare function createAilp(options: AilpOptions): AilpFn;
|
|
28
|
+
//# sourceMappingURL=ailp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ailp.d.ts","sourceRoot":"","sources":["../src/ailp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,GAAG,CACnB,QAAQ,EAAE,WAAW,EAAE,EACvB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,eAAe,KACtB,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEjC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAoBvD"}
|
package/dist/ailp.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AilpClient } from "./client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Create a pre-configured AILP assess function.
|
|
4
|
+
* Call createAilp() once at startup, then drop the returned function
|
|
5
|
+
* in after any LLM call.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const ailp = createAilp({
|
|
9
|
+
* baseUrl: "http://localhost:8000",
|
|
10
|
+
* programId: "my-program",
|
|
11
|
+
* frameworks: ["eu-ai-act", "owasp-llm"],
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* // after any LLM call:
|
|
15
|
+
* const res = await ailp(messages, llmOutput);
|
|
16
|
+
* console.log(res.risk_level);
|
|
17
|
+
*/
|
|
18
|
+
export function createAilp(options) {
|
|
19
|
+
const client = new AilpClient({
|
|
20
|
+
baseUrl: options.baseUrl,
|
|
21
|
+
timeoutMs: options.timeoutMs,
|
|
22
|
+
});
|
|
23
|
+
return function ailp(messages, output, callOptions) {
|
|
24
|
+
return client.assess({
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
input: { messages, endpoint: callOptions?.endpoint },
|
|
27
|
+
output,
|
|
28
|
+
model: callOptions?.model,
|
|
29
|
+
framework: options.frameworks,
|
|
30
|
+
genbounty: { programId: options.programId },
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=ailp.js.map
|
package/dist/ailp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ailp.js","sourceRoot":"","sources":["../src/ailp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAsBzC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,UAAU,CAAC,OAAoB;IAC7C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC;QAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;IAEH,OAAO,SAAS,IAAI,CAClB,QAAuB,EACvB,MAAc,EACd,WAA6B;QAE7B,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE;YACpD,MAAM;YACN,KAAK,EAAE,WAAW,EAAE,KAAK;YACzB,SAAS,EAAE,OAAO,CAAC,UAAU;YAC7B,SAAS,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE;SAC5C,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { createAilp } from "./ailp.js";
|
|
2
|
+
export type { AilpFn } from "./ailp.js";
|
|
1
3
|
export { AilpClient, AilpError } from "./client.js";
|
|
2
4
|
export { wrapLlmCall, wrapOpenAI } from "./wrap.js";
|
|
3
|
-
export type { AilpAssessResponse, AilpClientOptions, AilpExpertResult, AilpFrameworkSlug, AilpGenBounty, AilpLogEntry, AilpMessage, AilpRiskLevel, } from "./types.js";
|
|
4
5
|
export type { LlmWrapOptions, OpenAIWrapOptions, WrapOptions } from "./wrap.js";
|
|
6
|
+
export type { AilpAssessResponse, AilpCallOptions, AilpClientOptions, AilpExpertResult, AilpFrameworkSlug, AilpLogEntry, AilpMessage, AilpOptions, AilpRiskLevel, } from "./types.js";
|
|
5
7
|
//# 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,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACpD,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEhF,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { AilpAssessResponse, AilpCallOptions, AilpMessage } from "./types.js";
|
|
2
|
+
import type { AilpFn } from "./ailp.js";
|
|
3
3
|
export interface UseAssessState {
|
|
4
4
|
/** Last successful response, or null if not yet assessed. */
|
|
5
5
|
result: AilpAssessResponse | null;
|
|
@@ -7,10 +7,10 @@ export interface UseAssessState {
|
|
|
7
7
|
loading: boolean;
|
|
8
8
|
/** Last error thrown by assess, or null. */
|
|
9
9
|
error: Error | null;
|
|
10
|
-
/** Submit
|
|
11
|
-
assess: (
|
|
10
|
+
/** Submit messages and LLM output for assessment. Returns the response, or null on error. */
|
|
11
|
+
assess: (messages: AilpMessage[], output: string, options?: AilpCallOptions) => Promise<AilpAssessResponse | null>;
|
|
12
12
|
/** Clear result and error back to initial state. */
|
|
13
13
|
reset: () => void;
|
|
14
14
|
}
|
|
15
|
-
export declare function useAssess(
|
|
15
|
+
export declare function useAssess(ailp: AilpFn): UseAssessState;
|
|
16
16
|
//# sourceMappingURL=react.d.ts.map
|
package/dist/react.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAClC,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,6FAA6F;IAC7F,MAAM,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IACnH,oDAAoD;IACpD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAkCtD"}
|
package/dist/react.js
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* React hook for AILP assess.
|
|
3
|
-
* Import from "ailp/react" to keep React out of the main bundle.
|
|
3
|
+
* Import from "@genbounty/ailp/react" to keep React out of the main bundle.
|
|
4
4
|
*
|
|
5
5
|
* @example
|
|
6
|
-
* import {
|
|
7
|
-
*
|
|
6
|
+
* import { createAilp } from "@genbounty/ailp";
|
|
7
|
+
* import { useAssess } from "@genbounty/ailp/react";
|
|
8
|
+
*
|
|
9
|
+
* const ailp = createAilp({ baseUrl: "...", programId: "...", frameworks: ["eu-ai-act"] });
|
|
10
|
+
*
|
|
11
|
+
* function ChatWidget() {
|
|
12
|
+
* const { assess, result, loading, error } = useAssess(ailp);
|
|
13
|
+
* const res = await assess(messages, llmOutput);
|
|
14
|
+
* }
|
|
8
15
|
*/
|
|
9
16
|
import { useCallback, useState } from "react";
|
|
10
|
-
export function useAssess(
|
|
17
|
+
export function useAssess(ailp) {
|
|
11
18
|
const [result, setResult] = useState(null);
|
|
12
19
|
const [loading, setLoading] = useState(false);
|
|
13
20
|
const [error, setError] = useState(null);
|
|
14
|
-
const assess = useCallback(async (
|
|
21
|
+
const assess = useCallback(async (messages, output, options) => {
|
|
15
22
|
setLoading(true);
|
|
16
23
|
setError(null);
|
|
17
24
|
try {
|
|
18
|
-
const res = await
|
|
25
|
+
const res = await ailp(messages, output, options);
|
|
19
26
|
setResult(res);
|
|
20
27
|
return res;
|
|
21
28
|
}
|
|
@@ -27,7 +34,7 @@ export function useAssess(client) {
|
|
|
27
34
|
finally {
|
|
28
35
|
setLoading(false);
|
|
29
36
|
}
|
|
30
|
-
}, [
|
|
37
|
+
}, [ailp]);
|
|
31
38
|
const reset = useCallback(() => {
|
|
32
39
|
setResult(null);
|
|
33
40
|
setError(null);
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAiB9C,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAA4B,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,MAAM,GAAG,WAAW,CACxB,KAAK,EACH,QAAuB,EACvB,MAAc,EACd,OAAyB,EACW,EAAE;QACtC,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAClD,SAAS,CAAC,GAAG,CAAC,CAAC;YACf,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9D,QAAQ,CAAC,CAAC,CAAC,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EACD,CAAC,IAAI,CAAC,CACP,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACnD,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -4,15 +4,7 @@ export interface AilpMessage {
|
|
|
4
4
|
role: string;
|
|
5
5
|
content: string;
|
|
6
6
|
}
|
|
7
|
-
export interface AilpGenBounty {
|
|
8
|
-
/** Genbounty API key (returned as "***" in the echoed log). */
|
|
9
|
-
apiKey?: string;
|
|
10
|
-
programId?: string;
|
|
11
|
-
/** One or more framework slugs. First entry wins over top-level framework. */
|
|
12
|
-
frameworks?: AilpFrameworkSlug | AilpFrameworkSlug[];
|
|
13
|
-
}
|
|
14
7
|
export interface AilpLogEntry {
|
|
15
|
-
/** ISO 8601 timestamp of the LLM interaction. */
|
|
16
8
|
timestamp: string;
|
|
17
9
|
/** Name of the calling function / route handler. */
|
|
18
10
|
function?: string;
|
|
@@ -24,20 +16,16 @@ export interface AilpLogEntry {
|
|
|
24
16
|
};
|
|
25
17
|
/** Raw text output from the LLM. */
|
|
26
18
|
output: string;
|
|
27
|
-
promptTokens?: number;
|
|
28
|
-
completionTokens?: number;
|
|
29
|
-
totalTokens?: number;
|
|
30
|
-
/** Total latency in milliseconds. */
|
|
31
|
-
responseTime?: number;
|
|
32
19
|
endpoint?: string;
|
|
33
|
-
/** HTTP or logical status (e.g. "success", "error"). */
|
|
34
|
-
status?: string;
|
|
35
20
|
/**
|
|
36
21
|
* Framework slug(s) to assess against.
|
|
37
|
-
*
|
|
22
|
+
* Defaults to OECD if omitted everywhere.
|
|
38
23
|
*/
|
|
39
24
|
framework?: AilpFrameworkSlug | AilpFrameworkSlug[];
|
|
40
|
-
genbounty?:
|
|
25
|
+
genbounty?: {
|
|
26
|
+
programId?: string;
|
|
27
|
+
frameworks?: AilpFrameworkSlug | AilpFrameworkSlug[];
|
|
28
|
+
};
|
|
41
29
|
}
|
|
42
30
|
export interface AilpExpertResult {
|
|
43
31
|
framework: string;
|
|
@@ -53,15 +41,29 @@ export interface AilpAssessResponse {
|
|
|
53
41
|
frameworks: string[];
|
|
54
42
|
/** One entry per framework expert, in the same order as frameworks. */
|
|
55
43
|
experts: AilpExpertResult[];
|
|
56
|
-
/** Echo of the submitted log entry
|
|
44
|
+
/** Echo of the submitted log entry. */
|
|
57
45
|
log: AilpLogEntry;
|
|
58
46
|
}
|
|
59
|
-
export interface
|
|
47
|
+
export interface AilpOptions {
|
|
60
48
|
/** Base URL of the AILP server (no trailing slash). */
|
|
61
49
|
baseUrl: string;
|
|
50
|
+
/** Genbounty program ID to assess against. */
|
|
51
|
+
programId: string;
|
|
52
|
+
/** Framework slug(s) to run. */
|
|
53
|
+
frameworks: AilpFrameworkSlug | AilpFrameworkSlug[];
|
|
62
54
|
/** Optional request timeout in milliseconds (default: no timeout). */
|
|
63
55
|
timeoutMs?: number;
|
|
64
|
-
|
|
56
|
+
}
|
|
57
|
+
/** Options accepted per individual ailp() call. */
|
|
58
|
+
export interface AilpCallOptions {
|
|
59
|
+
/** Model identifier (e.g. "gpt-4o-mini"). */
|
|
60
|
+
model?: string;
|
|
61
|
+
/** Endpoint path to record (e.g. "/api/chat"). */
|
|
62
|
+
endpoint?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface AilpClientOptions {
|
|
65
|
+
baseUrl: string;
|
|
66
|
+
timeoutMs?: number;
|
|
65
67
|
headers?: Record<string, string>;
|
|
66
68
|
}
|
|
67
69
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,WAAW,GAAM,WAAW,GAC5B,MAAM,GACN,WAAW,GAAM,WAAW,GAC5B,aAAa,GAAI,aAAa,GAC9B,cAAc,GAAG,cAAc,GAC/B,KAAK,GACL,WAAW,GAAM,WAAW,GAC5B,eAAe,GAAE,eAAe,GAChC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB,MAAM,MAAM,aAAa,GACrB,UAAU,GACV,MAAM,GACN,QAAQ,GACR,KAAK,GACL,eAAe,GACf,WAAW,GACX,eAAe,CAAC;AAMpB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QACL,QAAQ,EAAE,WAAW,EAAE,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IACpD,SAAS,CAAC,EAAE;QACV,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;KACtD,CAAC;CACH;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,aAAa,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,UAAU,EAAE,aAAa,CAAC;IAC1B,0CAA0C;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,uEAAuE;IACvE,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,uCAAuC;IACvC,GAAG,EAAE,YAAY,CAAC;CACnB;AAMD,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,UAAU,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IACpD,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
|
package/dist/wrap.d.ts
CHANGED
|
@@ -1,35 +1,11 @@
|
|
|
1
1
|
import type { AilpClient } from "./client.js";
|
|
2
|
-
import type { AilpAssessResponse, AilpFrameworkSlug,
|
|
3
|
-
interface OpenAIMessage {
|
|
4
|
-
role: string;
|
|
5
|
-
content: string | null;
|
|
6
|
-
}
|
|
7
|
-
interface OpenAIChoice {
|
|
8
|
-
message: OpenAIMessage;
|
|
9
|
-
finish_reason?: string;
|
|
10
|
-
}
|
|
11
|
-
interface OpenAIUsage {
|
|
12
|
-
prompt_tokens?: number;
|
|
13
|
-
completion_tokens?: number;
|
|
14
|
-
total_tokens?: number;
|
|
15
|
-
}
|
|
16
|
-
interface OpenAIChatResponse {
|
|
17
|
-
id?: string;
|
|
18
|
-
model?: string;
|
|
19
|
-
choices: OpenAIChoice[];
|
|
20
|
-
usage?: OpenAIUsage;
|
|
21
|
-
}
|
|
22
|
-
interface OpenAIChatParams {
|
|
23
|
-
model: string;
|
|
24
|
-
messages: OpenAIMessage[];
|
|
25
|
-
[key: string]: unknown;
|
|
26
|
-
}
|
|
2
|
+
import type { AilpAssessResponse, AilpFrameworkSlug, AilpLogEntry, AilpMessage } from "./types.js";
|
|
27
3
|
export interface WrapOptions {
|
|
28
4
|
client: AilpClient;
|
|
29
5
|
/** Framework slug(s) to assess against. */
|
|
30
6
|
frameworks?: AilpFrameworkSlug | AilpFrameworkSlug[];
|
|
31
|
-
/**
|
|
32
|
-
|
|
7
|
+
/** Genbounty program ID. */
|
|
8
|
+
programId?: string;
|
|
33
9
|
/** Name of the calling function/route (logged as "function" in the entry). */
|
|
34
10
|
functionName?: string;
|
|
35
11
|
/** Endpoint path to record (e.g. "/api/chat"). */
|
|
@@ -48,37 +24,51 @@ export interface WrapOptions {
|
|
|
48
24
|
export interface LlmWrapOptions<TResult> extends WrapOptions {
|
|
49
25
|
/**
|
|
50
26
|
* Map the LLM result to the fields AILP needs.
|
|
51
|
-
*
|
|
27
|
+
* Only output text is required; model is optional.
|
|
52
28
|
*/
|
|
53
29
|
extractOutput: (result: TResult) => {
|
|
54
30
|
output: string;
|
|
55
31
|
model?: string;
|
|
56
|
-
promptTokens?: number;
|
|
57
|
-
completionTokens?: number;
|
|
58
|
-
totalTokens?: number;
|
|
59
32
|
};
|
|
60
33
|
/** Input messages to log. */
|
|
61
34
|
messages: AilpMessage[];
|
|
62
35
|
}
|
|
63
36
|
/**
|
|
64
|
-
* Generic wrapper: calls any async LLM function
|
|
65
|
-
*
|
|
66
|
-
*
|
|
37
|
+
* Generic wrapper: calls any async LLM function and fires an AILP assess
|
|
38
|
+
* in the background. Never blocks or throws on assess failures — your LLM
|
|
39
|
+
* call result is always returned.
|
|
67
40
|
*/
|
|
68
41
|
export declare function wrapLlmCall<TParams, TResult>(fn: (params: TParams) => Promise<TResult>, params: TParams, options: LlmWrapOptions<TResult>): Promise<TResult>;
|
|
42
|
+
interface OpenAIMessage {
|
|
43
|
+
role: string;
|
|
44
|
+
content: string | null;
|
|
45
|
+
}
|
|
46
|
+
interface OpenAIChoice {
|
|
47
|
+
message: OpenAIMessage;
|
|
48
|
+
finish_reason?: string;
|
|
49
|
+
}
|
|
50
|
+
interface OpenAIChatResponse {
|
|
51
|
+
id?: string;
|
|
52
|
+
model?: string;
|
|
53
|
+
choices: OpenAIChoice[];
|
|
54
|
+
}
|
|
55
|
+
interface OpenAIChatParams {
|
|
56
|
+
model: string;
|
|
57
|
+
messages: OpenAIMessage[];
|
|
58
|
+
[key: string]: unknown;
|
|
59
|
+
}
|
|
69
60
|
export interface OpenAIWrapOptions extends WrapOptions {
|
|
70
|
-
/** The endpoint path to log (default: "/v1/chat/completions"). */
|
|
71
61
|
endpoint?: string;
|
|
72
62
|
}
|
|
73
63
|
/**
|
|
74
64
|
* Drop-in wrapper for `openai.chat.completions.create()` (or any compatible API).
|
|
75
|
-
*
|
|
65
|
+
* Assessment runs fire-and-forget — your LLM call is never blocked or delayed.
|
|
76
66
|
*
|
|
77
67
|
* @example
|
|
78
68
|
* const response = await wrapOpenAI(
|
|
79
69
|
* (p) => openai.chat.completions.create(p),
|
|
80
70
|
* { model: "gpt-4o-mini", messages },
|
|
81
|
-
* { client, frameworks: ["eu-ai-act"
|
|
71
|
+
* { client, programId: "my-program", frameworks: ["eu-ai-act"] }
|
|
82
72
|
* );
|
|
83
73
|
*/
|
|
84
74
|
export declare function wrapOpenAI<T extends OpenAIChatParams>(fn: (params: T) => Promise<OpenAIChatResponse>, params: T, options: OpenAIWrapOptions): Promise<OpenAIChatResponse>;
|
package/dist/wrap.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMnG,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IACrD,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACrE;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CAC7D;AAMD,MAAM,WAAW,cAAc,CAAC,OAAO,CAAE,SAAQ,WAAW;IAC1D;;;OAGG;IACH,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK;QAClC,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,6BAA6B;IAC7B,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAChD,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,EACzC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CA2ClB;AAMD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,aAAa,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,kBAAkB;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAMD,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,gBAAgB,EACzD,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,kBAAkB,CAAC,EAC9C,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAkB7B"}
|
package/dist/wrap.js
CHANGED
|
@@ -1,32 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generic wrapper: calls any async LLM function
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Generic wrapper: calls any async LLM function and fires an AILP assess
|
|
3
|
+
* in the background. Never blocks or throws on assess failures — your LLM
|
|
4
|
+
* call result is always returned.
|
|
5
5
|
*/
|
|
6
6
|
export async function wrapLlmCall(fn, params, options) {
|
|
7
|
-
const start = Date.now();
|
|
8
7
|
let result;
|
|
9
|
-
let status = "success";
|
|
10
8
|
try {
|
|
11
9
|
result = await fn(params);
|
|
12
10
|
}
|
|
13
11
|
catch (err) {
|
|
14
|
-
status = "error";
|
|
15
12
|
_fireAssess({
|
|
16
|
-
timestamp: new Date(
|
|
13
|
+
timestamp: new Date().toISOString(),
|
|
17
14
|
function: options.functionName,
|
|
18
|
-
model: undefined,
|
|
19
15
|
input: { messages: options.messages, endpoint: options.endpoint },
|
|
20
16
|
output: err instanceof Error ? err.message : String(err),
|
|
21
|
-
responseTime: Date.now() - start,
|
|
22
17
|
endpoint: options.endpoint,
|
|
23
|
-
status,
|
|
24
18
|
framework: options.frameworks,
|
|
25
|
-
genbounty: options.
|
|
19
|
+
genbounty: { programId: options.programId },
|
|
26
20
|
}, options);
|
|
27
21
|
throw err;
|
|
28
22
|
}
|
|
29
|
-
const responseTime = Date.now() - start;
|
|
30
23
|
let extracted = { output: "" };
|
|
31
24
|
try {
|
|
32
25
|
extracted = options.extractOutput(result);
|
|
@@ -35,32 +28,27 @@ export async function wrapLlmCall(fn, params, options) {
|
|
|
35
28
|
// extractOutput threw — log what we have
|
|
36
29
|
}
|
|
37
30
|
const entry = {
|
|
38
|
-
timestamp: new Date(
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
39
32
|
function: options.functionName,
|
|
40
33
|
model: extracted.model,
|
|
41
34
|
input: { messages: options.messages, endpoint: options.endpoint },
|
|
42
35
|
output: extracted.output ?? "",
|
|
43
|
-
promptTokens: extracted.promptTokens,
|
|
44
|
-
completionTokens: extracted.completionTokens,
|
|
45
|
-
totalTokens: extracted.totalTokens,
|
|
46
|
-
responseTime,
|
|
47
36
|
endpoint: options.endpoint,
|
|
48
|
-
status,
|
|
49
37
|
framework: options.frameworks,
|
|
50
|
-
genbounty: options.
|
|
38
|
+
genbounty: { programId: options.programId },
|
|
51
39
|
};
|
|
52
40
|
_fireAssess(entry, options);
|
|
53
41
|
return result;
|
|
54
42
|
}
|
|
55
43
|
/**
|
|
56
44
|
* Drop-in wrapper for `openai.chat.completions.create()` (or any compatible API).
|
|
57
|
-
*
|
|
45
|
+
* Assessment runs fire-and-forget — your LLM call is never blocked or delayed.
|
|
58
46
|
*
|
|
59
47
|
* @example
|
|
60
48
|
* const response = await wrapOpenAI(
|
|
61
49
|
* (p) => openai.chat.completions.create(p),
|
|
62
50
|
* { model: "gpt-4o-mini", messages },
|
|
63
|
-
* { client, frameworks: ["eu-ai-act"
|
|
51
|
+
* { client, programId: "my-program", frameworks: ["eu-ai-act"] }
|
|
64
52
|
* );
|
|
65
53
|
*/
|
|
66
54
|
export async function wrapOpenAI(fn, params, options) {
|
|
@@ -72,19 +60,12 @@ export async function wrapOpenAI(fn, params, options) {
|
|
|
72
60
|
...options,
|
|
73
61
|
endpoint: options.endpoint ?? "/v1/chat/completions",
|
|
74
62
|
messages,
|
|
75
|
-
extractOutput: (res) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
output,
|
|
82
|
-
model: res.model ?? params.model,
|
|
83
|
-
promptTokens: res.usage?.prompt_tokens,
|
|
84
|
-
completionTokens: res.usage?.completion_tokens,
|
|
85
|
-
totalTokens: res.usage?.total_tokens,
|
|
86
|
-
};
|
|
87
|
-
},
|
|
63
|
+
extractOutput: (res) => ({
|
|
64
|
+
output: (typeof res.choices?.[0]?.message?.content === "string"
|
|
65
|
+
? res.choices[0].message.content
|
|
66
|
+
: null) ?? "",
|
|
67
|
+
model: res.model ?? params.model,
|
|
68
|
+
}),
|
|
88
69
|
});
|
|
89
70
|
}
|
|
90
71
|
// -------------------------------------------------------------------------
|
|
@@ -93,7 +74,7 @@ export async function wrapOpenAI(fn, params, options) {
|
|
|
93
74
|
function _fireAssess(entry, options) {
|
|
94
75
|
const onError = options.onAssessError ??
|
|
95
76
|
((err) => {
|
|
96
|
-
console.warn("[ailp
|
|
77
|
+
console.warn("[ailp] assess error (LLM call unaffected):", err);
|
|
97
78
|
});
|
|
98
79
|
options.client
|
|
99
80
|
.assess(entry)
|
package/dist/wrap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"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"}
|