ohlcv-ai 1.0.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -202
- package/dist/index.d.ts +166 -40
- package/dist/index.js +205 -32
- package/dist/index.mjs +1188 -637
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var
|
|
2
|
-
const
|
|
1
|
+
var N = /* @__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))(N || {});
|
|
2
|
+
const k = /* @__PURE__ */ new Map([
|
|
3
3
|
[
|
|
4
4
|
"qwen-turbo",
|
|
5
5
|
{
|
|
@@ -358,21 +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
|
-
|
|
375
|
+
function D(n) {
|
|
376
|
+
const e = Object.values(N);
|
|
377
|
+
for (const t of e)
|
|
378
|
+
if (t === n)
|
|
379
|
+
return t;
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
class q {
|
|
376
383
|
/**
|
|
377
384
|
* Constructor - Minimal configuration
|
|
378
385
|
* @param config.apiKey - API key (required)
|
|
@@ -380,67 +387,326 @@ class _ {
|
|
|
380
387
|
* @param config.timeout - Timeout, default 30 seconds
|
|
381
388
|
*/
|
|
382
389
|
constructor(e) {
|
|
383
|
-
if (this.apiKey = e.apiKey, this.modelType = e.modelType ||
|
|
390
|
+
if (this.apiKey = e.apiKey, this.modelType = e.modelType || N.QWEN_TURBO, this.timeout = e.timeout || 3e4, !this.apiKey)
|
|
384
391
|
throw new Error("API Key cannot be empty");
|
|
385
|
-
if (!
|
|
392
|
+
if (!k.get(this.modelType))
|
|
386
393
|
throw new Error(`Unsupported model type: ${this.modelType}`);
|
|
387
394
|
}
|
|
388
395
|
/**
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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: s?.modelType
|
|
401
415
|
});
|
|
402
|
-
return this.extractContent(
|
|
416
|
+
return this.extractContent(o);
|
|
403
417
|
}
|
|
404
418
|
/**
|
|
405
419
|
* Multi-turn conversation
|
|
406
420
|
* @param messages - Message history
|
|
421
|
+
* @param i18n - Language restriction for AI response
|
|
407
422
|
* @param options - Chat options
|
|
408
423
|
* @returns Complete API response
|
|
409
424
|
*/
|
|
410
|
-
async chatCompletion(e,
|
|
411
|
-
const
|
|
412
|
-
if (!
|
|
413
|
-
throw new Error(`Unsupported model type: ${
|
|
414
|
-
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);
|
|
415
436
|
try {
|
|
416
|
-
return await this.makeRequest(
|
|
417
|
-
} catch (
|
|
418
|
-
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}`);
|
|
419
440
|
}
|
|
420
441
|
}
|
|
421
442
|
/**
|
|
422
443
|
* Streaming conversation (only supports OpenAI format)
|
|
423
444
|
* @param messages - Message history
|
|
424
445
|
* @param callback - Streaming callback function
|
|
446
|
+
* @param i18n - Language restriction for AI response
|
|
425
447
|
* @param options - Chat options
|
|
426
448
|
*/
|
|
427
|
-
async chatStream(e,
|
|
428
|
-
const
|
|
429
|
-
if (!
|
|
430
|
-
throw new Error(`Unsupported model type: ${
|
|
431
|
-
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")
|
|
432
454
|
throw new Error("Streaming conversation only supports OpenAI format models");
|
|
433
|
-
const
|
|
434
|
-
|
|
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,
|
|
435
463
|
e,
|
|
436
|
-
|
|
437
|
-
|
|
464
|
+
i,
|
|
465
|
+
d,
|
|
438
466
|
!0
|
|
439
467
|
);
|
|
440
468
|
try {
|
|
441
|
-
await this.makeStreamRequest(
|
|
442
|
-
} catch (
|
|
443
|
-
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: r?.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: o?.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: r?.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)}...`);
|
|
444
710
|
}
|
|
445
711
|
}
|
|
446
712
|
/**
|
|
@@ -448,7 +714,7 @@ class _ {
|
|
|
448
714
|
* @param modelType - New model type
|
|
449
715
|
*/
|
|
450
716
|
setModel(e) {
|
|
451
|
-
if (!
|
|
717
|
+
if (!k.get(e))
|
|
452
718
|
throw new Error(`Unsupported model type: ${e}`);
|
|
453
719
|
this.modelType = e;
|
|
454
720
|
}
|
|
@@ -456,7 +722,7 @@ class _ {
|
|
|
456
722
|
* Get current model configuration
|
|
457
723
|
*/
|
|
458
724
|
getCurrentModel() {
|
|
459
|
-
const e =
|
|
725
|
+
const e = k.get(this.modelType);
|
|
460
726
|
if (!e)
|
|
461
727
|
throw new Error(`Model configuration does not exist: ${this.modelType}`);
|
|
462
728
|
return {
|
|
@@ -471,7 +737,7 @@ class _ {
|
|
|
471
737
|
*/
|
|
472
738
|
async testConnection() {
|
|
473
739
|
try {
|
|
474
|
-
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");
|
|
475
741
|
return {
|
|
476
742
|
success: !0,
|
|
477
743
|
model: this.modelType,
|
|
@@ -485,19 +751,19 @@ class _ {
|
|
|
485
751
|
};
|
|
486
752
|
}
|
|
487
753
|
}
|
|
488
|
-
buildOpenAIRequest(e,
|
|
754
|
+
buildOpenAIRequest(e, t, s, a, r) {
|
|
489
755
|
return {
|
|
490
756
|
model: e,
|
|
491
|
-
messages:
|
|
757
|
+
messages: t,
|
|
492
758
|
temperature: s,
|
|
493
759
|
max_tokens: a,
|
|
494
|
-
stream:
|
|
760
|
+
stream: r
|
|
495
761
|
};
|
|
496
762
|
}
|
|
497
|
-
buildDashScopeRequest(e,
|
|
763
|
+
buildDashScopeRequest(e, t, s, a) {
|
|
498
764
|
return {
|
|
499
765
|
model: e,
|
|
500
|
-
input: { messages:
|
|
766
|
+
input: { messages: t },
|
|
501
767
|
parameters: {
|
|
502
768
|
temperature: s,
|
|
503
769
|
max_tokens: a,
|
|
@@ -505,61 +771,61 @@ class _ {
|
|
|
505
771
|
}
|
|
506
772
|
};
|
|
507
773
|
}
|
|
508
|
-
async makeRequest(e,
|
|
509
|
-
const a = new AbortController(),
|
|
774
|
+
async makeRequest(e, t, s) {
|
|
775
|
+
const a = new AbortController(), r = setTimeout(() => a.abort(), this.timeout);
|
|
510
776
|
try {
|
|
511
|
-
const
|
|
777
|
+
const o = await fetch(e, {
|
|
512
778
|
method: "POST",
|
|
513
779
|
headers: {
|
|
514
780
|
Authorization: `Bearer ${this.apiKey}`,
|
|
515
781
|
"Content-Type": "application/json; charset=utf-8",
|
|
516
782
|
Accept: "application/json"
|
|
517
783
|
},
|
|
518
|
-
body: JSON.stringify(
|
|
784
|
+
body: JSON.stringify(t),
|
|
519
785
|
signal: a.signal
|
|
520
786
|
});
|
|
521
|
-
if (clearTimeout(
|
|
522
|
-
const
|
|
523
|
-
throw new Error(`HTTP ${
|
|
787
|
+
if (clearTimeout(r), !o.ok) {
|
|
788
|
+
const i = await o.text();
|
|
789
|
+
throw new Error(`HTTP ${o.status}: ${i}`);
|
|
524
790
|
}
|
|
525
|
-
return s ?
|
|
526
|
-
} catch (
|
|
527
|
-
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;
|
|
528
794
|
}
|
|
529
795
|
}
|
|
530
|
-
async makeStreamRequest(e,
|
|
531
|
-
const a = await this.makeRequest(e,
|
|
796
|
+
async makeStreamRequest(e, t, s) {
|
|
797
|
+
const a = await this.makeRequest(e, t, !0);
|
|
532
798
|
if (!a)
|
|
533
799
|
throw new Error("Failed to get streaming response");
|
|
534
|
-
const
|
|
535
|
-
let
|
|
800
|
+
const r = a.getReader(), o = new TextDecoder("utf-8");
|
|
801
|
+
let i = "";
|
|
536
802
|
try {
|
|
537
803
|
for (; ; ) {
|
|
538
|
-
const { done:
|
|
539
|
-
if (
|
|
804
|
+
const { done: d, value: l } = await r.read();
|
|
805
|
+
if (d) {
|
|
540
806
|
s("", !0);
|
|
541
807
|
break;
|
|
542
808
|
}
|
|
543
|
-
|
|
544
|
-
const
|
|
809
|
+
i += o.decode(l, { stream: !0 });
|
|
810
|
+
const u = i.split(`
|
|
545
811
|
`);
|
|
546
|
-
|
|
547
|
-
for (const
|
|
548
|
-
if (
|
|
549
|
-
const
|
|
550
|
-
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]") {
|
|
551
817
|
s("", !0);
|
|
552
818
|
return;
|
|
553
819
|
}
|
|
554
820
|
try {
|
|
555
|
-
const
|
|
556
|
-
|
|
821
|
+
const p = JSON.parse(c);
|
|
822
|
+
p.choices?.[0]?.delta?.content && s(p.choices[0].delta.content, !1);
|
|
557
823
|
} catch {
|
|
558
824
|
}
|
|
559
825
|
}
|
|
560
826
|
}
|
|
561
827
|
} finally {
|
|
562
|
-
|
|
828
|
+
r.releaseLock();
|
|
563
829
|
}
|
|
564
830
|
}
|
|
565
831
|
extractContent(e) {
|
|
@@ -571,101 +837,12 @@ class _ {
|
|
|
571
837
|
return e.output.text;
|
|
572
838
|
throw new Error("Unable to parse response content");
|
|
573
839
|
}
|
|
574
|
-
/**
|
|
575
|
-
* Specialized method for processing OHLCV arrays
|
|
576
|
-
* @param ohlcvArray - OHLCV data array
|
|
577
|
-
* @param instructions - Processing instructions, supports Chinese and English (optional, default: "Based on these OHLCV data, predict the next period")
|
|
578
|
-
* @param count - Number of OHLCV data items to return (optional, default: 1)
|
|
579
|
-
* @param options - Chat options
|
|
580
|
-
* @returns Predicted OHLCV array
|
|
581
|
-
*/
|
|
582
|
-
async predictingOHLCV(e, o, s, a) {
|
|
583
|
-
const i = o || "Based on these OHLCV data, predict the next period", n = s || 1;
|
|
584
|
-
if (!Number.isInteger(n) || n <= 0)
|
|
585
|
-
throw new Error(`Invalid count parameter: ${n}. Must be a positive integer.`);
|
|
586
|
-
const r = 50;
|
|
587
|
-
if (n > r)
|
|
588
|
-
throw new Error(`Count parameter too large: ${n}. Maximum allowed is ${r}. Please reduce the count or split your request.`);
|
|
589
|
-
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.
|
|
590
|
-
Your task: ${i}
|
|
591
|
-
CRITICAL RULES:
|
|
592
|
-
1. ${m}
|
|
593
|
-
2. Return ONLY a JSON array of OHLCV objects, NO explanations, comments, or other text
|
|
594
|
-
3. The OHLCV array format must match: [{open, high, low, close, volume}, ...]
|
|
595
|
-
4. All numbers must be valid numbers
|
|
596
|
-
5. Ensure technical rationality (high >= low, high >= close >= low, volume >= 0)
|
|
597
|
-
6. Maintain consistency with historical trends and patterns
|
|
598
|
-
7. For technical analysis, provide reasonable values based on typical patterns
|
|
599
|
-
8. Do not include markdown formatting, only pure JSON
|
|
600
|
-
${n === 1 ? `Example of valid response for 1 period:
|
|
601
|
-
[{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000}]` : `Example of valid response for ${n} periods:
|
|
602
|
-
[
|
|
603
|
-
{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000},
|
|
604
|
-
{"open": 117.5, "high": 120.0, "low": 116.0, "close": 119.0, "volume": 1400000}
|
|
605
|
-
${n > 2 ? `,
|
|
606
|
-
... ${n - 2} more OHLCV objects following the same pattern` : ""}
|
|
607
|
-
]`}`, p = JSON.stringify(e, null, 2), d = `Here is the historical OHLCV data (${e.length} periods):
|
|
608
|
-
${p}
|
|
609
|
-
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 = [
|
|
610
|
-
{ role: "system", content: c },
|
|
611
|
-
{ role: "user", content: d }
|
|
612
|
-
];
|
|
613
|
-
try {
|
|
614
|
-
const h = n * 50 + 100, x = Math.max(a?.maxTokens || 1e3, h), k = await this.chatCompletion(l, {
|
|
615
|
-
temperature: a?.temperature || 0.3,
|
|
616
|
-
maxTokens: x,
|
|
617
|
-
stream: !1,
|
|
618
|
-
modelType: a?.modelType
|
|
619
|
-
}), E = this.extractContent(k), g = this.parseOHLCVResponse(E);
|
|
620
|
-
if (g.length !== n)
|
|
621
|
-
throw new Error(`AI returned ${g.length} OHLCV objects, but expected ${n}.`);
|
|
622
|
-
return g;
|
|
623
|
-
} catch (h) {
|
|
624
|
-
throw new Error(`OHLCV analysis failed: ${h.message}`);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
/**
|
|
628
|
-
* Parse AI returned OHLCV response
|
|
629
|
-
* @private
|
|
630
|
-
*/
|
|
631
|
-
parseOHLCVResponse(e) {
|
|
632
|
-
try {
|
|
633
|
-
const o = JSON.parse(e);
|
|
634
|
-
if (!Array.isArray(o))
|
|
635
|
-
throw new Error("Response is not in array format");
|
|
636
|
-
return o.map((a, i) => {
|
|
637
|
-
if (typeof a != "object" || a === null)
|
|
638
|
-
throw new Error(`Element ${i} is not a valid object`);
|
|
639
|
-
const { open: n, high: r, low: m, close: c, volume: p } = a, d = ["open", "high", "low", "close", "volume"];
|
|
640
|
-
for (const l of d)
|
|
641
|
-
if (typeof a[l] != "number" || isNaN(a[l]))
|
|
642
|
-
throw new Error(`Element ${i} field ${l} is not a valid number`);
|
|
643
|
-
if (r < m)
|
|
644
|
-
throw new Error(`Element ${i}: high cannot be lower than low`);
|
|
645
|
-
if (c < m || c > r)
|
|
646
|
-
throw new Error(`Element ${i}: close must be between low and high`);
|
|
647
|
-
return {
|
|
648
|
-
open: Number(n),
|
|
649
|
-
high: Number(r),
|
|
650
|
-
low: Number(m),
|
|
651
|
-
close: Number(c),
|
|
652
|
-
volume: Number(p)
|
|
653
|
-
};
|
|
654
|
-
});
|
|
655
|
-
} catch (o) {
|
|
656
|
-
const s = e.match(/\[[\s\S]*\]/);
|
|
657
|
-
if (s)
|
|
658
|
-
return this.parseOHLCVResponse(s[0]);
|
|
659
|
-
throw new Error(`Unable to parse AI returned OHLCV data: ${o}
|
|
660
|
-
Original content: ${e.substring(0, 200)}...`);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
840
|
}
|
|
664
|
-
function
|
|
665
|
-
return new
|
|
841
|
+
function B(n, e) {
|
|
842
|
+
return new q({ apiKey: n, modelType: e });
|
|
666
843
|
}
|
|
667
|
-
var
|
|
668
|
-
const
|
|
844
|
+
var O = /* @__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))(O || {});
|
|
845
|
+
const $ = /* @__PURE__ */ new Map([
|
|
669
846
|
// Chat models
|
|
670
847
|
[
|
|
671
848
|
"deepseek-chat",
|
|
@@ -958,21 +1135,28 @@ const y = /* @__PURE__ */ new Map([
|
|
|
958
1135
|
}
|
|
959
1136
|
]
|
|
960
1137
|
]);
|
|
961
|
-
function
|
|
962
|
-
return
|
|
1138
|
+
function K(n) {
|
|
1139
|
+
return $.get(n);
|
|
963
1140
|
}
|
|
964
|
-
function
|
|
965
|
-
return Array.from(
|
|
1141
|
+
function F() {
|
|
1142
|
+
return Array.from($.values());
|
|
966
1143
|
}
|
|
967
|
-
function
|
|
968
|
-
for (const e of
|
|
969
|
-
if (e.name ===
|
|
1144
|
+
function U(n) {
|
|
1145
|
+
for (const e of $.values())
|
|
1146
|
+
if (e.name === n)
|
|
970
1147
|
return e;
|
|
971
1148
|
}
|
|
972
|
-
function
|
|
973
|
-
return Array.from(
|
|
1149
|
+
function Q() {
|
|
1150
|
+
return Array.from($.keys());
|
|
1151
|
+
}
|
|
1152
|
+
function z(n) {
|
|
1153
|
+
const e = Object.values(O);
|
|
1154
|
+
for (const t of e)
|
|
1155
|
+
if (t === n)
|
|
1156
|
+
return t;
|
|
1157
|
+
return null;
|
|
974
1158
|
}
|
|
975
|
-
class
|
|
1159
|
+
class H {
|
|
976
1160
|
/**
|
|
977
1161
|
* Constructor - Minimal configuration
|
|
978
1162
|
* @param config.apiKey - API key (required)
|
|
@@ -981,92 +1165,270 @@ class C {
|
|
|
981
1165
|
* @param config.baseURL - Base URL for API, default official endpoint
|
|
982
1166
|
*/
|
|
983
1167
|
constructor(e) {
|
|
984
|
-
if (this.apiKey = e.apiKey, this.modelType = e.modelType ||
|
|
1168
|
+
if (this.apiKey = e.apiKey, this.modelType = e.modelType || O.DEEPSEEK_CHAT, this.timeout = e.timeout || 3e4, this.baseURL = e.baseURL || "https://api.deepseek.com", !this.apiKey)
|
|
985
1169
|
throw new Error("API Key cannot be empty");
|
|
986
|
-
if (
|
|
1170
|
+
if (!$.get(this.modelType))
|
|
987
1171
|
throw new Error(`Unsupported model type: ${this.modelType}`);
|
|
988
1172
|
}
|
|
989
1173
|
/**
|
|
990
|
-
* Simplest method: single conversation
|
|
1174
|
+
* Simplest method: single conversation with i18n support
|
|
991
1175
|
* @param message - User message
|
|
1176
|
+
* @param i18n - Language restriction for AI response
|
|
992
1177
|
* @param options - Chat options
|
|
993
1178
|
* @returns AI response
|
|
994
1179
|
*/
|
|
995
|
-
async chat(e,
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
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,
|
|
1001
1191
|
stream: !1,
|
|
1002
|
-
modelType:
|
|
1003
|
-
topP:
|
|
1004
|
-
frequencyPenalty:
|
|
1005
|
-
presencePenalty:
|
|
1006
|
-
stop:
|
|
1007
|
-
tools:
|
|
1008
|
-
toolChoice:
|
|
1192
|
+
modelType: s?.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
|
|
1009
1199
|
});
|
|
1010
|
-
return this.extractContent(
|
|
1200
|
+
return this.extractContent(o);
|
|
1011
1201
|
}
|
|
1012
1202
|
/**
|
|
1013
|
-
* Multi-turn conversation
|
|
1203
|
+
* Multi-turn conversation with i18n support
|
|
1014
1204
|
* @param messages - Message history
|
|
1205
|
+
* @param i18n - Language restriction for AI response
|
|
1015
1206
|
* @param options - Chat options
|
|
1016
1207
|
* @returns Complete API response
|
|
1017
1208
|
*/
|
|
1018
|
-
async chatCompletion(e,
|
|
1019
|
-
const
|
|
1020
|
-
if (!
|
|
1021
|
-
throw new Error(`Unsupported model type: ${
|
|
1022
|
-
const
|
|
1023
|
-
|
|
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,
|
|
1024
1221
|
e,
|
|
1222
|
+
o,
|
|
1025
1223
|
i,
|
|
1026
|
-
|
|
1027
|
-
|
|
1224
|
+
d,
|
|
1225
|
+
l,
|
|
1226
|
+
u,
|
|
1028
1227
|
m,
|
|
1029
1228
|
c,
|
|
1030
1229
|
p,
|
|
1031
|
-
|
|
1032
|
-
l,
|
|
1033
|
-
h
|
|
1230
|
+
g
|
|
1034
1231
|
);
|
|
1035
1232
|
try {
|
|
1036
|
-
return await this.makeRequest(
|
|
1037
|
-
} catch (
|
|
1038
|
-
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}`);
|
|
1039
1236
|
}
|
|
1040
1237
|
}
|
|
1041
1238
|
/**
|
|
1042
|
-
* Streaming conversation
|
|
1239
|
+
* Streaming conversation with i18n support
|
|
1043
1240
|
* @param messages - Message history
|
|
1044
1241
|
* @param callback - Streaming callback function
|
|
1242
|
+
* @param i18n - Language restriction for AI response
|
|
1045
1243
|
* @param options - Chat options
|
|
1046
1244
|
*/
|
|
1047
|
-
async chatStream(e,
|
|
1048
|
-
const
|
|
1049
|
-
if (!
|
|
1050
|
-
throw new Error(`Unsupported model type: ${
|
|
1051
|
-
const
|
|
1052
|
-
|
|
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,
|
|
1053
1257
|
e,
|
|
1054
|
-
|
|
1055
|
-
|
|
1258
|
+
i,
|
|
1259
|
+
d,
|
|
1056
1260
|
!0,
|
|
1261
|
+
l,
|
|
1262
|
+
u,
|
|
1057
1263
|
m,
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
s?.tools,
|
|
1062
|
-
s?.toolChoice
|
|
1264
|
+
a?.stop,
|
|
1265
|
+
a?.tools,
|
|
1266
|
+
a?.toolChoice
|
|
1063
1267
|
);
|
|
1064
1268
|
try {
|
|
1065
|
-
await this.makeStreamRequest(
|
|
1066
|
-
} catch (
|
|
1067
|
-
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}`);
|
|
1272
|
+
}
|
|
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: r?.modelType || O.DEEPSEEK_FINANCE,
|
|
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}`);
|
|
1068
1377
|
}
|
|
1069
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: o?.modelType || O.DEEPSEEK_FINANCE
|
|
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
|
+
}
|
|
1070
1432
|
/**
|
|
1071
1433
|
* Specialized method for processing OHLCV arrays
|
|
1072
1434
|
* @param ohlcvArray - OHLCV data array
|
|
@@ -1075,17 +1437,17 @@ class C {
|
|
|
1075
1437
|
* @param options - Chat options
|
|
1076
1438
|
* @returns Predicted OHLCV array
|
|
1077
1439
|
*/
|
|
1078
|
-
async predictingOHLCV(e,
|
|
1079
|
-
const
|
|
1080
|
-
if (!Number.isInteger(
|
|
1081
|
-
throw new Error(`Invalid count parameter: ${
|
|
1082
|
-
const
|
|
1083
|
-
if (
|
|
1084
|
-
throw new Error(`Count parameter too large: ${
|
|
1085
|
-
const
|
|
1086
|
-
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}
|
|
1087
1449
|
CRITICAL RULES:
|
|
1088
|
-
1. ${
|
|
1450
|
+
1. ${d}
|
|
1089
1451
|
2. Return ONLY a JSON array of OHLCV objects, NO explanations, comments, or other text
|
|
1090
1452
|
3. The OHLCV array format must match: [{open, high, low, close, volume}, ...]
|
|
1091
1453
|
4. All numbers must be valid numbers
|
|
@@ -1094,34 +1456,34 @@ CRITICAL RULES:
|
|
|
1094
1456
|
7. For technical analysis, provide reasonable values based on typical patterns
|
|
1095
1457
|
8. Do not include markdown formatting, only pure JSON
|
|
1096
1458
|
|
|
1097
|
-
${
|
|
1098
|
-
[{"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:
|
|
1099
1461
|
[
|
|
1100
1462
|
{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000},
|
|
1101
1463
|
{"open": 117.5, "high": 120.0, "low": 116.0, "close": 119.0, "volume": 1400000}
|
|
1102
|
-
${
|
|
1103
|
-
... ${
|
|
1104
|
-
]`}`,
|
|
1105
|
-
${
|
|
1106
|
-
Please process this data according to the system instructions. Remember to return EXACTLY ${
|
|
1107
|
-
{ role: "system", content:
|
|
1108
|
-
{ 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 }
|
|
1109
1471
|
];
|
|
1110
1472
|
try {
|
|
1111
|
-
const
|
|
1473
|
+
const p = o * 50 + 100, g = Math.max(a?.maxTokens || 2e3, p), y = await this.chatCompletion(c, "en", {
|
|
1112
1474
|
temperature: a?.temperature || 0.3,
|
|
1113
|
-
maxTokens:
|
|
1475
|
+
maxTokens: g,
|
|
1114
1476
|
stream: !1,
|
|
1115
|
-
modelType: a?.modelType ||
|
|
1477
|
+
modelType: a?.modelType || O.DEEPSEEK_FINANCE,
|
|
1116
1478
|
topP: a?.topP,
|
|
1117
1479
|
frequencyPenalty: a?.frequencyPenalty,
|
|
1118
1480
|
presencePenalty: a?.presencePenalty
|
|
1119
|
-
}),
|
|
1120
|
-
if (
|
|
1121
|
-
throw new Error(`AI returned ${
|
|
1122
|
-
return
|
|
1123
|
-
} catch (
|
|
1124
|
-
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}`);
|
|
1125
1487
|
}
|
|
1126
1488
|
}
|
|
1127
1489
|
/**
|
|
@@ -1129,7 +1491,7 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1129
1491
|
* @param modelType - New model type
|
|
1130
1492
|
*/
|
|
1131
1493
|
setModel(e) {
|
|
1132
|
-
if (
|
|
1494
|
+
if (!$.get(e))
|
|
1133
1495
|
throw new Error(`Unsupported model type: ${e}`);
|
|
1134
1496
|
this.modelType = e;
|
|
1135
1497
|
}
|
|
@@ -1137,7 +1499,7 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1137
1499
|
* Get current model configuration
|
|
1138
1500
|
*/
|
|
1139
1501
|
getCurrentModel() {
|
|
1140
|
-
const e =
|
|
1502
|
+
const e = $.get(this.modelType);
|
|
1141
1503
|
if (!e)
|
|
1142
1504
|
throw new Error(`Model configuration does not exist: ${this.modelType}`);
|
|
1143
1505
|
return {
|
|
@@ -1147,12 +1509,12 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1147
1509
|
};
|
|
1148
1510
|
}
|
|
1149
1511
|
/**
|
|
1150
|
-
* Test connection
|
|
1512
|
+
* Test connection with i18n support
|
|
1151
1513
|
* @returns Connection test result
|
|
1152
1514
|
*/
|
|
1153
1515
|
async testConnection() {
|
|
1154
1516
|
try {
|
|
1155
|
-
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");
|
|
1156
1518
|
return {
|
|
1157
1519
|
success: !0,
|
|
1158
1520
|
model: this.modelType,
|
|
@@ -1166,71 +1528,71 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1166
1528
|
};
|
|
1167
1529
|
}
|
|
1168
1530
|
}
|
|
1169
|
-
buildOpenAIRequest(e,
|
|
1170
|
-
const
|
|
1531
|
+
buildOpenAIRequest(e, t, s, a, r, o, i, d, l, u, m) {
|
|
1532
|
+
const c = {
|
|
1171
1533
|
model: e,
|
|
1172
|
-
messages:
|
|
1534
|
+
messages: t,
|
|
1173
1535
|
temperature: s,
|
|
1174
1536
|
max_tokens: a,
|
|
1175
|
-
stream:
|
|
1537
|
+
stream: r
|
|
1176
1538
|
};
|
|
1177
|
-
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;
|
|
1178
1540
|
}
|
|
1179
|
-
async makeRequest(e,
|
|
1180
|
-
const a = new AbortController(),
|
|
1541
|
+
async makeRequest(e, t, s) {
|
|
1542
|
+
const a = new AbortController(), r = setTimeout(() => a.abort(), this.timeout);
|
|
1181
1543
|
try {
|
|
1182
|
-
const
|
|
1544
|
+
const o = await fetch(e, {
|
|
1183
1545
|
method: "POST",
|
|
1184
1546
|
headers: {
|
|
1185
1547
|
Authorization: `Bearer ${this.apiKey}`,
|
|
1186
1548
|
"Content-Type": "application/json; charset=utf-8",
|
|
1187
1549
|
Accept: "application/json"
|
|
1188
1550
|
},
|
|
1189
|
-
body: JSON.stringify(
|
|
1551
|
+
body: JSON.stringify(t),
|
|
1190
1552
|
signal: a.signal
|
|
1191
1553
|
});
|
|
1192
|
-
if (clearTimeout(
|
|
1193
|
-
const
|
|
1194
|
-
throw new Error(`HTTP ${
|
|
1554
|
+
if (clearTimeout(r), !o.ok) {
|
|
1555
|
+
const i = await o.text();
|
|
1556
|
+
throw new Error(`HTTP ${o.status}: ${i}`);
|
|
1195
1557
|
}
|
|
1196
|
-
return s ?
|
|
1197
|
-
} catch (
|
|
1198
|
-
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;
|
|
1199
1561
|
}
|
|
1200
1562
|
}
|
|
1201
|
-
async makeStreamRequest(e,
|
|
1202
|
-
const a = await this.makeRequest(e,
|
|
1563
|
+
async makeStreamRequest(e, t, s) {
|
|
1564
|
+
const a = await this.makeRequest(e, t, !0);
|
|
1203
1565
|
if (!a)
|
|
1204
1566
|
throw new Error("Failed to get streaming response");
|
|
1205
|
-
const
|
|
1206
|
-
let
|
|
1567
|
+
const r = a.getReader(), o = new TextDecoder("utf-8");
|
|
1568
|
+
let i = "";
|
|
1207
1569
|
try {
|
|
1208
1570
|
for (; ; ) {
|
|
1209
|
-
const { done:
|
|
1210
|
-
if (
|
|
1571
|
+
const { done: d, value: l } = await r.read();
|
|
1572
|
+
if (d) {
|
|
1211
1573
|
s("", !0);
|
|
1212
1574
|
break;
|
|
1213
1575
|
}
|
|
1214
|
-
|
|
1215
|
-
const
|
|
1576
|
+
i += o.decode(l, { stream: !0 });
|
|
1577
|
+
const u = i.split(`
|
|
1216
1578
|
`);
|
|
1217
|
-
|
|
1218
|
-
for (const
|
|
1219
|
-
if (
|
|
1220
|
-
const
|
|
1221
|
-
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]") {
|
|
1222
1584
|
s("", !0);
|
|
1223
1585
|
return;
|
|
1224
1586
|
}
|
|
1225
1587
|
try {
|
|
1226
|
-
const
|
|
1227
|
-
|
|
1588
|
+
const p = JSON.parse(c);
|
|
1589
|
+
p.choices?.[0]?.delta?.content && s(p.choices[0].delta.content, !1);
|
|
1228
1590
|
} catch {
|
|
1229
1591
|
}
|
|
1230
1592
|
}
|
|
1231
1593
|
}
|
|
1232
1594
|
} finally {
|
|
1233
|
-
|
|
1595
|
+
r.releaseLock();
|
|
1234
1596
|
}
|
|
1235
1597
|
}
|
|
1236
1598
|
extractContent(e) {
|
|
@@ -1246,42 +1608,42 @@ Please process this data according to the system instructions. Remember to retur
|
|
|
1246
1608
|
}
|
|
1247
1609
|
parseOHLCVResponse(e) {
|
|
1248
1610
|
try {
|
|
1249
|
-
const
|
|
1250
|
-
if (!Array.isArray(
|
|
1611
|
+
const t = JSON.parse(e);
|
|
1612
|
+
if (!Array.isArray(t))
|
|
1251
1613
|
throw new Error("Response is not in array format");
|
|
1252
|
-
return
|
|
1614
|
+
return t.map((a, r) => {
|
|
1253
1615
|
if (typeof a != "object" || a === null)
|
|
1254
|
-
throw new Error(`Element ${
|
|
1255
|
-
const { open:
|
|
1256
|
-
for (const
|
|
1257
|
-
if (typeof a[
|
|
1258
|
-
throw new Error(`Element ${
|
|
1259
|
-
if (
|
|
1260
|
-
throw new Error(`Element ${
|
|
1261
|
-
if (
|
|
1262
|
-
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`);
|
|
1263
1625
|
return {
|
|
1264
|
-
open: Number(
|
|
1265
|
-
high: Number(
|
|
1266
|
-
low: Number(
|
|
1267
|
-
close: Number(
|
|
1268
|
-
volume: Number(
|
|
1626
|
+
open: Number(o),
|
|
1627
|
+
high: Number(i),
|
|
1628
|
+
low: Number(d),
|
|
1629
|
+
close: Number(l),
|
|
1630
|
+
volume: Number(u)
|
|
1269
1631
|
};
|
|
1270
1632
|
});
|
|
1271
|
-
} catch (
|
|
1633
|
+
} catch (t) {
|
|
1272
1634
|
const s = e.match(/\[[\s\S]*\]/);
|
|
1273
1635
|
if (s)
|
|
1274
1636
|
return this.parseOHLCVResponse(s[0]);
|
|
1275
|
-
throw new Error(`Unable to parse AI returned OHLCV data: ${
|
|
1637
|
+
throw new Error(`Unable to parse AI returned OHLCV data: ${t}
|
|
1276
1638
|
Original content: ${e.substring(0, 200)}...`);
|
|
1277
1639
|
}
|
|
1278
1640
|
}
|
|
1279
1641
|
}
|
|
1280
|
-
function
|
|
1281
|
-
return new
|
|
1642
|
+
function M(n, e) {
|
|
1643
|
+
return new H({ apiKey: n, modelType: e });
|
|
1282
1644
|
}
|
|
1283
|
-
var
|
|
1284
|
-
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([
|
|
1285
1647
|
// GPT-4 Series
|
|
1286
1648
|
[
|
|
1287
1649
|
"gpt-4",
|
|
@@ -1469,52 +1831,52 @@ const u = /* @__PURE__ */ new Map([
|
|
|
1469
1831
|
}
|
|
1470
1832
|
]
|
|
1471
1833
|
]);
|
|
1472
|
-
function
|
|
1473
|
-
return
|
|
1834
|
+
function j(n) {
|
|
1835
|
+
return x.get(n);
|
|
1474
1836
|
}
|
|
1475
|
-
function
|
|
1476
|
-
return Array.from(
|
|
1837
|
+
function L() {
|
|
1838
|
+
return Array.from(x.values());
|
|
1477
1839
|
}
|
|
1478
|
-
function
|
|
1479
|
-
for (const e of
|
|
1480
|
-
if (e.name ===
|
|
1840
|
+
function W(n) {
|
|
1841
|
+
for (const e of x.values())
|
|
1842
|
+
if (e.name === n)
|
|
1481
1843
|
return e;
|
|
1482
1844
|
}
|
|
1483
|
-
function
|
|
1484
|
-
return Array.from(
|
|
1845
|
+
function G() {
|
|
1846
|
+
return Array.from(x.keys());
|
|
1485
1847
|
}
|
|
1486
|
-
function
|
|
1487
|
-
return
|
|
1488
|
-
(
|
|
1848
|
+
function J() {
|
|
1849
|
+
return L().filter(
|
|
1850
|
+
(n) => n.capabilities.includes("chat")
|
|
1489
1851
|
);
|
|
1490
1852
|
}
|
|
1491
|
-
function
|
|
1492
|
-
return
|
|
1493
|
-
(
|
|
1853
|
+
function X() {
|
|
1854
|
+
return L().filter(
|
|
1855
|
+
(n) => n.capabilities.includes("text-completion")
|
|
1494
1856
|
);
|
|
1495
1857
|
}
|
|
1496
|
-
function
|
|
1497
|
-
return
|
|
1498
|
-
(
|
|
1858
|
+
function Z() {
|
|
1859
|
+
return L().filter(
|
|
1860
|
+
(n) => n.capabilities.includes("embeddings")
|
|
1499
1861
|
);
|
|
1500
1862
|
}
|
|
1501
|
-
function
|
|
1502
|
-
return
|
|
1503
|
-
(
|
|
1863
|
+
function Y() {
|
|
1864
|
+
return L().filter(
|
|
1865
|
+
(n) => n.capabilities.includes("vision") || n.capabilities.includes("image-generation")
|
|
1504
1866
|
);
|
|
1505
1867
|
}
|
|
1506
|
-
function
|
|
1507
|
-
return
|
|
1508
|
-
(
|
|
1868
|
+
function ee() {
|
|
1869
|
+
return L().filter(
|
|
1870
|
+
(n) => n.capabilities.includes("audio-processing") || n.capabilities.includes("speech-recognition") || n.capabilities.includes("speech-synthesis")
|
|
1509
1871
|
);
|
|
1510
1872
|
}
|
|
1511
|
-
function
|
|
1512
|
-
return
|
|
1513
|
-
(
|
|
1873
|
+
function te() {
|
|
1874
|
+
return L().filter(
|
|
1875
|
+
(n) => n.capabilities.includes("multimodal")
|
|
1514
1876
|
);
|
|
1515
1877
|
}
|
|
1516
|
-
function
|
|
1517
|
-
const
|
|
1878
|
+
function ne() {
|
|
1879
|
+
const n = [
|
|
1518
1880
|
"gpt-4o",
|
|
1519
1881
|
"gpt-4o-mini",
|
|
1520
1882
|
"gpt-4-turbo",
|
|
@@ -1523,60 +1885,67 @@ function G() {
|
|
|
1523
1885
|
"dall-e-3"
|
|
1524
1886
|
/* DALL_E_3 */
|
|
1525
1887
|
];
|
|
1526
|
-
return
|
|
1527
|
-
(e) =>
|
|
1888
|
+
return L().filter(
|
|
1889
|
+
(e) => n.includes(e.name)
|
|
1528
1890
|
);
|
|
1529
1891
|
}
|
|
1530
|
-
function
|
|
1531
|
-
return
|
|
1892
|
+
function oe() {
|
|
1893
|
+
return L().filter((n) => n.inputCostPer1KTokens && n.inputCostPer1KTokens < 1e-3).sort((n, e) => (n.inputCostPer1KTokens || 0) - (e.inputCostPer1KTokens || 0));
|
|
1532
1894
|
}
|
|
1533
|
-
function
|
|
1534
|
-
return
|
|
1895
|
+
function ae() {
|
|
1896
|
+
return L().filter((n) => n.contextLength && n.contextLength >= 128e3).sort((n, e) => (e.contextLength || 0) - (n.contextLength || 0));
|
|
1535
1897
|
}
|
|
1536
|
-
function
|
|
1537
|
-
const s = (
|
|
1898
|
+
function se(n, e, t = 0) {
|
|
1899
|
+
const s = (n.inputCostPer1KTokens || 0) / 1e3 * e, a = (n.outputCostPer1KTokens || 0) / 1e3 * t;
|
|
1538
1900
|
return {
|
|
1539
1901
|
inputTokens: e,
|
|
1540
|
-
outputTokens:
|
|
1902
|
+
outputTokens: t,
|
|
1541
1903
|
inputCost: s,
|
|
1542
1904
|
outputCost: a,
|
|
1543
1905
|
totalCost: s + a
|
|
1544
1906
|
};
|
|
1545
1907
|
}
|
|
1546
|
-
function
|
|
1547
|
-
let e =
|
|
1548
|
-
switch (
|
|
1908
|
+
function ie(n) {
|
|
1909
|
+
let e = L();
|
|
1910
|
+
switch (n.taskType) {
|
|
1549
1911
|
case "chat":
|
|
1550
|
-
e = e.filter((
|
|
1912
|
+
e = e.filter((t) => t.capabilities.includes("chat"));
|
|
1551
1913
|
break;
|
|
1552
1914
|
case "completion":
|
|
1553
|
-
e = e.filter((
|
|
1915
|
+
e = e.filter((t) => t.capabilities.includes("text-completion"));
|
|
1554
1916
|
break;
|
|
1555
1917
|
case "embedding":
|
|
1556
|
-
e = e.filter((
|
|
1918
|
+
e = e.filter((t) => t.capabilities.includes("embeddings"));
|
|
1557
1919
|
break;
|
|
1558
1920
|
case "image":
|
|
1559
1921
|
e = e.filter(
|
|
1560
|
-
(
|
|
1922
|
+
(t) => t.capabilities.includes("image-generation") || t.capabilities.includes("vision")
|
|
1561
1923
|
);
|
|
1562
1924
|
break;
|
|
1563
1925
|
case "audio":
|
|
1564
1926
|
e = e.filter(
|
|
1565
|
-
(
|
|
1927
|
+
(t) => t.capabilities.includes("speech-recognition") || t.capabilities.includes("speech-synthesis")
|
|
1566
1928
|
);
|
|
1567
1929
|
break;
|
|
1568
1930
|
}
|
|
1569
|
-
return
|
|
1570
|
-
(
|
|
1571
|
-
)),
|
|
1572
|
-
(
|
|
1573
|
-
(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)
|
|
1574
1936
|
)
|
|
1575
|
-
)),
|
|
1576
|
-
(
|
|
1937
|
+
)), n.budget && e.sort(
|
|
1938
|
+
(t, s) => (t.inputCostPer1KTokens || 0) - (s.inputCostPer1KTokens || 0)
|
|
1577
1939
|
), e.slice(0, 5);
|
|
1578
1940
|
}
|
|
1579
|
-
|
|
1941
|
+
function re(n) {
|
|
1942
|
+
const e = Object.values(T);
|
|
1943
|
+
for (const t of e)
|
|
1944
|
+
if (t === n)
|
|
1945
|
+
return t;
|
|
1946
|
+
return null;
|
|
1947
|
+
}
|
|
1948
|
+
class S {
|
|
1580
1949
|
/**
|
|
1581
1950
|
* Constructor - Minimal configuration
|
|
1582
1951
|
* @param config.apiKey - API key (required)
|
|
@@ -1586,77 +1955,313 @@ class L {
|
|
|
1586
1955
|
* @param config.baseURL - Custom base URL (optional)
|
|
1587
1956
|
*/
|
|
1588
1957
|
constructor(e) {
|
|
1589
|
-
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)
|
|
1590
1959
|
throw new Error("API Key cannot be empty");
|
|
1591
|
-
if (!
|
|
1960
|
+
if (!x.get(this.modelType))
|
|
1592
1961
|
throw new Error(`Unsupported model type: ${this.modelType}`);
|
|
1593
1962
|
}
|
|
1594
1963
|
/**
|
|
1595
|
-
* Simplest method: single conversation
|
|
1964
|
+
* Simplest method: single conversation with i18n support
|
|
1596
1965
|
* @param message - User message
|
|
1966
|
+
* @param i18n - Language restriction for AI response
|
|
1597
1967
|
* @param options - Chat options
|
|
1598
1968
|
* @returns AI response
|
|
1599
1969
|
*/
|
|
1600
|
-
async chat(e,
|
|
1601
|
-
const
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
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,
|
|
1606
1981
|
stream: !1,
|
|
1607
|
-
topP:
|
|
1608
|
-
frequencyPenalty:
|
|
1609
|
-
presencePenalty:
|
|
1610
|
-
stop:
|
|
1982
|
+
topP: s?.topP,
|
|
1983
|
+
frequencyPenalty: s?.frequencyPenalty,
|
|
1984
|
+
presencePenalty: s?.presencePenalty,
|
|
1985
|
+
stop: s?.stop
|
|
1611
1986
|
});
|
|
1612
|
-
return this.extractContent(
|
|
1987
|
+
return this.extractContent(o);
|
|
1613
1988
|
}
|
|
1614
1989
|
/**
|
|
1615
|
-
* Multi-turn conversation
|
|
1990
|
+
* Multi-turn conversation with i18n support
|
|
1616
1991
|
* @param messages - Message history
|
|
1992
|
+
* @param i18n - Language restriction for AI response
|
|
1617
1993
|
* @param options - Chat options
|
|
1618
1994
|
* @returns Complete API response
|
|
1619
1995
|
*/
|
|
1620
|
-
async chatCompletion(e,
|
|
1621
|
-
const
|
|
1622
|
-
if (!
|
|
1623
|
-
throw new Error(`Unsupported model type: ${
|
|
1624
|
-
const
|
|
1625
|
-
|
|
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,
|
|
1626
2008
|
e,
|
|
2009
|
+
o,
|
|
1627
2010
|
i,
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
o
|
|
2011
|
+
d,
|
|
2012
|
+
s
|
|
1631
2013
|
);
|
|
1632
2014
|
try {
|
|
1633
|
-
return await this.makeRequest(
|
|
1634
|
-
} catch (
|
|
1635
|
-
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}`);
|
|
1636
2018
|
}
|
|
1637
2019
|
}
|
|
1638
2020
|
/**
|
|
1639
|
-
* Streaming conversation
|
|
2021
|
+
* Streaming conversation with i18n support
|
|
1640
2022
|
* @param messages - Message history
|
|
1641
2023
|
* @param callback - Streaming callback function
|
|
2024
|
+
* @param i18n - Language restriction for AI response
|
|
1642
2025
|
* @param options - Chat options
|
|
1643
2026
|
*/
|
|
1644
|
-
async chatStream(e,
|
|
1645
|
-
const
|
|
1646
|
-
if (!
|
|
1647
|
-
throw new Error(`Unsupported model type: ${
|
|
1648
|
-
const
|
|
1649
|
-
|
|
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,
|
|
1650
2039
|
e,
|
|
1651
|
-
|
|
1652
|
-
|
|
2040
|
+
i,
|
|
2041
|
+
d,
|
|
1653
2042
|
!0,
|
|
1654
|
-
|
|
2043
|
+
a
|
|
1655
2044
|
);
|
|
1656
2045
|
try {
|
|
1657
|
-
await this.makeStreamRequest(
|
|
1658
|
-
} catch (
|
|
1659
|
-
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: r?.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: o?.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: a?.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}`);
|
|
1660
2265
|
}
|
|
1661
2266
|
}
|
|
1662
2267
|
/**
|
|
@@ -1665,31 +2270,31 @@ class L {
|
|
|
1665
2270
|
* @param options - Image generation options
|
|
1666
2271
|
* @returns Generated image URLs
|
|
1667
2272
|
*/
|
|
1668
|
-
async generateImage(e,
|
|
1669
|
-
const s =
|
|
1670
|
-
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)
|
|
1671
2276
|
throw new Error("Image generation only supports DALL-E models");
|
|
1672
|
-
const a =
|
|
2277
|
+
const a = x.get(s);
|
|
1673
2278
|
if (!a)
|
|
1674
2279
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1675
|
-
const
|
|
2280
|
+
const r = {
|
|
1676
2281
|
model: a.name,
|
|
1677
2282
|
prompt: e,
|
|
1678
|
-
n:
|
|
1679
|
-
size:
|
|
1680
|
-
quality:
|
|
1681
|
-
style:
|
|
1682
|
-
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"
|
|
1683
2288
|
};
|
|
1684
2289
|
try {
|
|
1685
|
-
const
|
|
1686
|
-
if (
|
|
1687
|
-
return
|
|
1688
|
-
(
|
|
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
|
|
1689
2294
|
);
|
|
1690
2295
|
throw new Error("Invalid response format from image generation");
|
|
1691
|
-
} catch (
|
|
1692
|
-
throw new Error(`Image generation failed: ${
|
|
2296
|
+
} catch (o) {
|
|
2297
|
+
throw new Error(`Image generation failed: ${o.message}`);
|
|
1693
2298
|
}
|
|
1694
2299
|
}
|
|
1695
2300
|
/**
|
|
@@ -1698,22 +2303,22 @@ class L {
|
|
|
1698
2303
|
* @param options - Embedding options
|
|
1699
2304
|
* @returns Embedding vectors
|
|
1700
2305
|
*/
|
|
1701
|
-
async createEmbeddings(e,
|
|
1702
|
-
const s =
|
|
2306
|
+
async createEmbeddings(e, t) {
|
|
2307
|
+
const s = t?.modelType || T.TEXT_EMBEDDING_ADA_002, a = x.get(s);
|
|
1703
2308
|
if (!a)
|
|
1704
2309
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1705
|
-
const
|
|
2310
|
+
const r = {
|
|
1706
2311
|
model: a.name,
|
|
1707
2312
|
input: e
|
|
1708
2313
|
};
|
|
1709
|
-
|
|
2314
|
+
t?.dimensions && a.name === T.TEXT_EMBEDDING_3_SMALL && (r.dimensions = t.dimensions);
|
|
1710
2315
|
try {
|
|
1711
|
-
const
|
|
1712
|
-
if (
|
|
1713
|
-
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);
|
|
1714
2319
|
throw new Error("Invalid response format from embeddings");
|
|
1715
|
-
} catch (
|
|
1716
|
-
throw new Error(`Embedding creation failed: ${
|
|
2320
|
+
} catch (o) {
|
|
2321
|
+
throw new Error(`Embedding creation failed: ${o.message}`);
|
|
1717
2322
|
}
|
|
1718
2323
|
}
|
|
1719
2324
|
/**
|
|
@@ -1722,19 +2327,19 @@ class L {
|
|
|
1722
2327
|
* @param options - Transcription options
|
|
1723
2328
|
* @returns Transcribed text
|
|
1724
2329
|
*/
|
|
1725
|
-
async transcribeAudio(e,
|
|
1726
|
-
const s =
|
|
2330
|
+
async transcribeAudio(e, t) {
|
|
2331
|
+
const s = t?.modelType || T.WHISPER_1, a = x.get(s);
|
|
1727
2332
|
if (!a)
|
|
1728
2333
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1729
|
-
const
|
|
2334
|
+
const r = new FormData();
|
|
1730
2335
|
if (typeof e == "string")
|
|
1731
2336
|
throw new Error("File path/Base64 support requires additional implementation");
|
|
1732
|
-
|
|
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());
|
|
1733
2338
|
try {
|
|
1734
|
-
const
|
|
1735
|
-
return
|
|
1736
|
-
} catch (
|
|
1737
|
-
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}`);
|
|
1738
2343
|
}
|
|
1739
2344
|
}
|
|
1740
2345
|
/**
|
|
@@ -1743,21 +2348,21 @@ class L {
|
|
|
1743
2348
|
* @param options - TTS options
|
|
1744
2349
|
* @returns Audio data (base64 or blob)
|
|
1745
2350
|
*/
|
|
1746
|
-
async textToSpeech(e,
|
|
1747
|
-
const s =
|
|
2351
|
+
async textToSpeech(e, t) {
|
|
2352
|
+
const s = t?.modelType || T.TTS_1_HD, a = x.get(s);
|
|
1748
2353
|
if (!a)
|
|
1749
2354
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1750
|
-
const
|
|
2355
|
+
const r = {
|
|
1751
2356
|
model: a.name,
|
|
1752
2357
|
input: e,
|
|
1753
|
-
voice:
|
|
1754
|
-
response_format:
|
|
1755
|
-
speed:
|
|
2358
|
+
voice: t?.voice || "alloy",
|
|
2359
|
+
response_format: t?.responseFormat || "mp3",
|
|
2360
|
+
speed: t?.speed || 1
|
|
1756
2361
|
};
|
|
1757
2362
|
try {
|
|
1758
|
-
return await this.makeRequest(a.endpoint,
|
|
1759
|
-
} catch (
|
|
1760
|
-
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}`);
|
|
1761
2366
|
}
|
|
1762
2367
|
}
|
|
1763
2368
|
/**
|
|
@@ -1766,18 +2371,18 @@ class L {
|
|
|
1766
2371
|
* @param options - Moderation options
|
|
1767
2372
|
* @returns Moderation results
|
|
1768
2373
|
*/
|
|
1769
|
-
async moderateContent(e,
|
|
1770
|
-
const s =
|
|
2374
|
+
async moderateContent(e, t) {
|
|
2375
|
+
const s = t?.modelType || T.MODERATION_LATEST, a = x.get(s);
|
|
1771
2376
|
if (!a)
|
|
1772
2377
|
throw new Error(`Unsupported model type: ${s}`);
|
|
1773
|
-
const
|
|
2378
|
+
const r = {
|
|
1774
2379
|
model: a.name,
|
|
1775
2380
|
input: e
|
|
1776
2381
|
};
|
|
1777
2382
|
try {
|
|
1778
|
-
return (await this.makeRequest(a.endpoint,
|
|
1779
|
-
} catch (
|
|
1780
|
-
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}`);
|
|
1781
2386
|
}
|
|
1782
2387
|
}
|
|
1783
2388
|
/**
|
|
@@ -1785,7 +2390,7 @@ class L {
|
|
|
1785
2390
|
* @param modelType - New model type
|
|
1786
2391
|
*/
|
|
1787
2392
|
setModel(e) {
|
|
1788
|
-
if (!
|
|
2393
|
+
if (!x.get(e))
|
|
1789
2394
|
throw new Error(`Unsupported model type: ${e}`);
|
|
1790
2395
|
this.modelType = e;
|
|
1791
2396
|
}
|
|
@@ -1793,7 +2398,7 @@ class L {
|
|
|
1793
2398
|
* Get current model configuration
|
|
1794
2399
|
*/
|
|
1795
2400
|
getCurrentModel() {
|
|
1796
|
-
const e =
|
|
2401
|
+
const e = x.get(this.modelType);
|
|
1797
2402
|
if (!e)
|
|
1798
2403
|
throw new Error(`Model configuration does not exist: ${this.modelType}`);
|
|
1799
2404
|
return {
|
|
@@ -1803,12 +2408,12 @@ class L {
|
|
|
1803
2408
|
};
|
|
1804
2409
|
}
|
|
1805
2410
|
/**
|
|
1806
|
-
* Test connection
|
|
2411
|
+
* Test connection with i18n support
|
|
1807
2412
|
* @returns Connection test result
|
|
1808
2413
|
*/
|
|
1809
2414
|
async testConnection() {
|
|
1810
2415
|
try {
|
|
1811
|
-
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");
|
|
1812
2417
|
return {
|
|
1813
2418
|
success: !0,
|
|
1814
2419
|
model: this.modelType,
|
|
@@ -1829,115 +2434,115 @@ class L {
|
|
|
1829
2434
|
* @param modelType - Model type (optional, uses current if not provided)
|
|
1830
2435
|
* @returns Cost estimate
|
|
1831
2436
|
*/
|
|
1832
|
-
estimateCost(e,
|
|
1833
|
-
const a = s || this.modelType,
|
|
1834
|
-
if (!
|
|
2437
|
+
estimateCost(e, t = 0, s) {
|
|
2438
|
+
const a = s || this.modelType, r = x.get(a);
|
|
2439
|
+
if (!r)
|
|
1835
2440
|
throw new Error(`Unsupported model type: ${a}`);
|
|
1836
|
-
const
|
|
2441
|
+
const o = (r.inputCostPer1KTokens || 0) / 1e3 * e, i = (r.outputCostPer1KTokens || 0) / 1e3 * t;
|
|
1837
2442
|
return {
|
|
1838
|
-
inputCost:
|
|
1839
|
-
outputCost:
|
|
1840
|
-
totalCost:
|
|
2443
|
+
inputCost: o,
|
|
2444
|
+
outputCost: i,
|
|
2445
|
+
totalCost: o + i
|
|
1841
2446
|
};
|
|
1842
2447
|
}
|
|
1843
|
-
buildOpenAIRequest(e,
|
|
1844
|
-
const
|
|
2448
|
+
buildOpenAIRequest(e, t, s, a, r, o) {
|
|
2449
|
+
const i = {
|
|
1845
2450
|
model: e,
|
|
1846
|
-
messages:
|
|
2451
|
+
messages: t,
|
|
1847
2452
|
temperature: s,
|
|
1848
2453
|
max_tokens: a,
|
|
1849
|
-
stream:
|
|
2454
|
+
stream: r
|
|
1850
2455
|
};
|
|
1851
|
-
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;
|
|
1852
2457
|
}
|
|
1853
|
-
async makeRequest(e,
|
|
1854
|
-
const
|
|
2458
|
+
async makeRequest(e, t, s, a = !1) {
|
|
2459
|
+
const r = new AbortController(), o = setTimeout(() => r.abort(), this.timeout);
|
|
1855
2460
|
try {
|
|
1856
|
-
const
|
|
2461
|
+
const i = e.startsWith("http") ? e : `${this.baseURL}${e}`, d = {
|
|
1857
2462
|
Authorization: `Bearer ${this.apiKey}`,
|
|
1858
2463
|
"Content-Type": "application/json"
|
|
1859
2464
|
};
|
|
1860
|
-
this.organization && (
|
|
1861
|
-
const
|
|
2465
|
+
this.organization && (d["OpenAI-Organization"] = this.organization);
|
|
2466
|
+
const l = await fetch(i, {
|
|
1862
2467
|
method: "POST",
|
|
1863
|
-
headers:
|
|
1864
|
-
body: JSON.stringify(
|
|
1865
|
-
signal:
|
|
2468
|
+
headers: d,
|
|
2469
|
+
body: JSON.stringify(t),
|
|
2470
|
+
signal: r.signal
|
|
1866
2471
|
});
|
|
1867
|
-
if (clearTimeout(
|
|
1868
|
-
const
|
|
2472
|
+
if (clearTimeout(o), !l.ok) {
|
|
2473
|
+
const u = await l.text();
|
|
1869
2474
|
try {
|
|
1870
|
-
const
|
|
1871
|
-
throw new Error(`HTTP ${
|
|
2475
|
+
const m = JSON.parse(u);
|
|
2476
|
+
throw new Error(`HTTP ${l.status}: ${m.error?.message || u}`);
|
|
1872
2477
|
} catch {
|
|
1873
|
-
throw new Error(`HTTP ${
|
|
2478
|
+
throw new Error(`HTTP ${l.status}: ${u}`);
|
|
1874
2479
|
}
|
|
1875
2480
|
}
|
|
1876
|
-
return a ? await
|
|
1877
|
-
} catch (
|
|
1878
|
-
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;
|
|
1879
2484
|
}
|
|
1880
2485
|
}
|
|
1881
|
-
async makeFormDataRequest(e,
|
|
1882
|
-
const a = new AbortController(),
|
|
2486
|
+
async makeFormDataRequest(e, t, s) {
|
|
2487
|
+
const a = new AbortController(), r = setTimeout(() => a.abort(), this.timeout);
|
|
1883
2488
|
try {
|
|
1884
|
-
const
|
|
2489
|
+
const o = e.startsWith("http") ? e : `${this.baseURL}${e}`, i = {
|
|
1885
2490
|
Authorization: `Bearer ${this.apiKey}`
|
|
1886
2491
|
};
|
|
1887
|
-
this.organization && (
|
|
1888
|
-
const
|
|
2492
|
+
this.organization && (i["OpenAI-Organization"] = this.organization);
|
|
2493
|
+
const d = await fetch(o, {
|
|
1889
2494
|
method: "POST",
|
|
1890
|
-
headers:
|
|
1891
|
-
body:
|
|
2495
|
+
headers: i,
|
|
2496
|
+
body: t,
|
|
1892
2497
|
signal: a.signal
|
|
1893
2498
|
});
|
|
1894
|
-
if (clearTimeout(
|
|
1895
|
-
const
|
|
2499
|
+
if (clearTimeout(r), !d.ok) {
|
|
2500
|
+
const l = await d.text();
|
|
1896
2501
|
try {
|
|
1897
|
-
const
|
|
1898
|
-
throw new Error(`HTTP ${
|
|
2502
|
+
const u = JSON.parse(l);
|
|
2503
|
+
throw new Error(`HTTP ${d.status}: ${u.error?.message || l}`);
|
|
1899
2504
|
} catch {
|
|
1900
|
-
throw new Error(`HTTP ${
|
|
2505
|
+
throw new Error(`HTTP ${d.status}: ${l}`);
|
|
1901
2506
|
}
|
|
1902
2507
|
}
|
|
1903
|
-
return s ?
|
|
1904
|
-
} catch (
|
|
1905
|
-
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;
|
|
1906
2511
|
}
|
|
1907
2512
|
}
|
|
1908
|
-
async makeStreamRequest(e,
|
|
1909
|
-
const a = await this.makeRequest(e,
|
|
2513
|
+
async makeStreamRequest(e, t, s) {
|
|
2514
|
+
const a = await this.makeRequest(e, t, !0);
|
|
1910
2515
|
if (!a)
|
|
1911
2516
|
throw new Error("Failed to get streaming response");
|
|
1912
|
-
const
|
|
1913
|
-
let
|
|
2517
|
+
const r = a.getReader(), o = new TextDecoder("utf-8");
|
|
2518
|
+
let i = "";
|
|
1914
2519
|
try {
|
|
1915
2520
|
for (; ; ) {
|
|
1916
|
-
const { done:
|
|
1917
|
-
if (
|
|
2521
|
+
const { done: d, value: l } = await r.read();
|
|
2522
|
+
if (d) {
|
|
1918
2523
|
s("", !0);
|
|
1919
2524
|
break;
|
|
1920
2525
|
}
|
|
1921
|
-
|
|
1922
|
-
const
|
|
2526
|
+
i += o.decode(l, { stream: !0 });
|
|
2527
|
+
const u = i.split(`
|
|
1923
2528
|
`);
|
|
1924
|
-
|
|
1925
|
-
for (const
|
|
1926
|
-
if (
|
|
1927
|
-
const
|
|
1928
|
-
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]") {
|
|
1929
2534
|
s("", !0);
|
|
1930
2535
|
return;
|
|
1931
2536
|
}
|
|
1932
2537
|
try {
|
|
1933
|
-
const
|
|
1934
|
-
|
|
2538
|
+
const p = JSON.parse(c);
|
|
2539
|
+
p.choices?.[0]?.delta?.content && s(p.choices[0].delta.content, !1);
|
|
1935
2540
|
} catch {
|
|
1936
2541
|
}
|
|
1937
2542
|
}
|
|
1938
2543
|
}
|
|
1939
2544
|
} finally {
|
|
1940
|
-
|
|
2545
|
+
r.releaseLock();
|
|
1941
2546
|
}
|
|
1942
2547
|
}
|
|
1943
2548
|
extractContent(e) {
|
|
@@ -1951,137 +2556,83 @@ class L {
|
|
|
1951
2556
|
return e.text;
|
|
1952
2557
|
throw new Error("Unable to parse response content");
|
|
1953
2558
|
}
|
|
1954
|
-
/**
|
|
1955
|
-
* Specialized method for processing OHLCV arrays
|
|
1956
|
-
* @param ohlcvArray - OHLCV data array
|
|
1957
|
-
* @param instructions - Processing instructions (optional, default: "Based on these OHLCV data, predict the next period")
|
|
1958
|
-
* @param count - Number of OHLCV data items to return (optional, default: 1)
|
|
1959
|
-
* @param options - Chat options
|
|
1960
|
-
* @returns Predicted OHLCV array
|
|
1961
|
-
*/
|
|
1962
|
-
async analyzeOHLCV(e, o, s, a) {
|
|
1963
|
-
const i = o || "Based on these OHLCV data, predict the next period", n = s || 1;
|
|
1964
|
-
if (!Number.isInteger(n) || n <= 0)
|
|
1965
|
-
throw new Error(`Invalid count parameter: ${n}. Must be a positive integer.`);
|
|
1966
|
-
const r = 50;
|
|
1967
|
-
if (n > r)
|
|
1968
|
-
throw new Error(`Count parameter too large: ${n}. Maximum allowed is ${r}. Please reduce the count or split your request.`);
|
|
1969
|
-
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.
|
|
1970
|
-
Your task: ${i}
|
|
1971
|
-
CRITICAL RULES:
|
|
1972
|
-
1. ${m}
|
|
1973
|
-
2. Return ONLY a JSON array of OHLCV objects, NO explanations, comments, or other text
|
|
1974
|
-
3. The OHLCV array format must match: [{open, high, low, close, volume}, ...]
|
|
1975
|
-
4. All numbers must be valid numbers
|
|
1976
|
-
5. Ensure technical rationality (high >= low, high >= close >= low, volume >= 0)
|
|
1977
|
-
6. Maintain consistency with historical trends and patterns
|
|
1978
|
-
7. For technical analysis, provide reasonable values based on typical patterns
|
|
1979
|
-
8. Do not include markdown formatting, only pure JSON
|
|
1980
|
-
${n === 1 ? `Example of valid response for 1 period:
|
|
1981
|
-
[{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000}]` : `Example of valid response for ${n} periods:
|
|
1982
|
-
[
|
|
1983
|
-
{"open": 115.5, "high": 118.0, "low": 114.0, "close": 117.0, "volume": 1350000},
|
|
1984
|
-
{"open": 117.5, "high": 120.0, "low": 116.0, "close": 119.0, "volume": 1400000}
|
|
1985
|
-
${n > 2 ? `,
|
|
1986
|
-
... ${n - 2} more OHLCV objects following the same pattern` : ""}
|
|
1987
|
-
]`}`, p = JSON.stringify(e, null, 2), d = `Here is the historical OHLCV data (${e.length} periods):
|
|
1988
|
-
${p}
|
|
1989
|
-
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 = [
|
|
1990
|
-
{ role: "system", content: c },
|
|
1991
|
-
{ role: "user", content: d }
|
|
1992
|
-
];
|
|
1993
|
-
try {
|
|
1994
|
-
const h = n * 50 + 100, x = Math.max(a?.maxTokens || 1e3, h), k = await this.chatCompletion(l, {
|
|
1995
|
-
temperature: a?.temperature || 0.3,
|
|
1996
|
-
maxTokens: x,
|
|
1997
|
-
stream: !1,
|
|
1998
|
-
modelType: a?.modelType,
|
|
1999
|
-
topP: a?.topP,
|
|
2000
|
-
frequencyPenalty: a?.frequencyPenalty,
|
|
2001
|
-
presencePenalty: a?.presencePenalty,
|
|
2002
|
-
stop: a?.stop
|
|
2003
|
-
}), E = this.extractContent(k), g = this.parseOHLCVResponse(E);
|
|
2004
|
-
if (g.length !== n)
|
|
2005
|
-
throw new Error(`AI returned ${g.length} OHLCV objects, but expected ${n}.`);
|
|
2006
|
-
return g;
|
|
2007
|
-
} catch (h) {
|
|
2008
|
-
throw new Error(`OHLCV analysis failed: ${h.message}`);
|
|
2009
|
-
}
|
|
2010
|
-
}
|
|
2011
2559
|
/**
|
|
2012
2560
|
* Parse AI returned OHLCV response
|
|
2013
2561
|
* @private
|
|
2014
2562
|
*/
|
|
2015
2563
|
parseOHLCVResponse(e) {
|
|
2016
2564
|
try {
|
|
2017
|
-
const
|
|
2018
|
-
if (!Array.isArray(
|
|
2565
|
+
const t = JSON.parse(e);
|
|
2566
|
+
if (!Array.isArray(t))
|
|
2019
2567
|
throw new Error("Response is not in array format");
|
|
2020
|
-
return
|
|
2568
|
+
return t.map((a, r) => {
|
|
2021
2569
|
if (typeof a != "object" || a === null)
|
|
2022
|
-
throw new Error(`Element ${
|
|
2023
|
-
const { open:
|
|
2024
|
-
for (const
|
|
2025
|
-
if (typeof a[
|
|
2026
|
-
throw new Error(`Element ${
|
|
2027
|
-
if (
|
|
2028
|
-
throw new Error(`Element ${
|
|
2029
|
-
if (
|
|
2030
|
-
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`);
|
|
2031
2579
|
return {
|
|
2032
|
-
open: Number(
|
|
2033
|
-
high: Number(
|
|
2034
|
-
low: Number(
|
|
2035
|
-
close: Number(
|
|
2036
|
-
volume: Number(
|
|
2580
|
+
open: Number(o),
|
|
2581
|
+
high: Number(i),
|
|
2582
|
+
low: Number(d),
|
|
2583
|
+
close: Number(l),
|
|
2584
|
+
volume: Number(u)
|
|
2037
2585
|
};
|
|
2038
2586
|
});
|
|
2039
|
-
} catch (
|
|
2587
|
+
} catch (t) {
|
|
2040
2588
|
const s = e.match(/\[[\s\S]*\]/);
|
|
2041
2589
|
if (s)
|
|
2042
2590
|
return this.parseOHLCVResponse(s[0]);
|
|
2043
|
-
throw new Error(`Unable to parse AI returned OHLCV data: ${
|
|
2591
|
+
throw new Error(`Unable to parse AI returned OHLCV data: ${t}
|
|
2044
2592
|
Original content: ${e.substring(0, 200)}...`);
|
|
2045
2593
|
}
|
|
2046
2594
|
}
|
|
2047
2595
|
}
|
|
2048
|
-
function
|
|
2049
|
-
return new
|
|
2596
|
+
function ce(n, e) {
|
|
2597
|
+
return new S({ apiKey: n, modelType: e });
|
|
2050
2598
|
}
|
|
2051
2599
|
export {
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2600
|
+
k as ALIYUN_MODELS,
|
|
2601
|
+
N as AliYunModelType,
|
|
2602
|
+
q as AliyunAI,
|
|
2603
|
+
$ as DEEPSEEK_MODELS,
|
|
2604
|
+
H as DeepSeekAI,
|
|
2605
|
+
O 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
|
|
2087
2638
|
};
|