@tstdl/base 0.92.12 → 0.92.14
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 +68 -55
- package/ai/types.d.ts +2 -2
- package/ai/types.js +5 -1
- 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
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import '../polyfills.js';
|
|
8
|
-
import { GoogleGenerativeAI } from '@google/generative-ai';
|
|
8
|
+
import { FunctionCallingMode as GoogleFunctionCallingMode, GoogleGenerativeAI } from '@google/generative-ai';
|
|
9
9
|
import { NotSupportedError } from '../errors/not-supported.error.js';
|
|
10
10
|
import { Singleton } from '../injector/decorators.js';
|
|
11
11
|
import { inject, injectArgument } from '../injector/inject.js';
|
|
@@ -17,12 +17,17 @@ import { assertDefinedPass, assertNotNullPass, isDefined } from '../utils/type-g
|
|
|
17
17
|
import { AiFileService } from './ai-file.service.js';
|
|
18
18
|
import { AiSession } from './ai-session.js';
|
|
19
19
|
import { isSchemaFunctionDeclarationWithHandler } from './types.js';
|
|
20
|
+
const functionCallingModeMap = {
|
|
21
|
+
auto: GoogleFunctionCallingMode.AUTO,
|
|
22
|
+
force: GoogleFunctionCallingMode.ANY,
|
|
23
|
+
none: GoogleFunctionCallingMode.NONE
|
|
24
|
+
};
|
|
20
25
|
let AiService = class AiService {
|
|
21
26
|
#options = injectArgument(this);
|
|
22
27
|
#fileService = inject(AiFileService, this.#options);
|
|
23
28
|
#genAI = new GoogleGenerativeAI(this.#options.apiKey);
|
|
24
29
|
defaultModel = this.#options.defaultModel ?? 'gemini-2.0-flash-exp';
|
|
25
|
-
|
|
30
|
+
createSession() {
|
|
26
31
|
return new AiSession(this);
|
|
27
32
|
}
|
|
28
33
|
async processFile(fileInput) {
|
|
@@ -31,38 +36,42 @@ let AiService = class AiService {
|
|
|
31
36
|
async processFiles(fileInputs) {
|
|
32
37
|
return this.#fileService.processFiles(fileInputs);
|
|
33
38
|
}
|
|
34
|
-
async classify(
|
|
39
|
+
async classify(parts, types, options) {
|
|
35
40
|
const generationSchema = object({
|
|
36
41
|
types: nullable(array(object({
|
|
37
42
|
type: enumeration(types, { description: 'Type of document' }),
|
|
38
|
-
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' })
|
|
39
44
|
}), { description: 'One or more document types that matches' }))
|
|
40
45
|
});
|
|
41
|
-
const
|
|
42
|
-
model,
|
|
46
|
+
const generation = await this.generate({
|
|
47
|
+
model: options?.model,
|
|
43
48
|
generationOptions: {
|
|
44
49
|
maxOutputTokens: 1048,
|
|
45
|
-
temperature: 0.5
|
|
50
|
+
temperature: 0.5,
|
|
51
|
+
...options
|
|
46
52
|
},
|
|
47
53
|
generationSchema,
|
|
48
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.',
|
|
49
|
-
contents:
|
|
50
|
-
role: 'user',
|
|
51
|
-
parts: [
|
|
52
|
-
...toArray(files),
|
|
53
|
-
{ 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.' }
|
|
54
|
-
]
|
|
55
|
-
}]
|
|
55
|
+
contents: this.getClassifyConents(parts)
|
|
56
56
|
});
|
|
57
57
|
return {
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
|
|
59
|
+
raw: generation
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
|
|
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,
|
|
64
74
|
generationOptions: {
|
|
65
|
-
maxOutputTokens: 8192,
|
|
66
75
|
temperature: 0.5,
|
|
67
76
|
...options
|
|
68
77
|
},
|
|
@@ -71,61 +80,62 @@ let AiService = class AiService {
|
|
|
71
80
|
|
|
72
81
|
**Instructions:**
|
|
73
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.`,
|
|
74
|
-
contents:
|
|
75
|
-
{
|
|
76
|
-
role: 'user',
|
|
77
|
-
parts: [
|
|
78
|
-
...toArray(files),
|
|
79
|
-
{ text: 'Classify the document. Output as JSON.' }
|
|
80
|
-
]
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
+
contents: this.getExtractDataConents(parts)
|
|
83
84
|
});
|
|
84
85
|
return {
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
|
|
87
|
+
raw: generation
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
|
-
|
|
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) {
|
|
90
100
|
const schema = object({
|
|
91
101
|
content: string({ description: 'Content of the document with important details only' }),
|
|
92
|
-
|
|
102
|
+
types: nullable(array(object({
|
|
93
103
|
type: enumeration(types, { description: 'Type of document' }),
|
|
94
104
|
confidence: enumeration(['high', 'medium', 'low'], { description: 'How sure/certain you are about the classficiation' })
|
|
95
|
-
}), { description: 'One or more document types that matches' }),
|
|
96
|
-
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 })
|
|
97
107
|
});
|
|
98
|
-
const
|
|
108
|
+
const generation = await this.generate({
|
|
99
109
|
generationOptions: {
|
|
100
110
|
maxOutputTokens: 2048,
|
|
101
111
|
temperature: 0.5,
|
|
102
112
|
...options
|
|
103
113
|
},
|
|
104
114
|
generationSchema: schema,
|
|
105
|
-
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.
|
|
106
116
|
|
|
107
117
|
**Instructions:**
|
|
108
|
-
Carefully read and analyze the provided
|
|
118
|
+
Carefully read and analyze the provided content.
|
|
109
119
|
Identify key points and relevant information that describes the content. Focus on a general overview without providing specific details.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
contents: [
|
|
115
|
-
{
|
|
116
|
-
role: 'user',
|
|
117
|
-
parts: [
|
|
118
|
-
file,
|
|
119
|
-
{ text: 'Classify the document. Output as JSON.' }
|
|
120
|
-
]
|
|
121
|
-
}
|
|
122
|
-
]
|
|
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)
|
|
123
124
|
});
|
|
124
125
|
return {
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
|
|
127
|
+
raw: generation
|
|
127
128
|
};
|
|
128
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
|
+
}
|
|
129
139
|
async callFunctions(functions, contents, options) {
|
|
130
140
|
const generation = await this.generate({
|
|
131
141
|
model: options?.model,
|
|
@@ -146,7 +156,10 @@ Always output the content and tags in Deutsch.`,
|
|
|
146
156
|
const handlerResult = isSchemaFunctionDeclarationWithHandler(fn) ? await fn.handler(parameters) : undefined;
|
|
147
157
|
result.push({ functionName: call.name, parameters: parameters, handlerResult: handlerResult });
|
|
148
158
|
}
|
|
149
|
-
return
|
|
159
|
+
return {
|
|
160
|
+
result,
|
|
161
|
+
raw: generation
|
|
162
|
+
};
|
|
150
163
|
}
|
|
151
164
|
async generate(request) {
|
|
152
165
|
const googleContent = this.convertContents(request.contents);
|
|
@@ -159,7 +172,7 @@ Always output the content and tags in Deutsch.`,
|
|
|
159
172
|
systemInstruction: request.systemInstruction,
|
|
160
173
|
tools: isDefined(googleFunctionDeclarations) ? [{ functionDeclarations: googleFunctionDeclarations }] : undefined,
|
|
161
174
|
toolConfig: isDefined(request.functionCallingMode)
|
|
162
|
-
? { functionCallingConfig: { mode:
|
|
175
|
+
? { functionCallingConfig: { mode: functionCallingModeMap[request.functionCallingMode] } }
|
|
163
176
|
: undefined,
|
|
164
177
|
contents: googleContent
|
|
165
178
|
});
|
|
@@ -216,7 +229,7 @@ Always output the content and tags in Deutsch.`,
|
|
|
216
229
|
return { text: part.text };
|
|
217
230
|
}
|
|
218
231
|
if (isDefined(part.fileData)) {
|
|
219
|
-
const file = assertDefinedPass(this.#fileService.getFileByUri(part.fileData.fileUri),
|
|
232
|
+
const file = assertDefinedPass(this.#fileService.getFileByUri(part.fileData.fileUri), 'File not found.');
|
|
220
233
|
return { file: file.id };
|
|
221
234
|
}
|
|
222
235
|
;
|
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;
|
package/ai/types.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { hasOwnProperty } from '../utils/object/object.js';
|
|
2
|
+
import { isDefined } from '../utils/type-guards.js';
|
|
2
3
|
export function declareFunctions(declarations) {
|
|
3
4
|
return declarations;
|
|
4
5
|
}
|
|
5
6
|
export function declareFunction(description, parameters, handler) {
|
|
6
|
-
|
|
7
|
+
if (isDefined(handler)) {
|
|
8
|
+
return { description, parameters, handler };
|
|
9
|
+
}
|
|
10
|
+
return { description, parameters };
|
|
7
11
|
}
|
|
8
12
|
export function isSchemaFunctionDeclarationWithHandler(declaration) {
|
|
9
13
|
return hasOwnProperty(declaration, 'handler');
|