@tstdl/base 0.92.13 → 0.92.15
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/ai/ai-session.d.ts +12 -3
- package/ai/ai-session.js +32 -6
- package/ai/ai.service.d.ts +24 -19
- package/ai/ai.service.js +70 -55
- package/ai/types.d.ts +2 -2
- package/package.json +1 -1
package/ai/ai-session.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import type { SchemaTestable } from '../schema/index.js';
|
|
2
|
+
import type { Enumeration, OneOrMany, TypedOmit } from '../types.js';
|
|
3
|
+
import type { AiService, AnalyzeContentResult, ClassificationResult, SpecializedGenerationResult } from './ai.service.js';
|
|
4
|
+
import type { Content, ContentPart, GenerationOptions, GenerationRequest, GenerationResult, SchemaFunctionDeclarations, SchemaFunctionDeclarationsResult } from './types.js';
|
|
4
5
|
export declare class AiSession {
|
|
5
6
|
#private;
|
|
6
7
|
readonly contents: Content[];
|
|
7
8
|
constructor(aiService: AiService);
|
|
9
|
+
addContent(content: OneOrMany<Content>): void;
|
|
10
|
+
analyzeContent<T extends Enumeration>(parts: OneOrMany<ContentPart>, types: T, options?: GenerationOptions & {
|
|
11
|
+
targetLanguage?: string;
|
|
12
|
+
maximumNumberOfTags?: number;
|
|
13
|
+
}): Promise<SpecializedGenerationResult<AnalyzeContentResult<T>>>;
|
|
14
|
+
classify<T extends Enumeration>(parts: OneOrMany<ContentPart>, types: T, options?: GenerationOptions & Pick<GenerationRequest, 'model'>): Promise<SpecializedGenerationResult<ClassificationResult<T>>>;
|
|
15
|
+
extractData<T>(parts: OneOrMany<ContentPart>, schema: SchemaTestable<T>, options?: GenerationOptions & Pick<GenerationRequest, 'model'>): Promise<SpecializedGenerationResult<T>>;
|
|
16
|
+
callFunctions<const T extends SchemaFunctionDeclarations>(functions: T, content: Content | [Content, ...Content[]], options?: Pick<GenerationRequest, 'model' | 'systemInstruction'> & GenerationOptions): Promise<SpecializedGenerationResult<SchemaFunctionDeclarationsResult<T>[]>>;
|
|
8
17
|
generate(content: Content | [Content, ...Content[]], request?: TypedOmit<GenerationRequest, 'contents'>): Promise<GenerationResult>;
|
|
9
18
|
}
|
package/ai/ai-session.js
CHANGED
|
@@ -5,13 +5,39 @@ export class AiSession {
|
|
|
5
5
|
constructor(aiService) {
|
|
6
6
|
this.#aiService = aiService;
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
});
|
|
8
|
+
addContent(content) {
|
|
9
|
+
this.contents.push(...toArray(content));
|
|
10
|
+
}
|
|
11
|
+
async analyzeContent(parts, types, options) {
|
|
12
|
+
const newContents = this.#aiService.getAnalyzeContentConents(parts);
|
|
14
13
|
this.contents.push(...newContents);
|
|
14
|
+
const result = await this.#aiService.analyzeContent(parts, types, options);
|
|
15
|
+
this.contents.push(result.raw.content);
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
async classify(parts, types, options) {
|
|
19
|
+
const newContents = this.#aiService.getExtractDataConents(parts);
|
|
20
|
+
this.contents.push(...newContents);
|
|
21
|
+
const result = await this.#aiService.classify(parts, types, options);
|
|
22
|
+
this.contents.push(result.raw.content);
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
async extractData(parts, schema, options) {
|
|
26
|
+
const newContents = this.#aiService.getExtractDataConents(parts);
|
|
27
|
+
this.contents.push(...newContents);
|
|
28
|
+
const result = await this.#aiService.extractData(parts, schema, options);
|
|
29
|
+
this.contents.push(result.raw.content);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
async callFunctions(functions, content, options) {
|
|
33
|
+
this.contents.push(...toArray(content));
|
|
34
|
+
const result = await this.#aiService.callFunctions(functions, this.contents, options);
|
|
35
|
+
this.contents.push(result.raw.content);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
async generate(content, request) {
|
|
39
|
+
this.contents.push(...toArray(content));
|
|
40
|
+
const result = await this.#aiService.generate({ ...request, contents: this.contents });
|
|
15
41
|
this.contents.push(result.content);
|
|
16
42
|
return result;
|
|
17
43
|
}
|
package/ai/ai.service.d.ts
CHANGED
|
@@ -3,39 +3,44 @@ import { Resolvable, type resolveArgumentType } from '../injector/interfaces.js'
|
|
|
3
3
|
import { OneOrMany, SchemaTestable } from '../schema/index.js';
|
|
4
4
|
import { Enumeration as EnumerationType, EnumerationValue } from '../types.js';
|
|
5
5
|
import { AiSession } from './ai-session.js';
|
|
6
|
-
import { AiModel, Content, FileContentPart, FileInput, GenerationOptions, GenerationRequest, GenerationResult,
|
|
6
|
+
import { AiModel, Content, ContentPart, FileContentPart, FileInput, GenerationOptions, GenerationRequest, GenerationResult, SchemaFunctionDeclarations, SchemaFunctionDeclarationsResult } from './types.js';
|
|
7
7
|
export type SpecializedGenerationResult<T> = {
|
|
8
8
|
result: T;
|
|
9
|
-
|
|
9
|
+
raw: GenerationResult;
|
|
10
10
|
};
|
|
11
11
|
export type AiServiceOptions = {
|
|
12
12
|
apiKey: string;
|
|
13
13
|
defaultModel?: AiModel;
|
|
14
14
|
};
|
|
15
15
|
export type AiServiceArgument = AiServiceOptions;
|
|
16
|
+
export type ClassificationResult<T extends EnumerationType> = {
|
|
17
|
+
types: {
|
|
18
|
+
type: EnumerationValue<T>;
|
|
19
|
+
confidence: 'high' | 'medium' | 'low';
|
|
20
|
+
}[] | null;
|
|
21
|
+
};
|
|
22
|
+
export type AnalyzeContentResult<T extends EnumerationType> = {
|
|
23
|
+
content: string[];
|
|
24
|
+
documentTypes: ClassificationResult<T>[];
|
|
25
|
+
tags: string[];
|
|
26
|
+
};
|
|
16
27
|
export declare class AiService implements Resolvable<AiServiceArgument> {
|
|
17
28
|
#private;
|
|
18
29
|
readonly defaultModel: AiModel;
|
|
19
30
|
readonly [resolveArgumentType]: AiServiceArgument;
|
|
20
|
-
|
|
31
|
+
createSession(): AiSession;
|
|
21
32
|
processFile(fileInput: FileInput): Promise<FileContentPart>;
|
|
22
33
|
processFiles(fileInputs: FileInput[]): Promise<FileContentPart[]>;
|
|
23
|
-
classify<T extends EnumerationType>(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
type: EnumerationValue<T>;
|
|
34
|
-
confidence: 'high' | 'medium' | 'low';
|
|
35
|
-
}[];
|
|
36
|
-
tags: string[];
|
|
37
|
-
}>>;
|
|
38
|
-
callFunctions<const T extends SchemaFunctionDeclarations>(functions: T, contents: Content[], options?: Pick<GenerationRequest, 'model' | 'systemInstruction'> & GenerationOptions): Promise<SchemaFunctionDeclarationsResult<T>[]>;
|
|
34
|
+
classify<T extends EnumerationType>(parts: OneOrMany<ContentPart>, types: T, options?: GenerationOptions & Pick<GenerationRequest, 'model'>): Promise<SpecializedGenerationResult<ClassificationResult<T>>>;
|
|
35
|
+
getClassifyConents(parts: OneOrMany<ContentPart>): Content[];
|
|
36
|
+
extractData<T>(parts: OneOrMany<ContentPart>, schema: SchemaTestable<T>, options?: GenerationOptions & Pick<GenerationRequest, 'model'>): Promise<SpecializedGenerationResult<T>>;
|
|
37
|
+
getExtractDataConents(parts: OneOrMany<ContentPart>): Content[];
|
|
38
|
+
analyzeContent<T extends EnumerationType>(parts: OneOrMany<ContentPart>, types: T, options?: GenerationOptions & {
|
|
39
|
+
targetLanguage?: string;
|
|
40
|
+
maximumNumberOfTags?: number;
|
|
41
|
+
}): Promise<SpecializedGenerationResult<AnalyzeContentResult<T>>>;
|
|
42
|
+
getAnalyzeContentConents(parts: OneOrMany<ContentPart>): Content[];
|
|
43
|
+
callFunctions<const T extends SchemaFunctionDeclarations>(functions: T, contents: Content[], options?: Pick<GenerationRequest, 'model' | 'systemInstruction'> & GenerationOptions): Promise<SpecializedGenerationResult<SchemaFunctionDeclarationsResult<T>[]>>;
|
|
39
44
|
generate(request: GenerationRequest): Promise<GenerationResult>;
|
|
40
45
|
private convertContents;
|
|
41
46
|
private convertContent;
|
package/ai/ai.service.js
CHANGED
|
@@ -27,7 +27,7 @@ let AiService = class AiService {
|
|
|
27
27
|
#fileService = inject(AiFileService, this.#options);
|
|
28
28
|
#genAI = new GoogleGenerativeAI(this.#options.apiKey);
|
|
29
29
|
defaultModel = this.#options.defaultModel ?? 'gemini-2.0-flash-exp';
|
|
30
|
-
|
|
30
|
+
createSession() {
|
|
31
31
|
return new AiSession(this);
|
|
32
32
|
}
|
|
33
33
|
async processFile(fileInput) {
|
|
@@ -36,38 +36,42 @@ let AiService = class AiService {
|
|
|
36
36
|
async processFiles(fileInputs) {
|
|
37
37
|
return this.#fileService.processFiles(fileInputs);
|
|
38
38
|
}
|
|
39
|
-
async classify(
|
|
39
|
+
async classify(parts, types, options) {
|
|
40
40
|
const generationSchema = object({
|
|
41
41
|
types: nullable(array(object({
|
|
42
42
|
type: enumeration(types, { description: 'Type of document' }),
|
|
43
|
-
confidence: enumeration(['high', 'medium', 'low'], { description: 'How sure/certain you are about the classficiation
|
|
43
|
+
confidence: enumeration(['high', 'medium', 'low'], { description: 'How sure/certain you are about the classficiation' })
|
|
44
44
|
}), { description: 'One or more document types that matches' }))
|
|
45
45
|
});
|
|
46
|
-
const
|
|
47
|
-
model,
|
|
46
|
+
const generation = await this.generate({
|
|
47
|
+
model: options?.model,
|
|
48
48
|
generationOptions: {
|
|
49
49
|
maxOutputTokens: 1048,
|
|
50
|
-
temperature: 0.5
|
|
50
|
+
temperature: 0.5,
|
|
51
|
+
...options
|
|
51
52
|
},
|
|
52
53
|
generationSchema,
|
|
53
54
|
systemInstruction: 'You are a highly accurate document classification AI. Your task is to analyze the content of a given document and determine its type based on a predefined list of possible document types.',
|
|
54
|
-
contents:
|
|
55
|
-
role: 'user',
|
|
56
|
-
parts: [
|
|
57
|
-
...toArray(files),
|
|
58
|
-
{ text: 'Classify the document. Output as JSON using the provided schema\n\nIf none of the provided document types are a suitable match, return null for types.' }
|
|
59
|
-
]
|
|
60
|
-
}]
|
|
55
|
+
contents: this.getClassifyConents(parts)
|
|
61
56
|
});
|
|
62
57
|
return {
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
|
|
59
|
+
raw: generation
|
|
65
60
|
};
|
|
66
61
|
}
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
getClassifyConents(parts) {
|
|
63
|
+
return [{
|
|
64
|
+
role: 'user',
|
|
65
|
+
parts: [
|
|
66
|
+
...toArray(parts),
|
|
67
|
+
{ text: 'Classify the document. Output as JSON using the provided schema\n\nIf none of the provided document types are a suitable match, return null for types.' }
|
|
68
|
+
]
|
|
69
|
+
}];
|
|
70
|
+
}
|
|
71
|
+
async extractData(parts, schema, options) {
|
|
72
|
+
const generation = await this.generate({
|
|
73
|
+
model: options?.model,
|
|
69
74
|
generationOptions: {
|
|
70
|
-
maxOutputTokens: 8192,
|
|
71
75
|
temperature: 0.5,
|
|
72
76
|
...options
|
|
73
77
|
},
|
|
@@ -76,61 +80,62 @@ let AiService = class AiService {
|
|
|
76
80
|
|
|
77
81
|
**Instructions:**
|
|
78
82
|
Carefully read and analyze the provided document. Identify relevant information that corresponds to each field in the JSON schema. Focus on accuracy and avoid making assumptions. If a field has multiple possible values, extract all relevant ones into the correct array structures ONLY IF the schema defines that field as an array; otherwise, extract only the single most relevant value.`,
|
|
79
|
-
contents:
|
|
80
|
-
{
|
|
81
|
-
role: 'user',
|
|
82
|
-
parts: [
|
|
83
|
-
...toArray(files),
|
|
84
|
-
{ text: 'Classify the document. Output as JSON.' }
|
|
85
|
-
]
|
|
86
|
-
}
|
|
87
|
-
]
|
|
83
|
+
contents: this.getExtractDataConents(parts)
|
|
88
84
|
});
|
|
89
85
|
return {
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
|
|
87
|
+
raw: generation
|
|
92
88
|
};
|
|
93
89
|
}
|
|
94
|
-
|
|
90
|
+
getExtractDataConents(parts) {
|
|
91
|
+
return [{
|
|
92
|
+
role: 'user',
|
|
93
|
+
parts: [
|
|
94
|
+
...toArray(parts),
|
|
95
|
+
{ text: 'Extract the data as specified in the schema. Output as JSON.' }
|
|
96
|
+
]
|
|
97
|
+
}];
|
|
98
|
+
}
|
|
99
|
+
async analyzeContent(parts, types, options) {
|
|
95
100
|
const schema = object({
|
|
96
101
|
content: string({ description: 'Content of the document with important details only' }),
|
|
97
|
-
|
|
102
|
+
types: nullable(array(object({
|
|
98
103
|
type: enumeration(types, { description: 'Type of document' }),
|
|
99
104
|
confidence: enumeration(['high', 'medium', 'low'], { description: 'How sure/certain you are about the classficiation' })
|
|
100
|
-
}), { description: 'One or more document types that matches' }),
|
|
101
|
-
tags: array(string({ description: 'Tag which describes the content' }), { description: 'List of tags', maximum: 5 })
|
|
105
|
+
}), { description: 'One or more document types that matches' })),
|
|
106
|
+
tags: array(string({ description: 'Tag which describes the content' }), { description: 'List of tags', maximum: options?.maximumNumberOfTags ?? 5 })
|
|
102
107
|
});
|
|
103
|
-
const
|
|
108
|
+
const generation = await this.generate({
|
|
104
109
|
generationOptions: {
|
|
105
110
|
maxOutputTokens: 2048,
|
|
106
111
|
temperature: 0.5,
|
|
107
112
|
...options
|
|
108
113
|
},
|
|
109
114
|
generationSchema: schema,
|
|
110
|
-
systemInstruction: `You are a highly skilled data extraction AI, specializing in accurately identifying and extracting information from unstructured
|
|
115
|
+
systemInstruction: `You are a highly skilled data extraction AI, specializing in accurately identifying and extracting information from unstructured content and converting it into a structured JSON format. Your primary goal is to meticulously follow the provided JSON schema and populate it with data extracted from the given document.
|
|
111
116
|
|
|
112
117
|
**Instructions:**
|
|
113
|
-
Carefully read and analyze the provided
|
|
118
|
+
Carefully read and analyze the provided content.
|
|
114
119
|
Identify key points and relevant information that describes the content. Focus on a general overview without providing specific details.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
contents: [
|
|
120
|
-
{
|
|
121
|
-
role: 'user',
|
|
122
|
-
parts: [
|
|
123
|
-
file,
|
|
124
|
-
{ text: 'Classify the document. Output as JSON.' }
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
]
|
|
120
|
+
Classify the content based on the provided list of types.
|
|
121
|
+
Output up to ${options?.maximumNumberOfTags ?? 5} tags.
|
|
122
|
+
Always output the content and tags in ${options?.targetLanguage ?? 'the same language as the content'}.`,
|
|
123
|
+
contents: this.getAnalyzeContentConents(parts)
|
|
128
124
|
});
|
|
129
125
|
return {
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
|
|
127
|
+
raw: generation
|
|
132
128
|
};
|
|
133
129
|
}
|
|
130
|
+
getAnalyzeContentConents(parts) {
|
|
131
|
+
return [{
|
|
132
|
+
role: 'user',
|
|
133
|
+
parts: [
|
|
134
|
+
...toArray(parts),
|
|
135
|
+
{ text: 'Classify the document. Output as JSON.' }
|
|
136
|
+
]
|
|
137
|
+
}];
|
|
138
|
+
}
|
|
134
139
|
async callFunctions(functions, contents, options) {
|
|
135
140
|
const generation = await this.generate({
|
|
136
141
|
model: options?.model,
|
|
@@ -151,14 +156,24 @@ Always output the content and tags in Deutsch.`,
|
|
|
151
156
|
const handlerResult = isSchemaFunctionDeclarationWithHandler(fn) ? await fn.handler(parameters) : undefined;
|
|
152
157
|
result.push({ functionName: call.name, parameters: parameters, handlerResult: handlerResult });
|
|
153
158
|
}
|
|
154
|
-
return
|
|
159
|
+
return {
|
|
160
|
+
result,
|
|
161
|
+
raw: generation
|
|
162
|
+
};
|
|
155
163
|
}
|
|
156
164
|
async generate(request) {
|
|
157
165
|
const googleContent = this.convertContents(request.contents);
|
|
158
166
|
const googleFunctionDeclarations = isDefined(request.functions) ? this.convertFunctions(request.functions) : undefined;
|
|
159
|
-
const generationConfig =
|
|
160
|
-
|
|
161
|
-
: request.generationOptions
|
|
167
|
+
const generationConfig = {
|
|
168
|
+
maxOutputTokens: request.generationOptions?.maxOutputTokens,
|
|
169
|
+
temperature: request.generationOptions?.temperature,
|
|
170
|
+
topP: request.generationOptions?.topP,
|
|
171
|
+
topK: request.generationOptions?.topK,
|
|
172
|
+
responseMimeType: isDefined(request.generationSchema) ? 'application/json' : undefined,
|
|
173
|
+
responseSchema: isDefined(request.generationSchema) ? convertToOpenApiSchema(request.generationSchema) : undefined,
|
|
174
|
+
presencePenalty: request.generationOptions?.presencePenalty,
|
|
175
|
+
frequencyPenalty: request.generationOptions?.frequencyPenalty
|
|
176
|
+
};
|
|
162
177
|
const generation = await this.getModel(request.model ?? this.defaultModel).generateContent({
|
|
163
178
|
generationConfig,
|
|
164
179
|
systemInstruction: request.systemInstruction,
|
package/ai/types.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export type FunctionResultContentPart = {
|
|
|
46
46
|
export type ContentPart = TextContentPart | FileContentPart | FunctionCallContentPart | FunctionResultContentPart;
|
|
47
47
|
export type Content = {
|
|
48
48
|
role: ContentRole;
|
|
49
|
-
parts: ContentPart[];
|
|
49
|
+
parts: readonly ContentPart[];
|
|
50
50
|
};
|
|
51
51
|
export type FunctionCallingMode = 'auto' | 'force' | 'none';
|
|
52
52
|
export type AiModel = LiteralUnion<'gemini-2.0-flash-exp' | 'gemini-exp-1206' | 'gemini-2.0-flash-thinking-exp-1219', string>;
|
|
@@ -61,7 +61,7 @@ export type GenerationOptions = {
|
|
|
61
61
|
export type GenerationRequest = {
|
|
62
62
|
model?: AiModel;
|
|
63
63
|
systemInstruction?: string;
|
|
64
|
-
contents: Content[];
|
|
64
|
+
contents: readonly Content[];
|
|
65
65
|
functions?: SchemaFunctionDeclarations;
|
|
66
66
|
functionCallingMode?: FunctionCallingMode;
|
|
67
67
|
generationSchema?: SchemaTestable;
|