-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathexpend.cpp
2711 lines (2358 loc) · 129 KB
/
expend.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "expend.h"
#include "ui_expend.h"
Expend::Expend(QWidget *parent, QString applicationDirPath_) : QWidget(parent), ui(new Ui::Expend) {
ui->setupUi(this);
applicationDirPath = applicationDirPath_;
//初始化选项卡
ui->info_card->setReadOnly(1); // 只读
ui->vocab_card->setReadOnly(1); // 只读
ui->modellog_card->setReadOnly(1); // 只读
ui->tabWidget->setCurrentIndex(0); //默认显示模机体介绍窗口
ui->sd_prompt_textEdit->setContextMenuPolicy(Qt::NoContextMenu); //取消右键菜单
ui->sd_prompt_textEdit->installEventFilter(this); //安装事件过滤器
ui->sd_negative_lineEdit->installEventFilter(this); //安装事件过滤器
ui->sd_modify_lineEdit->installEventFilter(this); //安装事件过滤器
ui->sd_img2img_lineEdit->installEventFilter(this); //安装事件过滤器
ui->vocab_card->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->modellog_card->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->whisper_log->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->embedding_test_log->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->embedding_test_result->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->model_quantize_log->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->sd_log->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->speech_log->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->modelconvert_log->setStyleSheet("background-color: rgba(128, 128, 128, 200);"); //灰色
ui->modellog_card->setLineWrapMode(QPlainTextEdit::NoWrap); // 禁用自动换行
ui->embedding_test_log->setLineWrapMode(QPlainTextEdit::NoWrap); // 禁用自动换行
ui->sync_plainTextEdit->setLineWrapMode(QPlainTextEdit::NoWrap); // 禁用自动换行
ui->sd_log->setLineWrapMode(QPlainTextEdit::NoWrap); // 禁用自动换行
ui->speech_log->setLineWrapMode(QPlainTextEdit::NoWrap);
ui->model_quantize_info->setStyleSheet("QTableWidget::item:selected { background-color: #FFA500; }"); // 设置选中行的颜色为橘黄色
//模型信息相关
ui->modelgrade_tableWidget->setColumnCount(1);//设置列数
ui->modelgrade_tableWidget->setRowCount(7);//设置行数
ui->modelgrade_tableWidget->horizontalHeader()->setVisible(false);// 隐藏列头
ui->modelgrade_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 列充满
ui->modelgrade_tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 行充满
//模型转换相关
// ui->modelconvert_modeltype_comboBox->addItems({modeltype_map[MODEL_TYPE_LLM],modeltype_map[MODEL_TYPE_WHISPER],modeltype_map[MODEL_TYPE_SD],modeltype_map[MODEL_TYPE_OUTETTS]});
ui->modelconvert_modeltype_comboBox->addItems({modeltype_map[MODEL_TYPE_LLM]});
ui->modelconvert_converttype_comboBox->addItems({modelquantize_map[MODEL_QUANTIZE_F32],modelquantize_map[MODEL_QUANTIZE_F16],modelquantize_map[MODEL_QUANTIZE_BF16],modelquantize_map[MODEL_QUANTIZE_Q8_0]});
ui->modelconvert_converttype_comboBox->setCurrentText(modelquantize_map[MODEL_QUANTIZE_F16]);//默认转换为f16的模型
ui->modelconvert_script_comboBox->addItems({CONVERT_HF_TO_GGUF_SCRIPT});
convert_command_process = new QProcess(this);
connect(convert_command_process, &QProcess::started, this, &Expend::convert_command_onProcessStarted); //连接开始信号
connect(convert_command_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &Expend::convert_command_onProcessFinished); //连接结束信号
connect(convert_command_process, &QProcess::readyReadStandardOutput, this, &Expend::readyRead_convert_command_process_StandardOutput);
connect(convert_command_process, &QProcess::readyReadStandardError, this, &Expend::readyRead_convert_command_process_StandardError);
//塞入第三方exe
server_process = new QProcess(this); // 创建一个QProcess实例用来启动llama-server
connect(server_process, &QProcess::started, this, &Expend::server_onProcessStarted); //连接开始信号
connect(server_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &Expend::server_onProcessFinished); //连接结束信号
quantize_process = new QProcess(this); // 创建一个QProcess实例用来启动llama-quantize
connect(quantize_process, &QProcess::started, this, &Expend::quantize_onProcessStarted); //连接开始信号
connect(quantize_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &Expend::quantize_onProcessFinished); //连接结束信号
whisper_process = new QProcess(this); //实例化
connect(whisper_process, &QProcess::started, this, &Expend::whisper_onProcessStarted); //连接开始信号
connect(whisper_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &Expend::whisper_onProcessFinished); //连接结束信号
sd_process = new QProcess(this); // 创建一个QProcess实例用来启动llama-quantize
connect(sd_process, &QProcess::started, this, &Expend::sd_onProcessStarted); //连接开始信号
connect(sd_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &Expend::sd_onProcessFinished); //连接结束信号
outetts_process = new QProcess(this);
connect(outetts_process, &QProcess::started, this, &Expend::outetts_onProcessStarted); //连接开始信号
connect(outetts_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &Expend::outetts_onProcessFinished); //连接结束信号
connect(outetts_process, &QProcess::readyReadStandardOutput, this, &Expend::readyRead_outetts_process_StandardOutput);
connect(outetts_process, &QProcess::readyReadStandardError, this, &Expend::readyRead_outetts_process_StandardError);
ui->embedding_txt_wait->setContextMenuPolicy(Qt::CustomContextMenu); //添加右键菜单
connect(ui->embedding_txt_wait, &QTableWidget::customContextMenuRequested, this, &Expend::show_embedding_txt_wait_menu);
//知识库相关
ui->embedding_txt_wait->setColumnCount(1); //设置一列
ui->embedding_txt_over->setColumnCount(1); //设置一列
ui->embedding_txt_wait->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 充满
ui->embedding_txt_over->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 充满
connect(server_process, &QProcess::readyReadStandardOutput, this, &Expend::readyRead_server_process_StandardOutput);
connect(server_process, &QProcess::readyReadStandardError, this, &Expend::readyRead_server_process_StandardError);
//同步率相关
ui->sync_tableWidget->setColumnCount(5); //设置列数
ui->sync_tableWidget->setRowCount(30); //创建行数
// ui->sync_tableWidget->verticalHeader()->setVisible(false);// 隐藏行头部
ui->sync_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 充满
// 设置某几列的最大宽度
QHeaderView *header = ui->sync_tableWidget->horizontalHeader(); // 获取水平表头
header->setSectionResizeMode(2, QHeaderView::Interactive); // action_name
header->setSectionResizeMode(4, QHeaderView::Interactive); // pass
header->setMaximumSectionSize(80);
//添加采样算法
ui->sd_sampletype->addItems({"euler", "euler_a", "heun", "dpm2", "dpm++2s_a", "dpm++2m", "dpm++2mv2", "lcm"});
ui->sd_sampletype->setCurrentText("euler");
//添加输出格式
ui->whisper_output_format->addItems({"txt", "srt", "csv", "json"});
// 文生图相关
// 构建模板 sd1.5-anything-3,sdxl-animagine-3.1,sd3.5-large,flux1-dev,custom1,custom2
SD_PARAMS sd_sd1_5_anything_3_template{"euler_a", "EasyNegative,badhandv4,ng_deepnegative_v1_75t,worst quality, low quality, normal quality, lowres, monochrome, grayscale, bad anatomy,DeepNegative, skin spots, acnes, skin blemishes, fat, facing away, looking away, tilted head, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, bad feet, poorly drawn hands, poorly drawn face, mutation, deformed, extra fingers, extra limbs, extra arms, extra legs, malformed limbs,fused fingers,too many fingers,long neck,cross-eyed,mutated hands,polar lowres,bad body,bad proportions,gross proportions,missing arms,missing legs,extra digit, extra arms, extra leg, extra foot,teethcroppe,signature, watermark, username,blurry,cropped,jpeg artifacts,text,error,Lower body exposure", "masterpieces, best quality, beauty, detailed, Pixar, 8k", 512, 512, 20, 1, -1, 2, 7.5};
SD_PARAMS sd_sdxl_animagine_3_1_template{"euler_a", "nsfw, lowres, (bad), text, error, fewer, extra, missing, worst quality, jpeg artifacts, low quality, watermark, unfinished, displeasing, oldest, early, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract]", "masterpiece, best quality", 768, 768, 30, 1, -1, 2, 7.5};
SD_PARAMS sd_sd3_5_large_template{"euler", "", "", 768, 768, 20, 1, -1, -1, 4.5};
SD_PARAMS sd_flux1_dev_template{"euler", "", "", 768, 768, 30, 1, -1, -1, 1.0};
SD_PARAMS sd_custom1_template{"euler", "", "", 512, 512, 20, 1, -1, -1, 7.5};
SD_PARAMS sd_custom2_template{"euler", "", "", 512, 512, 20, 1, -1, -1, 7.5};
sd_params_templates.insert("sd1.5-anything-3", sd_sd1_5_anything_3_template);
sd_params_templates.insert("sdxl-animagine-3.1", sd_sdxl_animagine_3_1_template);
sd_params_templates.insert("sd3.5-large", sd_sd3_5_large_template);
sd_params_templates.insert("flux1-dev", sd_flux1_dev_template);
sd_params_templates.insert("custom1", sd_custom1_template);
sd_params_templates.insert("custom2", sd_custom2_template);
for (const auto &key : sd_params_templates.keys()) {
ui->params_template_comboBox->addItem(key); // 添加模板选项
}
//记忆矩阵相关
ui->brain_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); //让表格自动撑满所在区域
ui->brain_tableWidget->verticalHeader()->setVisible(false); // 隐藏行头部
//文转声相关
connect(ui->speech_enable_radioButton, &QRadioButton::clicked, this, &Expend::speech_enable_change);
connect(ui->speech_source_comboBox, &QComboBox::currentTextChanged, this, &Expend::speech_source_change);
sys_speech = new QTextToSpeech(); // 系统声源
// 检查是否成功创建
#ifndef BODY_USE_32BIT // win7就不用检查了
if (sys_speech->state() == QTextToSpeech::Ready) {
// 遍历所有可用音色
foreach (const QVoice &speech, sys_speech->availableVoices()) { avaliable_speech_list << speech.name(); }
connect(sys_speech, &QTextToSpeech::stateChanged, this, &Expend::speechOver); //朗读结束后动作
is_sys_speech_available = true;
} else {
is_sys_speech_available = false;
}
#endif
avaliable_speech_list << SPPECH_OUTETTS; // 模型声源
this->set_sys_speech(avaliable_speech_list); // 设置可用声源
// 创建播放器对象
speech_player = new QMediaPlayer;
// 连接 mediaStatusChanged 信号到槽函数
QObject::connect(speech_player, &QMediaPlayer::mediaStatusChanged, this, &Expend::speech_player_over);
outettsDir = applicationDirPath + "/EVA_TEMP/outetts/"; // outetts生成的音频存放目录
connect(&speechTimer, SIGNAL(timeout()), this, SLOT(speech_process()));
connect(&speechPlayTimer, SIGNAL(timeout()), this, SLOT(speech_play_process()));
#ifndef BODY_USE_32BIT
speechTimer.start(500); //每半秒检查一次是否需要朗读
speechPlayTimer.start(500); //每半秒检查一次是否有音频需要朗读
#endif
//如果存在配置文件则读取它,并且应用,目前主要是文生图/声转文/文转声
readConfig();
qDebug() << "expend init over";
}
Expend::~Expend() {
delete ui;
server_process->kill(); //有点问题
sd_process->kill();
whisper_process->kill();
quantize_process->kill();
}
//创建临时文件夹EVA_TEMP
bool Expend::createTempDirectory(const QString &path) {
QDir dir;
// 检查路径是否存在
if (dir.exists(path)) {
return false;
} else {
// 尝试创建目录
if (dir.mkpath(path)) {
return true;
} else {
return false;
}
}
}
//传递llama.cpp的log,显示模型日志
void Expend::recv_llama_log(QString log) {
QTextCursor cursor = ui->modellog_card->textCursor();
cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
cursor.insertText(log);
ui->modellog_card->setTextCursor(cursor);
}
// 根据language.json和language_flag中找到对应的文字
QString Expend::jtr(QString customstr) { return wordsObj[customstr].toArray()[language_flag].toString(); }
//-------------------------------------------------------------------------
//----------------------------------界面相关--------------------------------
//-------------------------------------------------------------------------
//初始化增殖窗口
void Expend::init_expend() {
this->setWindowTitle(jtr("expend window")); //标题
ui->tabWidget->setTabText(window_map[INTRODUCTION_WINDOW], jtr("introduction")); //软件介绍
ui->tabWidget->setTabText(window_map[MODELINFO_WINDOW], jtr("model info")); //模型信息
ui->tabWidget->setTabText(window_map[MODELCONVERT_WINDOW], jtr("model")+jtr("convert")); //模型转换
ui->tabWidget->setTabText(window_map[QUANTIZE_WINDOW], jtr("model") + jtr("quantize")); //模型量化
ui->tabWidget->setTabText(window_map[KNOWLEDGE_WINDOW], jtr("knowledge")); //知识库
ui->tabWidget->setTabText(window_map[TXT2IMG_WINDOW], jtr("text2image")); //文生图
ui->tabWidget->setTabText(window_map[WHISPER_WINDOW], jtr("speech2text")); //声转文
ui->tabWidget->setTabText(window_map[TTS_WINDOW], jtr("text2speech")); //文转声
ui->tabWidget->setTabText(window_map[SYNC_WINDOW], jtr("sync rate")); //同步率
//模型信息
ui->vocab_groupBox->setTitle(jtr("vocab_groupBox_title"));
ui->brain_groupBox->setTitle(jtr("brain_groupBox_title"));
ui->modelgrade_groupBox->setTitle(jtr("grade") + " " + modelinfo.grade);
ui->modellog_groupBox->setTitle(jtr("model log"));
ui->modelgrade_tableWidget->setVerticalHeaderLabels(QStringList{jtr("model location"),jtr("model size"),jtr("max brain size"),jtr("Q16"),jtr("Q14"),jtr("batch decode"),jtr("single decode")});//设置行名
//软件介绍
showReadme();
//模型转换
ui->modelconvert_modeltype_label->setText(jtr("modelconvert_modeltype_label_text"));
ui->modelconvert_script_label->setText(jtr("modelconvert_script_label_text"));
ui->modelconvert_modelpath_label->setText(jtr("modelconvert_modelpath_label_text"));
ui->modelconvert_converttype_label->setText(jtr("modelconvert_converttype_label_text"));
ui->modelconvert_outputname_label->setText(jtr("modelconvert_outputname_label_text"));
ui->modelconvert_modelpath_lineEdit->setPlaceholderText(jtr("modelconvert_modelpath_lineEdit_placeholder"));
ui->modelconvert_outputname_lineEdit->setPlaceholderText(jtr("modelconvert_outputname_lineEdit_placeholder"));
ui->modelconvert_log->setPlaceholderText(jtr("modelconvert_log_placeholder"));
ui->modelconvert_log_groupBox->setTitle(jtr("log"));
if(ui->modelconvert_exec_pushButton->text()==wordsObj["exec convert"].toArray()[0].toString()||ui->modelconvert_exec_pushButton->text()==wordsObj["exec convert"].toArray()[1].toString()){ui->modelconvert_exec_pushButton->setText(jtr("exec convert"));}
else{ui->modelconvert_exec_pushButton->setText(jtr("shut down"));}
//模型量化
ui->model_quantize_label->setText(jtr("model_quantize_label_text"));
ui->model_quantize_label_2->setText(jtr("model_quantize_label_2_text"));
ui->model_quantize_label_3->setText(jtr("model_quantize_label_3_text"));
ui->model_quantize_row_modelpath_lineedit->setPlaceholderText(jtr("model_quantize_row_modelpath_lineedit_placeholder"));
ui->model_quantize_important_datapath_lineedit->setPlaceholderText(jtr("model_quantize_important_datapath_lineedit_placeholder"));
ui->model_quantize_output_modelpath_lineedit->setPlaceholderText(jtr("model_quantize_output_modelpath_lineedit_placeholder"));
ui->quantize_info_groupBox->setTitle(jtr("quantize_info_groupBox_title"));
show_quantize_types();
ui->model_quantize_type_label->setText(jtr("select quantize type"));
ui->model_quantize_execute->setText(jtr("execute quantize"));
ui->quantize_log_groupBox->setTitle("llama-quantize " + jtr("execute log"));
//知识库
ui->embedding_txt_over->setHorizontalHeaderLabels(QStringList{jtr("embeded text segment")}); //设置列名
ui->embedding_txt_wait->setHorizontalHeaderLabels(QStringList{jtr("embedless text segment")}); //设置列名
ui->embedding_model_label->setText(jtr("embd model"));
ui->embedding_dim_label->setText(jtr("embd dim"));
ui->embedding_model_lineedit->setPlaceholderText(jtr("embedding_model_lineedit_placeholder"));
ui->embedding_split_label->setText(jtr("split length"));
ui->embedding_overlap_label->setText(jtr("overlap length"));
ui->embedding_source_doc_label->setText(jtr("source txt"));
ui->embedding_txt_lineEdit->setPlaceholderText(jtr("embedding_txt_lineEdit_placeholder"));
ui->embedding_describe_label->setText(jtr("knowledge base description"));
ui->embedding_txt_describe_lineEdit->setPlaceholderText(jtr("embedding_txt_describe_lineEdit_placeholder"));
ui->embedding_txt_embedding->setText(jtr("embedding txt"));
ui->embedding_test_groupBox->setTitle(jtr("test"));
ui->embedding_test_textEdit->setPlaceholderText(jtr("embedding_test_textEdit_placeholder"));
ui->embedding_test_pushButton->setText(jtr("retrieval"));
ui->embedding_result_groupBox->setTitle(jtr("retrieval result"));
ui->embedding_log_groupBox->setTitle(jtr("log"));
ui->embedding_resultnumb_label->setText(jtr("resultnumb"));
//文生图
ui->sd_pathset_groupBox->setTitle(jtr("path set"));
ui->sd_paramsset_groupBox->setTitle(jtr("params set"));
ui->sd_prompt_groupBox->setTitle(jtr("prompt"));
ui->sd_result_groupBox->setTitle(jtr("result"));
ui->sd_log_groupBox->setTitle(jtr("log"));
ui->sd_modelpath_label->setText(jtr("diffusion") + jtr("model"));
ui->sd_vaepath_label->setText("vae " + jtr("model"));
ui->sd_clip_l_path_label->setText("clip_l " + jtr("model"));
ui->sd_clip_g_path_label->setText("clip_g " + jtr("model"));
ui->sd_t5path_label->setText("t5 " + jtr("model"));
ui->sd_lorapath_label->setText("lora " + jtr("model"));
ui->sd_modelpath_lineEdit->setPlaceholderText(jtr("sd_modelpath_lineEdit_placeholder"));
ui->sd_vaepath_lineEdit->setPlaceholderText(jtr("sd_vaepath_lineEdit_placeholder"));
ui->sd_clip_l_path_lineEdit->setPlaceholderText(jtr("sd_vaepath_lineEdit_placeholder"));
ui->sd_clip_g_path_lineEdit->setPlaceholderText(jtr("sd_vaepath_lineEdit_placeholder"));
ui->sd_t5path_lineEdit->setPlaceholderText(jtr("sd_vaepath_lineEdit_placeholder"));
ui->sd_lorapath_lineEdit->setPlaceholderText(jtr("sd_vaepath_lineEdit_placeholder"));
ui->params_template_label->setText(jtr("params template"));
ui->sd_imagewidth_label->setText(jtr("image width"));
ui->sd_imageheight_label->setText(jtr("image height"));
ui->sd_sampletype_label->setText(jtr("sample type"));
ui->sd_samplesteps_label->setText(jtr("sample steps"));
ui->sd_cfg_label->setText(jtr("cfg scale"));
ui->sd_imagenums_label->setText(jtr("image nums"));
ui->sd_seed_label->setText(jtr("seed"));
ui->sd_clipskip_label->setText(jtr("clip skip"));
ui->sd_negative_label->setText(jtr("negative"));
ui->sd_negative_lineEdit->setPlaceholderText(jtr("sd_negative_lineEdit_placeholder"));
ui->sd_modify_label->setText(jtr("modify"));
ui->sd_modify_lineEdit->setPlaceholderText(jtr("sd_modify_lineEdit_placeholder"));
ui->sd_prompt_textEdit->setPlaceholderText(jtr("sd_prompt_textEdit_placeholder"));
if(ui->sd_draw_pushButton->text()==wordsObj["text to image"].toArray()[0].toString()||ui->sd_draw_pushButton->text()==wordsObj["text to image"].toArray()[1].toString()){ui->sd_draw_pushButton->setText(jtr("text to image"));}
else{ui->sd_draw_pushButton->setText("stop");}
if(ui->sd_img2img_pushButton->text()==wordsObj["image to image"].toArray()[0].toString()||ui->sd_img2img_pushButton->text()==wordsObj["image to image"].toArray()[1].toString()){ui->sd_img2img_pushButton->setText(jtr("image to image"));}
else{ui->sd_img2img_pushButton->setText("stop");}
ui->sd_img2img_lineEdit->setPlaceholderText(jtr("sd_img2img_lineEdit_placeholder"));
ui->sd_log->setPlainText(jtr("sd_log_plainText"));
//声转文
ui->whisper_modelpath_label->setText(jtr("whisper path"));
ui->whisper_load_modelpath_linedit->setPlaceholderText(jtr("whisper_load_modelpath_linedit_placeholder"));
ui->speech_load_groupBox_4->setTitle("whisper " + jtr("log"));
ui->whisper_wav2text_label->setText(jtr("wav2text"));
ui->whisper_wavpath_pushButton->setText(jtr("wav path"));
ui->whisper_format_label->setText(jtr("format"));
ui->whisper_execute_pushbutton->setText(jtr("exec convert"));
//文转声
ui->speech_available_label->setText(jtr("Available sound"));
ui->speech_enable_radioButton->setText(jtr("enable"));
ui->speech_outetts_modelpath_label->setText("OuteTTS " + jtr("model"));
ui->speech_wavtokenizer_modelpath_label->setText("WavTokenizer " + jtr("model"));
ui->speech_log_groupBox->setTitle(jtr("log"));
ui->speech_outetts_modelpath_lineEdit->setPlaceholderText(jtr("speech_outetts_modelpath_lineEdit placehold"));
ui->speech_wavtokenizer_modelpath_lineEdit->setPlaceholderText(jtr("speech_outetts_modelpath_lineEdit placehold"));
ui->speech_manual_plainTextEdit->setPlaceholderText(jtr("speech_manual_plainTextEdit placehold"));
ui->speech_manual_pushButton->setText(jtr("convert to audio"));
ui->speech_source_comboBox->setCurrentText(speech_params.speech_name);
ui->speech_enable_radioButton->setChecked(speech_params.enable_speech);
//同步率
init_syncrate();
}
//用户切换选项卡时响应
// 0软件介绍,1模型信息
void Expend::on_tabWidget_tabBarClicked(int index) {
if (index == window_map[INTRODUCTION_WINDOW] && is_first_show_info) //第一次点软件介绍
{
is_first_show_info = false;
//展示readme内容
showReadme();
//强制延迟见顶
QTimer::singleShot(0, this, [this]() {
ui->info_card->verticalScrollBar()->setValue(0);
ui->info_card->horizontalScrollBar()->setValue(0);
});
}
else if (index == window_map[QUANTIZE_WINDOW] && is_first_show_modelproliferation) //第一次展示量化方法
{
is_first_show_modelproliferation = false;
show_quantize_types();
}
else if (index == window_map[SYNC_WINDOW] && is_first_show_sync) //第一次展示同步率
{
is_first_show_sync = false;
ui->sync_tableWidget->setHorizontalHeaderLabels(QStringList{jtr("task"), jtr("response"), "tool", "value", jtr("pass")}); //设置列名
}
else if(index == window_map[MODELINFO_WINDOW] && is_first_show_modelinfo)//第一次展示模型信息窗口
{
is_first_show_modelinfo = false;
ui->vocab_card->setPlainText(vocab);//更新一次模型词表
}
}
// 接收模型词表
void Expend::recv_vocab(QString vocab_) {
vocab = vocab_;
if(!is_first_show_modelinfo){ui->vocab_card->setPlainText(vocab);}
init_brain_matrix();
reflash_brain_matrix();
}
//通知显示增殖窗口
void Expend::recv_expend_show(EXPEND_WINDOW window) {
if (window == NO_WINDOW) {
this->close();
return;
} else if (window == SYNC_WINDOW && is_first_show_sync) //第一次点同步率
{
is_first_show_sync = false;
ui->sync_tableWidget->setHorizontalHeaderLabels(QStringList{jtr("task"), jtr("response"), "action_name", "action_input", jtr("pass")}); //设置列名
}
if (is_first_show_expend) //第一次显示的话
{
is_first_show_expend = false;
this->init_expend();
if (vocab == "") {
vocab = jtr("lode model first");
}
if (ui->modellog_card->toPlainText() == "") {
ui->modellog_card->setPlainText(jtr("lode model first"));
}
}
//词表滑动到底部
QScrollBar *vScrollBar = ui->vocab_card->verticalScrollBar();
vScrollBar->setValue(vScrollBar->maximum());
//打开指定页数窗口
ui->tabWidget->setCurrentIndex(window_map[window]);
this->setWindowState(Qt::WindowActive); // 激活窗口并恢复正常状态
this->show();
this->activateWindow(); // 激活增殖窗口
}
QString Expend::customOpenfile(QString dirpath, QString describe, QString format) {
QString filepath = "";
filepath = QFileDialog::getOpenFileName(nullptr, describe, dirpath, format);
return filepath;
}
//传递使用的语言
void Expend::recv_language(int language_flag_) {
language_flag = language_flag_;
init_expend();
}
//读取配置文件并应用
void Expend::readConfig() {
QFile configfile(applicationDirPath + "/EVA_TEMP/eva_config.ini");
//如果默认要填入的模型存在,则默认填入
QString default_sd_modelpath = applicationDirPath + DEFAULT_SD_MODEL_PATH;
QString default_sd_params_template = "sd1.5-anything-3";
QFile default_sd_modelpath_file(default_sd_modelpath);
if(!default_sd_modelpath_file.exists()) {default_sd_modelpath = "";default_sd_params_template = "custom1";}//不存在则默认为空
QString default_whisper_modelpath = applicationDirPath + DEFAULT_WHISPER_MODEL_PATH;
QFile default_whisper_modelpath_file(default_whisper_modelpath);
if(!default_whisper_modelpath_file.exists()) {default_whisper_modelpath = "";}//不存在则默认为空
QString default_outetts_modelpath = applicationDirPath + DEFAULT_OUTETTS_MODEL_PATH;
QFile default_outetts_modelpath_file(default_outetts_modelpath);
if(!default_outetts_modelpath_file.exists()) {default_outetts_modelpath = "";}//不存在则默认为空
QString default_WavTokenizer_modelpath = applicationDirPath + DEFAULT_WAVTOKENIZER_MODEL_PATH;
QFile default_WavTokenizer_modelpath_file(default_WavTokenizer_modelpath);
if(!default_WavTokenizer_modelpath_file.exists()) {default_WavTokenizer_modelpath = "";}//不存在则默认为空
// 读取配置文件中的值
QSettings settings(applicationDirPath + "/EVA_TEMP/eva_config.ini", QSettings::IniFormat);
settings.setIniCodec("utf-8");
QString sd_params_template = settings.value("sd_params_template", default_sd_params_template).toString(); // 参数模板,默认是custom1
QString sd_modelpath = settings.value("sd_modelpath", default_sd_modelpath).toString(); // sd模型路径
QString vae_modelpath = settings.value("vae_modelpath", "").toString(); // vae模型路径
QString clip_l_modelpath = settings.value("clip_l_modelpath", "").toString(); // clip_l模型路径
QString clip_g_modelpath = settings.value("clip_g_modelpath", "").toString(); // clip_g模型路径
QString t5_modelpath = settings.value("t5_modelpath", "").toString(); // t5模型路径
QString lora_modelpath = settings.value("lora_modelpath", "").toString(); // lora模型路径
QString sd_prompt = settings.value("sd_prompt", "").toString(); // sd提示词
QString whisper_modelpath = settings.value("whisper_modelpath", default_whisper_modelpath).toString(); // whisper模型路径
speech_params.enable_speech = settings.value("speech_enable", "").toBool(); //是否启用语音朗读
speech_params.speech_name = settings.value("speech_name", "").toString(); //朗读者
QString outetts_modelpath = settings.value("outetts_modelpath", default_outetts_modelpath).toString(); // outetts模型路径
QString wavtokenizer_modelpath = settings.value("wavtokenizer_modelpath", default_WavTokenizer_modelpath).toString(); // wavtokenizer模型路径
ui->speech_outetts_modelpath_lineEdit->setText(outetts_modelpath);
ui->speech_wavtokenizer_modelpath_lineEdit->setText(wavtokenizer_modelpath);
// 应用值
QFile sd_modelpath_file(sd_modelpath);
if (sd_modelpath_file.exists()) {
ui->sd_modelpath_lineEdit->setText(sd_modelpath);
}
QFile vae_modelpath_file(vae_modelpath);
if (vae_modelpath_file.exists()) {
ui->sd_vaepath_lineEdit->setText(vae_modelpath);
}
QFile clip_l_modelpath_file(clip_l_modelpath);
if (clip_l_modelpath_file.exists()) {
ui->sd_clip_l_path_lineEdit->setText(clip_l_modelpath);
}
QFile clip_g_modelpath_file(clip_g_modelpath);
if (clip_g_modelpath_file.exists()) {
ui->sd_clip_g_path_lineEdit->setText(clip_g_modelpath);
}
QFile t5_modelpath_file(t5_modelpath);
if (t5_modelpath_file.exists()) {
ui->sd_t5path_lineEdit->setText(t5_modelpath);
}
QFile lora_modelpath_file(lora_modelpath);
if (lora_modelpath_file.exists()) {
ui->sd_lorapath_lineEdit->setText(lora_modelpath);
}
sd_params_templates["custom1"].batch_count = settings.value("sd_custom1_image_nums", 1).toInt();
sd_params_templates["custom1"].cfg_scale = settings.value("sd_custom1_cfg", 7.5).toFloat();
sd_params_templates["custom1"].clip_skip = settings.value("sd_custom1_clip_skip", -1).toInt();
sd_params_templates["custom1"].height = settings.value("sd_custom1_image_height", 512).toInt();
sd_params_templates["custom1"].width = settings.value("sd_custom1_image_width", 512).toInt();
sd_params_templates["custom1"].seed = settings.value("sd_custom1_seed", -1).toInt();
sd_params_templates["custom1"].steps = settings.value("sd_custom1_sample_steps", 20).toInt();
sd_params_templates["custom1"].sample_type = settings.value("sd_custom1_sample_type", "euler").toString();
sd_params_templates["custom1"].negative_prompt = settings.value("sd_custom1_negative", "").toString();
sd_params_templates["custom1"].modify_prompt = settings.value("sd_custom1_modify", "").toString();
sd_params_templates["custom2"].batch_count = settings.value("sd_custom2_image_nums", 1).toInt();
sd_params_templates["custom2"].cfg_scale = settings.value("sd_custom2_cfg", 7.5).toFloat();
sd_params_templates["custom2"].clip_skip = settings.value("sd_custom2_clip_skip", -1).toInt();
sd_params_templates["custom2"].height = settings.value("sd_custom2_image_height", 512).toInt();
sd_params_templates["custom2"].width = settings.value("sd_custom2_image_width", 512).toInt();
sd_params_templates["custom2"].seed = settings.value("sd_custom2_seed", -1).toInt();
sd_params_templates["custom2"].steps = settings.value("sd_custom2_sample_steps", 20).toInt();
sd_params_templates["custom2"].sample_type = settings.value("sd_custom2_sample_type", "euler").toString();
sd_params_templates["custom2"].negative_prompt = settings.value("sd_custom2_negative", "").toString();
sd_params_templates["custom2"].modify_prompt = settings.value("sd_custom2_modify", "").toString();
ui->params_template_comboBox->setCurrentText(sd_params_template); // 应用模板
sd_apply_template(sd_params_templates[ui->params_template_comboBox->currentText()]);
is_readconfig = true;
QFile whisper_load_modelpath_file(whisper_modelpath);
if (whisper_load_modelpath_file.exists()) {
ui->whisper_load_modelpath_linedit->setText(whisper_modelpath);
whisper_params.model = whisper_modelpath.toStdString();
}
//知识库,在main.cpp里有启动的部分
ui->embedding_txt_describe_lineEdit->setText(settings.value("embedding_describe", "").toString()); //知识库描述
ui->embedding_split_spinbox->setValue(settings.value("embedding_split", DEFAULT_EMBEDDING_SPLITLENTH).toInt());
ui->embedding_resultnumb_spinBox->setValue(settings.value("embedding_resultnumb", DEFAULT_EMBEDDING_RESULTNUMB).toInt());
ui->embedding_overlap_spinbox->setValue(settings.value("embedding_overlap", DEFAULT_EMBEDDING_OVERLAP).toInt());
ui->embedding_dim_spinBox->setValue(settings.value("embedding_dim", 1024).toInt());
QString embedding_sourcetxt = settings.value("embedding_sourcetxt", "").toString(); //源文档路径
QFile embedding_sourcetxt_file(embedding_sourcetxt);
if (embedding_sourcetxt_file.exists()) {
txtpath = embedding_sourcetxt;
ui->embedding_txt_lineEdit->setText(txtpath);
preprocessTXT(); //预处理文件内容
}
}
void Expend::showReadme() {
QString readme_content;
QFile file;
QString imagefile = ":/logo/ui_demo.png"; // 图片路径固定
// 根据语言标志选择不同的 README 文件
if (language_flag == 0) {
file.setFileName(":/README.md");
} else if (language_flag == 1) {
file.setFileName(":/README_en.md");
}
// 打开文件并读取内容
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
in.setCodec("UTF-8");
readme_content = in.readAll();
file.close();
}
// 使用正则表达式删除指定的 HTML 内容
QRegularExpression imgRegex("<img src=\"https://github.com/ylsdamxssjxxdd/eva/assets/[^>]+>");
readme_content.remove(imgRegex);
// 删除 <summary> 和 </summary> 标签
readme_content.remove(QRegularExpression("<summary>|</summary>"));
// 删除 <details> 和 </details> 标签
readme_content.remove("<details>");
readme_content.remove("</details>");
// 添加编译信息
QString compileInfo = QString("%1: %2\n\n %3: %4\n\n %5: %6\n\n %7: %8\n\n %9: %10\n\n")
.arg(jtr("EVA_ENVIRONMENT"), QString(EVA_ENVIRONMENT))
.arg(jtr("EVA_PRODUCT_TIME"), QString(EVA_PRODUCT_TIME))
.arg(jtr("QT_VERSION_"), QString(QT_VERSION_))
.arg(jtr("COMPILE_VERSION"), QString(COMPILE_VERSION))
.arg(jtr("EVA_VERSION"), QString(EVA_VERSION));
readme_content.prepend(compileInfo); // 将编译信息放在文件内容前
// 设置 Markdown 内容
ui->info_card->setMarkdown(readme_content);
// 加载并缩放图片
QImage image(imagefile);
int originalWidth = image.width() / devicePixelRatioF() / 1.5;
int originalHeight = image.height() / devicePixelRatioF() / 1.5;
// 插入图片到 QTextEdit
QTextCursor cursor(ui->info_card->textCursor());
cursor.movePosition(QTextCursor::Start);
QTextImageFormat imageFormat;
imageFormat.setWidth(originalWidth);
imageFormat.setHeight(originalHeight);
imageFormat.setName(imagefile);
cursor.insertImage(imageFormat);
cursor.insertText("\n\n");
}
//事件过滤器,鼠标跟踪效果不好要在各种控件单独实现
bool Expend::eventFilter(QObject *obj, QEvent *event) {
//响应已安装控件上的鼠标右击事件
if (obj == ui->sd_prompt_textEdit && event->type() == QEvent::ContextMenu) {
// 自动填充提示词
ui->sd_prompt_textEdit->setText("full body, Ayanami Rei, beautiful face, Blue hair, 1 girl");
return true;
} else if (obj == ui->sd_negative_lineEdit && event->type() == QEvent::ContextMenu) {
//还原负面词
ui->sd_negative_lineEdit->setText(sd_params_templates[ui->params_template_comboBox->currentText()].negative_prompt);
return true;
} else if (obj == ui->sd_modify_lineEdit && event->type() == QEvent::ContextMenu) {
//还原修饰词
ui->sd_modify_lineEdit->setText(sd_params_templates[ui->params_template_comboBox->currentText()].modify_prompt);
} else if (obj == ui->sd_img2img_lineEdit && event->type() == QEvent::ContextMenu) {
//选择图像
currentpath = customOpenfile(currentpath, "choose an imgage", "(*.png *.jpg *.bmp)");
if (currentpath != "") {
ui->sd_img2img_pushButton->setEnabled(1);
ui->sd_img2img_lineEdit->setText(currentpath);
} else {
ui->sd_img2img_pushButton->setEnabled(0);
}
return true;
}
return QObject::eventFilter(obj, event);
}
//关闭事件
void Expend::closeEvent(QCloseEvent *event) {
//--------------保存当前用户配置---------------
sd_save_template(ui->params_template_comboBox->currentText());
// 创建 QSettings 对象,指定配置文件的名称和格式
createTempDirectory(applicationDirPath + "/EVA_TEMP");
QSettings settings(applicationDirPath + "/EVA_TEMP/eva_config.ini", QSettings::IniFormat);
settings.setIniCodec("utf-8");
settings.setValue("sd_params_template", ui->params_template_comboBox->currentText());
settings.setValue("sd_modelpath", ui->sd_modelpath_lineEdit->text());
settings.setValue("vae_modelpath", ui->sd_vaepath_lineEdit->text());
settings.setValue("clip_l_modelpath", ui->sd_clip_l_path_lineEdit->text());
settings.setValue("clip_g_modelpath", ui->sd_clip_g_path_lineEdit->text());
settings.setValue("t5_modelpath", ui->sd_t5path_lineEdit->text());
settings.setValue("lora_modelpath", ui->sd_lorapath_lineEdit->text());
settings.setValue("sd_prompt", ui->sd_prompt_textEdit->toPlainText());
settings.setValue("sd_params_template", ui->params_template_comboBox->currentText());
settings.setValue("sd_custom1_negative", sd_params_templates["custom1"].negative_prompt);
settings.setValue("sd_custom1_modify", sd_params_templates["custom1"].modify_prompt);
settings.setValue("sd_custom1_image_width", sd_params_templates["custom1"].width);
settings.setValue("sd_custom1_image_height", sd_params_templates["custom1"].height);
settings.setValue("sd_custom1_sample_type", sd_params_templates["custom1"].sample_type);
settings.setValue("sd_custom1_sample_steps", sd_params_templates["custom1"].steps);
settings.setValue("sd_custom1_cfg", sd_params_templates["custom1"].cfg_scale);
settings.setValue("sd_custom1_seed", sd_params_templates["custom1"].seed);
settings.setValue("sd_custom1_image_nums", sd_params_templates["custom1"].batch_count);
settings.setValue("sd_custom1_clip_skip", sd_params_templates["custom1"].clip_skip);
settings.setValue("sd_custom2_negative", sd_params_templates["custom2"].negative_prompt);
settings.setValue("sd_custom2_modify", sd_params_templates["custom2"].modify_prompt);
settings.setValue("sd_custom2_image_width", sd_params_templates["custom2"].width);
settings.setValue("sd_custom2_image_height", sd_params_templates["custom2"].height);
settings.setValue("sd_custom2_sample_type", sd_params_templates["custom2"].sample_type);
settings.setValue("sd_custom2_sample_steps", sd_params_templates["custom2"].steps);
settings.setValue("sd_custom2_cfg", sd_params_templates["custom2"].cfg_scale);
settings.setValue("sd_custom2_seed", sd_params_templates["custom2"].seed);
settings.setValue("sd_custom2_image_nums", sd_params_templates["custom2"].batch_count);
settings.setValue("sd_custom2_clip_skip", sd_params_templates["custom2"].clip_skip);
settings.setValue("whisper_modelpath", ui->whisper_load_modelpath_linedit->text());
settings.setValue("speech_enable", ui->speech_enable_radioButton->isChecked());
settings.setValue("speech_name", ui->speech_source_comboBox->currentText());
settings.setValue("outetts_modelpath", ui->speech_outetts_modelpath_lineEdit->text());
settings.setValue("wavtokenizer_modelpath", ui->speech_wavtokenizer_modelpath_lineEdit->text());
settings.setValue("embedding_modelpath", embedding_params.modelpath);
settings.setValue("embedding_dim", ui->embedding_dim_spinBox->text());
settings.setValue("embedding_server_need", embedding_server_need);
settings.setValue("embedding_split", ui->embedding_split_spinbox->value());
settings.setValue("embedding_resultnumb", embedding_resultnumb);
settings.setValue("embedding_overlap", ui->embedding_overlap_spinbox->value());
settings.setValue("embedding_sourcetxt", ui->embedding_txt_lineEdit->text());
settings.setValue("embedding_describe", ui->embedding_txt_describe_lineEdit->text());
settings.setValue("shell", shell); //shell路径
settings.setValue("python", python); //python版本
// event->accept();
}
//-------------------------------------------------------------------------
//----------------------------------声转文相关--------------------------------
//-------------------------------------------------------------------------
//用户点击选择whisper路径时响应
void Expend::on_whisper_load_modelpath_button_clicked() {
currentpath = customOpenfile(currentpath, "choose whisper model", "(*.bin *.gguf)");
whisper_params.model = currentpath.toStdString();
ui->whisper_load_modelpath_linedit->setText(currentpath);
emit expend2ui_whisper_modelpath(currentpath);
ui->whisper_log->setPlainText(jtr("once selected, you can record by pressing f2"));
}
//开始语音转文字
void Expend::recv_speechdecode(QString wavpath, QString out_format) {
whisper_time.restart();
#ifdef BODY_LINUX_PACK
QString appDirPath = qgetenv("APPDIR");
QString localPath = QString(appDirPath + "/usr/bin/whisper-cli") + SFX_NAME;
#else
QString localPath = QString("./whisper-cli") + SFX_NAME;
#endif
//将wav文件重采样为16khz音频文件
#ifdef _WIN32
QTextCodec *code = QTextCodec::codecForName("GB2312"); // mingw中文路径支持
std::string wav_path_c = code->fromUnicode(wavpath).data();
#elif __linux__
std::string wav_path_c = wavpath.toStdString();
#endif
resampleWav(wav_path_c, wav_path_c);
// 设置要运行的exe文件的路径
QString program = localPath;
// 如果你的程序需要命令行参数,你可以将它们放在一个QStringList中
QStringList arguments;
arguments << "-m" << QString::fromStdString(whisper_params.model); //模型路径
arguments << "-f" << wavpath; // wav文件路径
arguments << "--language" << QString::fromStdString(whisper_params.language); //识别语种
arguments << "--threads" << QString::number(max_thread * 0.5);
if (out_format == "txt") {
arguments << "--output-txt";
} //结果输出为一个txt
else if (out_format == "srt") {
arguments << "--output-srt";
} else if (out_format == "csv") {
arguments << "--output-csv";
} else if (out_format == "json") {
arguments << "--output-json";
}
// 开始运行程序
//连接信号和槽,获取程序的输出
connect(whisper_process, &QProcess::readyReadStandardOutput, [=]() {
QString output = whisper_process->readAllStandardOutput();
ui->whisper_log->appendPlainText(output);
});
connect(whisper_process, &QProcess::readyReadStandardError, [=]() {
QString output = whisper_process->readAllStandardError();
ui->whisper_log->appendPlainText(output);
});
createTempDirectory(applicationDirPath + "/EVA_TEMP");
whisper_process->start(program, arguments);
}
void Expend::whisper_onProcessStarted() {
if (!is_handle_whisper) {
emit expend2ui_state("expend:" + jtr("calling whisper to decode recording"), USUAL_SIGNAL);
}
}
void Expend::whisper_onProcessFinished() {
if (!is_handle_whisper) {
QString content;
// 文件路径
QString filePath = applicationDirPath + "/EVA_TEMP/" + QString("EVA_") + ".wav.txt";
// 创建 QFile 对象
QFile file(filePath);
// 打开文件
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file); // 创建 QTextStream 对象
in.setCodec("UTF-8");
content = in.readAll(); // 读取文件内容
}
file.close();
emit expend2ui_state("expend:" + jtr("decode over") + " " + QString::number(whisper_time.nsecsElapsed() / 1000000000.0, 'f', 2) + "s ->" + content, SUCCESS_SIGNAL);
emit expend2ui_speechdecode_over(content);
} else {
ui->whisper_log->appendPlainText(jtr("the result has been saved in the source wav file directory") + " " + QString::number(whisper_time.nsecsElapsed() / 1000000000.0, 'f', 2) + "s");
}
is_handle_whisper = false;
}
//用户点击选择wav路径时响应
void Expend::on_whisper_wavpath_pushButton_clicked() {
currentpath = customOpenfile(currentpath, "choose a .wav file", "(*.wav)");
wavpath = currentpath;
if (wavpath == "") {
return;
}
ui->whisper_wavpath_lineedit->setText(wavpath);
}
//用户点击执行转换时响应
void Expend::on_whisper_execute_pushbutton_clicked() {
//执行whisper
is_handle_whisper = true;
whisper_process->kill();
recv_speechdecode(ui->whisper_wavpath_lineedit->text(), ui->whisper_output_format->currentText());
}
//-------------------------------------------------------------------------
//----------------------------------知识库相关--------------------------------
//-------------------------------------------------------------------------
//用户点击选择嵌入模型路径时响应
void Expend::on_embedding_txt_modelpath_button_clicked() {
server_process->kill(); // 终止server
Embedding_DB.clear(); // 清空向量数据库
ui->embedding_txt_over->clear(); //清空已嵌入文本段表格内容
ui->embedding_txt_over->setRowCount(0); //设置已嵌入文本段表格为0行
ui->embedding_txt_over->setHorizontalHeaderLabels(QStringList{jtr("embeded text segment")}); //设置列名
// 清空表格
currentpath = customOpenfile(currentpath, jtr("select embedding model"), "(*.bin *.gguf)");
embedding_params.modelpath = currentpath;
if (embedding_params.modelpath == "") {
ui->embedding_model_lineedit->setText("");//清空启动的服务
return;
}
// 100 ms后尝试启动服务, 因为要等待server_process->kill()
QTimer::singleShot(100, this, &Expend::embedding_server_start);
}
// 尝试启动server
void Expend::embedding_server_start() {
#ifdef BODY_LINUX_PACK
QString appDirPath = qgetenv("APPDIR");
QString localPath = QString(appDirPath + "/usr/bin/llama-server") + SFX_NAME;
QString program = localPath; // 设置要运行的exe文件的路径
#else
QString localPath = QString("./llama-server") + SFX_NAME;
QString program = localPath; // 设置要运行的exe文件的路径
#endif
// 如果你的程序需要命令行参数,你可以将它们放在一个QStringList中
QStringList arguments;
arguments << "-m" << embedding_params.modelpath;
arguments << "--host"
<< "0.0.0.0"; //暴露本机ip
arguments << "--port" << DEFAULT_EMBEDDING_PORT; //服务端口
arguments << "--threads" << QString::number(max_thread * 0.5); //使用线程
arguments << "-cb"; //允许连续批处理
arguments << "--embedding"; //允许词嵌入
// arguments << "--log-disable"; //不要日志
if(!DEFAULT_USE_MMAP){arguments << "--no-mmap";}
// 开始运行程序
server_process->start(program, arguments);
}
// 获取server_process日志输出
void Expend::readyRead_server_process_StandardOutput()
{
QString server_output = server_process->readAllStandardOutput();
// qDebug()<<"std "<<server_output;
}
// 获取server_process日志输出
void Expend::readyRead_server_process_StandardError() {
QString server_output = server_process->readAllStandardError();
// qDebug()<<"error "<<server_output;
//启动成功的标志
QString log_output;
if (server_output.contains(SERVER_START)) {
keep_embedding_server = true;
ui->embedding_model_lineedit->setText(embedding_params.modelpath);
keep_embedding_server = false;
ui->embedding_txt_modelpath_button->setText(jtr("abort server"));
qDebug()<<"嵌入服务启动成功"<<embedding_server_api;
log_output += jtr("embedding") + jtr("service startup completed") + "\n";
log_output += jtr("embd api") + ": " + embedding_server_api;
log_output += "\n" + jtr("embd dim") + ": " + QString::number(embedding_server_dim);
}
if (log_output != "") {
ui->embedding_test_log->appendPlainText(log_output);
}
if (server_output.contains(SERVER_EMBD_INFO)) {
embedding_server_dim = server_output.split(SERVER_EMBD_INFO).at(1).split("\n").at(0).toInt();
ui->embedding_dim_spinBox->setValue(embedding_server_dim);
qDebug()<<"该模型的嵌入维度为: "<<embedding_server_dim<<ui->embedding_dim_spinBox->value();
if (embedding_embed_need) //用来自动构建知识库
{
embedding_embed_need = false;
QTimer::singleShot(1000, this, SLOT(embedding_processing())); //1s后再执行构建以免冲突
}
}
}
//进程开始响应
void Expend::server_onProcessStarted() {}
//进程结束响应
void Expend::server_onProcessFinished()
{
ui->embedding_test_log->appendPlainText(jtr("embedding server abort"));
ui->embedding_txt_modelpath_button->setText("...");
qDebug()<<"嵌入服务终止";
}
//用户点击上传路径时响应
void Expend::on_embedding_txt_upload_clicked() {
currentpath = customOpenfile(currentpath, jtr("choose a txt to embed"), "(*.txt)");
txtpath = currentpath;
ui->embedding_txt_lineEdit->setText(txtpath);
preprocessTXT(); //预处理文件内容
}
// 分词函数
QStringList Expend::tokenizeContent(const QString& content)
{
QStringList tokens;
// 正则表达式匹配中文、英文单词、Emoji及其他字符
QRegularExpression re(
"(\\p{Han}+)" // 中文字符
"|([A-Za-z]+)" // 英文单词
"|([\\x{1F300}-\\x{1F5FF}])" // Emoji 范围1
"|([\\x{1F600}-\\x{1F64F}])" // Emoji 范围2
"|([\\x{1F680}-\\x{1F6FF}])" // Emoji 范围3
"|([\\x{2600}-\\x{26FF}])" // 其他符号
"|(\\s+)" // 空白字符
"|(.)", // 其他任意单字符
QRegularExpression::UseUnicodePropertiesOption
);
QRegularExpressionMatchIterator it = re.globalMatch(content);
while (it.hasNext()) {
QRegularExpressionMatch match = it.next();
if (match.hasMatch()) {
QString token;
if (match.captured(1).length() > 0)
token = match.captured(1); // 中文
else if (match.captured(2).length() > 0)
token = match.captured(2); // 英文单词
else if (match.captured(3).length() > 0 ||
match.captured(4).length() > 0 ||
match.captured(5).length() > 0 ||
match.captured(6).length() > 0)
token = match.captured(); // Emoji
else if (match.captured(7).length() > 0)
token = match.captured(7); // 空白
else
token = match.captured(8); // 其他字符
tokens << token;
}
}
return tokens;
}
//预处理文件内容
void Expend::preprocessTXT() {
// 读取文件内容
QString content;
QFile file(txtpath);
// 打开文件
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file); // 创建 QTextStream 对象
in.setCodec("UTF-8");
content = in.readAll(); // 读取文件内容
}
file.close();
// -------------------分词-----------------
QStringList tokens = tokenizeContent(content);
// -------------------分段-----------------
QStringList paragraphs;
int splitLength = ui->embedding_split_spinbox->value();
int overlap = ui->embedding_overlap_spinbox->value();
int splitNums = 0;
int startTokenIndex = 0;