-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreport_engine.py
More file actions
1226 lines (1075 loc) · 55.3 KB
/
Copy pathreport_engine.py
File metadata and controls
1226 lines (1075 loc) · 55.3 KB
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
"""
报告生成引擎 - 支持多级标题、字数达标、输出目录选择
基于学习到的模板生成符合学校要求的Word文档
"""
import os
import re
import json
import random
from datetime import datetime
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn
# 尝试导入doc_parser和llm_client
try:
from doc_parser import DocParser, TemplateLearner
except ImportError:
DocParser = None
TemplateLearner = None
try:
from llm_client import LLMClient, LLMContentGenerator
except ImportError:
LLMClient = None
LLMContentGenerator = None
class ContentGenerator:
"""智能内容生成器 - 根据标题语义动态生成内容"""
def __init__(self, topic, target_words=5000):
self.topic = topic
self.target_words = target_words
self.current_words = 0
# 分析标题语义
self.topic_type = self._analyze_topic(topic)
def _analyze_topic(self, topic):
"""分析标题语义,确定内容方向"""
topic_lower = topic.lower()
# 检测标题类型
if any(kw in topic for kw in ['深度学习', '神经网络', 'CNN', 'RNN', '图像识别', '模型训练']):
return {'type': 'ai_ml', 'domain': '人工智能/机器学习', 'has_experiment': True}
elif any(kw in topic for kw in ['数据库', 'SQL', 'MySQL', '数据查询', '数据管理']):
return {'type': 'database', 'domain': '数据库技术', 'has_experiment': True}
elif any(kw in topic for kw in ['Web', '网页', '网站', '前端', '后端', 'HTTP', 'Flask', 'Django']):
return {'type': 'web', 'domain': 'Web开发', 'has_experiment': True}
elif any(kw in topic for kw in ['数据分析', '数据预处理', '可视化', 'pandas', 'matplotlib']):
return {'type': 'data_analysis', 'domain': '数据分析', 'has_experiment': True}
elif any(kw in topic for kw in ['NLP', '自然语言', '情感分类', '文本', '对话', 'LangChain', 'Hugging Face']):
return {'type': 'nlp', 'domain': '自然语言处理', 'has_experiment': True}
elif any(kw in topic for kw in ['PyTorch', 'TensorFlow', 'Keras', '框架', '训练']):
return {'type': 'framework', 'domain': '深度学习框架', 'has_experiment': True}
elif any(kw in topic for kw in ['论', '研究', '分析', '探讨', '必要性', '意义', '价值']):
return {'type': 'essay', 'domain': '论述分析', 'has_experiment': False}
elif any(kw in topic for kw in ['设计', '实现', '开发', '构建', '搭建', '平台']):
return {'type': 'project', 'domain': '项目开发', 'has_experiment': True}
else:
return {'type': 'general', 'domain': '综合实践', 'has_experiment': True}
def generate_paragraph(self, theme, min_sentences=3, max_sentences=8):
"""根据标题语义生成段落"""
t = self.topic_type
paragraphs_pool = {
'ai_ml': [
f"在{theme}方面,深度学习技术展现出了强大的特征提取与模式识别能力,通过多层神经网络结构自动学习数据的高层抽象表示。",
f"针对{theme},采用了端到端的学习范式,将原始数据输入模型后,通过网络前向传播与反向传播不断优化参数,逐步逼近最优解。",
f"{theme}的实现依托于GPU并行计算能力,显著加速了大规模矩阵运算与梯度下降过程,使模型训练效率得到质的提升。",
f"通过引入正则化、Dropout、批归一化等技术手段,有效缓解了{theme}过程中的过拟合问题,提升了模型的泛化能力。",
f"在{theme}的实验中,采用交叉验证与网格搜索策略进行超参数调优,确保模型在不同数据分布下均能保持稳定的表现。",
],
'database': [
f"在{theme}方面,关系型数据库提供了结构化数据存储与高效查询的核心能力,通过SQL语句实现复杂的数据操作。",
f"针对{theme},设计了规范化的数据库表结构,遵循第三范式要求,消除数据冗余,保证数据一致性。",
f"{theme}的实现涉及事务管理、索引优化、查询计划分析等关键技术,通过合理配置提升数据库整体性能。",
f"通过建立适当的索引策略,{theme}的查询效率得到了显著提升,特别是在大数据量场景下表现尤为突出。",
],
'nlp': [
f"在{theme}方面,自然语言处理技术通过对文本数据进行分词、编码、向量化等预处理操作,将人类语言转化为模型可处理的数值表示。",
f"针对{theme},采用了预训练语言模型作为基础,通过微调适配特定任务场景,大幅降低了对标注数据的需求。",
f"{theme}的实现融合了注意力机制与上下文感知能力,使模型能够准确捕捉文本中的长距离依赖关系与语义信息。",
f"通过构建高质量的提示词模板,{theme}的输出质量得到了有效控制,模型生成的文本更加符合预期格式与内容要求。",
],
'essay': [
f"关于{theme},这是一个值得深入探讨的课题。从理论层面来看,{self.topic}涉及多个核心维度的考量。",
f"从实践角度分析,{theme}的意义不仅体现在学术研究层面,更对实际应用产生了深远影响。",
f"深入思考{theme},可以发现其背后蕴含着丰富的理论价值与现实意义,值得我们从多角度进行剖析。",
f"综合来看,{theme}的必要性体现在以下几个方面:一是理论层面的支撑作用,二是实践层面的指导意义,三是发展层面的推动力量。",
],
'project': [
f"在{theme}方面,采用了模块化的系统设计思路,将整体功能拆分为多个独立组件,降低了系统复杂度。",
f"针对{theme},遵循软件工程规范,从需求分析、概要设计、详细设计到编码实现,形成了完整的开发流程。",
f"{theme}的实现过程中,注重代码质量与可维护性,采用面向对象设计原则,确保系统的可扩展性。",
f"通过持续的集成测试与系统测试,{theme}的各个功能模块均达到了预期设计目标,系统运行稳定可靠。",
],
'general': [
f"在{theme}方面,本次实践采用了系统化的方法论,从理论分析到实践验证,形成了完整的研究闭环。",
f"针对{theme},综合运用了课堂所学知识与课外拓展资料,确保内容的准确性与深度。",
f"{theme}的实现过程注重理论与实践的结合,通过具体案例验证了相关原理的正确性与适用性。",
f"在{theme}的实践过程中,积累了丰富的经验教训,为后续更深入的研究奠定了基础。",
],
'web': [
f"在{theme}方面,采用了前后端分离的架构设计,前端负责用户交互与数据展示,后端处理业务逻辑与数据存储。",
f"针对{theme},运用了响应式设计原则,确保系统在不同终端设备上均能提供良好的用户体验。",
f"{theme}的实现涉及HTTP协议、RESTful API设计、会话管理等Web开发核心技术。",
],
'data_analysis': [
f"在{theme}方面,数据预处理是整个分析流程的基础环节,包括缺失值处理、异常值检测、特征工程等关键步骤。",
f"针对{theme},采用了多种可视化手段直观呈现数据分布规律与分析结果,辅助决策判断。",
f"{theme}的实现依托Python数据科学生态,运用pandas进行数据操作,matplotlib和seaborn进行图表绘制。",
],
'framework': [
f"在{theme}方面,深度学习框架提供了高层次的API抽象,大幅简化了模型构建与训练的代码复杂度。",
f"针对{theme},充分利用了框架内置的自动微分、模型并行、混合精度训练等高级特性。",
f"{theme}的实现过程中,深入理解了计算图、动态图与静态图的区别,掌握了模型部署与推理优化的基本方法。",
]
}
# 根据类型选择内容池
pool = paragraphs_pool.get(t['type'], paragraphs_pool['general'])
# 通用补充段落
general_pool = [
f"{theme}的完成需要扎实的理论基础与丰富的实践经验相结合,两者缺一不可。",
f"在实施{theme}的过程中,注重细节把控与质量验证,确保最终成果的可靠性与有效性。",
f"通过本次{theme}的实践,对相关领域有了更加全面深入的认识,为今后的学习与工作打下了坚实基础。",
]
all_pool = pool + general_pool
num = random.randint(min_sentences, max_sentences)
selected = random.sample(all_pool, min(num, len(all_pool)))
content = ''.join(selected)
self.current_words += len(content)
return content
def generate_detailed_content(self, section_name, sub_section=None):
"""根据章节类型和标题语义生成内容"""
t = self.topic_type
paragraphs = []
if '目的' in section_name:
paragraphs = self._generate_purpose_content()
elif '环境' in section_name or '基本信息' in section_name:
paragraphs = self._generate_env_content(sub_section)
elif '内容' in section_name or '步骤' in section_name:
paragraphs = self._generate_content_steps(sub_section)
elif '结果' in section_name or '分析' in section_name:
paragraphs = self._generate_results_content(sub_section)
elif '总结' in section_name or '体会' in section_name:
paragraphs = self._generate_summary_content()
elif '原理' in section_name:
paragraphs = self._generate_theory_content(sub_section)
else:
paragraphs = [self.generate_paragraph(section_name, 5, 8)]
return paragraphs
def _generate_purpose_content(self):
"""根据标题类型生成实验目的"""
t = self.topic_type
domain = t['domain']
if t['type'] == 'essay':
return [
f"1. 深入分析{self.topic}的理论基础与现实背景,建立完整的认知框架。",
f"2. 从多角度探讨{self.topic}的必要性,包括理论支撑、实践需求、发展趋势等方面。",
f"3. 结合具体案例与数据,论证{self.topic}的核心观点与价值主张。",
f"4. 培养独立思考与批判性分析能力,形成对{self.topic}的系统性认识。",
f"5. 提升学术写作与逻辑表达能力,能够清晰准确地阐述研究观点。",
]
return [
f"1. 深入理解{domain}领域内{self.topic}的核心概念、基本原理与技术架构,建立完整的知识体系。",
f"2. 熟练掌握{self.topic}相关的开发工具、编程语言与框架库的使用方法,具备独立开展实践的能力。",
f"3. 通过{self.topic}的实际操作,加深对课堂理论知识的理解与应用能力,实现知行合一。",
f"4. 培养{domain}领域的工程实践能力,包括需求分析、方案设计、功能实现、测试验证等完整流程。",
f"5. 了解{self.topic}在实际工程项目中的应用场景与最佳实践,拓展技术视野。",
f"6. 培养规范化的实验记录习惯与严谨的科学研究态度,提升综合素养。",
]
def _generate_env_content(self, sub_section):
"""根据标题类型生成环境内容"""
t = self.topic_type
if t['type'] == 'essay':
return [
"本次研究主要依托以下资源与条件开展:",
"文献资源:通过图书馆数据库、学术搜索引擎(如中国知网、Google Scholar)获取相关领域的学术论文、专著与研究报告。",
"数据来源:收集整理了相关的统计数据、调查报告、案例分析等一手与二手资料。",
"分析工具:运用逻辑分析、比较研究、案例分析法等多种研究方法,确保论证的严谨性与全面性。",
]
if t['type'] == 'ai_ml' or t['type'] == 'nlp' or t['type'] == 'framework':
return [
"硬件环境:个人计算机,配备NVIDIA GPU(如RTX 3060及以上),支持CUDA并行计算,加速模型训练过程。",
"操作系统:Windows 10/11 或 Ubuntu 20.04 LTS,提供稳定的开发与运行环境。",
"编程语言:Python 3.8及以上版本,拥有丰富的深度学习与数据科学第三方库生态。",
"核心框架:PyTorch / TensorFlow / Keras 等主流深度学习框架,提供高效的模型构建与训练工具。",
"开发工具:Visual Studio Code / PyCharm / Jupyter Notebook,支持代码编写、调试与交互式分析。",
"辅助库:numpy(数值计算)、pandas(数据处理)、matplotlib(可视化)、scikit-learn(预处理)等。",
]
if t['type'] == 'database':
return [
"硬件环境:个人计算机,满足数据库服务运行的基本硬件需求。",
"操作系统:Windows 10/11,支持MySQL/PostgreSQL等主流数据库系统。",
"数据库管理系统:MySQL 8.0 / PostgreSQL 14,提供稳定可靠的数据存储与查询服务。",
"开发工具:Navicat / DBeaver / MySQL Workbench,用于数据库设计、管理与查询操作。",
"编程语言:Python 3.8+,通过pymysql/psycopg2等驱动实现程序与数据库的交互。",
]
if t['type'] == 'web':
return [
"硬件环境:个人计算机,满足Web应用开发与测试的基本需求。",
"操作系统:Windows 10/11,支持主流Web服务器与浏览器环境。",
"后端技术:Python + Flask/Django,提供RESTful API与服务器端逻辑处理能力。",
"前端技术:HTML5 + CSS3 + JavaScript,实现响应式用户界面设计与交互功能。",
"开发工具:VS Code,配合Live Server、Postman等插件提升开发效率。",
]
return [
"硬件环境:个人计算机,配置满足实验基本需求。",
"操作系统:Windows 10/11,提供稳定的开发与运行环境。",
"编程语言:Python 3.8及以上版本,拥有丰富的第三方库生态与活跃的社区支持。",
"开发工具:Visual Studio Code 或 PyCharm,提供智能代码补全、调试、版本控制等功能。",
"核心依赖库:根据实验需求安装相应的Python第三方库,确保功能完整实现。",
]
def _generate_content_steps(self, sub_section):
"""根据标题类型生成实验步骤"""
t = self.topic_type
if t['type'] == 'essay':
return [
f"第一步:文献综述与资料收集。通过学术数据库检索{self.topic}相关的核心文献,梳理研究现状与理论脉络。",
f"第二步:问题定义与分析框架构建。明确{self.topic}的核心研究问题,建立多维度的分析框架。",
f"第三步:论点论证与案例分析。围绕{self.topic}的核心观点,运用理论推演与实证分析相结合的方式进行论证。",
f"第四步:数据整理与图表制作。将分析过程中涉及的统计数据、对比结果以清晰的图表形式呈现。",
f"第五步:总结归纳与报告撰写。整合所有分析内容,形成逻辑清晰、论证充分的完整报告。",
]
return [
f"步骤一:{self.topic}相关理论知识学习与资料收集。通过阅读教材、查阅官方文档、参考优秀开源项目,全面了解涉及的核心概念与技术要点。",
f"步骤二:实验环境搭建与工具配置。安装必要的软件、配置开发环境、导入依赖库,确保实验能够顺利进行。",
f"步骤三:核心功能模块设计与开发。根据实验要求,分模块进行代码编写,实现{self.topic}的核心功能。",
f"步骤四:功能测试与调试优化。对开发的代码进行全面的功能测试,发现并修复潜在问题,优化代码性能与可读性。",
f"步骤五:实验结果记录与数据分析。详细记录实验过程中的关键数据与现象,对结果进行深入分析,验证实验假设。",
f"步骤六:实验报告撰写与总结反思。整理实验资料,撰写规范的实验报告,总结实验收获与不足之处。",
]
def _generate_results_content(self, sub_section):
"""根据标题类型生成实验结果"""
t = self.topic_type
if t['type'] == 'essay':
return [
self.generate_paragraph("研究结论", 4, 6),
f"综合以上分析,{self.topic}的必要性得到了充分论证。从理论层面、实践层面和发展层面三个维度来看,其价值与意义均不可忽视。",
"研究结果与预期基本一致,论证逻辑清晰,数据支撑充分,达到了本次研究的预期目标。",
]
return [
self.generate_paragraph("实验结果分析", 5, 8),
"通过本次实验,成功实现了预期的功能目标,各项技术指标均达到或超过预期要求。",
"实验过程中收集的数据与预期结果基本吻合,验证了方案的可行性与有效性。",
"针对实验中出现的问题,通过分析原因、调整参数、优化算法,最终都得到了有效解决。",
]
def _generate_summary_content(self):
"""根据标题类型生成总结"""
t = self.topic_type
if t['type'] == 'essay':
return [
self.generate_paragraph("总结反思", 5, 8),
f"通过对{self.topic}的深入研究与分析,我对该课题有了更加全面和深刻的认识。",
"本次研究不仅巩固了相关理论知识,更锻炼了独立思考、文献检索、逻辑分析等综合能力。",
"在研究过程中也发现了一些值得进一步探讨的问题,这些问题将成为未来深入研究的方向。",
]
return [
self.generate_paragraph("实验总结", 6, 10),
f"通过本次{self.topic}的实验实践,不仅掌握了相关技术的基本使用方法,更重要的是培养了独立解决问题的能力。",
"实验过程中遇到的困难与挑战,都是宝贵的学习机会,通过不断尝试与探索,最终都找到了解决方案。",
"在今后的学习中,将继续保持这种积极探索的态度,不断提升自己的专业能力与综合素质。",
]
def _generate_theory_content(self, sub_section):
"""根据标题类型生成原理内容"""
t = self.topic_type
if t['type'] == 'essay':
return [
self.generate_paragraph("理论基础", 4, 6),
f"{self.topic}的理论基础涉及多个学科领域的知识交叉,需要从多角度进行理解与把握。",
"相关理论框架为本次研究提供了坚实的学术支撑,确保了论证过程的科学性与严谨性。",
]
return [
self.generate_paragraph("实验原理", 5, 8),
f"{self.topic}涉及的核心原理需要从理论层面进行深入理解,这是正确实施实验的前提条件。",
"理解这些原理对于正确实施实验、分析实验结果、优化实验方案具有重要意义。",
]
class ReportEngine:
"""报告生成引擎 - 新流程:Word解析→题目→RAG→模板→AI填充→检查→输出"""
def __init__(self, reports_dir=None, output_dir=None, llm_api_key=None):
self.reports_dir = reports_dir
self.output_dir = output_dir or os.path.join(os.path.expanduser('~'), 'Documents', 'Reports')
self.parser = DocParser() if DocParser else None
self.template_info = None
self.target_word_count = 5000
self.exp_count = 1
self.imported_word_content = "" # 导入的Word内容(作为需求)
# 初始化LLM客户端
self.llm_client = None
self.llm_generator = None
if LLMClient and llm_api_key:
self.llm_client = LLMClient(api_key=llm_api_key)
if self.llm_client.is_available():
self.llm_generator = LLMContentGenerator(self.llm_client)
# 学习模板
if reports_dir and self.parser:
self.parser.learn_templates(reports_dir)
self.template_info = self.parser.get_template_info()
if self.template_info:
self.target_word_count = self.parser.get_avg_word_count()
self.exp_count = self.parser.get_avg_exp_count()
def set_llm_api_key(self, api_key):
"""设置LLM API密钥"""
if LLMClient and api_key:
self.llm_client = LLMClient(api_key=api_key)
if self.llm_client.is_available():
self.llm_generator = LLMContentGenerator(self.llm_client)
return True
return False
def is_llm_available(self):
"""检查LLM是否可用"""
return self.llm_client is not None and self.llm_client.is_available()
def set_word_content(self, content):
"""设置导入的Word内容(作为需求输入)"""
self.imported_word_content = content
def set_target_word_count(self, count):
"""设置目标字数"""
self.target_word_count = max(1000, int(count))
def set_output_dir(self, output_dir):
"""设置输出目录"""
self.output_dir = output_dir
os.makedirs(self.output_dir, exist_ok=True)
def add_to_rag_library(self, file_path):
"""将Word文件添加到RAG知识库"""
import shutil
# RAG库目录
rag_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'rag_library')
os.makedirs(rag_dir, exist_ok=True)
# 复制文件到RAG库
filename = os.path.basename(file_path)
# 添加时间戳避免重名
name, ext = os.path.splitext(filename)
timestamp = time.strftime("%Y%m%d_%H%M%S")
dest_filename = f"{name}_{timestamp}{ext}"
dest_path = os.path.join(rag_dir, dest_filename)
shutil.copy2(file_path, dest_path)
# 重新学习模板
if self.parser:
self.parser.learn_templates(rag_dir)
self.template_info = self.parser.get_template_info()
return dest_path
def generate_simple(self, title, template_info=None, imported_content="", complex_data=None):
"""简易模式生成报告"""
# 构建报告数据结构
report_data = self._build_report_data(title, imported_content, complex_data)
# 生成Word文件
output_path = self._create_word_document(report_data)
# 生成预览文本
preview_text = self._generate_preview(report_data)
return {
'success': True,
'data': report_data,
'file_path': output_path,
'preview_text': preview_text,
'word_count': report_data.get('total_words', 0),
'message': f'报告生成成功!共 {report_data.get("total_words", 0)} 字'
}
def generate_complex(self, title, template_info=None):
"""复杂模式生成报告"""
results = {
'title': title,
'chain_of_thought': [],
'rag_results': [],
'samples': [],
'scores': [],
'optimized': None,
'final_data': None
}
# 1. 思维链分析
cot = self._chain_of_thought_analysis(title)
results['chain_of_thought'] = cot
# 2. RAG检索
rag = self._rag_retrieval(title)
results['rag_results'] = rag
# 3. 生成3个样本
for i in range(3):
sample = self._generate_sample(title, cot, rag, i+1)
results['samples'].append(sample)
# 4. 自评打分
scores = self._self_evaluation(results['samples'])
results['scores'] = scores
# 5. 选择最佳样本
best_idx = scores.index(max(scores))
best_sample = results['samples'][best_idx]
# 6. 优化建议
suggestions = self._generate_suggestions(best_sample, scores[best_idx])
results['optimized'] = {
'sample': best_sample,
'suggestions': suggestions,
'score': scores[best_idx]
}
# 7. 生成最终数据
final_data = self._create_final_data(title, best_sample, rag)
results['final_data'] = final_data
# 生成预览文本
preview_text = self._generate_complex_preview(results)
return {
'success': True,
'results': results,
'preview_text': preview_text,
'message': '复杂模式分析完成'
}
def _build_report_data(self, title, imported_content, complex_data):
"""构建报告数据"""
report_data = {
'title': title or '实验报告',
'headers': {
'课程名称': '待填写',
'实验名称': title or '待填写',
'实验地点': '待填写',
'专业班级': '待填写',
'学号': '待填写',
'学生姓名': '待填写',
'指导教师': '待填写',
'日期': datetime.now().strftime('%Y年%m月%d日')
},
'experiments': [],
'total_words': 0
}
# 确定实验数量
num_experiments = self._detect_experiment_count(title, imported_content)
# 生成每个实验的内容
for exp_idx in range(1, num_experiments + 1):
exp_data = self._generate_experiment_content(title, exp_idx, num_experiments)
report_data['experiments'].append(exp_data)
report_data['total_words'] += exp_data['word_count']
return report_data
def _detect_experiment_count(self, title, imported_content):
"""检测实验数量"""
# 从标题中检测
if '实验一' in str(title) or '实验1' in str(title):
return max(2, self.exp_count)
# 从导入内容中检测
if imported_content:
exp_matches = re.findall(r'实验[一二三四五六七八九十\d]', str(imported_content))
if exp_matches:
return max(len(set(exp_matches)), self.exp_count)
return max(1, self.exp_count)
def _generate_experiment_content(self, title, exp_idx, total_exps):
"""生成单个实验的完整内容 - 新流程:模板→AI填充→检查→输出"""
exp_num_cn = ['一', '二', '三', '四', '五']
exp_name = f"实验{exp_num_cn[exp_idx-1]}、{title}"
exp_target_words = self.target_word_count // total_exps
generator = ContentGenerator(title, exp_target_words)
t = generator.topic_type
# 步骤1:准备RAG上下文
rag_context = self._build_rag_context()
# 步骤2:生成模板结构
if t['type'] == 'essay':
template_structure = self._build_essay_template(title)
else:
template_structure = self._build_experiment_template(title)
# 步骤3:使用LLM一次性填充所有内容(只调用一次API)
llm_contents = {}
if self.llm_generator and self.is_llm_available():
word_per_section = exp_target_words // max(1, sum(len(s.get('subsections', [])) for s in template_structure))
llm_contents = self.llm_generator.generate_experiment_content(
title=title,
template_structure=template_structure,
rag_context=rag_context,
word_target=exp_target_words
)
# 步骤4:填充内容到模板
sections = []
for sec in template_structure:
subsections = []
for sub in sec.get('subsections', []):
sub_heading = sub['heading']
if sub_heading in llm_contents and llm_contents[sub_heading]:
# 使用LLM生成的内容
content = llm_contents[sub_heading]
else:
# 回退到模板生成
content = generator.generate_detailed_content(sub_heading, sub_heading)
subsections.append({
'heading': sub_heading,
'level': 2,
'content': content if isinstance(content, list) else [content]
})
sections.append({
'heading': sec['heading'],
'level': 1,
'subsections': subsections
})
# 步骤5:检查并修复格式,确保字数达标
sections = self._check_and_fix_format(sections, exp_target_words)
# 计算字数
word_count = 0
for section in sections:
word_count += len(section['heading'])
for sub in section.get('subsections', []):
word_count += len(sub['heading'])
for content in sub.get('content', []):
word_count += len(content)
return {
'name': exp_name,
'sections': sections,
'word_count': word_count
}
def _build_rag_context(self):
"""构建RAG上下文"""
rag_context = ""
# 从模板信息中提取
if self.template_info and isinstance(self.template_info, dict):
patterns = self.template_info.get('patterns', {})
if isinstance(patterns, dict):
heading_patterns = patterns.get('heading_patterns', [])
if heading_patterns:
try:
titles = [p[0] for p in heading_patterns[:10] if isinstance(p, (list, tuple)) and len(p) > 0]
if titles:
rag_context += "参考模板章节: " + ", ".join(titles) + "\n"
except:
pass
# 从导入的Word内容中提取需求
if self.imported_word_content:
rag_context += "\n用户需求: " + str(self.imported_word_content)[:500]
return rag_context if rag_context else "标准实验报告格式"
def _build_experiment_template(self, title):
"""构建实验类模板结构"""
return [
{'heading': '一、实验基本信息', 'subsections': [
{'heading': '1.1 实验环境'},
{'heading': '1.2 实验工具与库'},
{'heading': '1.3 实验数据集'}
]},
{'heading': '二、实验目的', 'subsections': [
{'heading': f'2.1 {title}核心能力培养'},
{'heading': '2.2 实践动手能力提升'},
{'heading': '2.3 综合素养培养'}
]},
{'heading': '三、实验内容与任务', 'subsections': [
{'heading': f'3.1 {title}基础任务'},
{'heading': f'3.2 {title}进阶任务'}
]},
{'heading': '四、实验步骤', 'subsections': [
{'heading': '4.1 环境安装与配置'},
{'heading': f'4.2 {title}核心功能开发'}
]},
{'heading': '五、实验结果与分析', 'subsections': [
{'heading': '5.1 实验数据对比'},
{'heading': '5.2 核心功能运行效果'},
{'heading': '5.3 问题与优化'}
]},
{'heading': '六、实验总结', 'subsections': [
{'heading': '6.1 实验成果'},
{'heading': '6.2 技术要点'},
{'heading': '6.3 学习体会'},
{'heading': '6.4 改进方向'}
]}
]
def _build_essay_template(self, title):
"""构建论述类模板结构"""
return [
{'heading': '一、研究背景与意义', 'subsections': [
{'heading': '1.1 研究背景'},
{'heading': '1.2 研究意义'}
]},
{'heading': '二、文献综述', 'subsections': [
{'heading': '2.1 国内研究现状'},
{'heading': '2.2 国外研究现状'},
{'heading': '2.3 研究述评'}
]},
{'heading': '三、核心论点分析', 'subsections': [
{'heading': f'3.1 {title}的理论基础'},
{'heading': '3.2 必要性论证'},
{'heading': '3.3 可行性分析'}
]},
{'heading': '四、案例分析', 'subsections': [
{'heading': '4.1 案例选取与介绍'},
{'heading': '4.2 案例分析过程'},
{'heading': '4.3 案例启示'}
]},
{'heading': '五、结论与展望', 'subsections': [
{'heading': '5.1 研究结论'},
{'heading': '5.2 研究不足'},
{'heading': '5.3 未来展望'}
]}
]
def _check_and_fix_format(self, sections, target_word_count=None):
"""检查并修复格式问题,确保字数达标"""
target = target_word_count or self.target_word_count
# 先清理格式
for section in sections:
for sub in section.get('subsections', []):
if not isinstance(sub.get('content'), list):
sub['content'] = [str(sub.get('content', ''))]
sub['content'] = [c for c in sub['content'] if c and str(c).strip()]
if not sub['content']:
sub['content'] = [f"请补充{sub['heading']}相关内容。"]
# 计算当前字数
current_words = 0
for section in sections:
for sub in section.get('subsections', []):
for para in sub['content']:
current_words += len(para)
# 如果字数不足,循环补充直到达标
generator = ContentGenerator("补充内容")
max_iterations = 100 # 防止无限循环
iteration = 0
while current_words < target and iteration < max_iterations:
iteration += 1
# 找到字数最少的子章节进行补充
min_sub = None
min_words = float('inf')
for section in sections:
for sub in section.get('subsections', []):
sub_words = sum(len(p) for p in sub['content'])
if sub_words < min_words:
min_words = sub_words
min_sub = sub
if min_sub is None:
break
# 计算需要补充的字数
shortage = target - current_words
# 为该子章节生成补充内容,段落数根据缺口调整
para_count = min(10, max(3, shortage // 500))
extra = generator.generate_paragraph(min_sub['heading'], para_count, para_count + 2)
min_sub['content'].append(extra)
current_words += len(extra)
return sections
def _generate_essay_sections(self, title, generator, rag_context=""):
"""生成论述类章节结构 - 使用LLM丰富内容"""
sections = []
t = generator.topic_type
# 设置总章节数(用于进度显示)
if self.llm_generator:
self.llm_generator.total_sections = 17 # 5个主章节,共17个子章节
# 辅助函数:获取内容(优先LLM,回退模板),始终返回列表
def get_content(section_name, sub_name, word_target=300):
if self.llm_generator:
text = self.llm_generator.generate_content(
title=title,
section_name=section_name,
subsection_name=sub_name,
topic_type=t['type'],
rag_context=rag_context,
word_target=word_target
)
if text:
# 将LLM返回的文本按段落分割成列表
paragraphs = [p.strip() for p in text.replace('\r\n', '\n').split('\n') if p.strip()]
return paragraphs if paragraphs else [text]
# 回退到模板生成
return generator.generate_detailed_content(section_name, sub_name)
sections.append({
'heading': '一、研究背景与意义',
'level': 1,
'subsections': [
{
'heading': '1.1 研究背景',
'level': 2,
'content': get_content('研究背景', '1.1', 400)
},
{
'heading': '1.2 研究意义',
'level': 2,
'content': get_content('研究意义', '1.2', 300)
}
]
})
sections.append({
'heading': '二、文献综述',
'level': 1,
'subsections': [
{
'heading': '2.1 国内研究现状',
'level': 2,
'content': get_content('国内研究现状', '2.1', 400)
},
{
'heading': '2.2 国外研究现状',
'level': 2,
'content': get_content('国外研究现状', '2.2', 400)
},
{
'heading': '2.3 研究述评',
'level': 2,
'content': get_content('研究述评', '2.3', 300)
}
]
})
sections.append({
'heading': '三、核心论点分析',
'level': 1,
'subsections': [
{
'heading': f'3.1 {title}的理论基础',
'level': 2,
'content': get_content('理论基础', '3.1', 400)
},
{
'heading': '3.2 必要性论证',
'level': 2,
'content': get_content('必要性论证', '3.2', 400)
},
{
'heading': '3.3 可行性分析',
'level': 2,
'content': get_content('可行性分析', '3.3', 300)
}
]
})
sections.append({
'heading': '四、案例分析',
'level': 1,
'subsections': [
{
'heading': '4.1 案例选取与介绍',
'level': 2,
'content': get_content('案例选取', '4.1', 300)
},
{
'heading': '4.2 案例分析过程',
'level': 2,
'content': get_content('案例分析', '4.2', 400)
},
{
'heading': '4.3 案例启示',
'level': 2,
'content': get_content('案例启示', '4.3', 300)
}
]
})
sections.append({
'heading': '五、结论与展望',
'level': 1,
'subsections': [
{
'heading': '5.1 研究结论',
'level': 2,
'content': get_content('研究结论', '5.1', 400)
},
{
'heading': '5.2 研究不足',
'level': 2,
'content': get_content('研究不足', '5.2', 200)
},
{
'heading': '5.3 未来展望',
'level': 2,
'content': get_content('未来展望', '5.3', 300)
}
]
})
return sections
def _generate_experiment_sections(self, title, generator, rag_context=""):
"""生成实验类章节结构 - 使用LLM丰富内容"""
exp_num_cn = ['一', '二', '三', '四', '五']
exp_name = f"实验{exp_num_cn[0]}、{title}"
sections = []
t = generator.topic_type
# 设置总章节数(用于进度显示)
if self.llm_generator:
self.llm_generator.total_sections = 19 # 6个主章节,共19个子章节
# 辅助函数:获取内容(优先LLM,回退模板),始终返回列表
def get_content(section_name, sub_name, word_target=300):
if self.llm_generator:
text = self.llm_generator.generate_content(
title=title,
section_name=section_name,
subsection_name=sub_name,
topic_type=t['type'],
rag_context=rag_context,
word_target=word_target
)
if text:
paragraphs = [p.strip() for p in text.replace('\r\n', '\n').split('\n') if p.strip()]
return paragraphs if paragraphs else [text]
return generator.generate_detailed_content(section_name, sub_name)
# 一、实验基本信息
sections.append({
'heading': '一、实验基本信息',
'level': 1,
'subsections': [
{
'heading': '1.1 实验环境',
'level': 2,
'content': get_content('实验环境', '1.1 实验环境', 300)
},
{
'heading': '1.2 实验工具与库',
'level': 2,
'content': get_content('实验工具与库', '1.2', 300)
},
{
'heading': '1.3 实验数据集',
'level': 2,
'content': get_content('实验数据集', '1.3', 300)
}
]
})
# 二、实验目的
sections.append({
'heading': '二、实验目的',
'level': 1,
'subsections': [
{
'heading': f'2.1 {title}核心能力培养',
'level': 2,
'content': get_content('实验目的', '2.1', 400)
},
{
'heading': '2.2 实践动手能力提升',
'level': 2,
'content': get_content('实践动手能力', '2.2', 300)
},
{
'heading': '2.3 综合素养培养',
'level': 2,
'content': get_content('综合素养', '2.3', 300)
}
]
})
# 三、实验内容与任务
sections.append({
'heading': '三、实验内容与任务',
'level': 1,
'subsections': [
{
'heading': f'3.1 {title}基础任务',
'level': 2,
'content': get_content('实验内容', '3.1', 400)
},
{
'heading': f'3.2 {title}进阶任务',
'level': 2,
'content': get_content('进阶任务', '3.2', 400)
}
]
})
# 四、实验步骤
sections.append({
'heading': '四、实验步骤',
'level': 1,
'subsections': [
{
'heading': '4.1 环境安装与配置',
'level': 2,
'content': get_content('实验步骤', '4.1', 400)
},
{
'heading': f'4.2 {title}核心功能开发',
'level': 2,
'content': get_content('核心功能开发', '4.2', 400)
}
]
})
# 五、实验结果与分析
sections.append({
'heading': '五、实验结果与分析',
'level': 1,
'subsections': [
{
'heading': '5.1 实验数据对比',
'level': 2,
'content': get_content('实验结果', '5.1', 400)
},
{
'heading': '5.2 核心功能运行效果',
'level': 2,
'content': get_content('核心功能运行效果', '5.2', 300)
},
{
'heading': '5.3 问题与优化',
'level': 2,
'content': get_content('问题与优化', '5.3', 300)
}
]
})
# 六、实验总结
sections.append({
'heading': '六、实验总结',
'level': 1,
'subsections': [
{
'heading': '6.1 实验成果',
'level': 2,
'content': get_content('实验总结', '6.1', 400)
},
{
'heading': '6.2 技术要点',
'level': 2,
'content': get_content('技术要点', '6.2', 300)
},
{
'heading': '6.3 学习体会',
'level': 2,
'content': get_content('学习体会', '6.3', 300)
},
{
'heading': '6.4 改进方向',