@onurege3467/zerohelper 10.2.6 → 10.3.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 +75 -0
- package/dist/functions/ai.d.ts +126 -0
- package/dist/functions/ai.js +387 -0
- package/dist/functions/index.d.ts +24 -0
- package/dist/functions/index.js +5 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,7 @@ We have now decided to open the vault. By open-sourcing this battle-hardened fra
|
|
|
50
50
|
- [Math & Statistics](#math-module)
|
|
51
51
|
- [String & Slug Module](#string-module)
|
|
52
52
|
- [Array & Collection Module](#array-module)
|
|
53
|
+
- [AI Module](#ai-module)
|
|
53
54
|
- [Security & Cryptography](#security-cryptography)
|
|
54
55
|
12. [Validation & Sanitization Engine](#-validation--sanitization-engine)
|
|
55
56
|
13. [Professional Logger Pro](#-professional-logger-pro)
|
|
@@ -460,6 +461,80 @@ functions.object_module.deepMerge(obj1, obj2);
|
|
|
460
461
|
functions.object_module.filterObjectByKey(obj, ['name', 'email']);
|
|
461
462
|
```
|
|
462
463
|
|
|
464
|
+
### 🤖 AI Module (`ai_module`)
|
|
465
|
+
|
|
466
|
+
LLM/AI çalışmaları için yardımcı utility fonksiyonları. Token hesaplama, prompt yönetimi, maliyet tahmini ve context optimizasyonu.
|
|
467
|
+
|
|
468
|
+
#### Token İşlemleri
|
|
469
|
+
```typescript
|
|
470
|
+
// Yaklaşık token sayısı hesaplama
|
|
471
|
+
const tokens = functions.ai_module.estimateTokens("Hello world this is a test");
|
|
472
|
+
|
|
473
|
+
// Metni token limitine göre kırpma
|
|
474
|
+
const truncated = functions.ai_module.truncateToTokenLimit(longText, 1000);
|
|
475
|
+
|
|
476
|
+
// Metni parçalara bölme
|
|
477
|
+
const chunks = functions.ai_module.splitByTokenLimit(longText, 4000);
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
#### Prompt Yönetimi
|
|
481
|
+
```typescript
|
|
482
|
+
// Chat mesajı formatlama
|
|
483
|
+
const message = functions.ai_module.formatChatMessage('user', 'Hello');
|
|
484
|
+
|
|
485
|
+
// Few-shot prompt oluşturma
|
|
486
|
+
const prompt = functions.ai_module.createFewShotPrompt([
|
|
487
|
+
{ input: '2+2?', output: '4' },
|
|
488
|
+
{ input: '3+3?', output: '6' }
|
|
489
|
+
], '4+4?');
|
|
490
|
+
|
|
491
|
+
// Sistem ve kullanıcı mesajlarını birleştirme
|
|
492
|
+
const messages = functions.ai_module.mergeSystemAndUser(
|
|
493
|
+
'You are a helpful assistant',
|
|
494
|
+
'What is the weather?'
|
|
495
|
+
);
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
#### Context & Conversation Yönetimi
|
|
499
|
+
```typescript
|
|
500
|
+
// Mesajları context penceresine sığdırma
|
|
501
|
+
const fitted = functions.ai_module.fitMessagesToContext(messages, 8000);
|
|
502
|
+
|
|
503
|
+
// Konuşma geçmişini sıkıştırma
|
|
504
|
+
const compressed = functions.ai_module.compressConversationHistory(messages, 4);
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
#### Maliyet Hesaplama
|
|
508
|
+
```typescript
|
|
509
|
+
// Konuşma maliyetini tahmin etme
|
|
510
|
+
const cost = functions.ai_module.estimateConversationCost(messages, 'gpt-4');
|
|
511
|
+
console.log(cost.totalCost); // USD cinsinden toplam maliyet
|
|
512
|
+
|
|
513
|
+
// Model bilgileri
|
|
514
|
+
const limit = functions.ai_module.getModelTokenLimit('gpt-4o'); // 128000
|
|
515
|
+
const pricing = functions.ai_module.getModelPricing('claude-3-sonnet');
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
#### Output İşlemleri
|
|
519
|
+
```typescript
|
|
520
|
+
// Markdown'dan JSON çıkarma
|
|
521
|
+
const json = functions.ai_module.extractJSONFromMarkdown('```json\n{"key": "value"}\n```');
|
|
522
|
+
|
|
523
|
+
// Streaming response parse etme
|
|
524
|
+
const chunk = functions.ai_module.parseStreamingChunk('data: {"choices": [{"delta": {"content": "Hello"}}]}');
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
#### Utility Fonksiyonlar
|
|
528
|
+
```typescript
|
|
529
|
+
// Token limit kontrolü
|
|
530
|
+
if (functions.ai_module.isTokenLimitExceeded(prompt, 4000)) {
|
|
531
|
+
// Prompt çok uzun
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Yüzdeye göre kısaltma
|
|
535
|
+
const shorter = functions.ai_module.truncatePromptByPercentage(prompt, 50); // %50 kısalt
|
|
536
|
+
```
|
|
537
|
+
|
|
463
538
|
---
|
|
464
539
|
|
|
465
540
|
## 🔐 Security & Cryptography
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export interface ChatMessage {
|
|
2
|
+
role: 'system' | 'user' | 'assistant';
|
|
3
|
+
content: string;
|
|
4
|
+
}
|
|
5
|
+
export interface CostEstimate {
|
|
6
|
+
inputTokens: number;
|
|
7
|
+
outputTokens: number;
|
|
8
|
+
inputCost: number;
|
|
9
|
+
outputCost: number;
|
|
10
|
+
totalCost: number;
|
|
11
|
+
}
|
|
12
|
+
export interface StreamingResponse {
|
|
13
|
+
content: string;
|
|
14
|
+
finishReason?: string;
|
|
15
|
+
isComplete: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Metin için yaklaşık token sayısı hesaplar
|
|
19
|
+
* Basit heuristic: kelime başına ~1.3 token, karakter başına ~0.25 token
|
|
20
|
+
* @param text - Token sayısı hesaplanacak metin
|
|
21
|
+
* @returns Yaklaşık token sayısı
|
|
22
|
+
*/
|
|
23
|
+
export declare function estimateTokens(text: string): number;
|
|
24
|
+
/**
|
|
25
|
+
* Metni belirli bir token limitine göre kırpar
|
|
26
|
+
* @param text - Kırpılacak metin
|
|
27
|
+
* @param maxTokens - Maksimum token sayısı
|
|
28
|
+
* @returns Kırpılmış metin
|
|
29
|
+
*/
|
|
30
|
+
export declare function truncateToTokenLimit(text: string, maxTokens: number): string;
|
|
31
|
+
/**
|
|
32
|
+
* Metni belirli token limitlerinde parçalara böler
|
|
33
|
+
* @param text - Bölünecek metin
|
|
34
|
+
* @param maxTokens - Her parça için maksimum token sayısı
|
|
35
|
+
* @returns Metin parçaları dizisi
|
|
36
|
+
*/
|
|
37
|
+
export declare function splitByTokenLimit(text: string, maxTokens: number): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Chat mesajı formatında oluşturur
|
|
40
|
+
* @param role - Mesaj rolü (system/user/assistant)
|
|
41
|
+
* @param content - Mesaj içeriği
|
|
42
|
+
* @returns ChatMessage objesi
|
|
43
|
+
*/
|
|
44
|
+
export declare function formatChatMessage(role: 'system' | 'user' | 'assistant', content: string): ChatMessage;
|
|
45
|
+
/**
|
|
46
|
+
* Few-shot öğrenme için prompt oluşturur
|
|
47
|
+
* @param examples - Örnek input/output çiftleri
|
|
48
|
+
* @param query - Kullanıcının sorgusu
|
|
49
|
+
* @returns Formatlanmış few-shot prompt
|
|
50
|
+
*/
|
|
51
|
+
export declare function createFewShotPrompt(examples: Array<{
|
|
52
|
+
input: string;
|
|
53
|
+
output: string;
|
|
54
|
+
}>, query: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Sistem ve kullanıcı promptlarını chat mesajlarına dönüştürür
|
|
57
|
+
* @param systemPrompt - Sistem talimatları
|
|
58
|
+
* @param userPrompt - Kullanıcı sorgusu
|
|
59
|
+
* @returns ChatMessage dizisi
|
|
60
|
+
*/
|
|
61
|
+
export declare function mergeSystemAndUser(systemPrompt: string, userPrompt: string): ChatMessage[];
|
|
62
|
+
/**
|
|
63
|
+
* Mesajları context penceresine sığdırır (eski mesajları çıkarır)
|
|
64
|
+
* @param messages - Mevcut mesajlar
|
|
65
|
+
* @param maxTokens - Maksimum token sayısı
|
|
66
|
+
* @returns Sığdırılmış mesajlar
|
|
67
|
+
*/
|
|
68
|
+
export declare function fitMessagesToContext(messages: ChatMessage[], maxTokens: number): ChatMessage[];
|
|
69
|
+
/**
|
|
70
|
+
* Konuşma maliyetini tahmin eder
|
|
71
|
+
* @param messages - Mesajlar
|
|
72
|
+
* @param model - Model adı
|
|
73
|
+
* @param expectedOutputTokens - Beklenen output token sayısı (varsayılan: input'un %50'si)
|
|
74
|
+
* @returns Maliyet tahmini
|
|
75
|
+
*/
|
|
76
|
+
export declare function estimateConversationCost(messages: ChatMessage[], model?: string, expectedOutputTokens?: number): CostEstimate;
|
|
77
|
+
/**
|
|
78
|
+
* Model için context limitini döndürür
|
|
79
|
+
* @param model - Model adı
|
|
80
|
+
* @returns Token limiti
|
|
81
|
+
*/
|
|
82
|
+
export declare function getModelTokenLimit(model: string): number;
|
|
83
|
+
/**
|
|
84
|
+
* Model için fiyat bilgilerini döndürür
|
|
85
|
+
* @param model - Model adı
|
|
86
|
+
* @returns Input ve output fiyatları (per 1K tokens)
|
|
87
|
+
*/
|
|
88
|
+
export declare function getModelPricing(model: string): {
|
|
89
|
+
input: number;
|
|
90
|
+
output: number;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Markdown formatındaki metinden JSON çıkarır
|
|
94
|
+
* @param text - Markdown formatındaki metin (```json ... ```)
|
|
95
|
+
* @returns Parse edilmiş JSON objesi veya null
|
|
96
|
+
*/
|
|
97
|
+
export declare function extractJSONFromMarkdown(text: string): any;
|
|
98
|
+
/**
|
|
99
|
+
* Streaming response chunk'ını parse eder
|
|
100
|
+
* @param chunk - Streaming chunk
|
|
101
|
+
* @returns StreamingResponse objesi
|
|
102
|
+
*/
|
|
103
|
+
export declare function parseStreamingChunk(chunk: string): StreamingResponse;
|
|
104
|
+
/**
|
|
105
|
+
* Prompt için token sayısı kontrolü yapar ve limit aşımı durumunda uyarır
|
|
106
|
+
* @param prompt - Kontrol edilecek prompt
|
|
107
|
+
* @param maxTokens - Maksimum token sayısı
|
|
108
|
+
* @returns Limit aşıldıysa true
|
|
109
|
+
*/
|
|
110
|
+
export declare function isTokenLimitExceeded(prompt: string, maxTokens: number): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Prompt'u belirli bir yüzde oranında kısaltır
|
|
113
|
+
* @param prompt - Kısaltılacak prompt
|
|
114
|
+
* @param percentage - Kısaltma yüzdesi (0-100)
|
|
115
|
+
* @returns Kısaltılmış prompt
|
|
116
|
+
*/
|
|
117
|
+
export declare function truncatePromptByPercentage(prompt: string, percentage: number): string;
|
|
118
|
+
/**
|
|
119
|
+
* Konuşma geçmişini özetlemek için mesajları sıkıştırır
|
|
120
|
+
* (Eski mesajları birleştirir, son N mesajı ayrı tutar)
|
|
121
|
+
* @param messages - Tüm mesajlar
|
|
122
|
+
* @param keepRecent - Son tutulacak mesaj sayısı
|
|
123
|
+
* @param maxSummaryTokens - Özet için ayrılacak token sayısı
|
|
124
|
+
* @returns Sıkıştırılmış mesajlar
|
|
125
|
+
*/
|
|
126
|
+
export declare function compressConversationHistory(messages: ChatMessage[], keepRecent?: number, maxSummaryTokens?: number): ChatMessage[];
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI Utility Functions
|
|
3
|
+
// LLM/AI çalışmaları için yardımcı fonksiyonlar
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.estimateTokens = estimateTokens;
|
|
6
|
+
exports.truncateToTokenLimit = truncateToTokenLimit;
|
|
7
|
+
exports.splitByTokenLimit = splitByTokenLimit;
|
|
8
|
+
exports.formatChatMessage = formatChatMessage;
|
|
9
|
+
exports.createFewShotPrompt = createFewShotPrompt;
|
|
10
|
+
exports.mergeSystemAndUser = mergeSystemAndUser;
|
|
11
|
+
exports.fitMessagesToContext = fitMessagesToContext;
|
|
12
|
+
exports.estimateConversationCost = estimateConversationCost;
|
|
13
|
+
exports.getModelTokenLimit = getModelTokenLimit;
|
|
14
|
+
exports.getModelPricing = getModelPricing;
|
|
15
|
+
exports.extractJSONFromMarkdown = extractJSONFromMarkdown;
|
|
16
|
+
exports.parseStreamingChunk = parseStreamingChunk;
|
|
17
|
+
exports.isTokenLimitExceeded = isTokenLimitExceeded;
|
|
18
|
+
exports.truncatePromptByPercentage = truncatePromptByPercentage;
|
|
19
|
+
exports.compressConversationHistory = compressConversationHistory;
|
|
20
|
+
// Model bilgileri
|
|
21
|
+
const MODEL_TOKEN_LIMITS = {
|
|
22
|
+
'gpt-4': 8192,
|
|
23
|
+
'gpt-4-32k': 32768,
|
|
24
|
+
'gpt-4-turbo': 128000,
|
|
25
|
+
'gpt-4o': 128000,
|
|
26
|
+
'gpt-4o-mini': 128000,
|
|
27
|
+
'gpt-3.5-turbo': 4096,
|
|
28
|
+
'gpt-3.5-turbo-16k': 16384,
|
|
29
|
+
'claude-3-opus': 200000,
|
|
30
|
+
'claude-3-sonnet': 200000,
|
|
31
|
+
'claude-3-haiku': 200000,
|
|
32
|
+
'claude-2': 100000,
|
|
33
|
+
'gemini-pro': 32768,
|
|
34
|
+
'gemini-ultra': 32768,
|
|
35
|
+
'default': 4096,
|
|
36
|
+
};
|
|
37
|
+
// Model fiyatları (per 1K tokens - USD)
|
|
38
|
+
const MODEL_PRICING = {
|
|
39
|
+
'gpt-4': { input: 0.03, output: 0.06 },
|
|
40
|
+
'gpt-4-32k': { input: 0.06, output: 0.12 },
|
|
41
|
+
'gpt-4-turbo': { input: 0.01, output: 0.03 },
|
|
42
|
+
'gpt-4o': { input: 0.005, output: 0.015 },
|
|
43
|
+
'gpt-4o-mini': { input: 0.00015, output: 0.0006 },
|
|
44
|
+
'gpt-3.5-turbo': { input: 0.0015, output: 0.002 },
|
|
45
|
+
'gpt-3.5-turbo-16k': { input: 0.003, output: 0.004 },
|
|
46
|
+
'claude-3-opus': { input: 0.015, output: 0.075 },
|
|
47
|
+
'claude-3-sonnet': { input: 0.003, output: 0.015 },
|
|
48
|
+
'claude-3-haiku': { input: 0.00025, output: 0.00125 },
|
|
49
|
+
'claude-2': { input: 0.008, output: 0.024 },
|
|
50
|
+
'gemini-pro': { input: 0.0005, output: 0.0015 },
|
|
51
|
+
'gemini-ultra': { input: 0.001, output: 0.003 },
|
|
52
|
+
'default': { input: 0.001, output: 0.002 },
|
|
53
|
+
};
|
|
54
|
+
// Token İşlemleri
|
|
55
|
+
/**
|
|
56
|
+
* Metin için yaklaşık token sayısı hesaplar
|
|
57
|
+
* Basit heuristic: kelime başına ~1.3 token, karakter başına ~0.25 token
|
|
58
|
+
* @param text - Token sayısı hesaplanacak metin
|
|
59
|
+
* @returns Yaklaşık token sayısı
|
|
60
|
+
*/
|
|
61
|
+
function estimateTokens(text) {
|
|
62
|
+
if (!text || text.length === 0)
|
|
63
|
+
return 0;
|
|
64
|
+
// Kelime sayısı (boşluklara göre)
|
|
65
|
+
const wordCount = text.trim().split(/\s+/).length;
|
|
66
|
+
// Karakter sayısı
|
|
67
|
+
const charCount = text.length;
|
|
68
|
+
// Heuristic: kelime başına 1.3 token + karakter başına 0.25 token
|
|
69
|
+
// Bu yaklaşık bir tahmindir, tiktoken gibi kütüphaneler daha doğrudur
|
|
70
|
+
const estimatedTokens = Math.ceil(wordCount * 1.3 + charCount * 0.25);
|
|
71
|
+
return estimatedTokens;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Metni belirli bir token limitine göre kırpar
|
|
75
|
+
* @param text - Kırpılacak metin
|
|
76
|
+
* @param maxTokens - Maksimum token sayısı
|
|
77
|
+
* @returns Kırpılmış metin
|
|
78
|
+
*/
|
|
79
|
+
function truncateToTokenLimit(text, maxTokens) {
|
|
80
|
+
if (!text || estimateTokens(text) <= maxTokens) {
|
|
81
|
+
return text;
|
|
82
|
+
}
|
|
83
|
+
// Binary search ile doğru kesme noktasını bul
|
|
84
|
+
let left = 0;
|
|
85
|
+
let right = text.length;
|
|
86
|
+
let bestLength = 0;
|
|
87
|
+
while (left <= right) {
|
|
88
|
+
const mid = Math.floor((left + right) / 2);
|
|
89
|
+
const truncated = text.substring(0, mid);
|
|
90
|
+
const tokens = estimateTokens(truncated);
|
|
91
|
+
if (tokens <= maxTokens) {
|
|
92
|
+
bestLength = mid;
|
|
93
|
+
left = mid + 1;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
right = mid - 1;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return text.substring(0, bestLength);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Metni belirli token limitlerinde parçalara böler
|
|
103
|
+
* @param text - Bölünecek metin
|
|
104
|
+
* @param maxTokens - Her parça için maksimum token sayısı
|
|
105
|
+
* @returns Metin parçaları dizisi
|
|
106
|
+
*/
|
|
107
|
+
function splitByTokenLimit(text, maxTokens) {
|
|
108
|
+
if (!text || text.length === 0)
|
|
109
|
+
return [];
|
|
110
|
+
const chunks = [];
|
|
111
|
+
let remaining = text;
|
|
112
|
+
while (remaining.length > 0) {
|
|
113
|
+
if (estimateTokens(remaining) <= maxTokens) {
|
|
114
|
+
chunks.push(remaining);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
// Binary search ile token limitine sığan en uzun kısmı bul
|
|
118
|
+
let left = 0;
|
|
119
|
+
let right = remaining.length;
|
|
120
|
+
let bestLength = 0;
|
|
121
|
+
while (left <= right) {
|
|
122
|
+
const mid = Math.floor((left + right) / 2);
|
|
123
|
+
const testText = remaining.substring(0, mid);
|
|
124
|
+
const tokens = estimateTokens(testText);
|
|
125
|
+
if (tokens <= maxTokens) {
|
|
126
|
+
bestLength = mid;
|
|
127
|
+
left = mid + 1;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
right = mid - 1;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// En iyi kesme noktasını bul (cümle/paragraf/kelime sonu)
|
|
134
|
+
let cutPoint = findBestCutPoint(remaining, bestLength);
|
|
135
|
+
chunks.push(remaining.substring(0, cutPoint));
|
|
136
|
+
remaining = remaining.substring(cutPoint).trim();
|
|
137
|
+
}
|
|
138
|
+
return chunks;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* En iyi kesme noktasını bulur (cümle/paragraf sonu tercih eder)
|
|
142
|
+
*/
|
|
143
|
+
function findBestCutPoint(text, maxLength) {
|
|
144
|
+
// Cümle sonu ara (.!? followed by space)
|
|
145
|
+
const textToSearch = text.substring(0, maxLength);
|
|
146
|
+
const sentenceMatches = textToSearch.match(/[.!?]\s+/g);
|
|
147
|
+
if (sentenceMatches) {
|
|
148
|
+
const lastSentenceEnd = textToSearch.lastIndexOf(sentenceMatches[sentenceMatches.length - 1]);
|
|
149
|
+
if (lastSentenceEnd > maxLength * 0.5) {
|
|
150
|
+
return lastSentenceEnd + 2;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Paragraf sonu ara
|
|
154
|
+
const paragraphEnd = textToSearch.lastIndexOf('\n\n');
|
|
155
|
+
if (paragraphEnd > maxLength * 0.3) {
|
|
156
|
+
return paragraphEnd + 2;
|
|
157
|
+
}
|
|
158
|
+
// Kelime sonu ara
|
|
159
|
+
const lastSpace = textToSearch.lastIndexOf(' ');
|
|
160
|
+
if (lastSpace > maxLength * 0.8) {
|
|
161
|
+
return lastSpace + 1;
|
|
162
|
+
}
|
|
163
|
+
return maxLength;
|
|
164
|
+
}
|
|
165
|
+
// Prompt Yönetimi
|
|
166
|
+
/**
|
|
167
|
+
* Chat mesajı formatında oluşturur
|
|
168
|
+
* @param role - Mesaj rolü (system/user/assistant)
|
|
169
|
+
* @param content - Mesaj içeriği
|
|
170
|
+
* @returns ChatMessage objesi
|
|
171
|
+
*/
|
|
172
|
+
function formatChatMessage(role, content) {
|
|
173
|
+
return { role, content };
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Few-shot öğrenme için prompt oluşturur
|
|
177
|
+
* @param examples - Örnek input/output çiftleri
|
|
178
|
+
* @param query - Kullanıcının sorgusu
|
|
179
|
+
* @returns Formatlanmış few-shot prompt
|
|
180
|
+
*/
|
|
181
|
+
function createFewShotPrompt(examples, query) {
|
|
182
|
+
let prompt = '';
|
|
183
|
+
for (const example of examples) {
|
|
184
|
+
prompt += `Input: ${example.input}\n`;
|
|
185
|
+
prompt += `Output: ${example.output}\n\n`;
|
|
186
|
+
}
|
|
187
|
+
prompt += `Input: ${query}\n`;
|
|
188
|
+
prompt += 'Output:';
|
|
189
|
+
return prompt;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Sistem ve kullanıcı promptlarını chat mesajlarına dönüştürür
|
|
193
|
+
* @param systemPrompt - Sistem talimatları
|
|
194
|
+
* @param userPrompt - Kullanıcı sorgusu
|
|
195
|
+
* @returns ChatMessage dizisi
|
|
196
|
+
*/
|
|
197
|
+
function mergeSystemAndUser(systemPrompt, userPrompt) {
|
|
198
|
+
return [
|
|
199
|
+
{ role: 'system', content: systemPrompt },
|
|
200
|
+
{ role: 'user', content: userPrompt }
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
// Context & Conversation
|
|
204
|
+
/**
|
|
205
|
+
* Mesajları context penceresine sığdırır (eski mesajları çıkarır)
|
|
206
|
+
* @param messages - Mevcut mesajlar
|
|
207
|
+
* @param maxTokens - Maksimum token sayısı
|
|
208
|
+
* @returns Sığdırılmış mesajlar
|
|
209
|
+
*/
|
|
210
|
+
function fitMessagesToContext(messages, maxTokens) {
|
|
211
|
+
if (!messages || messages.length === 0)
|
|
212
|
+
return [];
|
|
213
|
+
let totalTokens = 0;
|
|
214
|
+
const fittedMessages = [];
|
|
215
|
+
// Sondan başa doğru ekle (en yeni mesajlar önemli)
|
|
216
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
217
|
+
const message = messages[i];
|
|
218
|
+
const messageTokens = estimateTokens(message.content) + 4; // +4 for role tokens
|
|
219
|
+
if (totalTokens + messageTokens <= maxTokens) {
|
|
220
|
+
fittedMessages.unshift(message);
|
|
221
|
+
totalTokens += messageTokens;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return fittedMessages;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Konuşma maliyetini tahmin eder
|
|
231
|
+
* @param messages - Mesajlar
|
|
232
|
+
* @param model - Model adı
|
|
233
|
+
* @param expectedOutputTokens - Beklenen output token sayısı (varsayılan: input'un %50'si)
|
|
234
|
+
* @returns Maliyet tahmini
|
|
235
|
+
*/
|
|
236
|
+
function estimateConversationCost(messages, model = 'default', expectedOutputTokens) {
|
|
237
|
+
// Input token sayısı
|
|
238
|
+
let inputTokens = 0;
|
|
239
|
+
for (const message of messages) {
|
|
240
|
+
inputTokens += estimateTokens(message.content) + 4; // +4 for role tokens
|
|
241
|
+
}
|
|
242
|
+
// Output token sayısı (tahmin)
|
|
243
|
+
const outputTokens = expectedOutputTokens ?? Math.ceil(inputTokens * 0.5);
|
|
244
|
+
// Fiyatları al
|
|
245
|
+
const pricing = MODEL_PRICING[model] || MODEL_PRICING['default'];
|
|
246
|
+
const inputCost = (inputTokens / 1000) * pricing.input;
|
|
247
|
+
const outputCost = (outputTokens / 1000) * pricing.output;
|
|
248
|
+
return {
|
|
249
|
+
inputTokens,
|
|
250
|
+
outputTokens,
|
|
251
|
+
inputCost,
|
|
252
|
+
outputCost,
|
|
253
|
+
totalCost: inputCost + outputCost
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// Model Bilgileri
|
|
257
|
+
/**
|
|
258
|
+
* Model için context limitini döndürür
|
|
259
|
+
* @param model - Model adı
|
|
260
|
+
* @returns Token limiti
|
|
261
|
+
*/
|
|
262
|
+
function getModelTokenLimit(model) {
|
|
263
|
+
return MODEL_TOKEN_LIMITS[model] || MODEL_TOKEN_LIMITS['default'];
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Model için fiyat bilgilerini döndürür
|
|
267
|
+
* @param model - Model adı
|
|
268
|
+
* @returns Input ve output fiyatları (per 1K tokens)
|
|
269
|
+
*/
|
|
270
|
+
function getModelPricing(model) {
|
|
271
|
+
return MODEL_PRICING[model] || MODEL_PRICING['default'];
|
|
272
|
+
}
|
|
273
|
+
// Output İşlemleri
|
|
274
|
+
/**
|
|
275
|
+
* Markdown formatındaki metinden JSON çıkarır
|
|
276
|
+
* @param text - Markdown formatındaki metin (```json ... ```)
|
|
277
|
+
* @returns Parse edilmiş JSON objesi veya null
|
|
278
|
+
*/
|
|
279
|
+
function extractJSONFromMarkdown(text) {
|
|
280
|
+
if (!text)
|
|
281
|
+
return null;
|
|
282
|
+
// ```json ... ``` veya ``` ... ``` bloklarını ara
|
|
283
|
+
const jsonRegex = /```(?:json)?\s*([\s\S]*?)```/;
|
|
284
|
+
const match = text.match(jsonRegex);
|
|
285
|
+
if (match && match[1]) {
|
|
286
|
+
try {
|
|
287
|
+
return JSON.parse(match[1].trim());
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Markdown yoksa direkt parse dene
|
|
294
|
+
try {
|
|
295
|
+
return JSON.parse(text.trim());
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Streaming response chunk'ını parse eder
|
|
303
|
+
* @param chunk - Streaming chunk
|
|
304
|
+
* @returns StreamingResponse objesi
|
|
305
|
+
*/
|
|
306
|
+
function parseStreamingChunk(chunk) {
|
|
307
|
+
if (!chunk) {
|
|
308
|
+
return { content: '', isComplete: true };
|
|
309
|
+
}
|
|
310
|
+
// OpenAI formatı: data: {...}
|
|
311
|
+
if (chunk.startsWith('data: ')) {
|
|
312
|
+
const jsonStr = chunk.substring(6).trim();
|
|
313
|
+
if (jsonStr === '[DONE]') {
|
|
314
|
+
return { content: '', isComplete: true };
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
const data = JSON.parse(jsonStr);
|
|
318
|
+
const content = data.choices?.[0]?.delta?.content || '';
|
|
319
|
+
const finishReason = data.choices?.[0]?.finish_reason;
|
|
320
|
+
return {
|
|
321
|
+
content,
|
|
322
|
+
finishReason,
|
|
323
|
+
isComplete: finishReason !== null && finishReason !== undefined
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
return { content: '', isComplete: false };
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
// Düz metin
|
|
331
|
+
return {
|
|
332
|
+
content: chunk,
|
|
333
|
+
isComplete: false
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
// Yardımcı Fonksiyonlar
|
|
337
|
+
/**
|
|
338
|
+
* Prompt için token sayısı kontrolü yapar ve limit aşımı durumunda uyarır
|
|
339
|
+
* @param prompt - Kontrol edilecek prompt
|
|
340
|
+
* @param maxTokens - Maksimum token sayısı
|
|
341
|
+
* @returns Limit aşıldıysa true
|
|
342
|
+
*/
|
|
343
|
+
function isTokenLimitExceeded(prompt, maxTokens) {
|
|
344
|
+
return estimateTokens(prompt) > maxTokens;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Prompt'u belirli bir yüzde oranında kısaltır
|
|
348
|
+
* @param prompt - Kısaltılacak prompt
|
|
349
|
+
* @param percentage - Kısaltma yüzdesi (0-100)
|
|
350
|
+
* @returns Kısaltılmış prompt
|
|
351
|
+
*/
|
|
352
|
+
function truncatePromptByPercentage(prompt, percentage) {
|
|
353
|
+
if (percentage <= 0)
|
|
354
|
+
return prompt;
|
|
355
|
+
if (percentage >= 100)
|
|
356
|
+
return '';
|
|
357
|
+
const targetLength = Math.floor(prompt.length * (1 - percentage / 100));
|
|
358
|
+
return prompt.substring(0, targetLength);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Konuşma geçmişini özetlemek için mesajları sıkıştırır
|
|
362
|
+
* (Eski mesajları birleştirir, son N mesajı ayrı tutar)
|
|
363
|
+
* @param messages - Tüm mesajlar
|
|
364
|
+
* @param keepRecent - Son tutulacak mesaj sayısı
|
|
365
|
+
* @param maxSummaryTokens - Özet için ayrılacak token sayısı
|
|
366
|
+
* @returns Sıkıştırılmış mesajlar
|
|
367
|
+
*/
|
|
368
|
+
function compressConversationHistory(messages, keepRecent = 4, maxSummaryTokens = 500) {
|
|
369
|
+
if (messages.length <= keepRecent) {
|
|
370
|
+
return messages;
|
|
371
|
+
}
|
|
372
|
+
// Son mesajları ayır
|
|
373
|
+
const recentMessages = messages.slice(-keepRecent);
|
|
374
|
+
// Eski mesajları al ve özetle (basit birleştirme)
|
|
375
|
+
const oldMessages = messages.slice(0, -keepRecent);
|
|
376
|
+
let summary = 'Previous conversation summary:\n';
|
|
377
|
+
for (const msg of oldMessages) {
|
|
378
|
+
const prefix = msg.role === 'user' ? 'User' : 'Assistant';
|
|
379
|
+
summary += `${prefix}: ${msg.content.substring(0, 100)}${msg.content.length > 100 ? '...' : ''}\n`;
|
|
380
|
+
}
|
|
381
|
+
// Özeti kırp
|
|
382
|
+
summary = truncateToTokenLimit(summary, maxSummaryTokens);
|
|
383
|
+
return [
|
|
384
|
+
{ role: 'system', content: summary },
|
|
385
|
+
...recentMessages
|
|
386
|
+
];
|
|
387
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as security from './security';
|
|
2
2
|
import * as toon from './toon';
|
|
3
|
+
import * as ai from './ai';
|
|
3
4
|
export declare function makeUniqueId(): string;
|
|
4
5
|
export declare function randomArray<T>(arr: T[]): T;
|
|
5
6
|
export declare function randomText(length?: number): string;
|
|
@@ -197,3 +198,26 @@ export declare const toon_module: {
|
|
|
197
198
|
stringify: typeof toon.stringify;
|
|
198
199
|
parse: typeof toon.parse;
|
|
199
200
|
};
|
|
201
|
+
export declare const ai_module: {
|
|
202
|
+
estimateTokens(text: string): number;
|
|
203
|
+
truncateToTokenLimit(text: string, maxTokens: number): string;
|
|
204
|
+
splitByTokenLimit(text: string, maxTokens: number): string[];
|
|
205
|
+
formatChatMessage(role: "system" | "user" | "assistant", content: string): ai.ChatMessage;
|
|
206
|
+
createFewShotPrompt(examples: Array<{
|
|
207
|
+
input: string;
|
|
208
|
+
output: string;
|
|
209
|
+
}>, query: string): string;
|
|
210
|
+
mergeSystemAndUser(systemPrompt: string, userPrompt: string): ai.ChatMessage[];
|
|
211
|
+
fitMessagesToContext(messages: ai.ChatMessage[], maxTokens: number): ai.ChatMessage[];
|
|
212
|
+
estimateConversationCost(messages: ai.ChatMessage[], model?: string, expectedOutputTokens?: number): ai.CostEstimate;
|
|
213
|
+
getModelTokenLimit(model: string): number;
|
|
214
|
+
getModelPricing(model: string): {
|
|
215
|
+
input: number;
|
|
216
|
+
output: number;
|
|
217
|
+
};
|
|
218
|
+
extractJSONFromMarkdown(text: string): any;
|
|
219
|
+
parseStreamingChunk(chunk: string): ai.StreamingResponse;
|
|
220
|
+
isTokenLimitExceeded(prompt: string, maxTokens: number): boolean;
|
|
221
|
+
truncatePromptByPercentage(prompt: string, percentage: number): string;
|
|
222
|
+
compressConversationHistory(messages: ai.ChatMessage[], keepRecent?: number, maxSummaryTokens?: number): ai.ChatMessage[];
|
|
223
|
+
};
|
package/dist/functions/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.toon_module = exports.worker_module = exports.security_module = exports.logger_module = exports.validation_module = exports.math_module = exports.crypto_module = exports.object_module = exports.array_module = exports.string_module = exports.random_module = exports.date_module = exports.http_module = exports.Logger = void 0;
|
|
39
|
+
exports.ai_module = exports.toon_module = exports.worker_module = exports.security_module = exports.logger_module = exports.validation_module = exports.math_module = exports.crypto_module = exports.object_module = exports.array_module = exports.string_module = exports.random_module = exports.date_module = exports.http_module = exports.Logger = void 0;
|
|
40
40
|
exports.makeUniqueId = makeUniqueId;
|
|
41
41
|
exports.randomArray = randomArray;
|
|
42
42
|
exports.randomText = randomText;
|
|
@@ -104,6 +104,7 @@ const url_1 = require("url");
|
|
|
104
104
|
const security = __importStar(require("./security"));
|
|
105
105
|
const worker = __importStar(require("./worker"));
|
|
106
106
|
const toon = __importStar(require("./toon"));
|
|
107
|
+
const ai = __importStar(require("./ai"));
|
|
107
108
|
// Random İşlemler
|
|
108
109
|
function makeUniqueId() {
|
|
109
110
|
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
@@ -680,3 +681,6 @@ exports.toon_module = {
|
|
|
680
681
|
stringify: toon.stringify,
|
|
681
682
|
parse: toon.parse
|
|
682
683
|
};
|
|
684
|
+
exports.ai_module = {
|
|
685
|
+
...ai
|
|
686
|
+
};
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onurege3467/zerohelper",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.3.0",
|
|
4
4
|
"description": "ZeroHelper is a versatile high-performance utility library and database framework for Node.js, fully written in TypeScript.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onurege3467/zerohelper",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.3.0",
|
|
4
4
|
"description": "ZeroHelper is a versatile high-performance utility library and database framework for Node.js, fully written in TypeScript.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|