ohlcv-ai 1.0.9 → 1.1.1
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/LICENSE +661 -202
- package/dist/index.d.ts +160 -43
- package/dist/index.js +205 -32
- package/dist/index.mjs +1182 -655
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var
|
|
2
|
-
const
|
|
1
|
+
var O = /* @__PURE__ */ ((n) => (n.QWEN_TURBO = "qwen-turbo", n.QWEN_PLUS = "qwen-plus", n.QWEN_MAX = "qwen-max", n.QWEN_MAX_LONGCONTEXT = "qwen-max-longcontext", n.QWEN_2_5B = "qwen2.5-0.5b", n.QWEN_2_5B_INSTRUCT = "qwen2.5-0.5b-instruct", n.QWEN_2_5B_7B = "qwen2.5-7b", n.QWEN_2_5B_7B_INSTRUCT = "qwen2.5-7b-instruct", n.QWEN_2_5B_14B = "qwen2.5-14b", n.QWEN_2_5B_14B_INSTRUCT = "qwen2.5-14b-instruct", n.QWEN_2_5B_32B = "qwen2.5-32b", n.QWEN_2_5B_32B_INSTRUCT = "qwen2.5-32b-instruct", n.QWEN_2_5B_72B = "qwen2.5-72b", n.QWEN_2_5B_72B_INSTRUCT = "qwen2.5-72b-instruct", n.QWEN_2_5B_CODER = "qwen2.5-coder", n.QWEN_2_5B_CODER_7B = "qwen2.5-coder-7b", n.QWEN_2_5B_CODER_14B = "qwen2.5-coder-14b", n.QWEN_2_5B_CODER_32B = "qwen2.5-coder-32b", n.QWEN_VL_LITE = "qwen-vl-lite", n.QWEN_VL_PLUS = "qwen-vl-plus", n.QWEN_VL_MAX = "qwen-vl-max", n.QWEN_AUDIO_TURBO = "qwen-audio-turbo", n.QWEN_AUDIO_CHAT = "qwen-audio-chat", n.QWEN_MATH_7B = "qwen-math-7b", n.LLAMA2_7B_CHAT_V2 = "llama2-7b-chat-v2", n.BAICHUAN2_7B_CHAT_V1 = "baichuan2-7b-chat-v1", n.QWEN_FINANCIAL = "qwen-financial", n.QWEN_FINANCIAL_14B = "qwen-financial-14b", n.QWEN_FINANCIAL_32B = "qwen-financial-32b", n.QWEN_MEDICAL = "qwen-medical", n.QWEN_MEDICAL_14B = "qwen-medical-14b", n.QWEN_MEDICAL_32B = "qwen-medical-32b", n.QWEN_OMNI = "qwen-omni", n.QWEN_OMNI_PRO = "qwen-omni-pro", n))(O || {});
|
|
2
|
+
const k = /* @__PURE__ */ new Map([
|
|
3
3
|
[
|
|
4
4
|
"qwen-turbo",
|
|
5
5
|
{
|
|
@@ -358,28 +358,28 @@ const b = /* @__PURE__ */ new Map([
|
|
|
358
358
|
}
|
|
359
359
|
]
|
|
360
360
|
]);
|
|
361
|
-
function
|
|
362
|
-
return
|
|
361
|
+
function V(n) {
|
|
362
|
+
return k.get(n);
|
|
363
363
|
}
|
|
364
|
-
function
|
|
365
|
-
return Array.from(
|
|
364
|
+
function R() {
|
|
365
|
+
return Array.from(k.values());
|
|
366
366
|
}
|
|
367
|
-
function
|
|
368
|
-
for (const e of
|
|
369
|
-
if (e.name ===
|
|
367
|
+
function A(n) {
|
|
368
|
+
for (const e of k.values())
|
|
369
|
+
if (e.name === n)
|
|
370
370
|
return e;
|
|
371
371
|
}
|
|
372
|
-
function
|
|
373
|
-
return Array.from(
|
|
372
|
+
function I() {
|
|
373
|
+
return Array.from(k.keys());
|
|
374
374
|
}
|
|
375
|
-
function
|
|
376
|
-
const e = Object.values(
|
|
377
|
-
for (const
|
|
378
|
-
if (
|
|
379
|
-
return
|
|
375
|
+
function D(n) {
|
|
376
|
+
const e = Object.values(O);
|
|
377
|
+
for (const t of e)
|
|
378
|
+
if (t === n)
|
|
379
|
+
return t;
|
|
380
380
|
return null;
|
|
381
381
|
}
|
|
382
|
-
class
|
|
382
|
+
class q {
|
|
383
383
|
/**
|
|
384
384
|
* Constructor - Minimal configuration
|
|
385
385
|
* @param config.apiKey - API key (required)
|
|
@@ -387,67 +387,326 @@ class _ {
|
|
|
387
387
|
* @param config.timeout - Timeout, default 30 seconds
|
|
388
388
|
*/
|
|
389
389
|
constructor(e) {
|
|
390
|
-
if (this.apiKey = e.apiKey, this.modelType = e.modelType ||
|
|
390
|
+
if (this.apiKey = e.apiKey, this.modelType = e.modelType || O.QWEN_TURBO, this.timeout = e.timeout || 3e4, !this.apiKey)
|
|
391
391
|
throw new Error("API Key cannot be empty");
|
|
392
|
-
if (!
|
|
392
|
+
if (!k.get(this.modelType))
|
|
393
393
|
throw new Error(`Unsupported model type: ${this.modelType}`);
|
|
394
394
|
}
|
|
395
395
|
/**
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
396
|
+
* Simplest method: single conversation
|
|
397
|
+
* @param message - User message
|
|
398
|
+
* @param i18n - Language restriction for AI response
|
|
399
|
+
* @param options - Chat options
|
|
400
|
+
* @returns AI response
|
|
401
|
+
*/
|
|
402
|
+
async chat(e, t, s) {
|
|
403
|
+
const a = [], r = t === "en" ? "Please respond in English only." : t === "cn" ? "请使用中文回答。" : "";
|
|
404
|
+
if (s?.systemPrompt || r) {
|
|
405
|
+
const i = [s?.systemPrompt, r].filter(Boolean).join(`
|
|
406
|
+
`);
|
|
407
|
+
a.push({ role: "system", content: i });
|
|
408
|
+
}
|
|
409
|
+
a.push({ role: "user", content: e });
|
|
410
|
+
const o = await this.chatCompletion(a, t, {
|
|
411
|
+
temperature: s?.temperature,
|
|
412
|
+
maxTokens: s?.maxTokens,
|
|
413
|
+
stream: !1,
|
|
414
|
+
modelType: this.modelType
|
|
408
415
|
});
|
|
409
|
-
return this.extractContent(
|
|
416
|
+
return this.extractContent(o);
|
|
410
417
|
}
|
|
411
418
|
/**
|
|
412
419
|
* Multi-turn conversation
|
|
413
420
|
* @param messages - Message history
|
|
421
|
+
* @param i18n - Language restriction for AI response
|
|
414
422
|
* @param options - Chat options
|
|
415
423
|
* @returns Complete API response
|
|
416
424
|
*/
|
|
417
|
-
async chatCompletion(e,
|
|
418
|
-
const
|
|
419
|
-
if (!
|
|
420
|
-
throw new Error(`Unsupported model type: ${
|
|
421
|
-
const
|
|
425
|
+
async chatCompletion(e, t, s) {
|
|
426
|
+
const a = s?.modelType || this.modelType, r = k.get(a);
|
|
427
|
+
if (!r)
|
|
428
|
+
throw new Error(`Unsupported model type: ${a}`);
|
|
429
|
+
const o = s?.temperature ?? 0.7, i = s?.maxTokens ?? 1e3, d = s?.stream ?? !1, l = t === "en" ? "Please respond in English only." : t === "cn" ? "请使用中文回答。" : "";
|
|
430
|
+
l && (e.some((g) => g.role === "system") ? e = e.map((g) => g.role === "system" ? {
|
|
431
|
+
...g,
|
|
432
|
+
content: `${g.content}
|
|
433
|
+
${l}`
|
|
434
|
+
} : g) : e.unshift({ role: "system", content: l }));
|
|
435
|
+
const u = r.endpoint, c = r.format === "openai" ? this.buildOpenAIRequest(r.name, e, o, i, d) : this.buildDashScopeRequest(r.name, e, o, i);
|
|
422
436
|
try {
|
|
423
|
-
return await this.makeRequest(
|
|
424
|
-
} catch (
|
|
425
|
-
throw new Error(`Aliyun AI request failed: ${
|
|
437
|
+
return await this.makeRequest(u, c, d);
|
|
438
|
+
} catch (p) {
|
|
439
|
+
throw new Error(`Aliyun AI request failed: ${p.message}`);
|
|
426
440
|
}
|
|
427
441
|
}
|
|
428
442
|
/**
|
|
429
443
|
* Streaming conversation (only supports OpenAI format)
|
|
430
444
|
* @param messages - Message history
|
|
431
445
|
* @param callback - Streaming callback function
|
|
446
|
+
* @param i18n - Language restriction for AI response
|
|
432
447
|
* @param options - Chat options
|
|
433
448
|
*/
|
|
434
|
-
async chatStream(e,
|
|
435
|
-
const
|
|
436
|
-
if (!
|
|
437
|
-
throw new Error(`Unsupported model type: ${
|
|
438
|
-
if (
|
|
449
|
+
async chatStream(e, t, s, a) {
|
|
450
|
+
const r = a?.modelType || this.modelType, o = k.get(r);
|
|
451
|
+
if (!o)
|
|
452
|
+
throw new Error(`Unsupported model type: ${r}`);
|
|
453
|
+
if (o.format !== "openai")
|
|
439
454
|
throw new Error("Streaming conversation only supports OpenAI format models");
|
|
440
|
-
const
|
|
441
|
-
|
|
455
|
+
const i = a?.temperature ?? 0.7, d = a?.maxTokens ?? 1e3, l = s === "en" ? "Please respond in English only." : s === "cn" ? "请使用中文回答。" : "";
|
|
456
|
+
l && (e.some((c) => c.role === "system") ? e = e.map((c) => c.role === "system" ? {
|
|
457
|
+
...c,
|
|
458
|
+
content: `${c.content}
|
|
459
|
+
${l}`
|
|
460
|
+
} : c) : e.unshift({ role: "system", content: l }));
|
|
461
|
+
const u = this.buildOpenAIRequest(
|
|
462
|
+
o.name,
|
|
442
463
|
e,
|
|
443
|
-
|
|
444
|
-
|
|
464
|
+
i,
|
|
465
|
+
d,
|
|
445
466
|
!0
|
|
446
467
|
);
|
|
447
468
|
try {
|
|
448
|
-
await this.makeStreamRequest(
|
|
449
|
-
} catch (
|
|
450
|
-
throw new Error(`Streaming request failed: ${
|
|
469
|
+
await this.makeStreamRequest(o.endpoint, u, t);
|
|
470
|
+
} catch (m) {
|
|
471
|
+
throw new Error(`Streaming request failed: ${m.message}`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Analyze OHLCV data and return AI analysis results
|
|
476
|
+
* @param ohlcvArray - OHLCV data array
|
|
477
|
+
* @param i18n - Language restriction for AI response
|
|
478
|
+
* @param analysisType - Analysis type (optional, default: "comprehensive")
|
|
479
|
+
* - "trend": Trend analysis
|
|
480
|
+
* - "volume": Volume analysis
|
|
481
|
+
* - "technical": Technical analysis
|
|
482
|
+
* - "comprehensive": Comprehensive analysis
|
|
483
|
+
* @param message - User's subjective request or specific question (optional)
|
|
484
|
+
* @param options - Chat options
|
|
485
|
+
* @returns AI analysis result of OHLCV data (text description)
|
|
486
|
+
*/
|
|
487
|
+
async analyzeOHLCV(e, t, s, a, r) {
|
|
488
|
+
const o = s || "comprehensive", i = e.length, l = {
|
|
489
|
+
trend: t === "en" ? "Provide a detailed trend analysis of this OHLCV data, including price direction, support/resistance levels, and trend strength." : "提供详细的OHLCV数据趋势分析,包括价格方向、支撑/阻力位和趋势强度。",
|
|
490
|
+
volume: t === "en" ? "Analyze the volume patterns in this OHLCV data, including volume trends, unusual volume spikes, and volume-price relationships." : "分析OHLCV数据中的成交量模式,包括成交量趋势、异常成交量波动和量价关系。",
|
|
491
|
+
technical: t === "en" ? "Perform technical analysis on this OHLCV data, identifying potential technical indicators, patterns, and trading signals." : "对OHLCV数据进行技术分析,识别潜在的技术指标、图表形态和交易信号。",
|
|
492
|
+
comprehensive: t === "en" ? "Provide a comprehensive analysis of this OHLCV data, covering trends, volume, technical aspects, and potential market implications." : "提供全面的OHLCV数据分析,涵盖趋势、成交量、技术面和潜在市场影响。"
|
|
493
|
+
}[o], u = t === "en" ? "Please provide your analysis in English." : "请用中文进行分析。";
|
|
494
|
+
let m = "";
|
|
495
|
+
if (i > 0) {
|
|
496
|
+
const h = e[0], f = e[i - 1].close - h.close, w = f / h.close * 100;
|
|
497
|
+
let C = h.high, v = h.low, P = 0;
|
|
498
|
+
for (const E of e)
|
|
499
|
+
E.high > C && (C = E.high), E.low < v && (v = E.low), P += E.volume;
|
|
500
|
+
const _ = P / i;
|
|
501
|
+
m = t === "en" ? `This dataset contains ${i} periods of OHLCV data.
|
|
502
|
+
Price range: ${v.toFixed(2)} - ${C.toFixed(2)}
|
|
503
|
+
Overall price change: ${f >= 0 ? "+" : ""}${f.toFixed(2)} (${f >= 0 ? "+" : ""}${w.toFixed(2)}%)
|
|
504
|
+
Average volume: ${_.toFixed(0)}` : `该数据集包含 ${i} 个周期的OHLCV数据。
|
|
505
|
+
价格范围:${v.toFixed(2)} - ${C.toFixed(2)}
|
|
506
|
+
总体价格变化:${f >= 0 ? "+" : ""}${f.toFixed(2)} (${f >= 0 ? "+" : ""}${w.toFixed(2)}%)
|
|
507
|
+
平均成交量:${_.toFixed(0)}`;
|
|
508
|
+
}
|
|
509
|
+
let c = t === "en" ? `You are a professional financial data analyst. Your task is to analyze OHLCV (Open, High, Low, Close, Volume) data and provide insights.
|
|
510
|
+
Analysis focus: ${l}
|
|
511
|
+
${m ? `Data characteristics:
|
|
512
|
+
${m}
|
|
513
|
+
|
|
514
|
+
` : ""}
|
|
515
|
+
Please provide:
|
|
516
|
+
1. Clear and structured analysis
|
|
517
|
+
2. Key observations from the data
|
|
518
|
+
3. Potential implications or insights
|
|
519
|
+
4. Recommendations or considerations (if applicable)
|
|
520
|
+
Format your response as a well-organized text analysis.` : `您是一位专业的金融数据分析师。您的任务是分析OHLCV(开盘价、最高价、最低价、收盘价、成交量)数据并提供见解。
|
|
521
|
+
分析重点:${l}
|
|
522
|
+
${m ? `数据特征:
|
|
523
|
+
${m}
|
|
524
|
+
|
|
525
|
+
` : ""}
|
|
526
|
+
请提供:
|
|
527
|
+
1. 清晰且有结构的分析
|
|
528
|
+
2. 数据的关键观察结果
|
|
529
|
+
3. 潜在的启示或见解
|
|
530
|
+
4. 建议或注意事项(如适用)
|
|
531
|
+
请以组织良好的文本分析形式回复。`;
|
|
532
|
+
c += `
|
|
533
|
+
|
|
534
|
+
${u}`;
|
|
535
|
+
const p = JSON.stringify(e, null, 2);
|
|
536
|
+
let g = "";
|
|
537
|
+
a ? g = t === "en" ? `Here is the OHLCV data (${i} periods):
|
|
538
|
+
${p}
|
|
539
|
+
My specific question or request: ${a}
|
|
540
|
+
Please analyze this data considering my request above.` : `这是OHLCV数据(${i}个周期):
|
|
541
|
+
${p}
|
|
542
|
+
我的具体问题或需求:${a}
|
|
543
|
+
请根据我的上述需求分析这些数据。` : g = t === "en" ? `Here is the OHLCV data (${i} periods):
|
|
544
|
+
${p}
|
|
545
|
+
Please analyze this data as requested.` : `这是OHLCV数据(${i}个周期):
|
|
546
|
+
${p}
|
|
547
|
+
请按要求分析这些数据。`;
|
|
548
|
+
const y = [
|
|
549
|
+
{ role: "system", content: c },
|
|
550
|
+
{ role: "user", content: g }
|
|
551
|
+
];
|
|
552
|
+
try {
|
|
553
|
+
const h = await this.chatCompletion(y, t, {
|
|
554
|
+
temperature: r?.temperature || 0.5,
|
|
555
|
+
maxTokens: r?.maxTokens || 1500,
|
|
556
|
+
stream: !1,
|
|
557
|
+
modelType: this.modelType
|
|
558
|
+
});
|
|
559
|
+
return this.extractContent(h);
|
|
560
|
+
} catch (h) {
|
|
561
|
+
throw new Error(`OHLCV analysis failed: ${h.message}`);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Enhanced version: Analyze OHLCV and return structured results (optional)
|
|
566
|
+
* @param ohlcvArray - OHLCV data array
|
|
567
|
+
* @param i18n - Language restriction for AI response
|
|
568
|
+
* @param analysisType - Analysis type
|
|
569
|
+
* @param message - User's subjective request or specific question
|
|
570
|
+
* @param structured - Whether to return structured results (default: false)
|
|
571
|
+
* @param options - Chat options
|
|
572
|
+
* @returns AI analysis results
|
|
573
|
+
*/
|
|
574
|
+
async analyzeOHLCVEnhanced(e, t, s, a, r = !1, o) {
|
|
575
|
+
if (r) {
|
|
576
|
+
const i = t === "en" ? `You are a professional financial data analyst. Analyze the OHLCV data and provide a structured response with:
|
|
577
|
+
1. Summary (brief overview)
|
|
578
|
+
2. Details (key observations, 3-5 points)
|
|
579
|
+
3. Recommendations (actionable insights, 2-3 points)
|
|
580
|
+
Format as JSON: {"summary": "...", "details": ["...", "..."], "recommendations": ["...", "..."]}` : `您是一位专业的金融数据分析师。分析OHLCV数据并提供结构化响应:
|
|
581
|
+
1. 总结(简要概述)
|
|
582
|
+
2. 详情(关键观察结果,3-5点)
|
|
583
|
+
3. 建议(可操作的见解,2-3点)
|
|
584
|
+
格式化为JSON:{"summary": "...", "details": ["...", "..."], "recommendations": ["...", "..."]}`, d = JSON.stringify(e, null, 2);
|
|
585
|
+
let l = t === "en" ? `Analyze this OHLCV data (${e.length} periods):
|
|
586
|
+
${d}` : `分析此OHLCV数据(${e.length}个周期):
|
|
587
|
+
${d}`;
|
|
588
|
+
a && (l += t === "en" ? `
|
|
589
|
+
|
|
590
|
+
Additional request: ${a}` : `
|
|
591
|
+
|
|
592
|
+
附加要求:${a}`);
|
|
593
|
+
const u = [
|
|
594
|
+
{ role: "system", content: i },
|
|
595
|
+
{ role: "user", content: l }
|
|
596
|
+
];
|
|
597
|
+
try {
|
|
598
|
+
const m = await this.chatCompletion(u, t, {
|
|
599
|
+
temperature: o?.temperature || 0.4,
|
|
600
|
+
maxTokens: o?.maxTokens || 1200,
|
|
601
|
+
stream: !1,
|
|
602
|
+
modelType: this.modelType
|
|
603
|
+
}), c = this.extractContent(m);
|
|
604
|
+
try {
|
|
605
|
+
const p = JSON.parse(c);
|
|
606
|
+
if (p.summary && Array.isArray(p.details) && Array.isArray(p.recommendations))
|
|
607
|
+
return p;
|
|
608
|
+
} catch {
|
|
609
|
+
}
|
|
610
|
+
return c;
|
|
611
|
+
} catch (m) {
|
|
612
|
+
throw new Error(`Structured OHLCV analysis failed: ${m.message}`);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return this.analyzeOHLCV(e, t, s, a, o);
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Specialized method for processing OHLCV arrays
|
|
619
|
+
* @param ohlcvArray - OHLCV data array
|
|
620
|
+
* @param i18n - Language restriction for AI response
|
|
621
|
+
* @param instructions - Processing instructions, supports Chinese and English (optional, default: "Based on these OHLCV data, predict the next period")
|
|
622
|
+
* @param count - Number of OHLCV data items to return (optional, default: 1)
|
|
623
|
+
* @param options - Chat options
|
|
624
|
+
* @returns Predicted OHLCV array
|
|
625
|
+
*/
|
|
626
|
+
async predictingOHLCV(e, t, s, a, r) {
|
|
627
|
+
const o = s || "Based on these OHLCV data, predict the next period", i = a || 1;
|
|
628
|
+
if (!Number.isInteger(i) || i <= 0)
|
|
629
|
+
throw new Error(`Invalid count parameter: ${i}. Must be a positive integer.`);
|
|
630
|
+
const d = 50;
|
|
631
|
+
if (i > d)
|
|
632
|
+
throw new Error(`Count parameter too large: ${i}. Maximum allowed is ${d}. Please reduce the count or split your request.`);
|
|
633
|
+
const l = i === 1 ? "Return EXACTLY 1 OHLCV object for the next period." : `Return EXACTLY ${i} consecutive OHLCV objects for the next ${i} periods.`, u = t === "en" ? "Please respond in English only." : t === "cn" ? "请使用中文回答。" : "";
|
|
634
|
+
let m = `You are a professional financial data analysis AI. The user will give you an array of OHLCV (Open, High, Low, Close, Volume) data.
|
|
635
|
+
Your task: ${o}
|
|
636
|
+
CRITICAL RULES:
|
|
637
|
+
1. ${l}
|
|
638
|
+
2. Return ONLY a JSON array of OHLCV objects, NO explanations, comments, or other text
|
|
639
|
+
3. The OHLCV array format must match: [{open, high, low, close, volume}, ...]
|
|
640
|
+
4. All numbers must be valid numbers
|
|
641
|
+
5. Ensure technical rationality (high >= low, high >= close >= low, volume >= 0)
|
|
642
|
+
6. Maintain consistency with historical trends and patterns
|
|
643
|
+
7. For technical analysis, provide reasonable values based on typical patterns
|
|
644
|
+
8. Do not include markdown formatting, only pure JSON
|
|
645
|
+
${i === 1 ? `Example of valid response for 1 period:
|
|
646
|
+
[{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000}]` : `Example of valid response for ${i} periods:
|
|
647
|
+
[
|
|
648
|
+
{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000},
|
|
649
|
+
{"open": 117.5, "high": 120.0, "low": 116.0, "close": 119.0, "volume": 1400000}
|
|
650
|
+
${i > 2 ? `,
|
|
651
|
+
... ${i - 2} more OHLCV objects following the same pattern` : ""}
|
|
652
|
+
]`}`;
|
|
653
|
+
u && (m = `${m}
|
|
654
|
+
|
|
655
|
+
${u}`);
|
|
656
|
+
const c = JSON.stringify(e, null, 2), p = `Here is the historical OHLCV data (${e.length} periods):
|
|
657
|
+
${c}
|
|
658
|
+
Please process this data according to the system instructions. Remember to return EXACTLY ${i} OHLCV object(s) in a JSON array with no additional text.`, g = [
|
|
659
|
+
{ role: "system", content: m },
|
|
660
|
+
{ role: "user", content: p }
|
|
661
|
+
];
|
|
662
|
+
try {
|
|
663
|
+
const y = i * 50 + 100, h = Math.max(r?.maxTokens || 1e3, y), b = await this.chatCompletion(g, t, {
|
|
664
|
+
temperature: r?.temperature || 0.3,
|
|
665
|
+
maxTokens: h,
|
|
666
|
+
stream: !1,
|
|
667
|
+
modelType: this.modelType
|
|
668
|
+
}), f = this.extractContent(b), w = this.parseOHLCVResponse(f);
|
|
669
|
+
if (w.length !== i)
|
|
670
|
+
throw new Error(`AI returned ${w.length} OHLCV objects, but expected ${i}.`);
|
|
671
|
+
return w;
|
|
672
|
+
} catch (y) {
|
|
673
|
+
throw new Error(`OHLCV analysis failed: ${y.message}`);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Parse AI returned OHLCV response
|
|
678
|
+
* @private
|
|
679
|
+
*/
|
|
680
|
+
parseOHLCVResponse(e) {
|
|
681
|
+
try {
|
|
682
|
+
const t = JSON.parse(e);
|
|
683
|
+
if (!Array.isArray(t))
|
|
684
|
+
throw new Error("Response is not in array format");
|
|
685
|
+
return t.map((a, r) => {
|
|
686
|
+
if (typeof a != "object" || a === null)
|
|
687
|
+
throw new Error(`Element ${r} is not a valid object`);
|
|
688
|
+
const { open: o, high: i, low: d, close: l, volume: u } = a, m = ["open", "high", "low", "close", "volume"];
|
|
689
|
+
for (const c of m)
|
|
690
|
+
if (typeof a[c] != "number" || isNaN(a[c]))
|
|
691
|
+
throw new Error(`Element ${r} field ${c} is not a valid number`);
|
|
692
|
+
if (i < d)
|
|
693
|
+
throw new Error(`Element ${r}: high cannot be lower than low`);
|
|
694
|
+
if (l < d || l > i)
|
|
695
|
+
throw new Error(`Element ${r}: close must be between low and high`);
|
|
696
|
+
return {
|
|
697
|
+
open: Number(o),
|
|
698
|
+
high: Number(i),
|
|
699
|
+
low: Number(d),
|
|
700
|
+
close: Number(l),
|
|
701
|
+
volume: Number(u)
|
|
702
|
+
};
|
|
703
|
+
});
|
|
704
|
+
} catch (t) {
|
|
705
|
+
const s = e.match(/\[[\s\S]*\]/);
|
|
706
|
+
if (s)
|
|
707
|
+
return this.parseOHLCVResponse(s[0]);
|
|
708
|
+
throw new Error(`Unable to parse AI returned OHLCV data: ${t}
|
|
709
|
+
Original content: ${e.substring(0, 200)}...`);
|
|
451
710
|
}
|
|
452
711
|
}
|
|
453
712
|
/**
|
|
@@ -455,7 +714,7 @@ class _ {
|
|
|
455
714
|
* @param modelType - New model type
|
|
456
715
|
*/
|
|
457
716
|
setModel(e) {
|
|
458
|
-
if (!
|
|
717
|
+
if (!k.get(e))
|
|
459
718
|
throw new Error(`Unsupported model type: ${e}`);
|
|
460
719
|
this.modelType = e;
|
|
461
720
|
}
|
|
@@ -463,7 +722,7 @@ class _ {
|
|
|
463
722
|
* Get current model configuration
|
|
464
723
|
*/
|
|
465
724
|
getCurrentModel() {
|
|
466
|
-
const e =
|
|
725
|
+
const e = k.get(this.modelType);
|
|
467
726
|
if (!e)
|
|
468
727
|
throw new Error(`Model configuration does not exist: ${this.modelType}`);
|
|
469
728
|
return {
|
|
@@ -478,7 +737,7 @@ class _ {
|
|
|
478
737
|
*/
|
|
479
738
|
async testConnection() {
|
|
480
739
|
try {
|
|
481
|
-
const e = await this.chat('Hello, respond with "OK" if you can hear me.');
|
|
740
|
+
const e = await this.chat('Hello, respond with "OK" if you can hear me.', "en");
|
|
482
741
|
return {
|
|
483
742
|
success: !0,
|
|
484
743
|
model: this.modelType,
|
|
@@ -492,19 +751,19 @@ class _ {
|
|
|
492
751
|
};
|
|
493
752
|
}
|
|
494
753
|
}
|
|
495
|
-
buildOpenAIRequest(e,
|
|
754
|
+
buildOpenAIRequest(e, t, s, a, r) {
|
|
496
755
|
return {
|
|
497
756
|
model: e,
|
|
498
|
-
messages:
|
|
757
|
+
messages: t,
|
|
499
758
|
temperature: s,
|
|
500
759
|
max_tokens: a,
|
|
501
|
-
stream:
|
|
760
|
+
stream: r
|
|
502
761
|
};
|
|
503
762
|
}
|
|
504
|
-
buildDashScopeRequest(e,
|
|
763
|
+
buildDashScopeRequest(e, t, s, a) {
|
|
505
764
|
return {
|
|
506
765
|
model: e,
|
|
507
|
-
input: { messages:
|
|
766
|
+
input: { messages: t },
|
|
508
767
|
parameters: {
|
|
509
768
|
temperature: s,
|
|
510
769
|
max_tokens: a,
|
|
@@ -512,61 +771,61 @@ class _ {
|
|
|
512
771
|
}
|
|
513
772
|
};
|
|
514
773
|
}
|
|
515
|
-
async makeRequest(e,
|
|
516
|
-
const a = new AbortController(),
|
|
774
|
+
async makeRequest(e, t, s) {
|
|
775
|
+
const a = new AbortController(), r = setTimeout(() => a.abort(), this.timeout);
|
|
517
776
|
try {
|
|
518
|
-
const
|
|
777
|
+
const o = await fetch(e, {
|
|
519
778
|
method: "POST",
|
|
520
779
|
headers: {
|
|
521
780
|
Authorization: `Bearer ${this.apiKey}`,
|
|
522
781
|
"Content-Type": "application/json; charset=utf-8",
|
|
523
782
|
Accept: "application/json"
|
|
524
783
|
},
|
|
525
|
-
body: JSON.stringify(
|
|
784
|
+
body: JSON.stringify(t),
|
|
526
785
|
signal: a.signal
|
|
527
786
|
});
|
|
528
|
-
if (clearTimeout(
|
|
529
|
-
const
|
|
530
|
-
throw new Error(`HTTP ${
|
|
787
|
+
if (clearTimeout(r), !o.ok) {
|
|
788
|
+
const i = await o.text();
|
|
789
|
+
throw new Error(`HTTP ${o.status}: ${i}`);
|
|
531
790
|
}
|
|
532
|
-
return s ?
|
|
533
|
-
} catch (
|
|
534
|
-
throw clearTimeout(
|
|
791
|
+
return s ? o.body : await o.json();
|
|
792
|
+
} catch (o) {
|
|
793
|
+
throw clearTimeout(r), o.name === "AbortError" ? new Error(`Request timeout (${this.timeout}ms)`) : o;
|
|
535
794
|
}
|
|
536
795
|
}
|
|
537
|
-
async makeStreamRequest(e,
|
|
538
|
-
const a = await this.makeRequest(e,
|
|
796
|
+
async makeStreamRequest(e, t, s) {
|
|
797
|
+
const a = await this.makeRequest(e, t, !0);
|
|
539
798
|
if (!a)
|
|
540
799
|
throw new Error("Failed to get streaming response");
|
|
541
|
-
const
|
|
542
|
-
let
|
|
800
|
+
const r = a.getReader(), o = new TextDecoder("utf-8");
|
|
801
|
+
let i = "";
|
|
543
802
|
try {
|
|
544
803
|
for (; ; ) {
|
|
545
|
-
const { done:
|
|
546
|
-
if (
|
|
804
|
+
const { done: d, value: l } = await r.read();
|
|
805
|
+
if (d) {
|
|
547
806
|
s("", !0);
|
|
548
807
|
break;
|
|
549
808
|
}
|
|
550
|
-
|
|
551
|
-
const
|
|
809
|
+
i += o.decode(l, { stream: !0 });
|
|
810
|
+
const u = i.split(`
|
|
552
811
|
`);
|
|
553
|
-
|
|
554
|
-
for (const
|
|
555
|
-
if (
|
|
556
|
-
const
|
|
557
|
-
if (
|
|
812
|
+
i = u.pop() || "";
|
|
813
|
+
for (const m of u)
|
|
814
|
+
if (m.startsWith("data: ")) {
|
|
815
|
+
const c = m.slice(6);
|
|
816
|
+
if (c === "[DONE]") {
|
|
558
817
|
s("", !0);
|
|
559
818
|
return;
|
|
560
819
|
}
|
|
561
820
|
try {
|
|
562
|
-
const
|
|
563
|
-
|
|
821
|
+
const p = JSON.parse(c);
|
|
822
|
+
p.choices?.[0]?.delta?.content && s(p.choices[0].delta.content, !1);
|
|
564
823
|
} catch {
|
|
565
824
|
}
|
|
566
825
|
}
|
|
567
826
|
}
|
|
568
827
|
} finally {
|
|
569
|
-
|
|
828
|
+
r.releaseLock();
|
|
570
829
|
}
|
|
571
830
|
}
|
|
572
831
|
extractContent(e) {
|
|
@@ -578,101 +837,12 @@ class _ {
|
|
|
578
837
|
return e.output.text;
|
|
579
838
|
throw new Error("Unable to parse response content");
|
|
580
839
|
}
|
|
581
|
-
/**
|
|
582
|
-
* Specialized method for processing OHLCV arrays
|
|
583
|
-
* @param ohlcvArray - OHLCV data array
|
|
584
|
-
* @param instructions - Processing instructions, supports Chinese and English (optional, default: "Based on these OHLCV data, predict the next period")
|
|
585
|
-
* @param count - Number of OHLCV data items to return (optional, default: 1)
|
|
586
|
-
* @param options - Chat options
|
|
587
|
-
* @returns Predicted OHLCV array
|
|
588
|
-
*/
|
|
589
|
-
async predictingOHLCV(e, o, s, a) {
|
|
590
|
-
const i = o || "Based on these OHLCV data, predict the next period", n = s || 1;
|
|
591
|
-
if (!Number.isInteger(n) || n <= 0)
|
|
592
|
-
throw new Error(`Invalid count parameter: ${n}. Must be a positive integer.`);
|
|
593
|
-
const r = 50;
|
|
594
|
-
if (n > r)
|
|
595
|
-
throw new Error(`Count parameter too large: ${n}. Maximum allowed is ${r}. Please reduce the count or split your request.`);
|
|
596
|
-
const m = n === 1 ? "Return EXACTLY 1 OHLCV object for the next period." : `Return EXACTLY ${n} consecutive OHLCV objects for the next ${n} periods.`, c = `You are a professional financial data analysis AI. The user will give you an array of OHLCV (Open, High, Low, Close, Volume) data.
|
|
597
|
-
Your task: ${i}
|
|
598
|
-
CRITICAL RULES:
|
|
599
|
-
1. ${m}
|
|
600
|
-
2. Return ONLY a JSON array of OHLCV objects, NO explanations, comments, or other text
|
|
601
|
-
3. The OHLCV array format must match: [{open, high, low, close, volume}, ...]
|
|
602
|
-
4. All numbers must be valid numbers
|
|
603
|
-
5. Ensure technical rationality (high >= low, high >= close >= low, volume >= 0)
|
|
604
|
-
6. Maintain consistency with historical trends and patterns
|
|
605
|
-
7. For technical analysis, provide reasonable values based on typical patterns
|
|
606
|
-
8. Do not include markdown formatting, only pure JSON
|
|
607
|
-
${n === 1 ? `Example of valid response for 1 period:
|
|
608
|
-
[{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000}]` : `Example of valid response for ${n} periods:
|
|
609
|
-
[
|
|
610
|
-
{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000},
|
|
611
|
-
{"open": 117.5, "high": 120.0, "low": 116.0, "close": 119.0, "volume": 1400000}
|
|
612
|
-
${n > 2 ? `,
|
|
613
|
-
... ${n - 2} more OHLCV objects following the same pattern` : ""}
|
|
614
|
-
]`}`, p = JSON.stringify(e, null, 2), d = `Here is the historical OHLCV data (${e.length} periods):
|
|
615
|
-
${p}
|
|
616
|
-
Please process this data according to the system instructions. Remember to return EXACTLY ${n} OHLCV object(s) in a JSON array with no additional text.`, l = [
|
|
617
|
-
{ role: "system", content: c },
|
|
618
|
-
{ role: "user", content: d }
|
|
619
|
-
];
|
|
620
|
-
try {
|
|
621
|
-
const u = n * 50 + 100, x = Math.max(a?.maxTokens || 1e3, u), v = await this.chatCompletion(l, {
|
|
622
|
-
temperature: a?.temperature || 0.3,
|
|
623
|
-
maxTokens: x,
|
|
624
|
-
stream: !1,
|
|
625
|
-
modelType: a?.modelType
|
|
626
|
-
}), E = this.extractContent(v), g = this.parseOHLCVResponse(E);
|
|
627
|
-
if (g.length !== n)
|
|
628
|
-
throw new Error(`AI returned ${g.length} OHLCV objects, but expected ${n}.`);
|
|
629
|
-
return g;
|
|
630
|
-
} catch (u) {
|
|
631
|
-
throw new Error(`OHLCV analysis failed: ${u.message}`);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* Parse AI returned OHLCV response
|
|
636
|
-
* @private
|
|
637
|
-
*/
|
|
638
|
-
parseOHLCVResponse(e) {
|
|
639
|
-
try {
|
|
640
|
-
const o = JSON.parse(e);
|
|
641
|
-
if (!Array.isArray(o))
|
|
642
|
-
throw new Error("Response is not in array format");
|
|
643
|
-
return o.map((a, i) => {
|
|
644
|
-
if (typeof a != "object" || a === null)
|
|
645
|
-
throw new Error(`Element ${i} is not a valid object`);
|
|
646
|
-
const { open: n, high: r, low: m, close: c, volume: p } = a, d = ["open", "high", "low", "close", "volume"];
|
|
647
|
-
for (const l of d)
|
|
648
|
-
if (typeof a[l] != "number" || isNaN(a[l]))
|
|
649
|
-
throw new Error(`Element ${i} field ${l} is not a valid number`);
|
|
650
|
-
if (r < m)
|
|
651
|
-
throw new Error(`Element ${i}: high cannot be lower than low`);
|
|
652
|
-
if (c < m || c > r)
|
|
653
|
-
throw new Error(`Element ${i}: close must be between low and high`);
|
|
654
|
-
return {
|
|
655
|
-
open: Number(n),
|
|
656
|
-
high: Number(r),
|
|
657
|
-
low: Number(m),
|
|
658
|
-
close: Number(c),
|
|
659
|
-
volume: Number(p)
|
|
660
|
-
};
|
|
661
|
-
});
|
|
662
|
-
} catch (o) {
|
|
663
|
-
const s = e.match(/\[[\s\S]*\]/);
|
|
664
|
-
if (s)
|
|
665
|
-
return this.parseOHLCVResponse(s[0]);
|
|
666
|
-
throw new Error(`Unable to parse AI returned OHLCV data: ${o}
|
|
667
|
-
Original content: ${e.substring(0, 200)}...`);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
840
|
}
|
|
671
|
-
function
|
|
672
|
-
return new
|
|
841
|
+
function B(n, e) {
|
|
842
|
+
return new q({ apiKey: n, modelType: e });
|
|
673
843
|
}
|
|
674
|
-
var
|
|
675
|
-
const
|
|
844
|
+
var N = /* @__PURE__ */ ((n) => (n.DEEPSEEK_CHAT = "deepseek-chat", n.DEEPSEEK_CHAT_LITE = "deepseek-chat-lite", n.DEEPSEEK_CHAT_PRO = "deepseek-chat-pro", n.DEEPSEEK_CHAT_MAX = "deepseek-chat-max", n.DEEPSEEK_CODER = "deepseek-coder", n.DEEPSEEK_CODER_LITE = "deepseek-coder-lite", n.DEEPSEEK_CODER_PRO = "deepseek-coder-pro", n.DEEPSEEK_MATH = "deepseek-math", n.DEEPSEEK_MATH_PRO = "deepseek-math-pro", n.DEEPSEEK_REASONER = "deepseek-reasoner", n.DEEPSEEK_REASONER_PRO = "deepseek-reasoner-pro", n.DEEPSEEK_VISION = "deepseek-vision", n.DEEPSEEK_VISION_PRO = "deepseek-vision-pro", n.DEEPSEEK_FINANCE = "deepseek-finance", n.DEEPSEEK_LAW = "deepseek-law", n.DEEPSEEK_MEDICAL = "deepseek-medical", n.DEEPSEEK_RESEARCH = "deepseek-research", n.DEEPSEEK_OMNI = "deepseek-omni", n.DEEPSEEK_OMNI_PRO = "deepseek-omni-pro", n.DEEPSEEK_LLM = "deepseek-llm", n.DEEPSEEK_LLM_67B = "deepseek-llm-67b", n.DEEPSEEK_LLM_131B = "deepseek-llm-131b", n))(N || {});
|
|
845
|
+
const $ = /* @__PURE__ */ new Map([
|
|
676
846
|
// Chat models
|
|
677
847
|
[
|
|
678
848
|
"deepseek-chat",
|
|
@@ -965,28 +1135,28 @@ const y = /* @__PURE__ */ new Map([
|
|
|
965
1135
|
}
|
|
966
1136
|
]
|
|
967
1137
|
]);
|
|
968
|
-
function
|
|
969
|
-
return
|
|
1138
|
+
function K(n) {
|
|
1139
|
+
return $.get(n);
|
|
970
1140
|
}
|
|
971
|
-
function
|
|
972
|
-
return Array.from(
|
|
1141
|
+
function F() {
|
|
1142
|
+
return Array.from($.values());
|
|
973
1143
|
}
|
|
974
|
-
function
|
|
975
|
-
for (const e of
|
|
976
|
-
if (e.name ===
|
|
1144
|
+
function U(n) {
|
|
1145
|
+
for (const e of $.values())
|
|
1146
|
+
if (e.name === n)
|
|
977
1147
|
return e;
|
|
978
1148
|
}
|
|
979
|
-
function
|
|
980
|
-
return Array.from(
|
|
1149
|
+
function Q() {
|
|
1150
|
+
return Array.from($.keys());
|
|
981
1151
|
}
|
|
982
|
-
function
|
|
983
|
-
const e = Object.values(
|
|
984
|
-
for (const
|
|
985
|
-
if (
|
|
986
|
-
return
|
|
1152
|
+
function z(n) {
|
|
1153
|
+
const e = Object.values(N);
|
|
1154
|
+
for (const t of e)
|
|
1155
|
+
if (t === n)
|
|
1156
|
+
return t;
|
|
987
1157
|
return null;
|
|
988
1158
|
}
|
|
989
|
-
class
|
|
1159
|
+
class H {
|
|
990
1160
|
/**
|
|
991
1161
|
* Constructor - Minimal configuration
|
|
992
1162
|
* @param config.apiKey - API key (required)
|
|
@@ -995,92 +1165,270 @@ class C {
|
|
|
995
1165
|
* @param config.baseURL - Base URL for API, default official endpoint
|
|
996
1166
|
*/
|
|
997
1167
|
constructor(e) {
|
|
998
|
-
if (this.apiKey = e.apiKey, this.modelType = e.modelType ||
|
|
1168
|
+
if (this.apiKey = e.apiKey, this.modelType = e.modelType || N.DEEPSEEK_CHAT, this.timeout = e.timeout || 3e4, this.baseURL = e.baseURL || "https://api.deepseek.com", !this.apiKey)
|
|
999
1169
|
throw new Error("API Key cannot be empty");
|
|
1000
|
-
if (
|
|
1170
|
+
if (!$.get(this.modelType))
|
|
1001
1171
|
throw new Error(`Unsupported model type: ${this.modelType}`);
|
|
1002
1172
|
}
|
|
1003
1173
|
/**
|
|
1004
|
-
* Simplest method: single conversation
|
|
1174
|
+
* Simplest method: single conversation with i18n support
|
|
1005
1175
|
* @param message - User message
|
|
1176
|
+
* @param i18n - Language restriction for AI response
|
|
1006
1177
|
* @param options - Chat options
|
|
1007
1178
|
* @returns AI response
|
|
1008
1179
|
*/
|
|
1009
|
-
async chat(e,
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1180
|
+
async chat(e, t, s) {
|
|
1181
|
+
const a = [], r = t === "en" ? "Please respond in English only." : t === "cn" ? "请使用中文回答。" : "";
|
|
1182
|
+
if (s?.systemPrompt || r) {
|
|
1183
|
+
const i = [s?.systemPrompt, r].filter(Boolean).join(`
|
|
1184
|
+
`);
|
|
1185
|
+
a.push({ role: "system", content: i });
|
|
1186
|
+
}
|
|
1187
|
+
a.push({ role: "user", content: e });
|
|
1188
|
+
const o = await this.chatCompletion(a, t, {
|
|
1189
|
+
temperature: s?.temperature,
|
|
1190
|
+
maxTokens: s?.maxTokens,
|
|
1015
1191
|
stream: !1,
|
|
1016
|
-
modelType:
|
|
1017
|
-
topP:
|
|
1018
|
-
frequencyPenalty:
|
|
1019
|
-
presencePenalty:
|
|
1020
|
-
stop:
|
|
1021
|
-
tools:
|
|
1022
|
-
toolChoice:
|
|
1192
|
+
modelType: this.modelType,
|
|
1193
|
+
topP: s?.topP,
|
|
1194
|
+
frequencyPenalty: s?.frequencyPenalty,
|
|
1195
|
+
presencePenalty: s?.presencePenalty,
|
|
1196
|
+
stop: s?.stop,
|
|
1197
|
+
tools: s?.tools,
|
|
1198
|
+
toolChoice: s?.toolChoice
|
|
1023
1199
|
});
|
|
1024
|
-
return this.extractContent(
|
|
1200
|
+
return this.extractContent(o);
|
|
1025
1201
|
}
|
|
1026
1202
|
/**
|
|
1027
|
-
* Multi-turn conversation
|
|
1203
|
+
* Multi-turn conversation with i18n support
|
|
1028
1204
|
* @param messages - Message history
|
|
1205
|
+
* @param i18n - Language restriction for AI response
|
|
1029
1206
|
* @param options - Chat options
|
|
1030
1207
|
* @returns Complete API response
|
|
1031
1208
|
*/
|
|
1032
|
-
async chatCompletion(e,
|
|
1033
|
-
const
|
|
1034
|
-
if (!
|
|
1035
|
-
throw new Error(`Unsupported model type: ${
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1209
|
+
async chatCompletion(e, t, s) {
|
|
1210
|
+
const a = s?.modelType || this.modelType, r = $.get(a);
|
|
1211
|
+
if (!r)
|
|
1212
|
+
throw new Error(`Unsupported model type: ${a}`);
|
|
1213
|
+
const o = s?.temperature ?? 0.7, i = s?.maxTokens ?? 2e3, d = s?.stream ?? !1, l = s?.topP ?? 1, u = s?.frequencyPenalty ?? 0, m = s?.presencePenalty ?? 0, c = s?.stop, p = s?.tools, g = s?.toolChoice, y = t === "en" ? "Please respond in English only." : t === "cn" ? "请使用中文回答。" : "";
|
|
1214
|
+
y && (e.some((w) => w.role === "system") ? e = e.map((w) => w.role === "system" ? {
|
|
1215
|
+
...w,
|
|
1216
|
+
content: `${w.content}
|
|
1217
|
+
${y}`
|
|
1218
|
+
} : w) : e.unshift({ role: "system", content: y }));
|
|
1219
|
+
const h = r.endpoint, b = this.buildOpenAIRequest(
|
|
1220
|
+
r.name,
|
|
1038
1221
|
e,
|
|
1222
|
+
o,
|
|
1039
1223
|
i,
|
|
1040
|
-
|
|
1041
|
-
|
|
1224
|
+
d,
|
|
1225
|
+
l,
|
|
1226
|
+
u,
|
|
1042
1227
|
m,
|
|
1043
1228
|
c,
|
|
1044
1229
|
p,
|
|
1045
|
-
|
|
1046
|
-
l,
|
|
1047
|
-
u
|
|
1230
|
+
g
|
|
1048
1231
|
);
|
|
1049
1232
|
try {
|
|
1050
|
-
return await this.makeRequest(
|
|
1051
|
-
} catch (
|
|
1052
|
-
throw new Error(`DeepSeek AI request failed: ${
|
|
1233
|
+
return await this.makeRequest(h, b, d);
|
|
1234
|
+
} catch (f) {
|
|
1235
|
+
throw new Error(`DeepSeek AI request failed: ${f.message}`);
|
|
1053
1236
|
}
|
|
1054
1237
|
}
|
|
1055
1238
|
/**
|
|
1056
|
-
* Streaming conversation
|
|
1239
|
+
* Streaming conversation with i18n support
|
|
1057
1240
|
* @param messages - Message history
|
|
1058
1241
|
* @param callback - Streaming callback function
|
|
1242
|
+
* @param i18n - Language restriction for AI response
|
|
1059
1243
|
* @param options - Chat options
|
|
1060
1244
|
*/
|
|
1061
|
-
async chatStream(e,
|
|
1062
|
-
const
|
|
1063
|
-
if (!
|
|
1064
|
-
throw new Error(`Unsupported model type: ${
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1245
|
+
async chatStream(e, t, s, a) {
|
|
1246
|
+
const r = a?.modelType || this.modelType, o = $.get(r);
|
|
1247
|
+
if (!o)
|
|
1248
|
+
throw new Error(`Unsupported model type: ${r}`);
|
|
1249
|
+
const i = a?.temperature ?? 0.7, d = a?.maxTokens ?? 2e3, l = a?.topP ?? 1, u = a?.frequencyPenalty ?? 0, m = a?.presencePenalty ?? 0, c = s === "en" ? "Please respond in English only." : s === "cn" ? "请使用中文回答。" : "";
|
|
1250
|
+
c && (e.some((y) => y.role === "system") ? e = e.map((y) => y.role === "system" ? {
|
|
1251
|
+
...y,
|
|
1252
|
+
content: `${y.content}
|
|
1253
|
+
${c}`
|
|
1254
|
+
} : y) : e.unshift({ role: "system", content: c }));
|
|
1255
|
+
const p = this.buildOpenAIRequest(
|
|
1256
|
+
o.name,
|
|
1067
1257
|
e,
|
|
1068
|
-
|
|
1069
|
-
|
|
1258
|
+
i,
|
|
1259
|
+
d,
|
|
1070
1260
|
!0,
|
|
1261
|
+
l,
|
|
1262
|
+
u,
|
|
1071
1263
|
m,
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
s?.tools,
|
|
1076
|
-
s?.toolChoice
|
|
1264
|
+
a?.stop,
|
|
1265
|
+
a?.tools,
|
|
1266
|
+
a?.toolChoice
|
|
1077
1267
|
);
|
|
1078
1268
|
try {
|
|
1079
|
-
await this.makeStreamRequest(
|
|
1080
|
-
} catch (
|
|
1081
|
-
throw new Error(`Streaming request failed: ${
|
|
1269
|
+
await this.makeStreamRequest(o.endpoint, p, t);
|
|
1270
|
+
} catch (g) {
|
|
1271
|
+
throw new Error(`Streaming request failed: ${g.message}`);
|
|
1082
1272
|
}
|
|
1083
1273
|
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Analyze OHLCV data and return AI analysis results (text description)
|
|
1276
|
+
* @param ohlcvArray - OHLCV data array
|
|
1277
|
+
* @param i18n - Language restriction for AI response
|
|
1278
|
+
* @param analysisType - Analysis type (optional, default: "comprehensive")
|
|
1279
|
+
* - "trend": Trend analysis
|
|
1280
|
+
* - "volume": Volume analysis
|
|
1281
|
+
* - "technical": Technical analysis
|
|
1282
|
+
* - "comprehensive": Comprehensive analysis
|
|
1283
|
+
* @param message - User's subjective request or specific question (optional)
|
|
1284
|
+
* @param options - Chat options
|
|
1285
|
+
* @returns AI analysis result of OHLCV data (text description)
|
|
1286
|
+
*/
|
|
1287
|
+
async analyzeOHLCV(e, t, s, a, r) {
|
|
1288
|
+
const o = s || "comprehensive", i = e.length, l = {
|
|
1289
|
+
trend: {
|
|
1290
|
+
en: "Provide a detailed trend analysis of this OHLCV data, including price direction, support/resistance levels, and trend strength.",
|
|
1291
|
+
cn: "提供详细的OHLCV数据趋势分析,包括价格方向、支撑/阻力位和趋势强度。"
|
|
1292
|
+
},
|
|
1293
|
+
volume: {
|
|
1294
|
+
en: "Analyze the volume patterns in this OHLCV data, including volume trends, unusual volume spikes, and volume-price relationships.",
|
|
1295
|
+
cn: "分析OHLCV数据中的成交量模式,包括成交量趋势、异常成交量波动和量价关系。"
|
|
1296
|
+
},
|
|
1297
|
+
technical: {
|
|
1298
|
+
en: "Perform technical analysis on this OHLCV data, identifying potential technical indicators, patterns, and trading signals.",
|
|
1299
|
+
cn: "对OHLCV数据进行技术分析,识别潜在的技术指标、图表形态和交易信号。"
|
|
1300
|
+
},
|
|
1301
|
+
comprehensive: {
|
|
1302
|
+
en: "Provide a comprehensive analysis of this OHLCV data, covering trends, volume, technical aspects, and potential market implications.",
|
|
1303
|
+
cn: "提供全面的OHLCV数据分析,涵盖趋势、成交量、技术面和潜在市场影响。"
|
|
1304
|
+
}
|
|
1305
|
+
}[o][t], u = t === "en" ? "Please provide your analysis in English." : "请用中文进行分析。";
|
|
1306
|
+
let m = "";
|
|
1307
|
+
if (i > 0) {
|
|
1308
|
+
const h = e[0], f = e[i - 1].close - h.close, w = f / h.close * 100;
|
|
1309
|
+
let C = h.high, v = h.low, P = 0;
|
|
1310
|
+
for (const E of e)
|
|
1311
|
+
E.high > C && (C = E.high), E.low < v && (v = E.low), P += E.volume;
|
|
1312
|
+
const _ = P / i;
|
|
1313
|
+
m = t === "en" ? `This dataset contains ${i} periods of OHLCV data.
|
|
1314
|
+
Price range: ${v.toFixed(2)} - ${C.toFixed(2)}
|
|
1315
|
+
Overall price change: ${f >= 0 ? "+" : ""}${f.toFixed(2)} (${f >= 0 ? "+" : ""}${w.toFixed(2)}%)
|
|
1316
|
+
Average volume: ${_.toFixed(0)}` : `该数据集包含 ${i} 个周期的OHLCV数据。
|
|
1317
|
+
价格范围:${v.toFixed(2)} - ${C.toFixed(2)}
|
|
1318
|
+
总体价格变化:${f >= 0 ? "+" : ""}${f.toFixed(2)} (${f >= 0 ? "+" : ""}${w.toFixed(2)}%)
|
|
1319
|
+
平均成交量:${_.toFixed(0)}`;
|
|
1320
|
+
}
|
|
1321
|
+
let c = t === "en" ? `You are a professional financial data analyst. Your task is to analyze OHLCV (Open, High, Low, Close, Volume) data and provide insights.
|
|
1322
|
+
Analysis focus: ${l}
|
|
1323
|
+
${m ? `Data characteristics:
|
|
1324
|
+
${m}
|
|
1325
|
+
|
|
1326
|
+
` : ""}
|
|
1327
|
+
Please provide:
|
|
1328
|
+
1. Clear and structured analysis
|
|
1329
|
+
2. Key observations from the data
|
|
1330
|
+
3. Potential implications or insights
|
|
1331
|
+
4. Recommendations or considerations (if applicable)
|
|
1332
|
+
Format your response as a well-organized text analysis.` : `您是一位专业的金融数据分析师。您的任务是分析OHLCV(开盘价、最高价、最低价、收盘价、成交量)数据并提供见解。
|
|
1333
|
+
分析重点:${l}
|
|
1334
|
+
${m ? `数据特征:
|
|
1335
|
+
${m}
|
|
1336
|
+
|
|
1337
|
+
` : ""}
|
|
1338
|
+
请提供:
|
|
1339
|
+
1. 清晰且有结构的分析
|
|
1340
|
+
2. 数据的关键观察结果
|
|
1341
|
+
3. 潜在的启示或见解
|
|
1342
|
+
4. 建议或注意事项(如适用)
|
|
1343
|
+
请以组织良好的文本分析形式回复。`;
|
|
1344
|
+
c += `
|
|
1345
|
+
|
|
1346
|
+
${u}`;
|
|
1347
|
+
const p = JSON.stringify(e, null, 2);
|
|
1348
|
+
let g = "";
|
|
1349
|
+
a ? g = t === "en" ? `Here is the OHLCV data (${i} periods):
|
|
1350
|
+
${p}
|
|
1351
|
+
My specific question or request: ${a}
|
|
1352
|
+
Please analyze this data considering my request above.` : `这是OHLCV数据(${i}个周期):
|
|
1353
|
+
${p}
|
|
1354
|
+
我的具体问题或需求:${a}
|
|
1355
|
+
请根据我的上述需求分析这些数据。` : g = t === "en" ? `Here is the OHLCV data (${i} periods):
|
|
1356
|
+
${p}
|
|
1357
|
+
Please analyze this data as requested.` : `这是OHLCV数据(${i}个周期):
|
|
1358
|
+
${p}
|
|
1359
|
+
请按要求分析这些数据。`;
|
|
1360
|
+
const y = [
|
|
1361
|
+
{ role: "system", content: c },
|
|
1362
|
+
{ role: "user", content: g }
|
|
1363
|
+
];
|
|
1364
|
+
try {
|
|
1365
|
+
const h = await this.chatCompletion(y, t, {
|
|
1366
|
+
temperature: r?.temperature || 0.5,
|
|
1367
|
+
maxTokens: r?.maxTokens || 1500,
|
|
1368
|
+
stream: !1,
|
|
1369
|
+
modelType: this.modelType,
|
|
1370
|
+
topP: r?.topP,
|
|
1371
|
+
frequencyPenalty: r?.frequencyPenalty,
|
|
1372
|
+
presencePenalty: r?.presencePenalty
|
|
1373
|
+
});
|
|
1374
|
+
return this.extractContent(h);
|
|
1375
|
+
} catch (h) {
|
|
1376
|
+
throw new Error(`OHLCV analysis failed: ${h.message}`);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Enhanced version: Analyze OHLCV and return structured results (optional)
|
|
1381
|
+
* @param ohlcvArray - OHLCV data array
|
|
1382
|
+
* @param i18n - Language restriction for AI response
|
|
1383
|
+
* @param analysisType - Analysis type
|
|
1384
|
+
* @param message - User's subjective request or specific question
|
|
1385
|
+
* @param structured - Whether to return structured results (default: false)
|
|
1386
|
+
* @param options - Chat options
|
|
1387
|
+
* @returns AI analysis results
|
|
1388
|
+
*/
|
|
1389
|
+
async analyzeOHLCVEnhanced(e, t, s, a, r = !1, o) {
|
|
1390
|
+
if (r) {
|
|
1391
|
+
const i = t === "en" ? `You are a professional financial data analyst. Analyze the OHLCV data and provide a structured response with:
|
|
1392
|
+
1. Summary (brief overview)
|
|
1393
|
+
2. Details (key observations, 3-5 points)
|
|
1394
|
+
3. Recommendations (actionable insights, 2-3 points)
|
|
1395
|
+
Format as JSON: {"summary": "...", "details": ["...", "..."], "recommendations": ["...", "..."]}` : `您是一位专业的金融数据分析师。分析OHLCV数据并提供结构化响应:
|
|
1396
|
+
1. 总结(简要概述)
|
|
1397
|
+
2. 详情(关键观察结果,3-5点)
|
|
1398
|
+
3. 建议(可操作的见解,2-3点)
|
|
1399
|
+
格式化为JSON:{"summary": "...", "details": ["...", "..."], "recommendations": ["...", "..."]}`, d = JSON.stringify(e, null, 2);
|
|
1400
|
+
let l = t === "en" ? `Analyze this OHLCV data (${e.length} periods):
|
|
1401
|
+
${d}` : `分析此OHLCV数据(${e.length}个周期):
|
|
1402
|
+
${d}`;
|
|
1403
|
+
a && (l += t === "en" ? `
|
|
1404
|
+
|
|
1405
|
+
Additional request: ${a}` : `
|
|
1406
|
+
|
|
1407
|
+
附加要求:${a}`);
|
|
1408
|
+
const u = [
|
|
1409
|
+
{ role: "system", content: i },
|
|
1410
|
+
{ role: "user", content: l }
|
|
1411
|
+
];
|
|
1412
|
+
try {
|
|
1413
|
+
const m = await this.chatCompletion(u, t, {
|
|
1414
|
+
temperature: o?.temperature || 0.4,
|
|
1415
|
+
maxTokens: o?.maxTokens || 1200,
|
|
1416
|
+
stream: !1,
|
|
1417
|
+
modelType: this.modelType
|
|
1418
|
+
}), c = this.extractContent(m);
|
|
1419
|
+
try {
|
|
1420
|
+
const p = JSON.parse(c);
|
|
1421
|
+
if (p.summary && Array.isArray(p.details) && Array.isArray(p.recommendations))
|
|
1422
|
+
return p;
|
|
1423
|
+
} catch {
|
|
1424
|
+
}
|
|
1425
|
+
return c;
|
|
1426
|
+
} catch (m) {
|
|
1427
|
+
throw new Error(`Structured OHLCV analysis failed: ${m.message}`);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
return this.analyzeOHLCV(e, t, s, a, o);
|
|
1431
|
+
}
|
|
1084
1432
|
/**
|
|
1085
1433
|
* Specialized method for processing OHLCV arrays
|
|
1086
1434
|
* @param ohlcvArray - OHLCV data array
|
|
@@ -1089,17 +1437,17 @@ class C {
|
|
|
1089
1437
|
* @param options - Chat options
|
|
1090
1438
|
* @returns Predicted OHLCV array
|
|
1091
1439
|
*/
|
|
1092
|
-
async predictingOHLCV(e,
|
|
1093
|
-
const
|
|
1094
|
-
if (!Number.isInteger(
|
|
1095
|
-
throw new Error(`Invalid count parameter: ${
|
|
1096
|
-
const
|
|
1097
|
-
if (
|
|
1098
|
-
throw new Error(`Count parameter too large: ${
|
|
1099
|
-
const
|
|
1100
|
-
Your task: ${
|
|
1440
|
+
async predictingOHLCV(e, t, s, a) {
|
|
1441
|
+
const r = t || "Based on these OHLCV data, predict the next period", o = s || 1;
|
|
1442
|
+
if (!Number.isInteger(o) || o <= 0)
|
|
1443
|
+
throw new Error(`Invalid count parameter: ${o}. Must be a positive integer.`);
|
|
1444
|
+
const i = 50;
|
|
1445
|
+
if (o > i)
|
|
1446
|
+
throw new Error(`Count parameter too large: ${o}. Maximum allowed is ${i}.`);
|
|
1447
|
+
const d = o === 1 ? "Return EXACTLY 1 OHLCV object for the next period." : `Return EXACTLY ${o} consecutive OHLCV objects for the next ${o} periods.`, l = `You are a professional financial data analysis AI. The user will give you an array of OHLCV (Open, High, Low, Close, Volume) data.
|
|
1448
|
+
Your task: ${r}
|
|
1101
1449
|
CRITICAL RULES:
|
|
1102
|
-
1. ${
|
|
1450
|
+
1. ${d}
|
|
1103
1451
|
2. Return ONLY a JSON array of OHLCV objects, NO explanations, comments, or other text
|
|
1104
1452
|
3. The OHLCV array format must match: [{open, high, low, close, volume}, ...]
|
|
1105
1453
|
4. All numbers must be valid numbers
|
|
@@ -1108,34 +1456,34 @@ CRITICAL RULES:
|
|
|
1108
1456
|
7. For technical analysis, provide reasonable values based on typical patterns
|
|
1109
1457
|
8. Do not include markdown formatting, only pure JSON
|
|
1110
1458
|
|
|
1111
|
-
${
|
|
1112
|
-
[{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000}]` : `Example of valid response for ${
|
|
1459
|
+
${o === 1 ? `Example of valid response for 1 period:
|
|
1460
|
+
[{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000}]` : `Example of valid response for ${o} periods:
|
|
1113
1461
|
[
|
|
1114
1462
|
{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000},
|
|
1115
1463
|
{"open": 117.5, "high": 120.0, "low": 116.0, "close": 119.0, "volume": 1400000}
|
|
1116
|
-
${
|
|
1117
|
-
... ${
|
|
1118
|
-
]`}`,
|
|
1119
|
-
${
|
|
1120
|
-
Please process this data according to the system instructions. Remember to return EXACTLY ${
|
|
1121
|
-
{ role: "system", content:
|
|
1122
|
-
{ role: "user", content:
|
|
1464
|
+
${o > 2 ? `,
|
|
1465
|
+
... ${o - 2} more OHLCV objects following the same pattern` : ""}
|
|
1466
|
+
]`}`, u = JSON.stringify(e, null, 2), m = `Here is the historical OHLCV data (${e.length} periods):
|
|
1467
|
+
${u}
|
|
1468
|
+
Please process this data according to the system instructions. Remember to return EXACTLY ${o} OHLCV object(s) in a JSON array with no additional text.`, c = [
|
|
1469
|
+
{ role: "system", content: l },
|
|
1470
|
+
{ role: "user", content: m }
|
|
1123
1471
|
];
|
|
1124
1472
|
try {
|
|
1125
|
-
const
|
|
1473
|
+
const p = o * 50 + 100, g = Math.max(a?.maxTokens || 2e3, p), y = await this.chatCompletion(c, "en", {
|
|
1126
1474
|
temperature: a?.temperature || 0.3,
|
|
1127
|
-
maxTokens:
|
|
1475
|
+
maxTokens: g,
|
|
1128
1476
|
stream: !1,
|
|
1129
|
-
modelType:
|
|
1477
|
+
modelType: this.modelType,
|
|
1130
1478
|
topP: a?.topP,
|
|
1131
1479
|
frequencyPenalty: a?.frequencyPenalty,
|
|
1132
1480
|
presencePenalty: a?.presencePenalty
|
|
1133
|
-
}),
|
|
1134
|
-
if (
|
|
1135
|
-
throw new Error(`AI returned ${
|
|
1136
|
-
return
|
|
1137
|
-
} catch (
|
|
1138
|
-
throw new Error(`OHLCV analysis failed: ${
|
|
1481
|
+
}), h = this.extractContent(y), b = this.parseOHLCVResponse(h);
|
|
1482
|
+
if (b.length !== o)
|
|
1483
|
+
throw new Error(`AI returned ${b.length} OHLCV objects, but expected ${o}.`);
|
|
1484
|
+
return b;
|
|
1485
|
+
} catch (p) {
|
|
1486
|
+
throw new Error(`OHLCV analysis failed: ${p.message}`);
|
|
1139
1487
|
}
|
|
1140
1488
|
}
|
|
1141
1489
|
/**
|
|
@@ -1143,7 +1491,7 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1143
1491
|
* @param modelType - New model type
|
|
1144
1492
|
*/
|
|
1145
1493
|
setModel(e) {
|
|
1146
|
-
if (
|
|
1494
|
+
if (!$.get(e))
|
|
1147
1495
|
throw new Error(`Unsupported model type: ${e}`);
|
|
1148
1496
|
this.modelType = e;
|
|
1149
1497
|
}
|
|
@@ -1151,7 +1499,7 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1151
1499
|
* Get current model configuration
|
|
1152
1500
|
*/
|
|
1153
1501
|
getCurrentModel() {
|
|
1154
|
-
const e =
|
|
1502
|
+
const e = $.get(this.modelType);
|
|
1155
1503
|
if (!e)
|
|
1156
1504
|
throw new Error(`Model configuration does not exist: ${this.modelType}`);
|
|
1157
1505
|
return {
|
|
@@ -1161,12 +1509,12 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1161
1509
|
};
|
|
1162
1510
|
}
|
|
1163
1511
|
/**
|
|
1164
|
-
* Test connection
|
|
1512
|
+
* Test connection with i18n support
|
|
1165
1513
|
* @returns Connection test result
|
|
1166
1514
|
*/
|
|
1167
1515
|
async testConnection() {
|
|
1168
1516
|
try {
|
|
1169
|
-
const e = await this.chat('Hello, respond with "OK" if you can hear me.');
|
|
1517
|
+
const e = await this.chat('Hello, respond with "OK" if you can hear me.', "en");
|
|
1170
1518
|
return {
|
|
1171
1519
|
success: !0,
|
|
1172
1520
|
model: this.modelType,
|
|
@@ -1180,71 +1528,71 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1180
1528
|
};
|
|
1181
1529
|
}
|
|
1182
1530
|
}
|
|
1183
|
-
buildOpenAIRequest(e,
|
|
1184
|
-
const
|
|
1531
|
+
buildOpenAIRequest(e, t, s, a, r, o, i, d, l, u, m) {
|
|
1532
|
+
const c = {
|
|
1185
1533
|
model: e,
|
|
1186
|
-
messages:
|
|
1534
|
+
messages: t,
|
|
1187
1535
|
temperature: s,
|
|
1188
1536
|
max_tokens: a,
|
|
1189
|
-
stream:
|
|
1537
|
+
stream: r
|
|
1190
1538
|
};
|
|
1191
|
-
return
|
|
1539
|
+
return o !== void 0 && (c.top_p = o), i !== void 0 && (c.frequency_penalty = i), d !== void 0 && (c.presence_penalty = d), l && (c.stop = l), u && (c.tools = u), m && (c.tool_choice = m), c;
|
|
1192
1540
|
}
|
|
1193
|
-
async makeRequest(e,
|
|
1194
|
-
const a = new AbortController(),
|
|
1541
|
+
async makeRequest(e, t, s) {
|
|
1542
|
+
const a = new AbortController(), r = setTimeout(() => a.abort(), this.timeout);
|
|
1195
1543
|
try {
|
|
1196
|
-
const
|
|
1544
|
+
const o = await fetch(e, {
|
|
1197
1545
|
method: "POST",
|
|
1198
1546
|
headers: {
|
|
1199
1547
|
Authorization: `Bearer ${this.apiKey}`,
|
|
1200
1548
|
"Content-Type": "application/json; charset=utf-8",
|
|
1201
1549
|
Accept: "application/json"
|
|
1202
1550
|
},
|
|
1203
|
-
body: JSON.stringify(
|
|
1551
|
+
body: JSON.stringify(t),
|
|
1204
1552
|
signal: a.signal
|
|
1205
1553
|
});
|
|
1206
|
-
if (clearTimeout(
|
|
1207
|
-
const
|
|
1208
|
-
throw new Error(`HTTP ${
|
|
1554
|
+
if (clearTimeout(r), !o.ok) {
|
|
1555
|
+
const i = await o.text();
|
|
1556
|
+
throw new Error(`HTTP ${o.status}: ${i}`);
|
|
1209
1557
|
}
|
|
1210
|
-
return s ?
|
|
1211
|
-
} catch (
|
|
1212
|
-
throw clearTimeout(
|
|
1558
|
+
return s ? o.body : await o.json();
|
|
1559
|
+
} catch (o) {
|
|
1560
|
+
throw clearTimeout(r), o.name === "AbortError" ? new Error(`Request timeout (${this.timeout}ms)`) : o;
|
|
1213
1561
|
}
|
|
1214
1562
|
}
|
|
1215
|
-
async makeStreamRequest(e,
|
|
1216
|
-
const a = await this.makeRequest(e,
|
|
1563
|
+
async makeStreamRequest(e, t, s) {
|
|
1564
|
+
const a = await this.makeRequest(e, t, !0);
|
|
1217
1565
|
if (!a)
|
|
1218
1566
|
throw new Error("Failed to get streaming response");
|
|
1219
|
-
const
|
|
1220
|
-
let
|
|
1567
|
+
const r = a.getReader(), o = new TextDecoder("utf-8");
|
|
1568
|
+
let i = "";
|
|
1221
1569
|
try {
|
|
1222
1570
|
for (; ; ) {
|
|
1223
|
-
const { done:
|
|
1224
|
-
if (
|
|
1571
|
+
const { done: d, value: l } = await r.read();
|
|
1572
|
+
if (d) {
|
|
1225
1573
|
s("", !0);
|
|
1226
1574
|
break;
|
|
1227
1575
|
}
|
|
1228
|
-
|
|
1229
|
-
const
|
|
1576
|
+
i += o.decode(l, { stream: !0 });
|
|
1577
|
+
const u = i.split(`
|
|
1230
1578
|
`);
|
|
1231
|
-
|
|
1232
|
-
for (const
|
|
1233
|
-
if (
|
|
1234
|
-
const
|
|
1235
|
-
if (
|
|
1579
|
+
i = u.pop() || "";
|
|
1580
|
+
for (const m of u)
|
|
1581
|
+
if (m.startsWith("data: ")) {
|
|
1582
|
+
const c = m.slice(6);
|
|
1583
|
+
if (c === "[DONE]") {
|
|
1236
1584
|
s("", !0);
|
|
1237
1585
|
return;
|
|
1238
1586
|
}
|
|
1239
1587
|
try {
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1588
|
+
const p = JSON.parse(c);
|
|
1589
|
+
p.choices?.[0]?.delta?.content && s(p.choices[0].delta.content, !1);
|
|
1242
1590
|
} catch {
|
|
1243
1591
|
}
|
|
1244
1592
|
}
|
|
1245
1593
|
}
|
|
1246
1594
|
} finally {
|
|
1247
|
-
|
|
1595
|
+
r.releaseLock();
|
|
1248
1596
|
}
|
|
1249
1597
|
}
|
|
1250
1598
|
extractContent(e) {
|
|
@@ -1260,42 +1608,42 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1260
1608
|
}
|
|
1261
1609
|
parseOHLCVResponse(e) {
|
|
1262
1610
|
try {
|
|
1263
|
-
const
|
|
1264
|
-
if (!Array.isArray(
|
|
1611
|
+
const t = JSON.parse(e);
|
|
1612
|
+
if (!Array.isArray(t))
|
|
1265
1613
|
throw new Error("Response is not in array format");
|
|
1266
|
-
return
|
|
1614
|
+
return t.map((a, r) => {
|
|
1267
1615
|
if (typeof a != "object" || a === null)
|
|
1268
|
-
throw new Error(`Element ${
|
|
1269
|
-
const { open:
|
|
1270
|
-
for (const
|
|
1271
|
-
if (typeof a[
|
|
1272
|
-
throw new Error(`Element ${
|
|
1273
|
-
if (
|
|
1274
|
-
throw new Error(`Element ${
|
|
1275
|
-
if (
|
|
1276
|
-
throw new Error(`Element ${
|
|
1616
|
+
throw new Error(`Element ${r} is not a valid object`);
|
|
1617
|
+
const { open: o, high: i, low: d, close: l, volume: u } = a, m = ["open", "high", "low", "close", "volume"];
|
|
1618
|
+
for (const c of m)
|
|
1619
|
+
if (typeof a[c] != "number" || isNaN(a[c]))
|
|
1620
|
+
throw new Error(`Element ${r} field ${c} is not a valid number`);
|
|
1621
|
+
if (i < d)
|
|
1622
|
+
throw new Error(`Element ${r}: high cannot be lower than low`);
|
|
1623
|
+
if (l < d || l > i)
|
|
1624
|
+
throw new Error(`Element ${r}: close must be between low and high`);
|
|
1277
1625
|
return {
|
|
1278
|
-
open: Number(
|
|
1279
|
-
high: Number(
|
|
1280
|
-
low: Number(
|
|
1281
|
-
close: Number(
|
|
1282
|
-
volume: Number(
|
|
1626
|
+
open: Number(o),
|
|
1627
|
+
high: Number(i),
|
|
1628
|
+
low: Number(d),
|
|
1629
|
+
close: Number(l),
|
|
1630
|
+
volume: Number(u)
|
|
1283
1631
|
};
|
|
1284
1632
|
});
|
|
1285
|
-
} catch (
|
|
1633
|
+
} catch (t) {
|
|
1286
1634
|
const s = e.match(/\[[\s\S]*\]/);
|
|
1287
1635
|
if (s)
|
|
1288
1636
|
return this.parseOHLCVResponse(s[0]);
|
|
1289
|
-
throw new Error(`Unable to parse AI returned OHLCV data: ${
|
|
1637
|
+
throw new Error(`Unable to parse AI returned OHLCV data: ${t}
|
|
1290
1638
|
Original content: ${e.substring(0, 200)}...`);
|
|
1291
1639
|
}
|
|
1292
1640
|
}
|
|
1293
1641
|
}
|
|
1294
|
-
function
|
|
1295
|
-
return new
|
|
1642
|
+
function M(n, e) {
|
|
1643
|
+
return new H({ apiKey: n, modelType: e });
|
|
1296
1644
|
}
|
|
1297
|
-
var
|
|
1298
|
-
const
|
|
1645
|
+
var T = /* @__PURE__ */ ((n) => (n.GPT4 = "gpt-4", n.GPT4_0314 = "gpt-4-0314", n.GPT4_0613 = "gpt-4-0613", n.GPT4_32K = "gpt-4-32k", n.GPT4_32K_0314 = "gpt-4-32k-0314", n.GPT4_32K_0613 = "gpt-4-32k-0613", n.GPT4_TURBO = "gpt-4-turbo", n.GPT4_TURBO_PREVIEW = "gpt-4-turbo-preview", n.GPT4_TURBO_2024_04_09 = "gpt-4-turbo-2024-04-09", n.GPT4_OMNI = "gpt-4o", n.GPT4_OMNI_2024_05_13 = "gpt-4o-2024-05-13", n.GPT4_OMNI_MINI = "gpt-4o-mini", n.GPT4_OMNI_MINI_2024_07_18 = "gpt-4o-mini-2024-07-18", n.GPT3_5_TURBO = "gpt-3.5-turbo", n.GPT3_5_TURBO_0125 = "gpt-3.5-turbo-0125", n.GPT3_5_TURBO_1106 = "gpt-3.5-turbo-1106", n.GPT3_5_TURBO_INSTRUCT = "gpt-3.5-turbo-instruct", n.GPT3_5_TURBO_16K = "gpt-3.5-turbo-16k", n.GPT3_5_TURBO_16K_0613 = "gpt-3.5-turbo-16k-0613", n.DAVINCI_002 = "davinci-002", n.BABBAGE_002 = "babbage-002", n.TEXT_DAVINCI_003 = "text-davinci-003", n.TEXT_DAVINCI_002 = "text-davinci-002", n.TEXT_DAVINCI_001 = "text-davinci-001", n.TEXT_CURIE_001 = "text-curie-001", n.TEXT_BABBAGE_001 = "text-babbage-001", n.TEXT_ADA_001 = "text-ada-001", n.TEXT_EMBEDDING_ADA_002 = "text-embedding-ada-002", n.TEXT_EMBEDDING_3_SMALL = "text-embedding-3-small", n.TEXT_EMBEDDING_3_LARGE = "text-embedding-3-large", n.DALL_E_2 = "dall-e-2", n.DALL_E_3 = "dall-e-3", n.WHISPER_1 = "whisper-1", n.TTS_1 = "tts-1", n.TTS_1_HD = "tts-1-hd", n.MODERATION_LATEST = "text-moderation-latest", n.MODERATION_STABLE = "text-moderation-stable", n.GPT3_5_TURBO_FINETUNED = "ft:gpt-3.5-turbo-0125:personal:", n.GPT4_FINETUNED = "ft:gpt-4-0125-preview:personal:", n.GPT4_VISION_PREVIEW = "gpt-4-vision-preview", n))(T || {});
|
|
1646
|
+
const x = /* @__PURE__ */ new Map([
|
|
1299
1647
|
// GPT-4 Series
|
|
1300
1648
|
[
|
|
1301
1649
|
"gpt-4",
|
|
@@ -1483,52 +1831,52 @@ const h = /* @__PURE__ */ new Map([
|
|
|
1483
1831
|
}
|
|
1484
1832
|
]
|
|
1485
1833
|
]);
|
|
1486
|
-
function
|
|
1487
|
-
return
|
|
1834
|
+
function j(n) {
|
|
1835
|
+
return x.get(n);
|
|
1488
1836
|
}
|
|
1489
|
-
function
|
|
1490
|
-
return Array.from(
|
|
1837
|
+
function L() {
|
|
1838
|
+
return Array.from(x.values());
|
|
1491
1839
|
}
|
|
1492
|
-
function
|
|
1493
|
-
for (const e of
|
|
1494
|
-
if (e.name ===
|
|
1840
|
+
function W(n) {
|
|
1841
|
+
for (const e of x.values())
|
|
1842
|
+
if (e.name === n)
|
|
1495
1843
|
return e;
|
|
1496
1844
|
}
|
|
1497
|
-
function
|
|
1498
|
-
return Array.from(
|
|
1845
|
+
function G() {
|
|
1846
|
+
return Array.from(x.keys());
|
|
1499
1847
|
}
|
|
1500
|
-
function
|
|
1501
|
-
return
|
|
1502
|
-
(
|
|
1848
|
+
function J() {
|
|
1849
|
+
return L().filter(
|
|
1850
|
+
(n) => n.capabilities.includes("chat")
|
|
1503
1851
|
);
|
|
1504
1852
|
}
|
|
1505
|
-
function
|
|
1506
|
-
return
|
|
1507
|
-
(
|
|
1853
|
+
function X() {
|
|
1854
|
+
return L().filter(
|
|
1855
|
+
(n) => n.capabilities.includes("text-completion")
|
|
1508
1856
|
);
|
|
1509
1857
|
}
|
|
1510
|
-
function
|
|
1511
|
-
return
|
|
1512
|
-
(
|
|
1858
|
+
function Z() {
|
|
1859
|
+
return L().filter(
|
|
1860
|
+
(n) => n.capabilities.includes("embeddings")
|
|
1513
1861
|
);
|
|
1514
1862
|
}
|
|
1515
|
-
function
|
|
1516
|
-
return
|
|
1517
|
-
(
|
|
1863
|
+
function Y() {
|
|
1864
|
+
return L().filter(
|
|
1865
|
+
(n) => n.capabilities.includes("vision") || n.capabilities.includes("image-generation")
|
|
1518
1866
|
);
|
|
1519
1867
|
}
|
|
1520
|
-
function
|
|
1521
|
-
return
|
|
1522
|
-
(
|
|
1868
|
+
function ee() {
|
|
1869
|
+
return L().filter(
|
|
1870
|
+
(n) => n.capabilities.includes("audio-processing") || n.capabilities.includes("speech-recognition") || n.capabilities.includes("speech-synthesis")
|
|
1523
1871
|
);
|
|
1524
1872
|
}
|
|
1525
|
-
function
|
|
1526
|
-
return
|
|
1527
|
-
(
|
|
1873
|
+
function te() {
|
|
1874
|
+
return L().filter(
|
|
1875
|
+
(n) => n.capabilities.includes("multimodal")
|
|
1528
1876
|
);
|
|
1529
1877
|
}
|
|
1530
|
-
function
|
|
1531
|
-
const
|
|
1878
|
+
function ne() {
|
|
1879
|
+
const n = [
|
|
1532
1880
|
"gpt-4o",
|
|
1533
1881
|
"gpt-4o-mini",
|
|
1534
1882
|
"gpt-4-turbo",
|
|
@@ -1537,67 +1885,67 @@ function z() {
|
|
|
1537
1885
|
"dall-e-3"
|
|
1538
1886
|
/* DALL_E_3 */
|
|
1539
1887
|
];
|
|
1540
|
-
return
|
|
1541
|
-
(e) =>
|
|
1888
|
+
return L().filter(
|
|
1889
|
+
(e) => n.includes(e.name)
|
|
1542
1890
|
);
|
|
1543
1891
|
}
|
|
1544
|
-
function
|
|
1545
|
-
return
|
|
1892
|
+
function oe() {
|
|
1893
|
+
return L().filter((n) => n.inputCostPer1KTokens && n.inputCostPer1KTokens < 1e-3).sort((n, e) => (n.inputCostPer1KTokens || 0) - (e.inputCostPer1KTokens || 0));
|
|
1546
1894
|
}
|
|
1547
|
-
function
|
|
1548
|
-
return
|
|
1895
|
+
function ae() {
|
|
1896
|
+
return L().filter((n) => n.contextLength && n.contextLength >= 128e3).sort((n, e) => (e.contextLength || 0) - (n.contextLength || 0));
|
|
1549
1897
|
}
|
|
1550
|
-
function
|
|
1551
|
-
const s = (
|
|
1898
|
+
function se(n, e, t = 0) {
|
|
1899
|
+
const s = (n.inputCostPer1KTokens || 0) / 1e3 * e, a = (n.outputCostPer1KTokens || 0) / 1e3 * t;
|
|
1552
1900
|
return {
|
|
1553
1901
|
inputTokens: e,
|
|
1554
|
-
outputTokens:
|
|
1902
|
+
outputTokens: t,
|
|
1555
1903
|
inputCost: s,
|
|
1556
1904
|
outputCost: a,
|
|
1557
1905
|
totalCost: s + a
|
|
1558
1906
|
};
|
|
1559
1907
|
}
|
|
1560
|
-
function
|
|
1561
|
-
let e =
|
|
1562
|
-
switch (
|
|
1908
|
+
function ie(n) {
|
|
1909
|
+
let e = L();
|
|
1910
|
+
switch (n.taskType) {
|
|
1563
1911
|
case "chat":
|
|
1564
|
-
e = e.filter((
|
|
1912
|
+
e = e.filter((t) => t.capabilities.includes("chat"));
|
|
1565
1913
|
break;
|
|
1566
1914
|
case "completion":
|
|
1567
|
-
e = e.filter((
|
|
1915
|
+
e = e.filter((t) => t.capabilities.includes("text-completion"));
|
|
1568
1916
|
break;
|
|
1569
1917
|
case "embedding":
|
|
1570
|
-
e = e.filter((
|
|
1918
|
+
e = e.filter((t) => t.capabilities.includes("embeddings"));
|
|
1571
1919
|
break;
|
|
1572
1920
|
case "image":
|
|
1573
1921
|
e = e.filter(
|
|
1574
|
-
(
|
|
1922
|
+
(t) => t.capabilities.includes("image-generation") || t.capabilities.includes("vision")
|
|
1575
1923
|
);
|
|
1576
1924
|
break;
|
|
1577
1925
|
case "audio":
|
|
1578
1926
|
e = e.filter(
|
|
1579
|
-
(
|
|
1927
|
+
(t) => t.capabilities.includes("speech-recognition") || t.capabilities.includes("speech-synthesis")
|
|
1580
1928
|
);
|
|
1581
1929
|
break;
|
|
1582
1930
|
}
|
|
1583
|
-
return
|
|
1584
|
-
(
|
|
1585
|
-
)),
|
|
1586
|
-
(
|
|
1587
|
-
(s) =>
|
|
1931
|
+
return n.contextLength && (e = e.filter(
|
|
1932
|
+
(t) => t.contextLength && t.contextLength >= n.contextLength
|
|
1933
|
+
)), n.features && n.features.length > 0 && (e = e.filter(
|
|
1934
|
+
(t) => n.features.every(
|
|
1935
|
+
(s) => t.supportedFeatures?.includes(s) || t.capabilities.includes(s)
|
|
1588
1936
|
)
|
|
1589
|
-
)),
|
|
1590
|
-
(
|
|
1937
|
+
)), n.budget && e.sort(
|
|
1938
|
+
(t, s) => (t.inputCostPer1KTokens || 0) - (s.inputCostPer1KTokens || 0)
|
|
1591
1939
|
), e.slice(0, 5);
|
|
1592
1940
|
}
|
|
1593
|
-
function
|
|
1594
|
-
const e = Object.values(
|
|
1595
|
-
for (const
|
|
1596
|
-
if (
|
|
1597
|
-
return
|
|
1941
|
+
function re(n) {
|
|
1942
|
+
const e = Object.values(T);
|
|
1943
|
+
for (const t of e)
|
|
1944
|
+
if (t === n)
|
|
1945
|
+
return t;
|
|
1598
1946
|
return null;
|
|
1599
1947
|
}
|
|
1600
|
-
class
|
|
1948
|
+
class S {
|
|
1601
1949
|
/**
|
|
1602
1950
|
* Constructor - Minimal configuration
|
|
1603
1951
|
* @param config.apiKey - API key (required)
|
|
@@ -1607,77 +1955,313 @@ class L {
|
|
|
1607
1955
|
* @param config.baseURL - Custom base URL (optional)
|
|
1608
1956
|
*/
|
|
1609
1957
|
constructor(e) {
|
|
1610
|
-
if (this.apiKey = e.apiKey, this.modelType = e.modelType ||
|
|
1958
|
+
if (this.apiKey = e.apiKey, this.modelType = e.modelType || T.GPT3_5_TURBO, this.timeout = e.timeout || 3e4, this.organization = e.organization, this.baseURL = e.baseURL || "https://api.openai.com/v1", !this.apiKey)
|
|
1611
1959
|
throw new Error("API Key cannot be empty");
|
|
1612
|
-
if (!
|
|
1960
|
+
if (!x.get(this.modelType))
|
|
1613
1961
|
throw new Error(`Unsupported model type: ${this.modelType}`);
|
|
1614
1962
|
}
|
|
1615
1963
|
/**
|
|
1616
|
-
* Simplest method: single conversation
|
|
1964
|
+
* Simplest method: single conversation with i18n support
|
|
1617
1965
|
* @param message - User message
|
|
1966
|
+
* @param i18n - Language restriction for AI response
|
|
1618
1967
|
* @param options - Chat options
|
|
1619
1968
|
* @returns AI response
|
|
1620
1969
|
*/
|
|
1621
|
-
async chat(e,
|
|
1622
|
-
const
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1970
|
+
async chat(e, t, s) {
|
|
1971
|
+
const a = [], r = t === "en" ? "Please respond in English only." : t === "cn" ? "请使用中文回答。" : "";
|
|
1972
|
+
if (s?.systemPrompt || r) {
|
|
1973
|
+
const i = [s?.systemPrompt, r].filter(Boolean).join(`
|
|
1974
|
+
`);
|
|
1975
|
+
a.push({ role: "system", content: i });
|
|
1976
|
+
}
|
|
1977
|
+
a.push({ role: "user", content: e });
|
|
1978
|
+
const o = await this.chatCompletion(a, t, {
|
|
1979
|
+
temperature: s?.temperature,
|
|
1980
|
+
maxTokens: s?.maxTokens,
|
|
1627
1981
|
stream: !1,
|
|
1628
|
-
topP:
|
|
1629
|
-
frequencyPenalty:
|
|
1630
|
-
presencePenalty:
|
|
1631
|
-
stop:
|
|
1982
|
+
topP: s?.topP,
|
|
1983
|
+
frequencyPenalty: s?.frequencyPenalty,
|
|
1984
|
+
presencePenalty: s?.presencePenalty,
|
|
1985
|
+
stop: s?.stop
|
|
1632
1986
|
});
|
|
1633
|
-
return this.extractContent(
|
|
1987
|
+
return this.extractContent(o);
|
|
1634
1988
|
}
|
|
1635
1989
|
/**
|
|
1636
|
-
* Multi-turn conversation
|
|
1990
|
+
* Multi-turn conversation with i18n support
|
|
1637
1991
|
* @param messages - Message history
|
|
1992
|
+
* @param i18n - Language restriction for AI response
|
|
1638
1993
|
* @param options - Chat options
|
|
1639
1994
|
* @returns Complete API response
|
|
1640
1995
|
*/
|
|
1641
|
-
async chatCompletion(e,
|
|
1642
|
-
const
|
|
1643
|
-
if (!
|
|
1644
|
-
throw new Error(`Unsupported model type: ${
|
|
1645
|
-
const
|
|
1646
|
-
|
|
1996
|
+
async chatCompletion(e, t, s) {
|
|
1997
|
+
const a = s?.modelType || this.modelType, r = x.get(a);
|
|
1998
|
+
if (!r)
|
|
1999
|
+
throw new Error(`Unsupported model type: ${a}`);
|
|
2000
|
+
const o = s?.temperature ?? 0.7, i = s?.maxTokens ?? 1e3, d = s?.stream ?? !1, l = r.endpoint, u = t === "en" ? "Please respond in English only." : t === "cn" ? "请使用中文回答。" : "";
|
|
2001
|
+
u && (e.some((p) => p.role === "system") ? e = e.map((p) => p.role === "system" ? {
|
|
2002
|
+
...p,
|
|
2003
|
+
content: `${p.content}
|
|
2004
|
+
${u}`
|
|
2005
|
+
} : p) : e.unshift({ role: "system", content: u }));
|
|
2006
|
+
const m = this.buildOpenAIRequest(
|
|
2007
|
+
r.name,
|
|
1647
2008
|
e,
|
|
2009
|
+
o,
|
|
1648
2010
|
i,
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
o
|
|
2011
|
+
d,
|
|
2012
|
+
s
|
|
1652
2013
|
);
|
|
1653
2014
|
try {
|
|
1654
|
-
return await this.makeRequest(
|
|
1655
|
-
} catch (
|
|
1656
|
-
throw new Error(`OpenAI request failed: ${
|
|
2015
|
+
return await this.makeRequest(l, m, d);
|
|
2016
|
+
} catch (c) {
|
|
2017
|
+
throw new Error(`OpenAI request failed: ${c.message}`);
|
|
1657
2018
|
}
|
|
1658
2019
|
}
|
|
1659
2020
|
/**
|
|
1660
|
-
* Streaming conversation
|
|
2021
|
+
* Streaming conversation with i18n support
|
|
1661
2022
|
* @param messages - Message history
|
|
1662
2023
|
* @param callback - Streaming callback function
|
|
2024
|
+
* @param i18n - Language restriction for AI response
|
|
1663
2025
|
* @param options - Chat options
|
|
1664
2026
|
*/
|
|
1665
|
-
async chatStream(e,
|
|
1666
|
-
const
|
|
1667
|
-
if (!
|
|
1668
|
-
throw new Error(`Unsupported model type: ${
|
|
1669
|
-
const
|
|
1670
|
-
|
|
2027
|
+
async chatStream(e, t, s, a) {
|
|
2028
|
+
const r = a?.modelType || this.modelType, o = x.get(r);
|
|
2029
|
+
if (!o)
|
|
2030
|
+
throw new Error(`Unsupported model type: ${r}`);
|
|
2031
|
+
const i = a?.temperature ?? 0.7, d = a?.maxTokens ?? 1e3, l = s === "en" ? "Please respond in English only." : s === "cn" ? "请使用中文回答。" : "";
|
|
2032
|
+
l && (e.some((c) => c.role === "system") ? e = e.map((c) => c.role === "system" ? {
|
|
2033
|
+
...c,
|
|
2034
|
+
content: `${c.content}
|
|
2035
|
+
${l}`
|
|
2036
|
+
} : c) : e.unshift({ role: "system", content: l }));
|
|
2037
|
+
const u = this.buildOpenAIRequest(
|
|
2038
|
+
o.name,
|
|
1671
2039
|
e,
|
|
1672
|
-
|
|
1673
|
-
|
|
2040
|
+
i,
|
|
2041
|
+
d,
|
|
1674
2042
|
!0,
|
|
1675
|
-
|
|
2043
|
+
a
|
|
1676
2044
|
);
|
|
1677
2045
|
try {
|
|
1678
|
-
await this.makeStreamRequest(
|
|
1679
|
-
} catch (
|
|
1680
|
-
throw new Error(`Streaming request failed: ${
|
|
2046
|
+
await this.makeStreamRequest(o.endpoint, u, t);
|
|
2047
|
+
} catch (m) {
|
|
2048
|
+
throw new Error(`Streaming request failed: ${m.message}`);
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* Analyze OHLCV data and return AI analysis results (text description)
|
|
2053
|
+
* @param ohlcvArray - OHLCV data array
|
|
2054
|
+
* @param i18n - Language restriction for AI response
|
|
2055
|
+
* @param analysisType - Analysis type (optional, default: "comprehensive")
|
|
2056
|
+
* - "trend": Trend analysis
|
|
2057
|
+
* - "volume": Volume analysis
|
|
2058
|
+
* - "technical": Technical analysis
|
|
2059
|
+
* - "comprehensive": Comprehensive analysis
|
|
2060
|
+
* @param message - User's subjective request or specific question (optional)
|
|
2061
|
+
* @param options - Chat options
|
|
2062
|
+
* @returns AI analysis result of OHLCV data (text description)
|
|
2063
|
+
*/
|
|
2064
|
+
async analyzeOHLCV(e, t, s, a, r) {
|
|
2065
|
+
const o = s || "comprehensive", i = e.length, l = {
|
|
2066
|
+
trend: {
|
|
2067
|
+
en: "Provide a detailed trend analysis of this OHLCV data, including price direction, support/resistance levels, and trend strength.",
|
|
2068
|
+
cn: "提供详细的OHLCV数据趋势分析,包括价格方向、支撑/阻力位和趋势强度。"
|
|
2069
|
+
},
|
|
2070
|
+
volume: {
|
|
2071
|
+
en: "Analyze the volume patterns in this OHLCV data, including volume trends, unusual volume spikes, and volume-price relationships.",
|
|
2072
|
+
cn: "分析OHLCV数据中的成交量模式,包括成交量趋势、异常成交量波动和量价关系。"
|
|
2073
|
+
},
|
|
2074
|
+
technical: {
|
|
2075
|
+
en: "Perform technical analysis on this OHLCV data, identifying potential technical indicators, patterns, and trading signals.",
|
|
2076
|
+
cn: "对OHLCV数据进行技术分析,识别潜在的技术指标、图表形态和交易信号。"
|
|
2077
|
+
},
|
|
2078
|
+
comprehensive: {
|
|
2079
|
+
en: "Provide a comprehensive analysis of this OHLCV data, covering trends, volume, technical aspects, and potential market implications.",
|
|
2080
|
+
cn: "提供全面的OHLCV数据分析,涵盖趋势、成交量、技术面和潜在市场影响。"
|
|
2081
|
+
}
|
|
2082
|
+
}[o][t], u = t === "en" ? "Please provide your analysis in English." : "请用中文进行分析。";
|
|
2083
|
+
let m = "";
|
|
2084
|
+
if (i > 0) {
|
|
2085
|
+
const h = e[0], f = e[i - 1].close - h.close, w = f / h.close * 100;
|
|
2086
|
+
let C = h.high, v = h.low, P = 0;
|
|
2087
|
+
for (const E of e)
|
|
2088
|
+
E.high > C && (C = E.high), E.low < v && (v = E.low), P += E.volume;
|
|
2089
|
+
const _ = P / i;
|
|
2090
|
+
m = t === "en" ? `This dataset contains ${i} periods of OHLCV data.
|
|
2091
|
+
Price range: ${v.toFixed(2)} - ${C.toFixed(2)}
|
|
2092
|
+
Overall price change: ${f >= 0 ? "+" : ""}${f.toFixed(2)} (${f >= 0 ? "+" : ""}${w.toFixed(2)}%)
|
|
2093
|
+
Average volume: ${_.toFixed(0)}` : `该数据集包含 ${i} 个周期的OHLCV数据。
|
|
2094
|
+
价格范围:${v.toFixed(2)} - ${C.toFixed(2)}
|
|
2095
|
+
总体价格变化:${f >= 0 ? "+" : ""}${f.toFixed(2)} (${f >= 0 ? "+" : ""}${w.toFixed(2)}%)
|
|
2096
|
+
平均成交量:${_.toFixed(0)}`;
|
|
2097
|
+
}
|
|
2098
|
+
let c = t === "en" ? `You are a professional financial data analyst. Your task is to analyze OHLCV (Open, High, Low, Close, Volume) data and provide insights.
|
|
2099
|
+
Analysis focus: ${l}
|
|
2100
|
+
${m ? `Data characteristics:
|
|
2101
|
+
${m}
|
|
2102
|
+
|
|
2103
|
+
` : ""}
|
|
2104
|
+
Please provide:
|
|
2105
|
+
1. Clear and structured analysis
|
|
2106
|
+
2. Key observations from the data
|
|
2107
|
+
3. Potential implications or insights
|
|
2108
|
+
4. Recommendations or considerations (if applicable)
|
|
2109
|
+
Format your response as a well-organized text analysis.` : `您是一位专业的金融数据分析师。您的任务是分析OHLCV(开盘价、最高价、最低价、收盘价、成交量)数据并提供见解。
|
|
2110
|
+
分析重点:${l}
|
|
2111
|
+
${m ? `数据特征:
|
|
2112
|
+
${m}
|
|
2113
|
+
|
|
2114
|
+
` : ""}
|
|
2115
|
+
请提供:
|
|
2116
|
+
1. 清晰且有结构的分析
|
|
2117
|
+
2. 数据的关键观察结果
|
|
2118
|
+
3. 潜在的启示或见解
|
|
2119
|
+
4. 建议或注意事项(如适用)
|
|
2120
|
+
请以组织良好的文本分析形式回复。`;
|
|
2121
|
+
c += `
|
|
2122
|
+
|
|
2123
|
+
${u}`;
|
|
2124
|
+
const p = JSON.stringify(e, null, 2);
|
|
2125
|
+
let g = "";
|
|
2126
|
+
a ? g = t === "en" ? `Here is the OHLCV data (${i} periods):
|
|
2127
|
+
${p}
|
|
2128
|
+
My specific question or request: ${a}
|
|
2129
|
+
Please analyze this data considering my request above.` : `这是OHLCV数据(${i}个周期):
|
|
2130
|
+
${p}
|
|
2131
|
+
我的具体问题或需求:${a}
|
|
2132
|
+
请根据我的上述需求分析这些数据。` : g = t === "en" ? `Here is the OHLCV data (${i} periods):
|
|
2133
|
+
${p}
|
|
2134
|
+
Please analyze this data as requested.` : `这是OHLCV数据(${i}个周期):
|
|
2135
|
+
${p}
|
|
2136
|
+
请按要求分析这些数据。`;
|
|
2137
|
+
const y = [
|
|
2138
|
+
{ role: "system", content: c },
|
|
2139
|
+
{ role: "user", content: g }
|
|
2140
|
+
];
|
|
2141
|
+
try {
|
|
2142
|
+
const h = await this.chatCompletion(y, t, {
|
|
2143
|
+
temperature: r?.temperature || 0.5,
|
|
2144
|
+
maxTokens: r?.maxTokens || 1500,
|
|
2145
|
+
stream: !1,
|
|
2146
|
+
modelType: this.modelType,
|
|
2147
|
+
topP: r?.topP,
|
|
2148
|
+
frequencyPenalty: r?.frequencyPenalty,
|
|
2149
|
+
presencePenalty: r?.presencePenalty,
|
|
2150
|
+
stop: r?.stop
|
|
2151
|
+
});
|
|
2152
|
+
return this.extractContent(h);
|
|
2153
|
+
} catch (h) {
|
|
2154
|
+
throw new Error(`OHLCV analysis failed: ${h.message}`);
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
/**
|
|
2158
|
+
* Enhanced version: Analyze OHLCV and return structured results (optional)
|
|
2159
|
+
* @param ohlcvArray - OHLCV data array
|
|
2160
|
+
* @param i18n - Language restriction for AI response
|
|
2161
|
+
* @param analysisType - Analysis type
|
|
2162
|
+
* @param message - User's subjective request or specific question
|
|
2163
|
+
* @param structured - Whether to return structured results (default: false)
|
|
2164
|
+
* @param options - Chat options
|
|
2165
|
+
* @returns AI analysis results
|
|
2166
|
+
*/
|
|
2167
|
+
async analyzeOHLCVEnhanced(e, t, s, a, r = !1, o) {
|
|
2168
|
+
if (r) {
|
|
2169
|
+
const i = t === "en" ? `You are a professional financial data analyst. Analyze the OHLCV data and provide a structured response with:
|
|
2170
|
+
1. Summary (brief overview)
|
|
2171
|
+
2. Details (key observations, 3-5 points)
|
|
2172
|
+
3. Recommendations (actionable insights, 2-3 points)
|
|
2173
|
+
Format as JSON: {"summary": "...", "details": ["...", "..."], "recommendations": ["...", "..."]}` : `您是一位专业的金融数据分析师。分析OHLCV数据并提供结构化响应:
|
|
2174
|
+
1. 总结(简要概述)
|
|
2175
|
+
2. 详情(关键观察结果,3-5点)
|
|
2176
|
+
3. 建议(可操作的见解,2-3点)
|
|
2177
|
+
格式化为JSON:{"summary": "...", "details": ["...", "..."], "recommendations": ["...", "..."]}`, d = JSON.stringify(e, null, 2);
|
|
2178
|
+
let l = t === "en" ? `Analyze this OHLCV data (${e.length} periods):
|
|
2179
|
+
${d}` : `分析此OHLCV数据(${e.length}个周期):
|
|
2180
|
+
${d}`;
|
|
2181
|
+
a && (l += t === "en" ? `
|
|
2182
|
+
|
|
2183
|
+
Additional request: ${a}` : `
|
|
2184
|
+
|
|
2185
|
+
附加要求:${a}`);
|
|
2186
|
+
const u = [
|
|
2187
|
+
{ role: "system", content: i },
|
|
2188
|
+
{ role: "user", content: l }
|
|
2189
|
+
];
|
|
2190
|
+
try {
|
|
2191
|
+
const m = await this.chatCompletion(u, t, {
|
|
2192
|
+
temperature: o?.temperature || 0.4,
|
|
2193
|
+
maxTokens: o?.maxTokens || 1200,
|
|
2194
|
+
stream: !1,
|
|
2195
|
+
modelType: this.modelType
|
|
2196
|
+
}), c = this.extractContent(m);
|
|
2197
|
+
try {
|
|
2198
|
+
const p = JSON.parse(c);
|
|
2199
|
+
if (p.summary && Array.isArray(p.details) && Array.isArray(p.recommendations))
|
|
2200
|
+
return p;
|
|
2201
|
+
} catch {
|
|
2202
|
+
}
|
|
2203
|
+
return c;
|
|
2204
|
+
} catch (m) {
|
|
2205
|
+
throw new Error(`Structured OHLCV analysis failed: ${m.message}`);
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
return this.analyzeOHLCV(e, t, s, a, o);
|
|
2209
|
+
}
|
|
2210
|
+
/**
|
|
2211
|
+
* Specialized method for processing OHLCV arrays (predict future values)
|
|
2212
|
+
* @param ohlcvArray - OHLCV data array
|
|
2213
|
+
* @param instructions - Processing instructions, supports Chinese and English (optional, default: "Based on these OHLCV data, predict the next period")
|
|
2214
|
+
* @param count - Number of OHLCV data items to return (optional, default: 1)
|
|
2215
|
+
* @param options - Chat options
|
|
2216
|
+
* @returns Predicted OHLCV array
|
|
2217
|
+
*/
|
|
2218
|
+
async predictingOHLCV(e, t, s, a) {
|
|
2219
|
+
const r = t || "Based on these OHLCV data, predict the next period", o = s || 1;
|
|
2220
|
+
if (!Number.isInteger(o) || o <= 0)
|
|
2221
|
+
throw new Error(`Invalid count parameter: ${o}. Must be a positive integer.`);
|
|
2222
|
+
const i = 50;
|
|
2223
|
+
if (o > i)
|
|
2224
|
+
throw new Error(`Count parameter too large: ${o}. Maximum allowed is ${i}. Please reduce the count or split your request.`);
|
|
2225
|
+
const d = o === 1 ? "Return EXACTLY 1 OHLCV object for the next period." : `Return EXACTLY ${o} consecutive OHLCV objects for the next ${o} periods.`, l = `You are a professional financial data analysis AI. The user will give you an array of OHLCV (Open, High, Low, Close, Volume) data.
|
|
2226
|
+
Your task: ${r}
|
|
2227
|
+
CRITICAL RULES:
|
|
2228
|
+
1. ${d}
|
|
2229
|
+
2. Return ONLY a JSON array of OHLCV objects, NO explanations, comments, or other text
|
|
2230
|
+
3. The OHLCV array format must match: [{open, high, low, close, volume}, ...]
|
|
2231
|
+
4. All numbers must be valid numbers
|
|
2232
|
+
5. Ensure technical rationality (high >= low, high >= close >= low, volume >= 0)
|
|
2233
|
+
6. Maintain consistency with historical trends and patterns
|
|
2234
|
+
7. For technical analysis, provide reasonable values based on typical patterns
|
|
2235
|
+
8. Do not include markdown formatting, only pure JSON
|
|
2236
|
+
${o === 1 ? `Example of valid response for 1 period:
|
|
2237
|
+
[{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000}]` : `Example of valid response for ${o} periods:
|
|
2238
|
+
[
|
|
2239
|
+
{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000},
|
|
2240
|
+
{"open": 117.5, "high": 120.0, "low": 116.0, "close": 119.0, "volume": 1400000}
|
|
2241
|
+
${o > 2 ? `,
|
|
2242
|
+
... ${o - 2} more OHLCV objects following the same pattern` : ""}
|
|
2243
|
+
]`}`, u = JSON.stringify(e, null, 2), m = `Here is the historical OHLCV data (${e.length} periods):
|
|
2244
|
+
${u}
|
|
2245
|
+
Please process this data according to the system instructions. Remember to return EXACTLY ${o} OHLCV object(s) in a JSON array with no additional text.`, c = [
|
|
2246
|
+
{ role: "system", content: l },
|
|
2247
|
+
{ role: "user", content: m }
|
|
2248
|
+
];
|
|
2249
|
+
try {
|
|
2250
|
+
const p = o * 50 + 100, g = Math.max(a?.maxTokens || 1e3, p), y = await this.chatCompletion(c, "en", {
|
|
2251
|
+
temperature: a?.temperature || 0.3,
|
|
2252
|
+
maxTokens: g,
|
|
2253
|
+
stream: !1,
|
|
2254
|
+
modelType: this.modelType,
|
|
2255
|
+
topP: a?.topP,
|
|
2256
|
+
frequencyPenalty: a?.frequencyPenalty,
|
|
2257
|
+
presencePenalty: a?.presencePenalty,
|
|
2258
|
+
stop: a?.stop
|
|
2259
|
+
}), h = this.extractContent(y), b = this.parseOHLCVResponse(h);
|
|
2260
|
+
if (b.length !== o)
|
|
2261
|
+
throw new Error(`AI returned ${b.length} OHLCV objects, but expected ${o}.`);
|
|
2262
|
+
return b;
|
|
2263
|
+
} catch (p) {
|
|
2264
|
+
throw new Error(`OHLCV analysis failed: ${p.message}`);
|
|
1681
2265
|
}
|
|
1682
2266
|
}
|
|
1683
2267
|
/**
|
|
@@ -1686,31 +2270,31 @@ class L {
|
|
|
1686
2270
|
* @param options - Image generation options
|
|
1687
2271
|
* @returns Generated image URLs
|
|
1688
2272
|
*/
|
|
1689
|
-
async generateImage(e,
|
|
1690
|
-
const s =
|
|
1691
|
-
if (s !==
|
|
2273
|
+
async generateImage(e, t) {
|
|
2274
|
+
const s = t?.modelType || T.DALL_E_3;
|
|
2275
|
+
if (s !== T.DALL_E_2 && s !== T.DALL_E_3)
|
|
1692
2276
|
throw new Error("Image generation only supports DALL-E models");
|
|
1693
|
-
const a =
|
|
2277
|
+
const a = x.get(s);
|
|
1694
2278
|
if (!a)
|
|
1695
2279
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1696
|
-
const
|
|
2280
|
+
const r = {
|
|
1697
2281
|
model: a.name,
|
|
1698
2282
|
prompt: e,
|
|
1699
|
-
n:
|
|
1700
|
-
size:
|
|
1701
|
-
quality:
|
|
1702
|
-
style:
|
|
1703
|
-
response_format:
|
|
2283
|
+
n: t?.n || 1,
|
|
2284
|
+
size: t?.size || "1024x1024",
|
|
2285
|
+
quality: t?.quality || "standard",
|
|
2286
|
+
style: t?.style || "vivid",
|
|
2287
|
+
response_format: t?.responseFormat || "url"
|
|
1704
2288
|
};
|
|
1705
2289
|
try {
|
|
1706
|
-
const
|
|
1707
|
-
if (
|
|
1708
|
-
return
|
|
1709
|
-
(
|
|
2290
|
+
const o = await this.makeRequest(a.endpoint, r, !1);
|
|
2291
|
+
if (o.data && Array.isArray(o.data))
|
|
2292
|
+
return o.data.map(
|
|
2293
|
+
(i) => t?.responseFormat === "b64_json" ? i.b64_json : i.url
|
|
1710
2294
|
);
|
|
1711
2295
|
throw new Error("Invalid response format from image generation");
|
|
1712
|
-
} catch (
|
|
1713
|
-
throw new Error(`Image generation failed: ${
|
|
2296
|
+
} catch (o) {
|
|
2297
|
+
throw new Error(`Image generation failed: ${o.message}`);
|
|
1714
2298
|
}
|
|
1715
2299
|
}
|
|
1716
2300
|
/**
|
|
@@ -1719,22 +2303,22 @@ class L {
|
|
|
1719
2303
|
* @param options - Embedding options
|
|
1720
2304
|
* @returns Embedding vectors
|
|
1721
2305
|
*/
|
|
1722
|
-
async createEmbeddings(e,
|
|
1723
|
-
const s =
|
|
2306
|
+
async createEmbeddings(e, t) {
|
|
2307
|
+
const s = t?.modelType || T.TEXT_EMBEDDING_ADA_002, a = x.get(s);
|
|
1724
2308
|
if (!a)
|
|
1725
2309
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1726
|
-
const
|
|
2310
|
+
const r = {
|
|
1727
2311
|
model: a.name,
|
|
1728
2312
|
input: e
|
|
1729
2313
|
};
|
|
1730
|
-
|
|
2314
|
+
t?.dimensions && a.name === T.TEXT_EMBEDDING_3_SMALL && (r.dimensions = t.dimensions);
|
|
1731
2315
|
try {
|
|
1732
|
-
const
|
|
1733
|
-
if (
|
|
1734
|
-
return
|
|
2316
|
+
const o = await this.makeRequest(a.endpoint, r, !1);
|
|
2317
|
+
if (o.data && Array.isArray(o.data))
|
|
2318
|
+
return o.data.map((i) => i.embedding);
|
|
1735
2319
|
throw new Error("Invalid response format from embeddings");
|
|
1736
|
-
} catch (
|
|
1737
|
-
throw new Error(`Embedding creation failed: ${
|
|
2320
|
+
} catch (o) {
|
|
2321
|
+
throw new Error(`Embedding creation failed: ${o.message}`);
|
|
1738
2322
|
}
|
|
1739
2323
|
}
|
|
1740
2324
|
/**
|
|
@@ -1743,19 +2327,19 @@ class L {
|
|
|
1743
2327
|
* @param options - Transcription options
|
|
1744
2328
|
* @returns Transcribed text
|
|
1745
2329
|
*/
|
|
1746
|
-
async transcribeAudio(e,
|
|
1747
|
-
const s =
|
|
2330
|
+
async transcribeAudio(e, t) {
|
|
2331
|
+
const s = t?.modelType || T.WHISPER_1, a = x.get(s);
|
|
1748
2332
|
if (!a)
|
|
1749
2333
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1750
|
-
const
|
|
2334
|
+
const r = new FormData();
|
|
1751
2335
|
if (typeof e == "string")
|
|
1752
2336
|
throw new Error("File path/Base64 support requires additional implementation");
|
|
1753
|
-
|
|
2337
|
+
r.append("file", e), r.append("model", a.name), t?.language && r.append("language", t.language), t?.prompt && r.append("prompt", t.prompt), t?.responseFormat && r.append("response_format", t.responseFormat), t?.temperature !== void 0 && r.append("temperature", t.temperature.toString());
|
|
1754
2338
|
try {
|
|
1755
|
-
const
|
|
1756
|
-
return
|
|
1757
|
-
} catch (
|
|
1758
|
-
throw new Error(`Audio transcription failed: ${
|
|
2339
|
+
const o = await this.makeFormDataRequest(a.endpoint, r, !1);
|
|
2340
|
+
return o.text || o.transcription || "";
|
|
2341
|
+
} catch (o) {
|
|
2342
|
+
throw new Error(`Audio transcription failed: ${o.message}`);
|
|
1759
2343
|
}
|
|
1760
2344
|
}
|
|
1761
2345
|
/**
|
|
@@ -1764,21 +2348,21 @@ class L {
|
|
|
1764
2348
|
* @param options - TTS options
|
|
1765
2349
|
* @returns Audio data (base64 or blob)
|
|
1766
2350
|
*/
|
|
1767
|
-
async textToSpeech(e,
|
|
1768
|
-
const s =
|
|
2351
|
+
async textToSpeech(e, t) {
|
|
2352
|
+
const s = t?.modelType || T.TTS_1_HD, a = x.get(s);
|
|
1769
2353
|
if (!a)
|
|
1770
2354
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1771
|
-
const
|
|
2355
|
+
const r = {
|
|
1772
2356
|
model: a.name,
|
|
1773
2357
|
input: e,
|
|
1774
|
-
voice:
|
|
1775
|
-
response_format:
|
|
1776
|
-
speed:
|
|
2358
|
+
voice: t?.voice || "alloy",
|
|
2359
|
+
response_format: t?.responseFormat || "mp3",
|
|
2360
|
+
speed: t?.speed || 1
|
|
1777
2361
|
};
|
|
1778
2362
|
try {
|
|
1779
|
-
return await this.makeRequest(a.endpoint,
|
|
1780
|
-
} catch (
|
|
1781
|
-
throw new Error(`Text-to-speech conversion failed: ${
|
|
2363
|
+
return await this.makeRequest(a.endpoint, r, !1, !0);
|
|
2364
|
+
} catch (o) {
|
|
2365
|
+
throw new Error(`Text-to-speech conversion failed: ${o.message}`);
|
|
1782
2366
|
}
|
|
1783
2367
|
}
|
|
1784
2368
|
/**
|
|
@@ -1787,18 +2371,18 @@ class L {
|
|
|
1787
2371
|
* @param options - Moderation options
|
|
1788
2372
|
* @returns Moderation results
|
|
1789
2373
|
*/
|
|
1790
|
-
async moderateContent(e,
|
|
1791
|
-
const s =
|
|
2374
|
+
async moderateContent(e, t) {
|
|
2375
|
+
const s = t?.modelType || T.MODERATION_LATEST, a = x.get(s);
|
|
1792
2376
|
if (!a)
|
|
1793
2377
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1794
|
-
const
|
|
2378
|
+
const r = {
|
|
1795
2379
|
model: a.name,
|
|
1796
2380
|
input: e
|
|
1797
2381
|
};
|
|
1798
2382
|
try {
|
|
1799
|
-
return (await this.makeRequest(a.endpoint,
|
|
1800
|
-
} catch (
|
|
1801
|
-
throw new Error(`Content moderation failed: ${
|
|
2383
|
+
return (await this.makeRequest(a.endpoint, r, !1)).results || [];
|
|
2384
|
+
} catch (o) {
|
|
2385
|
+
throw new Error(`Content moderation failed: ${o.message}`);
|
|
1802
2386
|
}
|
|
1803
2387
|
}
|
|
1804
2388
|
/**
|
|
@@ -1806,7 +2390,7 @@ class L {
|
|
|
1806
2390
|
* @param modelType - New model type
|
|
1807
2391
|
*/
|
|
1808
2392
|
setModel(e) {
|
|
1809
|
-
if (!
|
|
2393
|
+
if (!x.get(e))
|
|
1810
2394
|
throw new Error(`Unsupported model type: ${e}`);
|
|
1811
2395
|
this.modelType = e;
|
|
1812
2396
|
}
|
|
@@ -1814,7 +2398,7 @@ class L {
|
|
|
1814
2398
|
* Get current model configuration
|
|
1815
2399
|
*/
|
|
1816
2400
|
getCurrentModel() {
|
|
1817
|
-
const e =
|
|
2401
|
+
const e = x.get(this.modelType);
|
|
1818
2402
|
if (!e)
|
|
1819
2403
|
throw new Error(`Model configuration does not exist: ${this.modelType}`);
|
|
1820
2404
|
return {
|
|
@@ -1824,12 +2408,12 @@ class L {
|
|
|
1824
2408
|
};
|
|
1825
2409
|
}
|
|
1826
2410
|
/**
|
|
1827
|
-
* Test connection
|
|
2411
|
+
* Test connection with i18n support
|
|
1828
2412
|
* @returns Connection test result
|
|
1829
2413
|
*/
|
|
1830
2414
|
async testConnection() {
|
|
1831
2415
|
try {
|
|
1832
|
-
const e = await this.chat('Hello, respond with "OK" if you can hear me.');
|
|
2416
|
+
const e = await this.chat('Hello, respond with "OK" if you can hear me.', "en");
|
|
1833
2417
|
return {
|
|
1834
2418
|
success: !0,
|
|
1835
2419
|
model: this.modelType,
|
|
@@ -1850,115 +2434,115 @@ class L {
|
|
|
1850
2434
|
* @param modelType - Model type (optional, uses current if not provided)
|
|
1851
2435
|
* @returns Cost estimate
|
|
1852
2436
|
*/
|
|
1853
|
-
estimateCost(e,
|
|
1854
|
-
const a = s || this.modelType,
|
|
1855
|
-
if (!
|
|
2437
|
+
estimateCost(e, t = 0, s) {
|
|
2438
|
+
const a = s || this.modelType, r = x.get(a);
|
|
2439
|
+
if (!r)
|
|
1856
2440
|
throw new Error(`Unsupported model type: ${a}`);
|
|
1857
|
-
const
|
|
2441
|
+
const o = (r.inputCostPer1KTokens || 0) / 1e3 * e, i = (r.outputCostPer1KTokens || 0) / 1e3 * t;
|
|
1858
2442
|
return {
|
|
1859
|
-
inputCost:
|
|
1860
|
-
outputCost:
|
|
1861
|
-
totalCost:
|
|
2443
|
+
inputCost: o,
|
|
2444
|
+
outputCost: i,
|
|
2445
|
+
totalCost: o + i
|
|
1862
2446
|
};
|
|
1863
2447
|
}
|
|
1864
|
-
buildOpenAIRequest(e,
|
|
1865
|
-
const
|
|
2448
|
+
buildOpenAIRequest(e, t, s, a, r, o) {
|
|
2449
|
+
const i = {
|
|
1866
2450
|
model: e,
|
|
1867
|
-
messages:
|
|
2451
|
+
messages: t,
|
|
1868
2452
|
temperature: s,
|
|
1869
2453
|
max_tokens: a,
|
|
1870
|
-
stream:
|
|
2454
|
+
stream: r
|
|
1871
2455
|
};
|
|
1872
|
-
return
|
|
2456
|
+
return o?.topP !== void 0 && (i.top_p = o.topP), o?.frequencyPenalty !== void 0 && (i.frequency_penalty = o.frequencyPenalty), o?.presencePenalty !== void 0 && (i.presence_penalty = o.presencePenalty), o?.stop !== void 0 && (i.stop = o.stop), i;
|
|
1873
2457
|
}
|
|
1874
|
-
async makeRequest(e,
|
|
1875
|
-
const
|
|
2458
|
+
async makeRequest(e, t, s, a = !1) {
|
|
2459
|
+
const r = new AbortController(), o = setTimeout(() => r.abort(), this.timeout);
|
|
1876
2460
|
try {
|
|
1877
|
-
const
|
|
2461
|
+
const i = e.startsWith("http") ? e : `${this.baseURL}${e}`, d = {
|
|
1878
2462
|
Authorization: `Bearer ${this.apiKey}`,
|
|
1879
2463
|
"Content-Type": "application/json"
|
|
1880
2464
|
};
|
|
1881
|
-
this.organization && (
|
|
1882
|
-
const
|
|
2465
|
+
this.organization && (d["OpenAI-Organization"] = this.organization);
|
|
2466
|
+
const l = await fetch(i, {
|
|
1883
2467
|
method: "POST",
|
|
1884
|
-
headers:
|
|
1885
|
-
body: JSON.stringify(
|
|
1886
|
-
signal:
|
|
2468
|
+
headers: d,
|
|
2469
|
+
body: JSON.stringify(t),
|
|
2470
|
+
signal: r.signal
|
|
1887
2471
|
});
|
|
1888
|
-
if (clearTimeout(
|
|
1889
|
-
const
|
|
2472
|
+
if (clearTimeout(o), !l.ok) {
|
|
2473
|
+
const u = await l.text();
|
|
1890
2474
|
try {
|
|
1891
|
-
const
|
|
1892
|
-
throw new Error(`HTTP ${
|
|
2475
|
+
const m = JSON.parse(u);
|
|
2476
|
+
throw new Error(`HTTP ${l.status}: ${m.error?.message || u}`);
|
|
1893
2477
|
} catch {
|
|
1894
|
-
throw new Error(`HTTP ${
|
|
2478
|
+
throw new Error(`HTTP ${l.status}: ${u}`);
|
|
1895
2479
|
}
|
|
1896
2480
|
}
|
|
1897
|
-
return a ? await
|
|
1898
|
-
} catch (
|
|
1899
|
-
throw clearTimeout(
|
|
2481
|
+
return a ? await l.arrayBuffer() : s ? l.body : await l.json();
|
|
2482
|
+
} catch (i) {
|
|
2483
|
+
throw clearTimeout(o), i.name === "AbortError" ? new Error(`Request timeout (${this.timeout}ms)`) : i;
|
|
1900
2484
|
}
|
|
1901
2485
|
}
|
|
1902
|
-
async makeFormDataRequest(e,
|
|
1903
|
-
const a = new AbortController(),
|
|
2486
|
+
async makeFormDataRequest(e, t, s) {
|
|
2487
|
+
const a = new AbortController(), r = setTimeout(() => a.abort(), this.timeout);
|
|
1904
2488
|
try {
|
|
1905
|
-
const
|
|
2489
|
+
const o = e.startsWith("http") ? e : `${this.baseURL}${e}`, i = {
|
|
1906
2490
|
Authorization: `Bearer ${this.apiKey}`
|
|
1907
2491
|
};
|
|
1908
|
-
this.organization && (
|
|
1909
|
-
const
|
|
2492
|
+
this.organization && (i["OpenAI-Organization"] = this.organization);
|
|
2493
|
+
const d = await fetch(o, {
|
|
1910
2494
|
method: "POST",
|
|
1911
|
-
headers:
|
|
1912
|
-
body:
|
|
2495
|
+
headers: i,
|
|
2496
|
+
body: t,
|
|
1913
2497
|
signal: a.signal
|
|
1914
2498
|
});
|
|
1915
|
-
if (clearTimeout(
|
|
1916
|
-
const
|
|
2499
|
+
if (clearTimeout(r), !d.ok) {
|
|
2500
|
+
const l = await d.text();
|
|
1917
2501
|
try {
|
|
1918
|
-
const
|
|
1919
|
-
throw new Error(`HTTP ${
|
|
2502
|
+
const u = JSON.parse(l);
|
|
2503
|
+
throw new Error(`HTTP ${d.status}: ${u.error?.message || l}`);
|
|
1920
2504
|
} catch {
|
|
1921
|
-
throw new Error(`HTTP ${
|
|
2505
|
+
throw new Error(`HTTP ${d.status}: ${l}`);
|
|
1922
2506
|
}
|
|
1923
2507
|
}
|
|
1924
|
-
return s ?
|
|
1925
|
-
} catch (
|
|
1926
|
-
throw clearTimeout(
|
|
2508
|
+
return s ? d.body : await d.json();
|
|
2509
|
+
} catch (o) {
|
|
2510
|
+
throw clearTimeout(r), o.name === "AbortError" ? new Error(`Request timeout (${this.timeout}ms)`) : o;
|
|
1927
2511
|
}
|
|
1928
2512
|
}
|
|
1929
|
-
async makeStreamRequest(e,
|
|
1930
|
-
const a = await this.makeRequest(e,
|
|
2513
|
+
async makeStreamRequest(e, t, s) {
|
|
2514
|
+
const a = await this.makeRequest(e, t, !0);
|
|
1931
2515
|
if (!a)
|
|
1932
2516
|
throw new Error("Failed to get streaming response");
|
|
1933
|
-
const
|
|
1934
|
-
let
|
|
2517
|
+
const r = a.getReader(), o = new TextDecoder("utf-8");
|
|
2518
|
+
let i = "";
|
|
1935
2519
|
try {
|
|
1936
2520
|
for (; ; ) {
|
|
1937
|
-
const { done:
|
|
1938
|
-
if (
|
|
2521
|
+
const { done: d, value: l } = await r.read();
|
|
2522
|
+
if (d) {
|
|
1939
2523
|
s("", !0);
|
|
1940
2524
|
break;
|
|
1941
2525
|
}
|
|
1942
|
-
|
|
1943
|
-
const
|
|
2526
|
+
i += o.decode(l, { stream: !0 });
|
|
2527
|
+
const u = i.split(`
|
|
1944
2528
|
`);
|
|
1945
|
-
|
|
1946
|
-
for (const
|
|
1947
|
-
if (
|
|
1948
|
-
const
|
|
1949
|
-
if (
|
|
2529
|
+
i = u.pop() || "";
|
|
2530
|
+
for (const m of u)
|
|
2531
|
+
if (m.startsWith("data: ")) {
|
|
2532
|
+
const c = m.slice(6);
|
|
2533
|
+
if (c === "[DONE]") {
|
|
1950
2534
|
s("", !0);
|
|
1951
2535
|
return;
|
|
1952
2536
|
}
|
|
1953
2537
|
try {
|
|
1954
|
-
const
|
|
1955
|
-
|
|
2538
|
+
const p = JSON.parse(c);
|
|
2539
|
+
p.choices?.[0]?.delta?.content && s(p.choices[0].delta.content, !1);
|
|
1956
2540
|
} catch {
|
|
1957
2541
|
}
|
|
1958
2542
|
}
|
|
1959
2543
|
}
|
|
1960
2544
|
} finally {
|
|
1961
|
-
|
|
2545
|
+
r.releaseLock();
|
|
1962
2546
|
}
|
|
1963
2547
|
}
|
|
1964
2548
|
extractContent(e) {
|
|
@@ -1972,140 +2556,83 @@ class L {
|
|
|
1972
2556
|
return e.text;
|
|
1973
2557
|
throw new Error("Unable to parse response content");
|
|
1974
2558
|
}
|
|
1975
|
-
/**
|
|
1976
|
-
* Specialized method for processing OHLCV arrays
|
|
1977
|
-
* @param ohlcvArray - OHLCV data array
|
|
1978
|
-
* @param instructions - Processing instructions (optional, default: "Based on these OHLCV data, predict the next period")
|
|
1979
|
-
* @param count - Number of OHLCV data items to return (optional, default: 1)
|
|
1980
|
-
* @param options - Chat options
|
|
1981
|
-
* @returns Predicted OHLCV array
|
|
1982
|
-
*/
|
|
1983
|
-
async analyzeOHLCV(e, o, s, a) {
|
|
1984
|
-
const i = o || "Based on these OHLCV data, predict the next period", n = s || 1;
|
|
1985
|
-
if (!Number.isInteger(n) || n <= 0)
|
|
1986
|
-
throw new Error(`Invalid count parameter: ${n}. Must be a positive integer.`);
|
|
1987
|
-
const r = 50;
|
|
1988
|
-
if (n > r)
|
|
1989
|
-
throw new Error(`Count parameter too large: ${n}. Maximum allowed is ${r}. Please reduce the count or split your request.`);
|
|
1990
|
-
const m = n === 1 ? "Return EXACTLY 1 OHLCV object for the next period." : `Return EXACTLY ${n} consecutive OHLCV objects for the next ${n} periods.`, c = `You are a professional financial data analysis AI. The user will give you an array of OHLCV (Open, High, Low, Close, Volume) data.
|
|
1991
|
-
Your task: ${i}
|
|
1992
|
-
CRITICAL RULES:
|
|
1993
|
-
1. ${m}
|
|
1994
|
-
2. Return ONLY a JSON array of OHLCV objects, NO explanations, comments, or other text
|
|
1995
|
-
3. The OHLCV array format must match: [{open, high, low, close, volume}, ...]
|
|
1996
|
-
4. All numbers must be valid numbers
|
|
1997
|
-
5. Ensure technical rationality (high >= low, high >= close >= low, volume >= 0)
|
|
1998
|
-
6. Maintain consistency with historical trends and patterns
|
|
1999
|
-
7. For technical analysis, provide reasonable values based on typical patterns
|
|
2000
|
-
8. Do not include markdown formatting, only pure JSON
|
|
2001
|
-
${n === 1 ? `Example of valid response for 1 period:
|
|
2002
|
-
[{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000}]` : `Example of valid response for ${n} periods:
|
|
2003
|
-
[
|
|
2004
|
-
{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000},
|
|
2005
|
-
{"open": 117.5, "high": 120.0, "low": 116.0, "close": 119.0, "volume": 1400000}
|
|
2006
|
-
${n > 2 ? `,
|
|
2007
|
-
... ${n - 2} more OHLCV objects following the same pattern` : ""}
|
|
2008
|
-
]`}`, p = JSON.stringify(e, null, 2), d = `Here is the historical OHLCV data (${e.length} periods):
|
|
2009
|
-
${p}
|
|
2010
|
-
Please process this data according to the system instructions. Remember to return EXACTLY ${n} OHLCV object(s) in a JSON array with no additional text.`, l = [
|
|
2011
|
-
{ role: "system", content: c },
|
|
2012
|
-
{ role: "user", content: d }
|
|
2013
|
-
];
|
|
2014
|
-
try {
|
|
2015
|
-
const u = n * 50 + 100, x = Math.max(a?.maxTokens || 1e3, u), v = await this.chatCompletion(l, {
|
|
2016
|
-
temperature: a?.temperature || 0.3,
|
|
2017
|
-
maxTokens: x,
|
|
2018
|
-
stream: !1,
|
|
2019
|
-
modelType: a?.modelType,
|
|
2020
|
-
topP: a?.topP,
|
|
2021
|
-
frequencyPenalty: a?.frequencyPenalty,
|
|
2022
|
-
presencePenalty: a?.presencePenalty,
|
|
2023
|
-
stop: a?.stop
|
|
2024
|
-
}), E = this.extractContent(v), g = this.parseOHLCVResponse(E);
|
|
2025
|
-
if (g.length !== n)
|
|
2026
|
-
throw new Error(`AI returned ${g.length} OHLCV objects, but expected ${n}.`);
|
|
2027
|
-
return g;
|
|
2028
|
-
} catch (u) {
|
|
2029
|
-
throw new Error(`OHLCV analysis failed: ${u.message}`);
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
2559
|
/**
|
|
2033
2560
|
* Parse AI returned OHLCV response
|
|
2034
2561
|
* @private
|
|
2035
2562
|
*/
|
|
2036
2563
|
parseOHLCVResponse(e) {
|
|
2037
2564
|
try {
|
|
2038
|
-
const
|
|
2039
|
-
if (!Array.isArray(
|
|
2565
|
+
const t = JSON.parse(e);
|
|
2566
|
+
if (!Array.isArray(t))
|
|
2040
2567
|
throw new Error("Response is not in array format");
|
|
2041
|
-
return
|
|
2568
|
+
return t.map((a, r) => {
|
|
2042
2569
|
if (typeof a != "object" || a === null)
|
|
2043
|
-
throw new Error(`Element ${
|
|
2044
|
-
const { open:
|
|
2045
|
-
for (const
|
|
2046
|
-
if (typeof a[
|
|
2047
|
-
throw new Error(`Element ${
|
|
2048
|
-
if (
|
|
2049
|
-
throw new Error(`Element ${
|
|
2050
|
-
if (
|
|
2051
|
-
throw new Error(`Element ${
|
|
2570
|
+
throw new Error(`Element ${r} is not a valid object`);
|
|
2571
|
+
const { open: o, high: i, low: d, close: l, volume: u } = a, m = ["open", "high", "low", "close", "volume"];
|
|
2572
|
+
for (const c of m)
|
|
2573
|
+
if (typeof a[c] != "number" || isNaN(a[c]))
|
|
2574
|
+
throw new Error(`Element ${r} field ${c} is not a valid number`);
|
|
2575
|
+
if (i < d)
|
|
2576
|
+
throw new Error(`Element ${r}: high cannot be lower than low`);
|
|
2577
|
+
if (l < d || l > i)
|
|
2578
|
+
throw new Error(`Element ${r}: close must be between low and high`);
|
|
2052
2579
|
return {
|
|
2053
|
-
open: Number(
|
|
2054
|
-
high: Number(
|
|
2055
|
-
low: Number(
|
|
2056
|
-
close: Number(
|
|
2057
|
-
volume: Number(
|
|
2580
|
+
open: Number(o),
|
|
2581
|
+
high: Number(i),
|
|
2582
|
+
low: Number(d),
|
|
2583
|
+
close: Number(l),
|
|
2584
|
+
volume: Number(u)
|
|
2058
2585
|
};
|
|
2059
2586
|
});
|
|
2060
|
-
} catch (
|
|
2587
|
+
} catch (t) {
|
|
2061
2588
|
const s = e.match(/\[[\s\S]*\]/);
|
|
2062
2589
|
if (s)
|
|
2063
2590
|
return this.parseOHLCVResponse(s[0]);
|
|
2064
|
-
throw new Error(`Unable to parse AI returned OHLCV data: ${
|
|
2591
|
+
throw new Error(`Unable to parse AI returned OHLCV data: ${t}
|
|
2065
2592
|
Original content: ${e.substring(0, 200)}...`);
|
|
2066
2593
|
}
|
|
2067
2594
|
}
|
|
2068
2595
|
}
|
|
2069
|
-
function
|
|
2070
|
-
return new
|
|
2596
|
+
function ce(n, e) {
|
|
2597
|
+
return new S({ apiKey: n, modelType: e });
|
|
2071
2598
|
}
|
|
2072
2599
|
export {
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2600
|
+
k as ALIYUN_MODELS,
|
|
2601
|
+
O as AliYunModelType,
|
|
2602
|
+
q as AliyunAI,
|
|
2603
|
+
$ as DEEPSEEK_MODELS,
|
|
2604
|
+
H as DeepSeekAI,
|
|
2605
|
+
N as DeepSeekModelType,
|
|
2606
|
+
x as OPENAI_MODELS,
|
|
2607
|
+
S as OpenAI,
|
|
2608
|
+
T as OpenAIModelType,
|
|
2609
|
+
B as createAliyunAI,
|
|
2610
|
+
M as createDeepSeekAI,
|
|
2611
|
+
ce as createOpenAI,
|
|
2612
|
+
se as estimateCost,
|
|
2613
|
+
F as getAllDeepSeekModels,
|
|
2614
|
+
R as getAllModels,
|
|
2615
|
+
L as getAllOpenAIModels,
|
|
2616
|
+
ee as getAudioModelsOpenAI,
|
|
2617
|
+
I as getAvailableAliYunModelTypes,
|
|
2618
|
+
Q as getAvailableDeepSeekModelTypes,
|
|
2619
|
+
G as getAvailableOpenAIModelTypes,
|
|
2620
|
+
J as getChatModels,
|
|
2621
|
+
X as getCompletionModels,
|
|
2622
|
+
oe as getCostEfficientModels,
|
|
2623
|
+
K as getDeepSeekModel,
|
|
2624
|
+
U as getDeepSeekModelByName,
|
|
2625
|
+
Z as getEmbeddingModels,
|
|
2626
|
+
ae as getHighContextModels,
|
|
2627
|
+
ne as getLatestModels,
|
|
2628
|
+
V as getModel,
|
|
2629
|
+
A as getModelByName,
|
|
2630
|
+
te as getMultimodalModelsOpenAI,
|
|
2631
|
+
j as getOpenAIModel,
|
|
2632
|
+
W as getOpenAIModelByName,
|
|
2633
|
+
Y as getVisionModelsOpenAI,
|
|
2634
|
+
D as stringToAliYunModelType,
|
|
2635
|
+
z as stringToDeepSeekModelType,
|
|
2636
|
+
re as stringToOpenAIModelType,
|
|
2637
|
+
ie as suggestModel
|
|
2111
2638
|
};
|