typia 14.0.5 → 15.0.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.
Files changed (72) hide show
  1. package/README.md +3 -0
  2. package/lib/internal/_createLlmEvaluation.d.ts +1 -0
  3. package/lib/internal/_createLlmEvaluation.js +486 -0
  4. package/lib/internal/_createLlmEvaluation.js.map +1 -0
  5. package/lib/internal/_createLlmEvaluation.mjs +382 -0
  6. package/lib/internal/_createLlmEvaluation.mjs.map +1 -0
  7. package/lib/internal/_stringLengthGte.d.ts +1 -0
  8. package/lib/internal/_stringLengthGte.js +14 -0
  9. package/lib/internal/_stringLengthGte.js.map +1 -0
  10. package/lib/internal/_stringLengthGte.mjs +11 -0
  11. package/lib/internal/_stringLengthGte.mjs.map +1 -0
  12. package/lib/internal/_stringLengthLte.d.ts +1 -0
  13. package/lib/internal/_stringLengthLte.js +14 -0
  14. package/lib/internal/_stringLengthLte.js.map +1 -0
  15. package/lib/internal/_stringLengthLte.mjs +11 -0
  16. package/lib/internal/_stringLengthLte.mjs.map +1 -0
  17. package/lib/llm.d.ts +54 -1
  18. package/lib/llm.js +5 -0
  19. package/lib/llm.js.map +1 -1
  20. package/lib/llm.mjs +6 -1
  21. package/lib/llm.mjs.map +1 -1
  22. package/lib/re-exports.d.ts +1 -1
  23. package/lib/re-exports.js.map +1 -1
  24. package/native/cmd/ttsc-typia/build.go +2 -0
  25. package/native/cmd/ttsc-typia/dynamic_key_tags_transform_test.go +1 -1
  26. package/native/cmd/ttsc-typia/llm_evaluation_accepts_property_probability_test.go +27 -0
  27. package/native/cmd/ttsc-typia/llm_evaluation_accepts_unselected_source_probability_test.go +26 -0
  28. package/native/cmd/ttsc-typia/llm_evaluation_complete_object_shape_test.go +96 -0
  29. package/native/cmd/ttsc-typia/llm_evaluation_ignores_declaration_probability_without_call_test.go +18 -0
  30. package/native/cmd/ttsc-typia/llm_evaluation_plan_emission_transform_test.go +90 -0
  31. package/native/cmd/ttsc-typia/llm_evaluation_program_scan_dependencies_test.go +69 -0
  32. package/native/cmd/ttsc-typia/llm_evaluation_rejects_alias_comment_test.go +44 -0
  33. package/native/cmd/ttsc-typia/llm_evaluation_rejects_alias_refinement_test.go +45 -0
  34. package/native/cmd/ttsc-typia/llm_evaluation_rejects_computed_method_probability_test.go +30 -0
  35. package/native/cmd/ttsc-typia/llm_evaluation_rejects_imported_declaration_probability_test.go +48 -0
  36. package/native/cmd/ttsc-typia/llm_evaluation_rejects_invalid_probability_test.go +199 -0
  37. package/native/cmd/ttsc-typia/llm_evaluation_rejects_refinements_test.go +94 -0
  38. package/native/cmd/ttsc-typia/llm_evaluation_rejects_undecidable_types_test.go +232 -0
  39. package/native/cmd/ttsc-typia/metadata_type_tag_sole_malformed_diagnostic_test.go +94 -0
  40. package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +3 -2
  41. package/native/cmd/ttsc-typia/transform.go +2 -0
  42. package/native/cmd/ttsc-typia/transform_helpers_test.go +17 -3
  43. package/native/core/context/ITypiaContext.go +4 -0
  44. package/native/core/factories/IdentifierFactory.go +10 -0
  45. package/native/core/factories/LiteralFactory.go +16 -0
  46. package/native/core/factories/MetadataCommentTagFactory.go +12 -10
  47. package/native/core/factories/MetadataTypeTagFactory.go +97 -24
  48. package/native/core/factories/MetadataTypeTagSchemaFactory.go +5 -0
  49. package/native/core/factories/internal/metadata/IMetadataIteratorProps.go +6 -2
  50. package/native/core/factories/internal/metadata/emplace_metadata_object.go +49 -15
  51. package/native/core/factories/literal_factory_null_survives_objects_test.go +43 -0
  52. package/native/core/factories/metadata_comment_tag_factory_string_length_helpers_test.go +55 -0
  53. package/native/core/factories/metadata_type_tag_factory_reports_all_invalid_candidates_test.go +73 -0
  54. package/native/core/programmers/llm/LlmApplicationProgrammer.go +1 -0
  55. package/native/core/programmers/llm/LlmEvaluationProgrammer.go +555 -0
  56. package/native/core/programmers/llm/LlmParametersProgrammer.go +6 -5
  57. package/native/core/programmers/llm/LlmReferenceDescription.go +113 -0
  58. package/native/core/programmers/llm/llm_reference_description_test.go +134 -0
  59. package/native/core/schemas/metadata/MetadataDependency.go +9 -0
  60. package/native/transform/CallExpressionTransformer.go +1 -0
  61. package/native/transform/FileTransformer.go +5 -0
  62. package/native/transform/features/llm/LlmEvaluationProbabilityDeclarations.go +94 -0
  63. package/native/transform/features/llm/LlmEvaluationProbabilityDeclarations_test.go +50 -0
  64. package/native/transform/features/llm/LlmEvaluationTransformer.go +59 -0
  65. package/native/transform/features/llm/LlmSchemaTransformer.go +14 -11
  66. package/native/transform/features/llm/llm_transformer_entry_coverage_test.go +29 -27
  67. package/package.json +3 -3
  68. package/src/internal/_createLlmEvaluation.ts +678 -0
  69. package/src/internal/_stringLengthGte.ts +6 -0
  70. package/src/internal/_stringLengthLte.ts +6 -0
  71. package/src/llm.ts +64 -0
  72. package/src/re-exports.ts +1 -0
@@ -0,0 +1,382 @@
1
+ import { _accessExpressionAsString } from "./_accessExpressionAsString.mjs";
2
+ //#region src/internal/_createLlmEvaluation.ts
3
+ /**
4
+ * Creates the `ILlmEvaluation` of `typia.llm.evaluation<T>()` from its plan.
5
+ *
6
+ * Both the question map and the decoder derive their keys from here, so the
7
+ * readable path encoding has a single owner.
8
+ *
9
+ * @internal
10
+ */
11
+ const _createLlmEvaluation = (plan) => {
12
+ const questions = {};
13
+ for (const leaf of plan) if (leaf.kind === "set") for (const member of leaf.members) assign(questions, key([...leaf.path, member.value]), {
14
+ type: "boolean",
15
+ instructions: setInstructions(leaf, member)
16
+ });
17
+ else assign(questions, key(leaf.path), question(leaf));
18
+ return {
19
+ questions,
20
+ decode: (answers, rounding) => decode(plan, answers, rounding)
21
+ };
22
+ };
23
+ /**
24
+ * Encodes a property path as a question key, like `refund.requested`.
25
+ *
26
+ * Every segment after the first uses typia's accessor notation, so the key is
27
+ * the validation path without its `$input` root. The first segment is quoted
28
+ * when it is not an identifier, and always when it is `__proto__`, so no key
29
+ * can collide with another or reach an object's prototype.
30
+ */
31
+ const key = (path) => {
32
+ const head = path[0];
33
+ const postfix = _accessExpressionAsString(head);
34
+ return (head === "__proto__" ? `[${JSON.stringify(head)}]` : postfix.startsWith(".") ? head : postfix) + path.slice(1).map(_accessExpressionAsString).join("");
35
+ };
36
+ const question = (leaf) => {
37
+ if (leaf.kind === "boolean") return {
38
+ type: "boolean",
39
+ instructions: leaf.instructions
40
+ };
41
+ else if (leaf.kind === "choice") {
42
+ const criteria = {};
43
+ for (const option of leaf.options) assign(criteria, option.value, option.description ?? null);
44
+ return {
45
+ type: "choice",
46
+ instructions: leaf.instructions,
47
+ criteria
48
+ };
49
+ }
50
+ return {
51
+ type: "score",
52
+ instructions: leaf.instructions,
53
+ criteria: leaf.levels.map((level) => level.description ?? String(level.value))
54
+ };
55
+ };
56
+ const setInstructions = (leaf, member) => [
57
+ leaf.instructions,
58
+ "",
59
+ `Does the option ${JSON.stringify(member.value)} apply?`,
60
+ ...member.description !== void 0 ? [member.description] : []
61
+ ].join("\n");
62
+ const decode = (plan, answers, rounding) => {
63
+ const precision = (() => {
64
+ try {
65
+ return readPrecision(rounding);
66
+ } catch {
67
+ return null;
68
+ }
69
+ })();
70
+ if (precision === null) return {
71
+ success: false,
72
+ data: answers,
73
+ errors: [{
74
+ path: "$input",
75
+ expected: "rounding decimals in [0, 15]",
76
+ value: rounding,
77
+ description: "Evaluation rounding decimals must be integers between 0 and 15."
78
+ }]
79
+ };
80
+ const map = object(answers);
81
+ if (map === null) return {
82
+ success: false,
83
+ data: answers,
84
+ errors: [{
85
+ path: "$input",
86
+ expected: "Record<string, ILlmEvaluation answer>",
87
+ value: answers
88
+ }]
89
+ };
90
+ const errors = [];
91
+ const expected = /* @__PURE__ */ new Set();
92
+ const output = {};
93
+ const read = (id) => {
94
+ expected.add(id);
95
+ try {
96
+ return Object.prototype.hasOwnProperty.call(map, id) ? map[id] : void 0;
97
+ } catch {
98
+ return;
99
+ }
100
+ };
101
+ for (const leaf of plan) {
102
+ const path = accessor(leaf.path);
103
+ if (leaf.kind === "set") {
104
+ const values = [];
105
+ for (const member of leaf.members) {
106
+ const memberPath = [path, _accessExpressionAsString(member.value)].join("");
107
+ const answer = read(key([...leaf.path, member.value]));
108
+ const probability = inspect(memberPath, answer, errors, () => booleanProbability(answer, memberPath, errors));
109
+ if (probability !== null && probability >= member.threshold) values.push(member.value);
110
+ }
111
+ place(output, leaf.path, values);
112
+ continue;
113
+ }
114
+ const answer = read(key(leaf.path));
115
+ if (leaf.kind === "boolean") {
116
+ const probability = inspect(path, answer, errors, () => booleanProbability(answer, path, errors));
117
+ if (probability !== null) place(output, leaf.path, probability >= leaf.threshold);
118
+ } else if (leaf.kind === "choice") {
119
+ const value = inspect(path, answer, errors, () => choice(leaf, answer, path, errors, precision));
120
+ if (value !== null) place(output, leaf.path, value);
121
+ } else {
122
+ const value = inspect(path, answer, errors, () => score(leaf, answer, path, errors, precision));
123
+ if (value !== null) place(output, leaf.path, value);
124
+ }
125
+ }
126
+ let received;
127
+ try {
128
+ received = Object.keys(map);
129
+ } catch {
130
+ errors.push({
131
+ path: "$input",
132
+ expected: "readable evaluation answer map",
133
+ value: answers,
134
+ description: "Evaluation answer keys could not be inspected."
135
+ });
136
+ received = [];
137
+ }
138
+ for (const id of received) if (expected.has(id) === false) try {
139
+ errors.push({
140
+ path: `$input${_accessExpressionAsString(id)}`,
141
+ expected: "undefined",
142
+ value: map[id],
143
+ description: "The answer does not belong to any question."
144
+ });
145
+ } catch {
146
+ errors.push({
147
+ path: `$input${_accessExpressionAsString(id)}`,
148
+ expected: "readable evaluation answer",
149
+ value: void 0,
150
+ description: "The extra answer could not be inspected."
151
+ });
152
+ }
153
+ return errors.length === 0 ? {
154
+ success: true,
155
+ data: output
156
+ } : {
157
+ success: false,
158
+ data: answers,
159
+ errors
160
+ };
161
+ };
162
+ /** Contain exceptions from getters and proxies at the decision path. */
163
+ const inspect = (path, answer, errors, read) => {
164
+ try {
165
+ return read();
166
+ } catch {
167
+ errors.push({
168
+ path,
169
+ expected: "readable evaluation answer",
170
+ value: answer,
171
+ description: "The answer could not be inspected."
172
+ });
173
+ return null;
174
+ }
175
+ };
176
+ const booleanProbability = (answer, path, errors) => {
177
+ const record = object(answer);
178
+ const type = record?.type;
179
+ const probability = record === null ? void 0 : type === "boolean" ? record.probability : type === "noul" ? record.noul : void 0;
180
+ if (isProbability(probability)) return probability;
181
+ errors.push({
182
+ path,
183
+ expected: "{ type: \"boolean\"; probability: number } | { type: \"noul\"; noul: number }",
184
+ value: answer,
185
+ description: record === null ? "Missing boolean answer." : type !== "boolean" && type !== "noul" ? `Answer type must be "boolean" or "noul", but got ${label(type)}.` : "Boolean answer needs a probability in [0, 1]."
186
+ });
187
+ return null;
188
+ };
189
+ const choice = (leaf, answer, path, errors, precision) => {
190
+ const expected = `{ type: "choice"; choice: ${leaf.options.map((option) => JSON.stringify(option.value)).join(" | ")}; probabilities?: Record<string, number> }`;
191
+ const record = object(answer);
192
+ const type = record?.type;
193
+ const selected = type === "choice" ? record?.choice : void 0;
194
+ const option = record !== null && type === "choice" ? leaf.options.find((o) => o.value === selected) : void 0;
195
+ if (record === null || option === void 0) {
196
+ errors.push({
197
+ path,
198
+ expected,
199
+ value: answer,
200
+ description: record === null ? "Missing choice answer." : type !== "choice" ? `Answer type must be "choice", but got ${label(type)}.` : "Choice answer must select one of the declared options."
201
+ });
202
+ return null;
203
+ }
204
+ const probabilities = distribution(record.probabilities, leaf.options.map((o) => o.value), precision.probability);
205
+ if (probabilities === null) {
206
+ errors.push({
207
+ path,
208
+ expected,
209
+ value: answer,
210
+ description: "Choice probabilities must contain every declared option exactly once, use numbers in [0, 1], and sum to 1."
211
+ });
212
+ return null;
213
+ }
214
+ if (probabilities !== void 0) {
215
+ const selected = own(probabilities, option.value);
216
+ if (Object.values(probabilities).some((probability) => probability > selected + PROBABILITY_TOLERANCE)) {
217
+ errors.push({
218
+ path,
219
+ expected,
220
+ value: answer,
221
+ description: "Choice answer must select an option with maximum probability."
222
+ });
223
+ return null;
224
+ }
225
+ }
226
+ return accept(option, option.value, own(probabilities, option.value), path, answer, expected, errors) ? option.value : null;
227
+ };
228
+ const score = (leaf, answer, path, errors, precision) => {
229
+ const last = leaf.levels.length - 1;
230
+ const expected = `{ type: "score"; score: number; probabilities?: Record<string, number> }`;
231
+ const record = object(answer);
232
+ const type = record?.type;
233
+ const scored = type === "score" ? record?.score : void 0;
234
+ if (record === null || type !== "score" || typeof scored !== "number" || Number.isFinite(scored) === false || scored < 0 || scored > last) {
235
+ errors.push({
236
+ path,
237
+ expected,
238
+ value: answer,
239
+ description: record === null ? "Missing score answer." : type !== "score" ? `Answer type must be "score", but got ${label(type)}.` : `Score answer needs a score in [0, ${last}].`
240
+ });
241
+ return null;
242
+ }
243
+ const probabilities = distribution(record.probabilities, leaf.levels.map((_, i) => String(i)), precision.probability);
244
+ if (probabilities === null) {
245
+ errors.push({
246
+ path,
247
+ expected,
248
+ value: answer,
249
+ description: "Score probabilities must contain every level index exactly once, use numbers in [0, 1], and sum to 1."
250
+ });
251
+ return null;
252
+ }
253
+ if (probabilities !== void 0) {
254
+ const mean = leaf.levels.reduce((total, _, index) => total + index * own(probabilities, String(index)), 0);
255
+ const meanRoundingError = leaf.levels.reduce((total, _, index) => total + index * precision.probability, 0);
256
+ if (Math.abs(mean - scored) > PROBABILITY_TOLERANCE + meanRoundingError + precision.score) {
257
+ errors.push({
258
+ path,
259
+ expected,
260
+ value: answer,
261
+ description: "Score must equal the probability-weighted mean of its distribution."
262
+ });
263
+ return null;
264
+ }
265
+ }
266
+ let index = Math.round(scored);
267
+ if (probabilities !== void 0 && Object.keys(probabilities).length !== 0) {
268
+ index = -1;
269
+ leaf.levels.forEach((_, i) => {
270
+ const p = own(probabilities, String(i));
271
+ if (p !== void 0 && (index === -1 || p > own(probabilities, String(index)))) index = i;
272
+ });
273
+ }
274
+ const level = leaf.levels[index];
275
+ return accept(level, level.value, own(probabilities, String(index)), path, answer, expected, errors) ? level.value : null;
276
+ };
277
+ /** Enforces the acceptance minimum of the selected member, if any. */
278
+ const accept = (member, value, probability, path, answer, expected, errors) => {
279
+ if (member.minimum === void 0) return true;
280
+ if (probability === void 0) {
281
+ errors.push({
282
+ path,
283
+ expected,
284
+ value: answer,
285
+ description: `${JSON.stringify(value)} requires probability >= ${member.minimum}, but the answer has no probability for it.`
286
+ });
287
+ return false;
288
+ }
289
+ if (probability < member.minimum) {
290
+ errors.push({
291
+ path,
292
+ expected,
293
+ value: answer,
294
+ description: `${JSON.stringify(value)} has probability ${probability} < ${member.minimum}.`
295
+ });
296
+ return false;
297
+ }
298
+ return true;
299
+ };
300
+ /**
301
+ * Reads optional `probabilities`: `undefined` when absent, `null` when
302
+ * malformed.
303
+ */
304
+ const distribution = (input, keys, roundingError) => {
305
+ if (input === void 0) return void 0;
306
+ const record = object(input);
307
+ if (record === null) return null;
308
+ if (Object.keys(record).length !== keys.length) return null;
309
+ const output = {};
310
+ for (const key of keys) {
311
+ if (Object.prototype.hasOwnProperty.call(record, key) === false) return null;
312
+ const probability = record[key];
313
+ if (isProbability(probability) === false) return null;
314
+ assign(output, key, probability);
315
+ }
316
+ if (Math.abs(Object.values(output).reduce((sum, probability) => sum + probability, 0) - 1) > PROBABILITY_TOLERANCE + keys.length * roundingError) return null;
317
+ return output;
318
+ };
319
+ /** AI SDK's absolute tolerance for probability sums and derived values. */
320
+ const PROBABILITY_TOLERANCE = 1e-6;
321
+ /** AI SDK's declared decimal-precision rule, without an AI SDK dependency. */
322
+ const readPrecision = (rounding) => {
323
+ if (rounding === void 0) return {
324
+ probability: 0,
325
+ score: 0
326
+ };
327
+ if (typeof rounding !== "object" || rounding === null || Array.isArray(rounding)) return null;
328
+ const record = rounding;
329
+ const decimalError = (value) => value === void 0 ? 0 : typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 15 ? .5 * 10 ** -value : null;
330
+ const probability = decimalError(record.probabilityDecimals);
331
+ const score = decimalError(record.scoreDecimals);
332
+ return probability === null || score === null ? null : {
333
+ probability,
334
+ score
335
+ };
336
+ };
337
+ /**
338
+ * Renders an untrusted answer `type` for a message; unlike `JSON.stringify`, it
339
+ * never throws on a bigint or circular value.
340
+ */
341
+ const label = (value) => typeof value === "string" ? JSON.stringify(value) : typeof value;
342
+ const accessor = (path) => "$input" + path.map(_accessExpressionAsString).join("");
343
+ /** Match AI SDK's JSON-record boundary, including null-prototype dictionaries. */
344
+ const object = (input) => {
345
+ if (typeof input !== "object" || input === null) return null;
346
+ try {
347
+ if (Array.isArray(input)) return null;
348
+ const prototype = Object.getPrototypeOf(input);
349
+ return prototype === Object.prototype || prototype === null ? input : null;
350
+ } catch {
351
+ return null;
352
+ }
353
+ };
354
+ /**
355
+ * Reads an own probability, so an option named like an `Object.prototype`
356
+ * member (`constructor`, `toString`, ...) never inherits a value.
357
+ */
358
+ const own = (probabilities, key) => probabilities !== void 0 && Object.prototype.hasOwnProperty.call(probabilities, key) ? probabilities[key] : void 0;
359
+ const isProbability = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
360
+ /** Writes the leaf value, creating the intermediate objects of its path. */
361
+ const place = (output, path, value) => {
362
+ let target = output;
363
+ path.slice(0, -1).forEach((name) => {
364
+ if (Object.prototype.hasOwnProperty.call(target, name) === false) assign(target, name, {});
365
+ target = target[name];
366
+ });
367
+ assign(target, path[path.length - 1], value);
368
+ };
369
+ /** Own-property assignment that cannot reach the prototype via `__proto__`. */
370
+ const assign = (target, name, value) => {
371
+ if (name === "__proto__") Object.defineProperty(target, name, {
372
+ value,
373
+ enumerable: true,
374
+ writable: true,
375
+ configurable: true
376
+ });
377
+ else target[name] = value;
378
+ };
379
+ //#endregion
380
+ export { _createLlmEvaluation };
381
+
382
+ //# sourceMappingURL=_createLlmEvaluation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_createLlmEvaluation.mjs","names":[],"sources":["../../src/internal/_createLlmEvaluation.ts"],"sourcesContent":["import { ILlmEvaluation, IValidation } from \"@typia/interface\";\n\nimport { _accessExpressionAsString } from \"./_accessExpressionAsString\";\n\n/**\n * Compile-time plan of `typia.llm.evaluation<T>()`, one entry per decision leaf\n * of `T`.\n *\n * @internal\n */\nexport type _ILlmEvaluationPlan =\n | _ILlmEvaluationPlan.IBoolean\n | _ILlmEvaluationPlan.IChoice\n | _ILlmEvaluationPlan.IScore\n | _ILlmEvaluationPlan.ISet;\n\n/** @internal */\nexport namespace _ILlmEvaluationPlan {\n interface IBase {\n /** Property names from the root of `T` to the leaf. */\n path: string[];\n instructions: string;\n }\n export interface IBoolean extends IBase {\n kind: \"boolean\";\n threshold: number;\n }\n export interface IChoice extends IBase {\n kind: \"choice\";\n options: IMember<string>[];\n }\n export interface IScore extends IBase {\n kind: \"score\";\n /** Sorted in ascending value order; level `i` is `levels[i]`. */\n levels: IMember<number>[];\n }\n export interface ISet extends IBase {\n kind: \"set\";\n members: ISetMember[];\n }\n export interface IMember<Value extends string | number> {\n value: Value;\n description?: string;\n /** Acceptance minimum of the member, when it has one. */\n minimum?: number;\n }\n export interface ISetMember {\n value: string;\n description?: string;\n threshold: number;\n }\n}\n\n/**\n * Creates the `ILlmEvaluation` of `typia.llm.evaluation<T>()` from its plan.\n *\n * Both the question map and the decoder derive their keys from here, so the\n * readable path encoding has a single owner.\n *\n * @internal\n */\nexport const _createLlmEvaluation = <T>(\n plan: _ILlmEvaluationPlan[],\n): ILlmEvaluation<T> => {\n const questions: Record<string, ILlmEvaluation.IQuestion> = {};\n for (const leaf of plan) {\n if (leaf.kind === \"set\")\n for (const member of leaf.members)\n assign(questions, key([...leaf.path, member.value]), {\n type: \"boolean\",\n instructions: setInstructions(leaf, member),\n });\n else assign(questions, key(leaf.path), question(leaf));\n }\n return {\n questions,\n decode: (\n answers: unknown,\n rounding?: ILlmEvaluation.IRounding,\n ): IValidation<T> => decode(plan, answers, rounding),\n };\n};\n\n/* -----------------------------------------------------------\n QUESTIONS\n----------------------------------------------------------- */\n/**\n * Encodes a property path as a question key, like `refund.requested`.\n *\n * Every segment after the first uses typia's accessor notation, so the key is\n * the validation path without its `$input` root. The first segment is quoted\n * when it is not an identifier, and always when it is `__proto__`, so no key\n * can collide with another or reach an object's prototype.\n */\nconst key = (path: string[]): string => {\n const head: string = path[0]!;\n const postfix: string = _accessExpressionAsString(head);\n const first: string =\n head === \"__proto__\"\n ? `[${JSON.stringify(head)}]`\n : postfix.startsWith(\".\")\n ? head\n : postfix;\n return first + path.slice(1).map(_accessExpressionAsString).join(\"\");\n};\n\nconst question = (\n leaf:\n | _ILlmEvaluationPlan.IBoolean\n | _ILlmEvaluationPlan.IChoice\n | _ILlmEvaluationPlan.IScore,\n): ILlmEvaluation.IQuestion => {\n if (leaf.kind === \"boolean\")\n return { type: \"boolean\", instructions: leaf.instructions };\n else if (leaf.kind === \"choice\") {\n const criteria: Record<string, string | null> = {};\n for (const option of leaf.options)\n assign(criteria, option.value, option.description ?? null);\n return { type: \"choice\", instructions: leaf.instructions, criteria };\n }\n return {\n type: \"score\",\n instructions: leaf.instructions,\n // the transform rejects fewer than two levels\n criteria: leaf.levels.map(\n (level) => level.description ?? String(level.value),\n ) as [string, string, ...string[]],\n };\n};\n\nconst setInstructions = (\n leaf: _ILlmEvaluationPlan.ISet,\n member: _ILlmEvaluationPlan.ISetMember,\n): string =>\n [\n leaf.instructions,\n \"\",\n `Does the option ${JSON.stringify(member.value)} apply?`,\n ...(member.description !== undefined ? [member.description] : []),\n ].join(\"\\n\");\n\n/* -----------------------------------------------------------\n VALIDATION\n----------------------------------------------------------- */\nconst decode = <T>(\n plan: _ILlmEvaluationPlan[],\n answers: unknown,\n rounding?: ILlmEvaluation.IRounding,\n): IValidation<T> => {\n const precision: IPrecision | null = (() => {\n try {\n return readPrecision(rounding);\n } catch {\n // A trapping rounding object is an invalid declaration.\n return null;\n }\n })();\n if (precision === null)\n return {\n success: false,\n data: answers,\n errors: [\n {\n path: \"$input\",\n expected: \"rounding decimals in [0, 15]\",\n value: rounding,\n description:\n \"Evaluation rounding decimals must be integers between 0 and 15.\",\n },\n ],\n };\n const map: Record<string, unknown> | null = object(answers);\n if (map === null)\n return {\n success: false,\n data: answers,\n errors: [\n {\n path: \"$input\",\n expected: \"Record<string, ILlmEvaluation answer>\",\n value: answers,\n },\n ],\n };\n\n const errors: IValidation.IError[] = [];\n const expected: Set<string> = new Set();\n const output: Record<string, unknown> = {};\n const read = (id: string): unknown => {\n expected.add(id);\n try {\n return Object.prototype.hasOwnProperty.call(map, id)\n ? map[id]\n : undefined;\n } catch {\n // The decision reader reports the inaccessible answer on its own path.\n return undefined;\n }\n };\n\n for (const leaf of plan) {\n const path: string = accessor(leaf.path);\n if (leaf.kind === \"set\") {\n const values: string[] = [];\n for (const member of leaf.members) {\n const memberPath: string = [\n path,\n _accessExpressionAsString(member.value),\n ].join(\"\");\n const answer: unknown = read(key([...leaf.path, member.value]));\n const probability: number | null = inspect(\n memberPath,\n answer,\n errors,\n () => booleanProbability(answer, memberPath, errors),\n );\n if (probability !== null && probability >= member.threshold)\n values.push(member.value);\n }\n place(output, leaf.path, values);\n continue;\n }\n const answer: unknown = read(key(leaf.path));\n if (leaf.kind === \"boolean\") {\n const probability: number | null = inspect(path, answer, errors, () =>\n booleanProbability(answer, path, errors),\n );\n if (probability !== null)\n place(output, leaf.path, probability >= leaf.threshold);\n } else if (leaf.kind === \"choice\") {\n const value: string | null = inspect(path, answer, errors, () =>\n choice(leaf, answer, path, errors, precision),\n );\n if (value !== null) place(output, leaf.path, value);\n } else {\n const value: number | null = inspect(path, answer, errors, () =>\n score(leaf, answer, path, errors, precision),\n );\n if (value !== null) place(output, leaf.path, value);\n }\n }\n let received: string[];\n try {\n received = Object.keys(map);\n } catch {\n errors.push({\n path: \"$input\",\n expected: \"readable evaluation answer map\",\n value: answers,\n description: \"Evaluation answer keys could not be inspected.\",\n });\n received = [];\n }\n for (const id of received)\n if (expected.has(id) === false)\n try {\n errors.push({\n path: `$input${_accessExpressionAsString(id)}`,\n expected: \"undefined\",\n value: map[id],\n description: \"The answer does not belong to any question.\",\n });\n } catch {\n errors.push({\n path: `$input${_accessExpressionAsString(id)}`,\n expected: \"readable evaluation answer\",\n value: undefined,\n description: \"The extra answer could not be inspected.\",\n });\n }\n return errors.length === 0\n ? { success: true, data: output as T }\n : { success: false, data: answers, errors };\n};\n\n/** Contain exceptions from getters and proxies at the decision path. */\nconst inspect = <T>(\n path: string,\n answer: unknown,\n errors: IValidation.IError[],\n read: () => T,\n): T | null => {\n try {\n return read();\n } catch {\n errors.push({\n path,\n expected: \"readable evaluation answer\",\n value: answer,\n description: \"The answer could not be inspected.\",\n });\n return null;\n }\n};\n\nconst booleanProbability = (\n answer: unknown,\n path: string,\n errors: IValidation.IError[],\n): number | null => {\n const record: Record<string, unknown> | null = object(answer);\n const type: unknown = record?.type;\n const probability: unknown =\n record === null\n ? undefined\n : type === \"boolean\"\n ? record.probability\n : type === \"noul\"\n ? record.noul\n : undefined;\n if (isProbability(probability)) return probability;\n errors.push({\n path,\n expected:\n '{ type: \"boolean\"; probability: number } | { type: \"noul\"; noul: number }',\n value: answer,\n description:\n record === null\n ? \"Missing boolean answer.\"\n : type !== \"boolean\" && type !== \"noul\"\n ? `Answer type must be \"boolean\" or \"noul\", but got ${label(type)}.`\n : \"Boolean answer needs a probability in [0, 1].\",\n });\n return null;\n};\n\nconst choice = (\n leaf: _ILlmEvaluationPlan.IChoice,\n answer: unknown,\n path: string,\n errors: IValidation.IError[],\n precision: IPrecision,\n): string | null => {\n const expected: string = `{ type: \"choice\"; choice: ${leaf.options\n .map((option) => JSON.stringify(option.value))\n .join(\" | \")}; probabilities?: Record<string, number> }`;\n const record: Record<string, unknown> | null = object(answer);\n const type: unknown = record?.type;\n const selected: unknown = type === \"choice\" ? record?.choice : undefined;\n const option: _ILlmEvaluationPlan.IMember<string> | undefined =\n record !== null && type === \"choice\"\n ? leaf.options.find((o) => o.value === selected)\n : undefined;\n if (record === null || option === undefined) {\n errors.push({\n path,\n expected,\n value: answer,\n description:\n record === null\n ? \"Missing choice answer.\"\n : type !== \"choice\"\n ? `Answer type must be \"choice\", but got ${label(type)}.`\n : \"Choice answer must select one of the declared options.\",\n });\n return null;\n }\n const probabilities: Record<string, number> | null | undefined = distribution(\n record.probabilities,\n leaf.options.map((o) => o.value),\n precision.probability,\n );\n if (probabilities === null) {\n errors.push({\n path,\n expected,\n value: answer,\n description:\n \"Choice probabilities must contain every declared option exactly once, use numbers in [0, 1], and sum to 1.\",\n });\n return null;\n }\n if (probabilities !== undefined) {\n const selected: number = own(probabilities, option.value)!;\n if (\n Object.values(probabilities).some(\n (probability) => probability > selected + PROBABILITY_TOLERANCE,\n )\n ) {\n errors.push({\n path,\n expected,\n value: answer,\n description:\n \"Choice answer must select an option with maximum probability.\",\n });\n return null;\n }\n }\n return accept(\n option,\n option.value,\n own(probabilities, option.value),\n path,\n answer,\n expected,\n errors,\n )\n ? option.value\n : null;\n};\n\nconst score = (\n leaf: _ILlmEvaluationPlan.IScore,\n answer: unknown,\n path: string,\n errors: IValidation.IError[],\n precision: IPrecision,\n): number | null => {\n const last: number = leaf.levels.length - 1;\n const expected: string = `{ type: \"score\"; score: number; probabilities?: Record<string, number> }`;\n const record: Record<string, unknown> | null = object(answer);\n const type: unknown = record?.type;\n const scored: unknown = type === \"score\" ? record?.score : undefined;\n if (\n record === null ||\n type !== \"score\" ||\n typeof scored !== \"number\" ||\n Number.isFinite(scored) === false ||\n scored < 0 ||\n scored > last\n ) {\n errors.push({\n path,\n expected,\n value: answer,\n description:\n record === null\n ? \"Missing score answer.\"\n : type !== \"score\"\n ? `Answer type must be \"score\", but got ${label(type)}.`\n : `Score answer needs a score in [0, ${last}].`,\n });\n return null;\n }\n const probabilities: Record<string, number> | null | undefined = distribution(\n record.probabilities,\n leaf.levels.map((_, i) => String(i)),\n precision.probability,\n );\n if (probabilities === null) {\n errors.push({\n path,\n expected,\n value: answer,\n description:\n \"Score probabilities must contain every level index exactly once, use numbers in [0, 1], and sum to 1.\",\n });\n return null;\n }\n if (probabilities !== undefined) {\n const mean: number = leaf.levels.reduce(\n (total, _, index) => total + index * own(probabilities, String(index))!,\n 0,\n );\n const meanRoundingError: number = leaf.levels.reduce(\n (total, _, index) => total + index * precision.probability,\n 0,\n );\n if (\n Math.abs(mean - scored) >\n PROBABILITY_TOLERANCE + meanRoundingError + precision.score\n ) {\n errors.push({\n path,\n expected,\n value: answer,\n description:\n \"Score must equal the probability-weighted mean of its distribution.\",\n });\n return null;\n }\n }\n\n // the most probable level when a distribution exists, where a tie resolves\n // to the lower level; otherwise the level nearest to the fractional score,\n // where a half rounds up\n let index: number = Math.round(scored);\n if (probabilities !== undefined && Object.keys(probabilities).length !== 0) {\n index = -1;\n leaf.levels.forEach((_, i) => {\n const p: number | undefined = own(probabilities, String(i));\n if (\n p !== undefined &&\n (index === -1 || p > own(probabilities, String(index))!)\n )\n index = i;\n });\n }\n const level: _ILlmEvaluationPlan.IMember<number> = leaf.levels[index]!;\n return accept(\n level,\n level.value,\n own(probabilities, String(index)),\n path,\n answer,\n expected,\n errors,\n )\n ? level.value\n : null;\n};\n\n/** Enforces the acceptance minimum of the selected member, if any. */\nconst accept = (\n member: { minimum?: number },\n value: string | number,\n probability: number | undefined,\n path: string,\n answer: unknown,\n expected: string,\n errors: IValidation.IError[],\n): boolean => {\n if (member.minimum === undefined) return true;\n if (probability === undefined) {\n errors.push({\n path,\n expected,\n value: answer,\n description: `${JSON.stringify(value)} requires probability >= ${member.minimum}, but the answer has no probability for it.`,\n });\n return false;\n }\n if (probability < member.minimum) {\n errors.push({\n path,\n expected,\n value: answer,\n description: `${JSON.stringify(value)} has probability ${probability} < ${member.minimum}.`,\n });\n return false;\n }\n return true;\n};\n\n/**\n * Reads optional `probabilities`: `undefined` when absent, `null` when\n * malformed.\n */\nconst distribution = (\n input: unknown,\n keys: string[],\n roundingError: number,\n): Record<string, number> | null | undefined => {\n if (input === undefined) return undefined;\n const record: Record<string, unknown> | null = object(input);\n if (record === null) return null;\n if (Object.keys(record).length !== keys.length) return null;\n const output: Record<string, number> = {};\n for (const key of keys) {\n if (Object.prototype.hasOwnProperty.call(record, key) === false)\n return null;\n const probability: unknown = record[key];\n if (isProbability(probability) === false) return null;\n assign(output, key, probability);\n }\n if (\n Math.abs(\n Object.values(output).reduce((sum, probability) => sum + probability, 0) -\n 1,\n ) >\n PROBABILITY_TOLERANCE + keys.length * roundingError\n )\n return null;\n return output;\n};\n\n/** AI SDK's absolute tolerance for probability sums and derived values. */\nconst PROBABILITY_TOLERANCE = 1e-6;\n\ninterface IPrecision {\n probability: number;\n score: number;\n}\n\n/** AI SDK's declared decimal-precision rule, without an AI SDK dependency. */\nconst readPrecision = (\n rounding: ILlmEvaluation.IRounding | undefined,\n): IPrecision | null => {\n if (rounding === undefined) return { probability: 0, score: 0 };\n if (\n typeof rounding !== \"object\" ||\n rounding === null ||\n Array.isArray(rounding)\n )\n return null;\n const record: Record<string, unknown> = rounding as Record<string, unknown>;\n const decimalError = (value: unknown): number | null =>\n value === undefined\n ? 0\n : typeof value === \"number\" &&\n Number.isInteger(value) &&\n value >= 0 &&\n value <= 15\n ? 0.5 * 10 ** -value\n : null;\n const probability: number | null = decimalError(record.probabilityDecimals);\n const score: number | null = decimalError(record.scoreDecimals);\n return probability === null || score === null ? null : { probability, score };\n};\n\n/* -----------------------------------------------------------\n HELPERS\n----------------------------------------------------------- */\n/**\n * Renders an untrusted answer `type` for a message; unlike `JSON.stringify`, it\n * never throws on a bigint or circular value.\n */\nconst label = (value: unknown): string =>\n typeof value === \"string\" ? JSON.stringify(value) : typeof value;\n\nconst accessor = (path: string[]): string =>\n \"$input\" + path.map(_accessExpressionAsString).join(\"\");\n\n/** Match AI SDK's JSON-record boundary, including null-prototype dictionaries. */\nconst object = (input: unknown): Record<string, unknown> | null => {\n if (typeof input !== \"object\" || input === null) return null;\n try {\n if (Array.isArray(input)) return null;\n const prototype: object | null = Object.getPrototypeOf(input);\n return prototype === Object.prototype || prototype === null\n ? (input as Record<string, unknown>)\n : null;\n } catch {\n // A revoked or trapping proxy is not a usable answer record.\n return null;\n }\n};\n\n/**\n * Reads an own probability, so an option named like an `Object.prototype`\n * member (`constructor`, `toString`, ...) never inherits a value.\n */\nconst own = (\n probabilities: Record<string, number> | undefined,\n key: string,\n): number | undefined =>\n probabilities !== undefined &&\n Object.prototype.hasOwnProperty.call(probabilities, key)\n ? probabilities[key]\n : undefined;\n\nconst isProbability = (value: unknown): value is number =>\n typeof value === \"number\" &&\n Number.isFinite(value) &&\n value >= 0 &&\n value <= 1;\n\n/** Writes the leaf value, creating the intermediate objects of its path. */\nconst place = (\n output: Record<string, unknown>,\n path: string[],\n value: unknown,\n): void => {\n let target: Record<string, unknown> = output;\n path.slice(0, -1).forEach((name) => {\n if (Object.prototype.hasOwnProperty.call(target, name) === false)\n assign(target, name, {});\n target = target[name] as Record<string, unknown>;\n });\n assign(target, path[path.length - 1]!, value);\n};\n\n/** Own-property assignment that cannot reach the prototype via `__proto__`. */\nconst assign = (\n target: Record<string, unknown>,\n name: string,\n value: unknown,\n): void => {\n if (name === \"__proto__\")\n Object.defineProperty(target, name, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n else target[name] = value;\n};\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const _stringLengthGte: (value: string, length: number) => boolean;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports._stringLengthGte = void 0;
4
+ const _stringLengthGte = (value, length) => {
5
+ let count = 0;
6
+ if (length <= count)
7
+ return true;
8
+ for (const _ch of value)
9
+ if (length <= ++count)
10
+ return true;
11
+ return false;
12
+ };
13
+ exports._stringLengthGte = _stringLengthGte;
14
+ //# sourceMappingURL=_stringLengthGte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_stringLengthGte.js","sourceRoot":"","sources":["../../src/internal/_stringLengthGte.ts"],"names":[],"mappings":";;;AAAO,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAE,MAAc,EAAW,EAAE;IACzE,IAAI,KAAK,GAAW,CAAC,CAAC;IACtB,IAAI,MAAM,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,KAAK;QAAE,IAAI,MAAM,IAAI,EAAE,KAAK;YAAE,OAAO,IAAI,CAAC;IAC5D,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AALW,QAAA,gBAAgB,GAAhB,gBAAgB,CAK3B"}
@@ -0,0 +1,11 @@
1
+ //#region src/internal/_stringLengthGte.ts
2
+ const _stringLengthGte = (value, length) => {
3
+ let count = 0;
4
+ if (length <= count) return true;
5
+ for (const _ch of value) if (length <= ++count) return true;
6
+ return false;
7
+ };
8
+ //#endregion
9
+ export { _stringLengthGte };
10
+
11
+ //# sourceMappingURL=_stringLengthGte.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_stringLengthGte.mjs","names":[],"sources":["../../src/internal/_stringLengthGte.ts"],"sourcesContent":["export const _stringLengthGte = (value: string, length: number): boolean => {\n let count: number = 0;\n if (length <= count) return true;\n for (const _ch of value) if (length <= ++count) return true;\n return false;\n};\n"],"mappings":";AAAA,MAAa,oBAAoB,OAAe,WAA4B;CAC1E,IAAI,QAAgB;CACpB,IAAI,UAAU,OAAO,OAAO;CAC5B,KAAK,MAAM,OAAO,OAAO,IAAI,UAAU,EAAE,OAAO,OAAO;CACvD,OAAO;AACT"}
@@ -0,0 +1 @@
1
+ export declare const _stringLengthLte: (value: string, length: number) => boolean;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports._stringLengthLte = void 0;
4
+ const _stringLengthLte = (value, length) => {
5
+ let count = 0;
6
+ if (!(count <= length))
7
+ return false;
8
+ for (const _ch of value)
9
+ if (!(++count <= length))
10
+ return false;
11
+ return true;
12
+ };
13
+ exports._stringLengthLte = _stringLengthLte;
14
+ //# sourceMappingURL=_stringLengthLte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_stringLengthLte.js","sourceRoot":"","sources":["../../src/internal/_stringLengthLte.ts"],"names":[],"mappings":";;;AAAO,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAE,MAAc,EAAW,EAAE;IACzE,IAAI,KAAK,GAAW,CAAC,CAAC;IACtB,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,KAAK,MAAM,GAAG,IAAI,KAAK;QAAE,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;IAChE,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AALW,QAAA,gBAAgB,GAAhB,gBAAgB,CAK3B"}
@@ -0,0 +1,11 @@
1
+ //#region src/internal/_stringLengthLte.ts
2
+ const _stringLengthLte = (value, length) => {
3
+ let count = 0;
4
+ if (!(count <= length)) return false;
5
+ for (const _ch of value) if (!(++count <= length)) return false;
6
+ return true;
7
+ };
8
+ //#endregion
9
+ export { _stringLengthLte };
10
+
11
+ //# sourceMappingURL=_stringLengthLte.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_stringLengthLte.mjs","names":[],"sources":["../../src/internal/_stringLengthLte.ts"],"sourcesContent":["export const _stringLengthLte = (value: string, length: number): boolean => {\n let count: number = 0;\n if (!(count <= length)) return false;\n for (const _ch of value) if (!(++count <= length)) return false;\n return true;\n};\n"],"mappings":";AAAA,MAAa,oBAAoB,OAAe,WAA4B;CAC1E,IAAI,QAAgB;CACpB,IAAI,EAAE,SAAS,SAAS,OAAO;CAC/B,KAAK,MAAM,OAAO,OAAO,IAAI,EAAE,EAAE,SAAS,SAAS,OAAO;CAC1D,OAAO;AACT"}
package/lib/llm.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IJsonParseResult, ILlmApplication, ILlmController, ILlmSchema, ILlmStructuredOutput } from "@typia/interface";
1
+ import { IJsonParseResult, ILlmApplication, ILlmController, ILlmEvaluation, ILlmSchema, ILlmStructuredOutput } from "@typia/interface";
2
2
  /**
3
3
  * Creates LLM function calling controller.
4
4
  *
@@ -141,6 +141,59 @@ export declare function structuredOutput<T extends Record<string, any>, Config e
141
141
  */
142
142
  equals: boolean;
143
143
  }> = {}>(): ILlmStructuredOutput<T>;
144
+ /**
145
+ * Creates LLM evaluation questions.
146
+ *
147
+ * @danger You must configure the generic argument `T`
148
+ */
149
+ export declare function evaluation(): never;
150
+ /**
151
+ * Creates LLM evaluation questions from TypeScript object type.
152
+ *
153
+ * Generates {@link ILlmEvaluation} for evaluation models, which answer typed
154
+ * questions about a shared state with probabilities instead of generating text:
155
+ * TypeSafe's Jev natively, and OpenAI, Anthropic, and Google through Vercel AI
156
+ * SDK's `experimental_evaluate()`.
157
+ *
158
+ * Every leaf property of `T` becomes one question, and its JSDoc description
159
+ * becomes the question text:
160
+ *
161
+ * - `boolean` → boolean question
162
+ * - String enum or string literal union → choice question
163
+ * - Numeric enum or numeric literal union → score question
164
+ * - Array of a string literal union or string enum → one boolean question per
165
+ * member
166
+ * - Nested object → flattened, one question per leaf
167
+ *
168
+ * Types an evaluation model cannot answer, such as `string`, `number`, optional
169
+ * properties, or a leaf without a JSDoc description, are compile errors. Use
170
+ * `tags.Probability<N>` or `@probability N` to set decision thresholds and
171
+ * acceptance minimums. Once one choice, score, or set member declares a
172
+ * requirement, every member must declare one or inherit the property's
173
+ * `@probability` default. A nested object's own JSDoc description is not sent
174
+ * to the model; only the leaves' descriptions become question text. Other
175
+ * validation refinements that the answer decoder cannot enforce are compile
176
+ * errors.
177
+ *
178
+ * This feature is experimental. It follows Vercel AI SDK's evaluation model
179
+ * specification, which is itself experimental and may change in patch
180
+ * releases.
181
+ *
182
+ * Workflow:
183
+ *
184
+ * 1. Pass {@link ILlmEvaluation.questions} to the evaluation model
185
+ * 2. Receive the answer map keyed by the same question IDs
186
+ * 3. Use {@link ILlmEvaluation.decode} to fold the answers back into `T`; pass the
187
+ * model's declared rounding precision when available
188
+ *
189
+ * Related functions:
190
+ *
191
+ * - {@link structuredOutput} — Structured output generated as text by an LLM
192
+ *
193
+ * @template T Target decision type (object with static properties)
194
+ * @returns LLM evaluation questions with a checked answer decoder
195
+ */
196
+ export declare function evaluation<T extends Record<string, any>>(): ILlmEvaluation<T>;
144
197
  /**
145
198
  * Creates LLM parameters schema.
146
199
  *
package/lib/llm.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.controller = controller;
4
4
  exports.application = application;
5
5
  exports.structuredOutput = structuredOutput;
6
+ exports.evaluation = evaluation;
6
7
  exports.parameters = parameters;
7
8
  exports.schema = schema;
8
9
  exports.parse = parse;
@@ -23,6 +24,10 @@ function structuredOutput() {
23
24
  (0, NoTransformConfigurationError_1.NoTransformConfigurationError)("llm.structuredOutput");
24
25
  }
25
26
  /** @internal */
27
+ function evaluation() {
28
+ (0, NoTransformConfigurationError_1.NoTransformConfigurationError)("llm.evaluation");
29
+ }
30
+ /** @internal */
26
31
  function parameters() {
27
32
  (0, NoTransformConfigurationError_1.NoTransformConfigurationError)("llm.parameters");
28
33
  }
package/lib/llm.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":";;;;;;;;;;;AAQA,gGAA6F;AAmE7F,gBAAgB;AAChB,oBAA2B,GAAG,KAAY;IACxC,IAAA,6DAA6B,EAAC,gBAAgB,CAAC,CAAC;AAClD,CAAC;AA0DD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,iBAAiB,CAAC,CAAC;AACnD,CAAC;AA2DD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,sBAAsB,CAAC,CAAC;AACxD,CAAC;AAuCD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,gBAAgB,CAAC,CAAC;AAClD,CAAC;AAsCD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,YAAY,CAAC,CAAC;AAC9C,CAAC;AAoDD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,WAAW,CAAC,CAAC;AAC7C,CAAC;AAuCD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,YAAY,CAAC,CAAC;AAC9C,CAAC;AAiDD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,iBAAiB,CAAC,CAAC;AACnD,CAAC;AA2CD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,kBAAkB,CAAC,CAAC;AACpD,CAAC"}
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":";;;;;;;;;;;;AASA,gGAA6F;AAmE7F,gBAAgB;AAChB,oBAA2B,GAAG,KAAY;IACxC,IAAA,6DAA6B,EAAC,gBAAgB,CAAC,CAAC;AAClD,CAAC;AA0DD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,iBAAiB,CAAC,CAAC;AACnD,CAAC;AA2DD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,sBAAsB,CAAC,CAAC;AACxD,CAAC;AA4DD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,gBAAgB,CAAC,CAAC;AAClD,CAAC;AAuCD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,gBAAgB,CAAC,CAAC;AAClD,CAAC;AAsCD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,YAAY,CAAC,CAAC;AAC9C,CAAC;AAoDD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,WAAW,CAAC,CAAC;AAC7C,CAAC;AAuCD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,YAAY,CAAC,CAAC;AAC9C,CAAC;AAiDD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,iBAAiB,CAAC,CAAC;AACnD,CAAC;AA2CD,gBAAgB;AAChB;IACE,IAAA,6DAA6B,EAAC,kBAAkB,CAAC,CAAC;AACpD,CAAC"}
package/lib/llm.mjs CHANGED
@@ -7,6 +7,7 @@ var llm_exports = /* @__PURE__ */ __exportAll({
7
7
  controller: () => controller,
8
8
  createCoerce: () => createCoerce,
9
9
  createParse: () => createParse,
10
+ evaluation: () => evaluation,
10
11
  parameters: () => parameters,
11
12
  parse: () => parse,
12
13
  schema: () => schema,
@@ -25,6 +26,10 @@ function structuredOutput() {
25
26
  NoTransformConfigurationError("llm.structuredOutput");
26
27
  }
27
28
  /** @internal */
29
+ function evaluation() {
30
+ NoTransformConfigurationError("llm.evaluation");
31
+ }
32
+ /** @internal */
28
33
  function parameters() {
29
34
  NoTransformConfigurationError("llm.parameters");
30
35
  }
@@ -49,6 +54,6 @@ function createCoerce() {
49
54
  NoTransformConfigurationError("llm.createCoerce");
50
55
  }
51
56
  //#endregion
52
- export { application, coerce, controller, createCoerce, createParse, llm_exports, parameters, parse, schema, structuredOutput };
57
+ export { application, coerce, controller, createCoerce, createParse, evaluation, llm_exports, parameters, parse, schema, structuredOutput };
53
58
 
54
59
  //# sourceMappingURL=llm.mjs.map