vectorgov 0.3.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/README.md +37 -29
- package/dist/index.d.mts +64 -85
- package/dist/index.d.ts +64 -85
- package/dist/index.js +68 -125
- package/dist/index.mjs +68 -124
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -145,6 +145,42 @@ const balanced = await vg.search('O que é ETP?', { mode: 'balanced' });
|
|
|
145
145
|
const precise = await vg.search('O que é ETP?', { mode: 'precise' });
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
+
> **Importante:** O modo de busca **não afeta** a quantidade de tokens enviados ao seu LLM. Todos os modos retornam o mesmo número de resultados (controlado por `topK`). A diferença está na **qualidade** dos resultados:
|
|
149
|
+
> - **HyDE** (modo `precise`): Gera documentos hipotéticos para melhorar a busca - processamento extra no backend VectorGov
|
|
150
|
+
> - **Reranker** (modos `balanced` e `precise`): Reordena resultados por relevância - processamento extra no backend VectorGov
|
|
151
|
+
>
|
|
152
|
+
> Ou seja: você recebe resultados **mais relevantes**, não **mais resultados**.
|
|
153
|
+
|
|
154
|
+
## Estimativa de Tokens
|
|
155
|
+
|
|
156
|
+
Planeje o uso de contexto com estimativa de tokens antes de enviar para seu LLM:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const results = await vg.search('O que é ETP?', { topK: 5 });
|
|
160
|
+
|
|
161
|
+
// Estima tokens do contexto
|
|
162
|
+
const stats = await vg.estimateTokens(results);
|
|
163
|
+
|
|
164
|
+
console.log(`Tokens de contexto: ${stats.contextTokens}`);
|
|
165
|
+
console.log(`Tokens de sistema: ${stats.systemTokens}`);
|
|
166
|
+
console.log(`Total: ${stats.totalTokens}`);
|
|
167
|
+
console.log(`Caracteres: ${stats.charCount}`);
|
|
168
|
+
console.log(`Encoding: ${stats.encoding}`);
|
|
169
|
+
|
|
170
|
+
// Verificar se cabe no limite do modelo
|
|
171
|
+
if (stats.totalTokens > 4000) {
|
|
172
|
+
// Reduzir contexto
|
|
173
|
+
const smaller = await vg.search('O que é ETP?', { topK: 3 });
|
|
174
|
+
const smallerStats = await vg.estimateTokens(smaller);
|
|
175
|
+
console.log(`Novo total: ${smallerStats.totalTokens}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Com system prompt customizado
|
|
179
|
+
const customStats = await vg.estimateTokens(results, {
|
|
180
|
+
systemPrompt: 'Você é um especialista jurídico...'
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
148
184
|
## Filtros
|
|
149
185
|
|
|
150
186
|
```typescript
|
|
@@ -155,20 +191,6 @@ const results = await vg.search('dispensa de licitação', {
|
|
|
155
191
|
});
|
|
156
192
|
```
|
|
157
193
|
|
|
158
|
-
## Perguntas com Resposta
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
// Usa o LLM do VectorGov para gerar resposta
|
|
162
|
-
const response = await vg.ask('O que é ETP?');
|
|
163
|
-
|
|
164
|
-
console.log(response.answer);
|
|
165
|
-
console.log(`Confiança: ${(response.confidence * 100).toFixed(1)}%`);
|
|
166
|
-
|
|
167
|
-
for (const citation of response.citations) {
|
|
168
|
-
console.log(` - ${citation.short}`);
|
|
169
|
-
}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
194
|
## Feedback
|
|
173
195
|
|
|
174
196
|
```typescript
|
|
@@ -181,19 +203,6 @@ await vg.feedback(results.metadata.queryId, true);
|
|
|
181
203
|
await vg.feedback(results.metadata.queryId, false);
|
|
182
204
|
```
|
|
183
205
|
|
|
184
|
-
## Streaming
|
|
185
|
-
|
|
186
|
-
```typescript
|
|
187
|
-
// Resposta em tempo real com Server-Sent Events
|
|
188
|
-
for await (const chunk of vg.askStream('O que é ETP?')) {
|
|
189
|
-
if (chunk.type === 'token') {
|
|
190
|
-
process.stdout.write(chunk.content || '');
|
|
191
|
-
} else if (chunk.type === 'complete') {
|
|
192
|
-
console.log('\n\nCitações:', chunk.citations);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
206
|
## System Prompts
|
|
198
207
|
|
|
199
208
|
```typescript
|
|
@@ -374,9 +383,8 @@ const vg = new VectorGov({
|
|
|
374
383
|
| Método | Descrição |
|
|
375
384
|
|--------|-----------|
|
|
376
385
|
| `search(query, options?)` | Busca semântica |
|
|
377
|
-
| `ask(query, options?)` | Pergunta com resposta IA |
|
|
378
|
-
| `askStream(query, options?)` | Pergunta com streaming |
|
|
379
386
|
| `feedback(queryId, like)` | Envia feedback |
|
|
387
|
+
| `estimateTokens(content, options?)` | Estima tokens para LLM |
|
|
380
388
|
| `storeResponse(options)` | Armazena resposta do seu LLM |
|
|
381
389
|
| `getSystemPrompt(style)` | Obtém system prompt |
|
|
382
390
|
| `availablePrompts` | Lista prompts disponíveis |
|
package/dist/index.d.mts
CHANGED
|
@@ -86,39 +86,6 @@ interface Citation {
|
|
|
86
86
|
/** Número do artigo */
|
|
87
87
|
article?: string;
|
|
88
88
|
}
|
|
89
|
-
/** Metadados da resposta de pergunta */
|
|
90
|
-
interface AskMetadata {
|
|
91
|
-
/** Modelo usado */
|
|
92
|
-
model: string;
|
|
93
|
-
/** Tempo total em ms */
|
|
94
|
-
latencyMs: number;
|
|
95
|
-
/** Tempo de busca em ms */
|
|
96
|
-
retrievalMs?: number;
|
|
97
|
-
/** Tempo de geração em ms */
|
|
98
|
-
generationMs?: number;
|
|
99
|
-
/** Chunks usados */
|
|
100
|
-
chunksUsed: number;
|
|
101
|
-
/** Tokens usados */
|
|
102
|
-
tokens?: number;
|
|
103
|
-
/** Hash da query (para feedback) */
|
|
104
|
-
queryHash?: string;
|
|
105
|
-
}
|
|
106
|
-
/** Resposta de uma pergunta */
|
|
107
|
-
interface AskResponse {
|
|
108
|
-
/** Resposta gerada */
|
|
109
|
-
answer: string;
|
|
110
|
-
/** Citações */
|
|
111
|
-
citations: Citation[];
|
|
112
|
-
/** Confiança (0-1) */
|
|
113
|
-
confidence: number;
|
|
114
|
-
/** Metadados */
|
|
115
|
-
metadata: AskMetadata;
|
|
116
|
-
}
|
|
117
|
-
/** Opções para perguntar */
|
|
118
|
-
interface AskOptions extends SearchOptions {
|
|
119
|
-
/** Usar cache semântico */
|
|
120
|
-
useCache?: boolean;
|
|
121
|
-
}
|
|
122
89
|
/** Resposta de feedback */
|
|
123
90
|
interface FeedbackResponse {
|
|
124
91
|
success: boolean;
|
|
@@ -128,16 +95,16 @@ interface FeedbackResponse {
|
|
|
128
95
|
}
|
|
129
96
|
/** Erros da API */
|
|
130
97
|
declare class VectorGovError extends Error {
|
|
131
|
-
statusCode?: number
|
|
132
|
-
code?: string
|
|
133
|
-
constructor(message: string, statusCode?: number
|
|
98
|
+
statusCode?: number;
|
|
99
|
+
code?: string;
|
|
100
|
+
constructor(message: string, statusCode?: number, code?: string);
|
|
134
101
|
}
|
|
135
102
|
declare class AuthenticationError extends VectorGovError {
|
|
136
103
|
constructor(message?: string);
|
|
137
104
|
}
|
|
138
105
|
declare class RateLimitError extends VectorGovError {
|
|
139
|
-
retryAfter?: number
|
|
140
|
-
constructor(message?: string, retryAfter?: number
|
|
106
|
+
retryAfter?: number;
|
|
107
|
+
constructor(message?: string, retryAfter?: number);
|
|
141
108
|
}
|
|
142
109
|
/** Registro de evento de auditoria */
|
|
143
110
|
interface AuditLog {
|
|
@@ -241,25 +208,6 @@ interface StoreResponseResult {
|
|
|
241
208
|
/** Mensagem de status */
|
|
242
209
|
message: string;
|
|
243
210
|
}
|
|
244
|
-
/** Chunk de resposta em streaming */
|
|
245
|
-
interface StreamChunk {
|
|
246
|
-
/** Tipo do chunk (start, token, complete, error) */
|
|
247
|
-
type: 'start' | 'token' | 'complete' | 'error';
|
|
248
|
-
/** Conteúdo do chunk (token ou mensagem) */
|
|
249
|
-
content?: string;
|
|
250
|
-
/** Query original (em start) */
|
|
251
|
-
query?: string;
|
|
252
|
-
/** Chunks usados (em start) */
|
|
253
|
-
chunks?: number;
|
|
254
|
-
/** Tempo em ms (em complete) */
|
|
255
|
-
timeMs?: number;
|
|
256
|
-
/** Citações (em complete) */
|
|
257
|
-
citations?: Citation[];
|
|
258
|
-
/** Hash da query (em complete) */
|
|
259
|
-
queryHash?: string;
|
|
260
|
-
/** Mensagem de erro (em error) */
|
|
261
|
-
message?: string;
|
|
262
|
-
}
|
|
263
211
|
/** Resumo de um documento */
|
|
264
212
|
interface DocumentSummary {
|
|
265
213
|
/** ID único do documento */
|
|
@@ -382,6 +330,30 @@ interface GoogleTool {
|
|
|
382
330
|
}
|
|
383
331
|
/** Estilos de system prompt disponíveis */
|
|
384
332
|
type SystemPromptStyle = 'default' | 'concise' | 'detailed' | 'chatbot';
|
|
333
|
+
/** Estatísticas de tokens para planejamento de contexto LLM */
|
|
334
|
+
interface TokenStats {
|
|
335
|
+
/** Tokens do contexto (hits formatados) */
|
|
336
|
+
contextTokens: number;
|
|
337
|
+
/** Tokens do system prompt */
|
|
338
|
+
systemTokens: number;
|
|
339
|
+
/** Tokens da query do usuário */
|
|
340
|
+
queryTokens: number;
|
|
341
|
+
/** Total de tokens (context + system + query) */
|
|
342
|
+
totalTokens: number;
|
|
343
|
+
/** Quantidade de hits no contexto */
|
|
344
|
+
hitsCount: number;
|
|
345
|
+
/** Número total de caracteres */
|
|
346
|
+
charCount: number;
|
|
347
|
+
/** Encoding utilizado (cl100k_base compatível com GPT-4/Claude) */
|
|
348
|
+
encoding: string;
|
|
349
|
+
}
|
|
350
|
+
/** Opções para estimativa de tokens */
|
|
351
|
+
interface EstimateTokensOptions {
|
|
352
|
+
/** System prompt customizado (opcional) */
|
|
353
|
+
systemPrompt?: string;
|
|
354
|
+
/** Query do usuário (obrigatório quando content é string) */
|
|
355
|
+
query?: string;
|
|
356
|
+
}
|
|
385
357
|
|
|
386
358
|
/**
|
|
387
359
|
* VectorGov SDK Client
|
|
@@ -432,33 +404,6 @@ declare class VectorGov {
|
|
|
432
404
|
* ```
|
|
433
405
|
*/
|
|
434
406
|
search(query: string, options?: SearchOptions): Promise<SearchResult>;
|
|
435
|
-
/**
|
|
436
|
-
* Faz uma pergunta e recebe uma resposta gerada por IA
|
|
437
|
-
*
|
|
438
|
-
* @param query - Pergunta
|
|
439
|
-
* @param options - Opções
|
|
440
|
-
* @returns Resposta com citações
|
|
441
|
-
*/
|
|
442
|
-
ask(query: string, options?: AskOptions): Promise<AskResponse>;
|
|
443
|
-
/**
|
|
444
|
-
* Faz uma pergunta com resposta em streaming
|
|
445
|
-
*
|
|
446
|
-
* @param query - Pergunta do usuário
|
|
447
|
-
* @param options - Opções de busca
|
|
448
|
-
* @yields StreamChunk com cada parte da resposta
|
|
449
|
-
*
|
|
450
|
-
* @example
|
|
451
|
-
* ```typescript
|
|
452
|
-
* for await (const chunk of vg.askStream('O que é ETP?')) {
|
|
453
|
-
* if (chunk.type === 'token') {
|
|
454
|
-
* process.stdout.write(chunk.content || '');
|
|
455
|
-
* } else if (chunk.type === 'complete') {
|
|
456
|
-
* console.log(`\n\nFontes: ${chunk.citations?.length} citações`);
|
|
457
|
-
* }
|
|
458
|
-
* }
|
|
459
|
-
* ```
|
|
460
|
-
*/
|
|
461
|
-
askStream(query: string, options?: SearchOptions): AsyncGenerator<StreamChunk>;
|
|
462
407
|
/**
|
|
463
408
|
* Envia feedback (like/dislike) para uma resposta
|
|
464
409
|
*
|
|
@@ -691,6 +636,40 @@ declare class VectorGov {
|
|
|
691
636
|
* ```
|
|
692
637
|
*/
|
|
693
638
|
getAuditEventTypes(): Promise<string[]>;
|
|
639
|
+
/**
|
|
640
|
+
* Estima a quantidade de tokens que serão usados com um LLM
|
|
641
|
+
*
|
|
642
|
+
* Use para planejar o contexto antes de enviar para seu LLM:
|
|
643
|
+
* - Verificar se cabe no limite do modelo
|
|
644
|
+
* - Calcular custos estimados
|
|
645
|
+
* - Ajustar top_k se necessário
|
|
646
|
+
*
|
|
647
|
+
* @param content - SearchResult ou string de contexto
|
|
648
|
+
* @param options - Opções (systemPrompt customizado, query)
|
|
649
|
+
* @returns Estatísticas de tokens
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* ```typescript
|
|
653
|
+
* // Com SearchResult
|
|
654
|
+
* const results = await vg.search('O que é ETP?');
|
|
655
|
+
* const stats = await vg.estimateTokens(results);
|
|
656
|
+
* console.log(`Total de tokens: ${stats.totalTokens}`);
|
|
657
|
+
*
|
|
658
|
+
* if (stats.totalTokens > 4000) {
|
|
659
|
+
* // Reduzir contexto
|
|
660
|
+
* const smaller = await vg.search('O que é ETP?', { topK: 3 });
|
|
661
|
+
* }
|
|
662
|
+
*
|
|
663
|
+
* // Com string direta
|
|
664
|
+
* const stats2 = await vg.estimateTokens('Texto de contexto...');
|
|
665
|
+
*
|
|
666
|
+
* // Com system prompt customizado
|
|
667
|
+
* const stats3 = await vg.estimateTokens(results, {
|
|
668
|
+
* systemPrompt: 'Você é um especialista jurídico...'
|
|
669
|
+
* });
|
|
670
|
+
* ```
|
|
671
|
+
*/
|
|
672
|
+
estimateTokens(content: SearchResult | string, options?: EstimateTokensOptions): Promise<TokenStats>;
|
|
694
673
|
/**
|
|
695
674
|
* Converte hits para formato de mensagens de chat
|
|
696
675
|
*/
|
|
@@ -701,4 +680,4 @@ declare class VectorGov {
|
|
|
701
680
|
private hitsToContext;
|
|
702
681
|
}
|
|
703
682
|
|
|
704
|
-
export { type AnthropicTool, type
|
|
683
|
+
export { type AnthropicTool, type AuditLog, type AuditLogsOptions, type AuditLogsResponse, type AuditStats, AuthenticationError, type ChatMessage, type Citation, type DeleteResponse, type DocumentSummary, type DocumentsResponse, type EnrichStatus, type EstimateTokensOptions, type FeedbackResponse, type GoogleTool, type IngestStatus, type ListDocumentsOptions, type OpenAITool, RateLimitError, type SearchHit, type SearchMetadata, type SearchMode, type SearchOptions, type SearchResult, type StoreResponseOptions, type StoreResponseResult, type SystemPromptStyle, type TokenStats, type UploadResponse, VectorGov, type VectorGovConfig, VectorGovError };
|
package/dist/index.d.ts
CHANGED
|
@@ -86,39 +86,6 @@ interface Citation {
|
|
|
86
86
|
/** Número do artigo */
|
|
87
87
|
article?: string;
|
|
88
88
|
}
|
|
89
|
-
/** Metadados da resposta de pergunta */
|
|
90
|
-
interface AskMetadata {
|
|
91
|
-
/** Modelo usado */
|
|
92
|
-
model: string;
|
|
93
|
-
/** Tempo total em ms */
|
|
94
|
-
latencyMs: number;
|
|
95
|
-
/** Tempo de busca em ms */
|
|
96
|
-
retrievalMs?: number;
|
|
97
|
-
/** Tempo de geração em ms */
|
|
98
|
-
generationMs?: number;
|
|
99
|
-
/** Chunks usados */
|
|
100
|
-
chunksUsed: number;
|
|
101
|
-
/** Tokens usados */
|
|
102
|
-
tokens?: number;
|
|
103
|
-
/** Hash da query (para feedback) */
|
|
104
|
-
queryHash?: string;
|
|
105
|
-
}
|
|
106
|
-
/** Resposta de uma pergunta */
|
|
107
|
-
interface AskResponse {
|
|
108
|
-
/** Resposta gerada */
|
|
109
|
-
answer: string;
|
|
110
|
-
/** Citações */
|
|
111
|
-
citations: Citation[];
|
|
112
|
-
/** Confiança (0-1) */
|
|
113
|
-
confidence: number;
|
|
114
|
-
/** Metadados */
|
|
115
|
-
metadata: AskMetadata;
|
|
116
|
-
}
|
|
117
|
-
/** Opções para perguntar */
|
|
118
|
-
interface AskOptions extends SearchOptions {
|
|
119
|
-
/** Usar cache semântico */
|
|
120
|
-
useCache?: boolean;
|
|
121
|
-
}
|
|
122
89
|
/** Resposta de feedback */
|
|
123
90
|
interface FeedbackResponse {
|
|
124
91
|
success: boolean;
|
|
@@ -128,16 +95,16 @@ interface FeedbackResponse {
|
|
|
128
95
|
}
|
|
129
96
|
/** Erros da API */
|
|
130
97
|
declare class VectorGovError extends Error {
|
|
131
|
-
statusCode?: number
|
|
132
|
-
code?: string
|
|
133
|
-
constructor(message: string, statusCode?: number
|
|
98
|
+
statusCode?: number;
|
|
99
|
+
code?: string;
|
|
100
|
+
constructor(message: string, statusCode?: number, code?: string);
|
|
134
101
|
}
|
|
135
102
|
declare class AuthenticationError extends VectorGovError {
|
|
136
103
|
constructor(message?: string);
|
|
137
104
|
}
|
|
138
105
|
declare class RateLimitError extends VectorGovError {
|
|
139
|
-
retryAfter?: number
|
|
140
|
-
constructor(message?: string, retryAfter?: number
|
|
106
|
+
retryAfter?: number;
|
|
107
|
+
constructor(message?: string, retryAfter?: number);
|
|
141
108
|
}
|
|
142
109
|
/** Registro de evento de auditoria */
|
|
143
110
|
interface AuditLog {
|
|
@@ -241,25 +208,6 @@ interface StoreResponseResult {
|
|
|
241
208
|
/** Mensagem de status */
|
|
242
209
|
message: string;
|
|
243
210
|
}
|
|
244
|
-
/** Chunk de resposta em streaming */
|
|
245
|
-
interface StreamChunk {
|
|
246
|
-
/** Tipo do chunk (start, token, complete, error) */
|
|
247
|
-
type: 'start' | 'token' | 'complete' | 'error';
|
|
248
|
-
/** Conteúdo do chunk (token ou mensagem) */
|
|
249
|
-
content?: string;
|
|
250
|
-
/** Query original (em start) */
|
|
251
|
-
query?: string;
|
|
252
|
-
/** Chunks usados (em start) */
|
|
253
|
-
chunks?: number;
|
|
254
|
-
/** Tempo em ms (em complete) */
|
|
255
|
-
timeMs?: number;
|
|
256
|
-
/** Citações (em complete) */
|
|
257
|
-
citations?: Citation[];
|
|
258
|
-
/** Hash da query (em complete) */
|
|
259
|
-
queryHash?: string;
|
|
260
|
-
/** Mensagem de erro (em error) */
|
|
261
|
-
message?: string;
|
|
262
|
-
}
|
|
263
211
|
/** Resumo de um documento */
|
|
264
212
|
interface DocumentSummary {
|
|
265
213
|
/** ID único do documento */
|
|
@@ -382,6 +330,30 @@ interface GoogleTool {
|
|
|
382
330
|
}
|
|
383
331
|
/** Estilos de system prompt disponíveis */
|
|
384
332
|
type SystemPromptStyle = 'default' | 'concise' | 'detailed' | 'chatbot';
|
|
333
|
+
/** Estatísticas de tokens para planejamento de contexto LLM */
|
|
334
|
+
interface TokenStats {
|
|
335
|
+
/** Tokens do contexto (hits formatados) */
|
|
336
|
+
contextTokens: number;
|
|
337
|
+
/** Tokens do system prompt */
|
|
338
|
+
systemTokens: number;
|
|
339
|
+
/** Tokens da query do usuário */
|
|
340
|
+
queryTokens: number;
|
|
341
|
+
/** Total de tokens (context + system + query) */
|
|
342
|
+
totalTokens: number;
|
|
343
|
+
/** Quantidade de hits no contexto */
|
|
344
|
+
hitsCount: number;
|
|
345
|
+
/** Número total de caracteres */
|
|
346
|
+
charCount: number;
|
|
347
|
+
/** Encoding utilizado (cl100k_base compatível com GPT-4/Claude) */
|
|
348
|
+
encoding: string;
|
|
349
|
+
}
|
|
350
|
+
/** Opções para estimativa de tokens */
|
|
351
|
+
interface EstimateTokensOptions {
|
|
352
|
+
/** System prompt customizado (opcional) */
|
|
353
|
+
systemPrompt?: string;
|
|
354
|
+
/** Query do usuário (obrigatório quando content é string) */
|
|
355
|
+
query?: string;
|
|
356
|
+
}
|
|
385
357
|
|
|
386
358
|
/**
|
|
387
359
|
* VectorGov SDK Client
|
|
@@ -432,33 +404,6 @@ declare class VectorGov {
|
|
|
432
404
|
* ```
|
|
433
405
|
*/
|
|
434
406
|
search(query: string, options?: SearchOptions): Promise<SearchResult>;
|
|
435
|
-
/**
|
|
436
|
-
* Faz uma pergunta e recebe uma resposta gerada por IA
|
|
437
|
-
*
|
|
438
|
-
* @param query - Pergunta
|
|
439
|
-
* @param options - Opções
|
|
440
|
-
* @returns Resposta com citações
|
|
441
|
-
*/
|
|
442
|
-
ask(query: string, options?: AskOptions): Promise<AskResponse>;
|
|
443
|
-
/**
|
|
444
|
-
* Faz uma pergunta com resposta em streaming
|
|
445
|
-
*
|
|
446
|
-
* @param query - Pergunta do usuário
|
|
447
|
-
* @param options - Opções de busca
|
|
448
|
-
* @yields StreamChunk com cada parte da resposta
|
|
449
|
-
*
|
|
450
|
-
* @example
|
|
451
|
-
* ```typescript
|
|
452
|
-
* for await (const chunk of vg.askStream('O que é ETP?')) {
|
|
453
|
-
* if (chunk.type === 'token') {
|
|
454
|
-
* process.stdout.write(chunk.content || '');
|
|
455
|
-
* } else if (chunk.type === 'complete') {
|
|
456
|
-
* console.log(`\n\nFontes: ${chunk.citations?.length} citações`);
|
|
457
|
-
* }
|
|
458
|
-
* }
|
|
459
|
-
* ```
|
|
460
|
-
*/
|
|
461
|
-
askStream(query: string, options?: SearchOptions): AsyncGenerator<StreamChunk>;
|
|
462
407
|
/**
|
|
463
408
|
* Envia feedback (like/dislike) para uma resposta
|
|
464
409
|
*
|
|
@@ -691,6 +636,40 @@ declare class VectorGov {
|
|
|
691
636
|
* ```
|
|
692
637
|
*/
|
|
693
638
|
getAuditEventTypes(): Promise<string[]>;
|
|
639
|
+
/**
|
|
640
|
+
* Estima a quantidade de tokens que serão usados com um LLM
|
|
641
|
+
*
|
|
642
|
+
* Use para planejar o contexto antes de enviar para seu LLM:
|
|
643
|
+
* - Verificar se cabe no limite do modelo
|
|
644
|
+
* - Calcular custos estimados
|
|
645
|
+
* - Ajustar top_k se necessário
|
|
646
|
+
*
|
|
647
|
+
* @param content - SearchResult ou string de contexto
|
|
648
|
+
* @param options - Opções (systemPrompt customizado, query)
|
|
649
|
+
* @returns Estatísticas de tokens
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* ```typescript
|
|
653
|
+
* // Com SearchResult
|
|
654
|
+
* const results = await vg.search('O que é ETP?');
|
|
655
|
+
* const stats = await vg.estimateTokens(results);
|
|
656
|
+
* console.log(`Total de tokens: ${stats.totalTokens}`);
|
|
657
|
+
*
|
|
658
|
+
* if (stats.totalTokens > 4000) {
|
|
659
|
+
* // Reduzir contexto
|
|
660
|
+
* const smaller = await vg.search('O que é ETP?', { topK: 3 });
|
|
661
|
+
* }
|
|
662
|
+
*
|
|
663
|
+
* // Com string direta
|
|
664
|
+
* const stats2 = await vg.estimateTokens('Texto de contexto...');
|
|
665
|
+
*
|
|
666
|
+
* // Com system prompt customizado
|
|
667
|
+
* const stats3 = await vg.estimateTokens(results, {
|
|
668
|
+
* systemPrompt: 'Você é um especialista jurídico...'
|
|
669
|
+
* });
|
|
670
|
+
* ```
|
|
671
|
+
*/
|
|
672
|
+
estimateTokens(content: SearchResult | string, options?: EstimateTokensOptions): Promise<TokenStats>;
|
|
694
673
|
/**
|
|
695
674
|
* Converte hits para formato de mensagens de chat
|
|
696
675
|
*/
|
|
@@ -701,4 +680,4 @@ declare class VectorGov {
|
|
|
701
680
|
private hitsToContext;
|
|
702
681
|
}
|
|
703
682
|
|
|
704
|
-
export { type AnthropicTool, type
|
|
683
|
+
export { type AnthropicTool, type AuditLog, type AuditLogsOptions, type AuditLogsResponse, type AuditStats, AuthenticationError, type ChatMessage, type Citation, type DeleteResponse, type DocumentSummary, type DocumentsResponse, type EnrichStatus, type EstimateTokensOptions, type FeedbackResponse, type GoogleTool, type IngestStatus, type ListDocumentsOptions, type OpenAITool, RateLimitError, type SearchHit, type SearchMetadata, type SearchMode, type SearchOptions, type SearchResult, type StoreResponseOptions, type StoreResponseResult, type SystemPromptStyle, type TokenStats, type UploadResponse, VectorGov, type VectorGovConfig, VectorGovError };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __defProp = Object.defineProperty;
|
|
3
2
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -104,6 +103,9 @@ var TOOL_SCHEMA = {
|
|
|
104
103
|
}
|
|
105
104
|
};
|
|
106
105
|
var VectorGov = class {
|
|
106
|
+
apiKey;
|
|
107
|
+
baseUrl;
|
|
108
|
+
timeout;
|
|
107
109
|
constructor(config) {
|
|
108
110
|
if (!config.apiKey) {
|
|
109
111
|
throw new AuthenticationError("API key is required");
|
|
@@ -221,130 +223,6 @@ var VectorGov = class {
|
|
|
221
223
|
toContext: () => this.hitsToContext(hits)
|
|
222
224
|
};
|
|
223
225
|
}
|
|
224
|
-
/**
|
|
225
|
-
* Faz uma pergunta e recebe uma resposta gerada por IA
|
|
226
|
-
*
|
|
227
|
-
* @param query - Pergunta
|
|
228
|
-
* @param options - Opções
|
|
229
|
-
* @returns Resposta com citações
|
|
230
|
-
*/
|
|
231
|
-
async ask(query, options = {}) {
|
|
232
|
-
const {
|
|
233
|
-
topK = 5,
|
|
234
|
-
mode = "balanced",
|
|
235
|
-
useCache = true,
|
|
236
|
-
tipoDocumento,
|
|
237
|
-
ano
|
|
238
|
-
} = options;
|
|
239
|
-
const response = await this.request("/sdk/ask", {
|
|
240
|
-
method: "POST",
|
|
241
|
-
body: JSON.stringify({
|
|
242
|
-
query,
|
|
243
|
-
top_k: topK,
|
|
244
|
-
mode,
|
|
245
|
-
use_cache: useCache,
|
|
246
|
-
tipo_documento: tipoDocumento,
|
|
247
|
-
ano
|
|
248
|
-
})
|
|
249
|
-
});
|
|
250
|
-
return {
|
|
251
|
-
answer: response.data.answer,
|
|
252
|
-
citations: response.data.citations.map((c) => ({
|
|
253
|
-
text: c.text,
|
|
254
|
-
short: c.short,
|
|
255
|
-
documentType: c.document_type,
|
|
256
|
-
documentNumber: c.document_number,
|
|
257
|
-
year: c.year,
|
|
258
|
-
article: c.article
|
|
259
|
-
})),
|
|
260
|
-
confidence: response.data.confidence,
|
|
261
|
-
metadata: {
|
|
262
|
-
model: response.metadata.model,
|
|
263
|
-
latencyMs: response.metadata.latency_ms,
|
|
264
|
-
retrievalMs: response.metadata.retrieval_ms,
|
|
265
|
-
generationMs: response.metadata.generation_ms,
|
|
266
|
-
chunksUsed: response.metadata.chunks_used,
|
|
267
|
-
tokens: response.metadata.tokens,
|
|
268
|
-
queryHash: response.metadata.query_hash
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Faz uma pergunta com resposta em streaming
|
|
274
|
-
*
|
|
275
|
-
* @param query - Pergunta do usuário
|
|
276
|
-
* @param options - Opções de busca
|
|
277
|
-
* @yields StreamChunk com cada parte da resposta
|
|
278
|
-
*
|
|
279
|
-
* @example
|
|
280
|
-
* ```typescript
|
|
281
|
-
* for await (const chunk of vg.askStream('O que é ETP?')) {
|
|
282
|
-
* if (chunk.type === 'token') {
|
|
283
|
-
* process.stdout.write(chunk.content || '');
|
|
284
|
-
* } else if (chunk.type === 'complete') {
|
|
285
|
-
* console.log(`\n\nFontes: ${chunk.citations?.length} citações`);
|
|
286
|
-
* }
|
|
287
|
-
* }
|
|
288
|
-
* ```
|
|
289
|
-
*/
|
|
290
|
-
async *askStream(query, options = {}) {
|
|
291
|
-
const { topK = 5, mode = "balanced" } = options;
|
|
292
|
-
const url = `${this.baseUrl}/sdk/ask/stream`;
|
|
293
|
-
const response = await fetch(url, {
|
|
294
|
-
method: "POST",
|
|
295
|
-
headers: {
|
|
296
|
-
"Content-Type": "application/json",
|
|
297
|
-
"X-API-Key": this.apiKey
|
|
298
|
-
},
|
|
299
|
-
body: JSON.stringify({
|
|
300
|
-
query,
|
|
301
|
-
top_k: topK,
|
|
302
|
-
mode
|
|
303
|
-
})
|
|
304
|
-
});
|
|
305
|
-
if (!response.ok) {
|
|
306
|
-
throw new VectorGovError(`Stream request failed: ${response.status}`);
|
|
307
|
-
}
|
|
308
|
-
if (!response.body) {
|
|
309
|
-
throw new VectorGovError("No response body for streaming");
|
|
310
|
-
}
|
|
311
|
-
const reader = response.body.getReader();
|
|
312
|
-
const decoder = new TextDecoder();
|
|
313
|
-
let buffer = "";
|
|
314
|
-
try {
|
|
315
|
-
while (true) {
|
|
316
|
-
const { done, value } = await reader.read();
|
|
317
|
-
if (done) break;
|
|
318
|
-
buffer += decoder.decode(value, { stream: true });
|
|
319
|
-
const lines = buffer.split("\n");
|
|
320
|
-
buffer = lines.pop() || "";
|
|
321
|
-
for (const line of lines) {
|
|
322
|
-
if (line.startsWith("data: ")) {
|
|
323
|
-
const data = line.slice(6);
|
|
324
|
-
if (data === "[DONE]") return;
|
|
325
|
-
try {
|
|
326
|
-
const event = JSON.parse(data);
|
|
327
|
-
const chunk = {
|
|
328
|
-
type: event.type || "token",
|
|
329
|
-
content: event.content,
|
|
330
|
-
query: event.query,
|
|
331
|
-
chunks: event.chunks,
|
|
332
|
-
timeMs: event.time_ms,
|
|
333
|
-
citations: event.citations,
|
|
334
|
-
queryHash: event.query_hash,
|
|
335
|
-
message: event.message
|
|
336
|
-
};
|
|
337
|
-
yield chunk;
|
|
338
|
-
if (event.type === "error") return;
|
|
339
|
-
} catch {
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
} finally {
|
|
345
|
-
reader.releaseLock();
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
226
|
/**
|
|
349
227
|
* Envia feedback (like/dislike) para uma resposta
|
|
350
228
|
*
|
|
@@ -811,6 +689,71 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
811
689
|
return response.event_types;
|
|
812
690
|
}
|
|
813
691
|
// ===========================================================================
|
|
692
|
+
// CONTAGEM DE TOKENS
|
|
693
|
+
// ===========================================================================
|
|
694
|
+
/**
|
|
695
|
+
* Estima a quantidade de tokens que serão usados com um LLM
|
|
696
|
+
*
|
|
697
|
+
* Use para planejar o contexto antes de enviar para seu LLM:
|
|
698
|
+
* - Verificar se cabe no limite do modelo
|
|
699
|
+
* - Calcular custos estimados
|
|
700
|
+
* - Ajustar top_k se necessário
|
|
701
|
+
*
|
|
702
|
+
* @param content - SearchResult ou string de contexto
|
|
703
|
+
* @param options - Opções (systemPrompt customizado, query)
|
|
704
|
+
* @returns Estatísticas de tokens
|
|
705
|
+
*
|
|
706
|
+
* @example
|
|
707
|
+
* ```typescript
|
|
708
|
+
* // Com SearchResult
|
|
709
|
+
* const results = await vg.search('O que é ETP?');
|
|
710
|
+
* const stats = await vg.estimateTokens(results);
|
|
711
|
+
* console.log(`Total de tokens: ${stats.totalTokens}`);
|
|
712
|
+
*
|
|
713
|
+
* if (stats.totalTokens > 4000) {
|
|
714
|
+
* // Reduzir contexto
|
|
715
|
+
* const smaller = await vg.search('O que é ETP?', { topK: 3 });
|
|
716
|
+
* }
|
|
717
|
+
*
|
|
718
|
+
* // Com string direta
|
|
719
|
+
* const stats2 = await vg.estimateTokens('Texto de contexto...');
|
|
720
|
+
*
|
|
721
|
+
* // Com system prompt customizado
|
|
722
|
+
* const stats3 = await vg.estimateTokens(results, {
|
|
723
|
+
* systemPrompt: 'Você é um especialista jurídico...'
|
|
724
|
+
* });
|
|
725
|
+
* ```
|
|
726
|
+
*/
|
|
727
|
+
async estimateTokens(content, options = {}) {
|
|
728
|
+
let context;
|
|
729
|
+
let query = options.query || "";
|
|
730
|
+
let hitsCount = 0;
|
|
731
|
+
if (typeof content === "string") {
|
|
732
|
+
context = content;
|
|
733
|
+
} else {
|
|
734
|
+
context = content.toContext();
|
|
735
|
+
hitsCount = content.hits.length;
|
|
736
|
+
}
|
|
737
|
+
const systemPrompt = options.systemPrompt || SYSTEM_PROMPTS.default;
|
|
738
|
+
const response = await this.request("/sdk/tokens", {
|
|
739
|
+
method: "POST",
|
|
740
|
+
body: JSON.stringify({
|
|
741
|
+
context,
|
|
742
|
+
query,
|
|
743
|
+
system_prompt: systemPrompt
|
|
744
|
+
})
|
|
745
|
+
});
|
|
746
|
+
return {
|
|
747
|
+
contextTokens: response.context_tokens,
|
|
748
|
+
systemTokens: response.system_tokens,
|
|
749
|
+
queryTokens: response.query_tokens,
|
|
750
|
+
totalTokens: response.total_tokens,
|
|
751
|
+
hitsCount,
|
|
752
|
+
charCount: response.char_count,
|
|
753
|
+
encoding: response.encoding
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
// ===========================================================================
|
|
814
757
|
// MÉTODOS AUXILIARES
|
|
815
758
|
// ===========================================================================
|
|
816
759
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -75,6 +75,9 @@ var TOOL_SCHEMA = {
|
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
77
|
var VectorGov = class {
|
|
78
|
+
apiKey;
|
|
79
|
+
baseUrl;
|
|
80
|
+
timeout;
|
|
78
81
|
constructor(config) {
|
|
79
82
|
if (!config.apiKey) {
|
|
80
83
|
throw new AuthenticationError("API key is required");
|
|
@@ -192,130 +195,6 @@ var VectorGov = class {
|
|
|
192
195
|
toContext: () => this.hitsToContext(hits)
|
|
193
196
|
};
|
|
194
197
|
}
|
|
195
|
-
/**
|
|
196
|
-
* Faz uma pergunta e recebe uma resposta gerada por IA
|
|
197
|
-
*
|
|
198
|
-
* @param query - Pergunta
|
|
199
|
-
* @param options - Opções
|
|
200
|
-
* @returns Resposta com citações
|
|
201
|
-
*/
|
|
202
|
-
async ask(query, options = {}) {
|
|
203
|
-
const {
|
|
204
|
-
topK = 5,
|
|
205
|
-
mode = "balanced",
|
|
206
|
-
useCache = true,
|
|
207
|
-
tipoDocumento,
|
|
208
|
-
ano
|
|
209
|
-
} = options;
|
|
210
|
-
const response = await this.request("/sdk/ask", {
|
|
211
|
-
method: "POST",
|
|
212
|
-
body: JSON.stringify({
|
|
213
|
-
query,
|
|
214
|
-
top_k: topK,
|
|
215
|
-
mode,
|
|
216
|
-
use_cache: useCache,
|
|
217
|
-
tipo_documento: tipoDocumento,
|
|
218
|
-
ano
|
|
219
|
-
})
|
|
220
|
-
});
|
|
221
|
-
return {
|
|
222
|
-
answer: response.data.answer,
|
|
223
|
-
citations: response.data.citations.map((c) => ({
|
|
224
|
-
text: c.text,
|
|
225
|
-
short: c.short,
|
|
226
|
-
documentType: c.document_type,
|
|
227
|
-
documentNumber: c.document_number,
|
|
228
|
-
year: c.year,
|
|
229
|
-
article: c.article
|
|
230
|
-
})),
|
|
231
|
-
confidence: response.data.confidence,
|
|
232
|
-
metadata: {
|
|
233
|
-
model: response.metadata.model,
|
|
234
|
-
latencyMs: response.metadata.latency_ms,
|
|
235
|
-
retrievalMs: response.metadata.retrieval_ms,
|
|
236
|
-
generationMs: response.metadata.generation_ms,
|
|
237
|
-
chunksUsed: response.metadata.chunks_used,
|
|
238
|
-
tokens: response.metadata.tokens,
|
|
239
|
-
queryHash: response.metadata.query_hash
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Faz uma pergunta com resposta em streaming
|
|
245
|
-
*
|
|
246
|
-
* @param query - Pergunta do usuário
|
|
247
|
-
* @param options - Opções de busca
|
|
248
|
-
* @yields StreamChunk com cada parte da resposta
|
|
249
|
-
*
|
|
250
|
-
* @example
|
|
251
|
-
* ```typescript
|
|
252
|
-
* for await (const chunk of vg.askStream('O que é ETP?')) {
|
|
253
|
-
* if (chunk.type === 'token') {
|
|
254
|
-
* process.stdout.write(chunk.content || '');
|
|
255
|
-
* } else if (chunk.type === 'complete') {
|
|
256
|
-
* console.log(`\n\nFontes: ${chunk.citations?.length} citações`);
|
|
257
|
-
* }
|
|
258
|
-
* }
|
|
259
|
-
* ```
|
|
260
|
-
*/
|
|
261
|
-
async *askStream(query, options = {}) {
|
|
262
|
-
const { topK = 5, mode = "balanced" } = options;
|
|
263
|
-
const url = `${this.baseUrl}/sdk/ask/stream`;
|
|
264
|
-
const response = await fetch(url, {
|
|
265
|
-
method: "POST",
|
|
266
|
-
headers: {
|
|
267
|
-
"Content-Type": "application/json",
|
|
268
|
-
"X-API-Key": this.apiKey
|
|
269
|
-
},
|
|
270
|
-
body: JSON.stringify({
|
|
271
|
-
query,
|
|
272
|
-
top_k: topK,
|
|
273
|
-
mode
|
|
274
|
-
})
|
|
275
|
-
});
|
|
276
|
-
if (!response.ok) {
|
|
277
|
-
throw new VectorGovError(`Stream request failed: ${response.status}`);
|
|
278
|
-
}
|
|
279
|
-
if (!response.body) {
|
|
280
|
-
throw new VectorGovError("No response body for streaming");
|
|
281
|
-
}
|
|
282
|
-
const reader = response.body.getReader();
|
|
283
|
-
const decoder = new TextDecoder();
|
|
284
|
-
let buffer = "";
|
|
285
|
-
try {
|
|
286
|
-
while (true) {
|
|
287
|
-
const { done, value } = await reader.read();
|
|
288
|
-
if (done) break;
|
|
289
|
-
buffer += decoder.decode(value, { stream: true });
|
|
290
|
-
const lines = buffer.split("\n");
|
|
291
|
-
buffer = lines.pop() || "";
|
|
292
|
-
for (const line of lines) {
|
|
293
|
-
if (line.startsWith("data: ")) {
|
|
294
|
-
const data = line.slice(6);
|
|
295
|
-
if (data === "[DONE]") return;
|
|
296
|
-
try {
|
|
297
|
-
const event = JSON.parse(data);
|
|
298
|
-
const chunk = {
|
|
299
|
-
type: event.type || "token",
|
|
300
|
-
content: event.content,
|
|
301
|
-
query: event.query,
|
|
302
|
-
chunks: event.chunks,
|
|
303
|
-
timeMs: event.time_ms,
|
|
304
|
-
citations: event.citations,
|
|
305
|
-
queryHash: event.query_hash,
|
|
306
|
-
message: event.message
|
|
307
|
-
};
|
|
308
|
-
yield chunk;
|
|
309
|
-
if (event.type === "error") return;
|
|
310
|
-
} catch {
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
} finally {
|
|
316
|
-
reader.releaseLock();
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
198
|
/**
|
|
320
199
|
* Envia feedback (like/dislike) para uma resposta
|
|
321
200
|
*
|
|
@@ -782,6 +661,71 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
782
661
|
return response.event_types;
|
|
783
662
|
}
|
|
784
663
|
// ===========================================================================
|
|
664
|
+
// CONTAGEM DE TOKENS
|
|
665
|
+
// ===========================================================================
|
|
666
|
+
/**
|
|
667
|
+
* Estima a quantidade de tokens que serão usados com um LLM
|
|
668
|
+
*
|
|
669
|
+
* Use para planejar o contexto antes de enviar para seu LLM:
|
|
670
|
+
* - Verificar se cabe no limite do modelo
|
|
671
|
+
* - Calcular custos estimados
|
|
672
|
+
* - Ajustar top_k se necessário
|
|
673
|
+
*
|
|
674
|
+
* @param content - SearchResult ou string de contexto
|
|
675
|
+
* @param options - Opções (systemPrompt customizado, query)
|
|
676
|
+
* @returns Estatísticas de tokens
|
|
677
|
+
*
|
|
678
|
+
* @example
|
|
679
|
+
* ```typescript
|
|
680
|
+
* // Com SearchResult
|
|
681
|
+
* const results = await vg.search('O que é ETP?');
|
|
682
|
+
* const stats = await vg.estimateTokens(results);
|
|
683
|
+
* console.log(`Total de tokens: ${stats.totalTokens}`);
|
|
684
|
+
*
|
|
685
|
+
* if (stats.totalTokens > 4000) {
|
|
686
|
+
* // Reduzir contexto
|
|
687
|
+
* const smaller = await vg.search('O que é ETP?', { topK: 3 });
|
|
688
|
+
* }
|
|
689
|
+
*
|
|
690
|
+
* // Com string direta
|
|
691
|
+
* const stats2 = await vg.estimateTokens('Texto de contexto...');
|
|
692
|
+
*
|
|
693
|
+
* // Com system prompt customizado
|
|
694
|
+
* const stats3 = await vg.estimateTokens(results, {
|
|
695
|
+
* systemPrompt: 'Você é um especialista jurídico...'
|
|
696
|
+
* });
|
|
697
|
+
* ```
|
|
698
|
+
*/
|
|
699
|
+
async estimateTokens(content, options = {}) {
|
|
700
|
+
let context;
|
|
701
|
+
let query = options.query || "";
|
|
702
|
+
let hitsCount = 0;
|
|
703
|
+
if (typeof content === "string") {
|
|
704
|
+
context = content;
|
|
705
|
+
} else {
|
|
706
|
+
context = content.toContext();
|
|
707
|
+
hitsCount = content.hits.length;
|
|
708
|
+
}
|
|
709
|
+
const systemPrompt = options.systemPrompt || SYSTEM_PROMPTS.default;
|
|
710
|
+
const response = await this.request("/sdk/tokens", {
|
|
711
|
+
method: "POST",
|
|
712
|
+
body: JSON.stringify({
|
|
713
|
+
context,
|
|
714
|
+
query,
|
|
715
|
+
system_prompt: systemPrompt
|
|
716
|
+
})
|
|
717
|
+
});
|
|
718
|
+
return {
|
|
719
|
+
contextTokens: response.context_tokens,
|
|
720
|
+
systemTokens: response.system_tokens,
|
|
721
|
+
queryTokens: response.query_tokens,
|
|
722
|
+
totalTokens: response.total_tokens,
|
|
723
|
+
hitsCount,
|
|
724
|
+
charCount: response.char_count,
|
|
725
|
+
encoding: response.encoding
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
// ===========================================================================
|
|
785
729
|
// MÉTODOS AUXILIARES
|
|
786
730
|
// ===========================================================================
|
|
787
731
|
/**
|