@patdown/jev 0.4.0 → 0.5.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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/jev-choice-schema.d.ts +31 -0
- package/dist/jev-choice-schema.d.ts.map +1 -0
- package/dist/jev-choice-schema.js +23 -0
- package/dist/jev-system-one.d.ts +4 -0
- package/dist/jev-system-one.d.ts.map +1 -1
- package/dist/jev-system-one.js +70 -8
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { JevNoulAnswerSchema, JevNoulQuestionSchema, JevNoulResultSchema, JevUsageSchema, type JevNoulAnswer, type JevNoulResult, } from '#src/jev-noul-schema';
|
|
2
|
-
export {
|
|
2
|
+
export { JevChoiceAnswerSchema, JevChoiceQuestionSchema, JevChoiceResultSchema, type JevChoiceAnswer, type JevChoiceResult, } from '#src/jev-choice-schema';
|
|
3
|
+
export { JevRequestFailed, JevSystemOne, JevSystemOneLive, type JevChoiceCriteria, } from '#src/jev-system-one';
|
|
3
4
|
//# 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,EACN,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,aAAa,GAClB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,aAAa,GAClB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACN,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,GACpB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EACN,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,KAAK,iBAAiB,GACtB,MAAM,qBAAqB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { JevNoulAnswerSchema, JevNoulQuestionSchema, JevNoulResultSchema, JevUsageSchema, } from '#src/jev-noul-schema';
|
|
2
|
-
export {
|
|
2
|
+
export { JevChoiceAnswerSchema, JevChoiceQuestionSchema, JevChoiceResultSchema, } from '#src/jev-choice-schema';
|
|
3
|
+
export { JevRequestFailed, JevSystemOne, JevSystemOneLive, } from '#src/jev-system-one';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
/** Choice question body for POST /v1/systemone. Labels map to descriptions. */
|
|
3
|
+
export declare const JevChoiceQuestionSchema: Schema.Struct<{
|
|
4
|
+
readonly criteria: Schema.$Record<Schema.String, Schema.NullOr<Schema.String>>;
|
|
5
|
+
readonly instructions: Schema.optionalKey<Schema.String>;
|
|
6
|
+
readonly type: Schema.Literal<"choice">;
|
|
7
|
+
}>;
|
|
8
|
+
/** Choice answer from POST /v1/systemone. */
|
|
9
|
+
export declare const JevChoiceAnswerSchema: Schema.Struct<{
|
|
10
|
+
readonly choice: Schema.String;
|
|
11
|
+
readonly confidence: Schema.Finite;
|
|
12
|
+
readonly probabilities: Schema.$Record<Schema.String, Schema.Finite>;
|
|
13
|
+
readonly type: Schema.Literal<"choice">;
|
|
14
|
+
}>;
|
|
15
|
+
/** System One response when every question is choice. */
|
|
16
|
+
export declare const JevChoiceResultSchema: Schema.Struct<{
|
|
17
|
+
readonly answers: Schema.$Record<Schema.String, Schema.Struct<{
|
|
18
|
+
readonly choice: Schema.String;
|
|
19
|
+
readonly confidence: Schema.Finite;
|
|
20
|
+
readonly probabilities: Schema.$Record<Schema.String, Schema.Finite>;
|
|
21
|
+
readonly type: Schema.Literal<"choice">;
|
|
22
|
+
}>>;
|
|
23
|
+
readonly model: Schema.String;
|
|
24
|
+
readonly usage: Schema.Struct<{
|
|
25
|
+
readonly input_tokens: Schema.Finite;
|
|
26
|
+
readonly output_tokens: Schema.Finite;
|
|
27
|
+
}>;
|
|
28
|
+
}>;
|
|
29
|
+
export type JevChoiceAnswer = typeof JevChoiceAnswerSchema.Type;
|
|
30
|
+
export type JevChoiceResult = typeof JevChoiceResultSchema.Type;
|
|
31
|
+
//# sourceMappingURL=jev-choice-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jev-choice-schema.d.ts","sourceRoot":"","sources":["../src/jev-choice-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,+EAA+E;AAC/E,eAAO,MAAM,uBAAuB;;;;EAIlC,CAAA;AAEF,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB;;;;;EAKhC,CAAA;AAEF,yDAAyD;AACzD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;EAOhC,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,OAAO,qBAAqB,CAAC,IAAI,CAAA;AAE/D,MAAM,MAAM,eAAe,GAAG,OAAO,qBAAqB,CAAC,IAAI,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
/** Choice question body for POST /v1/systemone. Labels map to descriptions. */
|
|
3
|
+
export const JevChoiceQuestionSchema = Schema.Struct({
|
|
4
|
+
criteria: Schema.Record(Schema.String, Schema.NullOr(Schema.String)),
|
|
5
|
+
instructions: Schema.optionalKey(Schema.String),
|
|
6
|
+
type: Schema.Literal('choice'),
|
|
7
|
+
});
|
|
8
|
+
/** Choice answer from POST /v1/systemone. */
|
|
9
|
+
export const JevChoiceAnswerSchema = Schema.Struct({
|
|
10
|
+
choice: Schema.String,
|
|
11
|
+
confidence: Schema.Finite,
|
|
12
|
+
probabilities: Schema.Record(Schema.String, Schema.Finite),
|
|
13
|
+
type: Schema.Literal('choice'),
|
|
14
|
+
});
|
|
15
|
+
/** System One response when every question is choice. */
|
|
16
|
+
export const JevChoiceResultSchema = Schema.Struct({
|
|
17
|
+
answers: Schema.Record(Schema.String, JevChoiceAnswerSchema),
|
|
18
|
+
model: Schema.String,
|
|
19
|
+
usage: Schema.Struct({
|
|
20
|
+
input_tokens: Schema.Finite,
|
|
21
|
+
output_tokens: Schema.Finite,
|
|
22
|
+
}),
|
|
23
|
+
});
|
package/dist/jev-system-one.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from 'effect';
|
|
2
2
|
import { HttpClient } from 'effect/unstable/http';
|
|
3
|
+
import { type JevChoiceAnswer } from '#src/jev-choice-schema';
|
|
3
4
|
import { type JevNoulAnswer } from '#src/jev-noul-schema';
|
|
4
5
|
declare const JevRequestFailed_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
5
6
|
readonly _tag: "JevRequestFailed";
|
|
@@ -12,8 +13,11 @@ export declare class JevRequestFailed extends JevRequestFailed_base<{
|
|
|
12
13
|
readonly requestId?: string | undefined;
|
|
13
14
|
}> {
|
|
14
15
|
}
|
|
16
|
+
/** Labels for a Choice question. Values are short descriptions shown to the model. */
|
|
17
|
+
export type JevChoiceCriteria = Readonly<Record<string, string | null>>;
|
|
15
18
|
declare const JevSystemOne_base: Context.ServiceClass<JevSystemOne, "@patdown/jev/JevSystemOne", {
|
|
16
19
|
readonly askNoul: (instructions: string, state: string) => Effect.Effect<JevNoulAnswer, JevRequestFailed, HttpClient.HttpClient>;
|
|
20
|
+
readonly askChoice: (instructions: string, state: string, criteria: JevChoiceCriteria) => Effect.Effect<JevChoiceAnswer, JevRequestFailed, HttpClient.HttpClient>;
|
|
17
21
|
}>;
|
|
18
22
|
/**
|
|
19
23
|
* Client for TypeSafe System One (Jev). Implemented with Effect HttpClient so a Decision-based
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jev-system-one.d.ts","sourceRoot":"","sources":["../src/jev-system-one.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAoB,MAAM,QAAQ,CAAA;AAE/E,OAAO,EAAE,UAAU,EAAyC,MAAM,sBAAsB,CAAA;AAExF,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;;;;
|
|
1
|
+
{"version":3,"file":"jev-system-one.d.ts","sourceRoot":"","sources":["../src/jev-system-one.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAoB,MAAM,QAAQ,CAAA;AAE/E,OAAO,EAAE,UAAU,EAAyC,MAAM,sBAAsB,CAAA;AAExF,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACpF,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;;;;AAU9E,kGAAkG;AAClG,qBAAa,gBAAiB,SAAQ,sBAAqC;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC,CAAC;CAAG;AAEL,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;;sBASnD,CACjB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,gBAAgB,EAAE,UAAU,CAAC,UAAU,CAAC;wBACtD,CACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,iBAAiB,KACvB,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,gBAAgB,EAAE,UAAU,CAAC,UAAU,CAAC;;AAf9E;;;GAGG;AACH,qBAAa,YAAa,SAAQ,iBAaF;CAAG;AA8QnC,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,yCAG3B,CAAA"}
|
package/dist/jev-system-one.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Config, Context, Data, Effect, Layer, Redacted, Schema } from 'effect';
|
|
2
2
|
import { HttpClient, HttpClientRequest, HttpClientResponse } from 'effect/unstable/http';
|
|
3
|
+
import { JevChoiceResultSchema } from '#src/jev-choice-schema';
|
|
3
4
|
import { JevNoulResultSchema } from '#src/jev-noul-schema';
|
|
4
5
|
const defaultJevBaseUrl = 'https://api.typesafe.ai';
|
|
5
6
|
const defaultJevModel = 'jev-latest';
|
|
6
7
|
const defaultNoulQuestionName = 'noul';
|
|
8
|
+
const defaultChoiceQuestionName = 'choice';
|
|
7
9
|
/** Jev / System One HTTP or config failure. Swap this service later for Effect's Decision API. */
|
|
8
10
|
export class JevRequestFailed extends Data.TaggedError('JevRequestFailed') {
|
|
9
11
|
}
|
|
@@ -33,6 +35,15 @@ function noulAnswerFromResult(result, questionName) {
|
|
|
33
35
|
}
|
|
34
36
|
return Effect.succeed(answer);
|
|
35
37
|
}
|
|
38
|
+
function choiceAnswerFromResult(result, questionName) {
|
|
39
|
+
const answer = result.answers[questionName];
|
|
40
|
+
if (answer === undefined) {
|
|
41
|
+
return Effect.fail(new JevRequestFailed({
|
|
42
|
+
message: `jev: response missing choice answer ${questionName}`,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
return Effect.succeed(answer);
|
|
46
|
+
}
|
|
36
47
|
function encodeJevNoulBody(prepared, model, instructions, state) {
|
|
37
48
|
return HttpClientRequest.bodyJson(prepared, {
|
|
38
49
|
model,
|
|
@@ -51,6 +62,27 @@ function encodeJevNoulBody(prepared, model, instructions, state) {
|
|
|
51
62
|
message: 'jev: failed to encode System One request body',
|
|
52
63
|
})));
|
|
53
64
|
}
|
|
65
|
+
function encodeJevChoiceBody(prepared, options) {
|
|
66
|
+
const labels = Object.keys(options.criteria);
|
|
67
|
+
if (labels.length < 2) {
|
|
68
|
+
return Effect.fail(new JevRequestFailed({
|
|
69
|
+
message: 'jev: choice criteria need at least two labels',
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
return HttpClientRequest.bodyJson(prepared, {
|
|
73
|
+
model: options.model,
|
|
74
|
+
questions: {
|
|
75
|
+
[defaultChoiceQuestionName]: {
|
|
76
|
+
criteria: options.criteria,
|
|
77
|
+
instructions: options.instructions,
|
|
78
|
+
type: 'choice',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
state: options.state,
|
|
82
|
+
}).pipe(Effect.mapError(() => new JevRequestFailed({
|
|
83
|
+
message: 'jev: failed to encode System One choice request body',
|
|
84
|
+
})));
|
|
85
|
+
}
|
|
54
86
|
const JevErrorBodySchema = Schema.Struct({
|
|
55
87
|
detail: Schema.Struct({ error_type: Schema.String }),
|
|
56
88
|
});
|
|
@@ -88,21 +120,29 @@ function jevHttpFailure(response, state) {
|
|
|
88
120
|
});
|
|
89
121
|
});
|
|
90
122
|
}
|
|
91
|
-
function
|
|
123
|
+
function prepareJevSystemOneRequest(baseUrl, apiKey) {
|
|
124
|
+
return HttpClientRequest.post(`${baseUrl}/v1/systemone`).pipe(HttpClientRequest.bearerToken(apiKey), HttpClientRequest.acceptJson);
|
|
125
|
+
}
|
|
126
|
+
function executeJevSystemOneRequest(request, state) {
|
|
92
127
|
return Effect.gen(function* () {
|
|
93
|
-
const apiKey = yield* readJevApiKey();
|
|
94
|
-
const baseUrl = yield* Effect.orDie(readJevBaseUrl());
|
|
95
|
-
const model = yield* Effect.orDie(readJevModel());
|
|
96
128
|
const client = yield* HttpClient.HttpClient;
|
|
97
|
-
const prepared = HttpClientRequest.post(`${baseUrl}/v1/systemone`).pipe(HttpClientRequest.bearerToken(apiKey), HttpClientRequest.acceptJson);
|
|
98
|
-
const request = yield* encodeJevNoulBody(prepared, model, instructions, state);
|
|
99
129
|
const response = yield* client.execute(request).pipe(Effect.mapError((error) => new JevRequestFailed({
|
|
100
130
|
message: `jev: System One transport/request failure (${error.reason._tag}); no usable HTTP response`,
|
|
101
131
|
})));
|
|
102
132
|
if (response.status < 200 || response.status >= 300) {
|
|
103
|
-
|
|
104
|
-
return yield* error;
|
|
133
|
+
return yield* Effect.fail(yield* jevHttpFailure(response, state));
|
|
105
134
|
}
|
|
135
|
+
return response;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function askJevNoul(instructions, state) {
|
|
139
|
+
return Effect.gen(function* () {
|
|
140
|
+
const apiKey = yield* readJevApiKey();
|
|
141
|
+
const baseUrl = yield* Effect.orDie(readJevBaseUrl());
|
|
142
|
+
const model = yield* Effect.orDie(readJevModel());
|
|
143
|
+
const prepared = prepareJevSystemOneRequest(baseUrl, apiKey);
|
|
144
|
+
const request = yield* encodeJevNoulBody(prepared, model, instructions, state);
|
|
145
|
+
const response = yield* executeJevSystemOneRequest(request, state);
|
|
106
146
|
const result = yield* HttpClientResponse.schemaBodyJson(JevNoulResultSchema)(response).pipe(Effect.mapError(() => new JevRequestFailed({
|
|
107
147
|
message: `jev: System One HTTP ${String(response.status)} response could not be decoded as the expected noul result`,
|
|
108
148
|
status: response.status,
|
|
@@ -111,7 +151,29 @@ function askJevNoul(instructions, state) {
|
|
|
111
151
|
return yield* noulAnswerFromResult(result, defaultNoulQuestionName);
|
|
112
152
|
});
|
|
113
153
|
}
|
|
154
|
+
function askJevChoice(instructions, state, criteria) {
|
|
155
|
+
return Effect.gen(function* () {
|
|
156
|
+
const apiKey = yield* readJevApiKey();
|
|
157
|
+
const baseUrl = yield* Effect.orDie(readJevBaseUrl());
|
|
158
|
+
const model = yield* Effect.orDie(readJevModel());
|
|
159
|
+
const prepared = prepareJevSystemOneRequest(baseUrl, apiKey);
|
|
160
|
+
const request = yield* encodeJevChoiceBody(prepared, {
|
|
161
|
+
model,
|
|
162
|
+
instructions,
|
|
163
|
+
state,
|
|
164
|
+
criteria,
|
|
165
|
+
});
|
|
166
|
+
const response = yield* executeJevSystemOneRequest(request, state);
|
|
167
|
+
const result = yield* HttpClientResponse.schemaBodyJson(JevChoiceResultSchema)(response).pipe(Effect.mapError(() => new JevRequestFailed({
|
|
168
|
+
message: `jev: System One HTTP ${String(response.status)} response could not be decoded as the expected choice result`,
|
|
169
|
+
status: response.status,
|
|
170
|
+
requestId: safeJevErrorIdentifier(response.headers['x-typesafe-request-id']),
|
|
171
|
+
})));
|
|
172
|
+
return yield* choiceAnswerFromResult(result, defaultChoiceQuestionName);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
114
175
|
/** Live Jev client using Effect HttpClient and TYPESAFE_* config. */
|
|
115
176
|
export const JevSystemOneLive = Layer.succeed(JevSystemOne, {
|
|
116
177
|
askNoul: askJevNoul,
|
|
178
|
+
askChoice: askJevChoice,
|
|
117
179
|
});
|