From 3e4e486dbe2abfdf3c59810dd125858cb87bddc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B5=B7?= <10402852@qq.com> Date: Sat, 15 Feb 2025 22:02:25 +0800 Subject: [PATCH] 'commit' --- AI/D1_GenerateMarkdown.py | 197 ++++++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 81 deletions(-) diff --git a/AI/D1_GenerateMarkdown.py b/AI/D1_GenerateMarkdown.py index e034f818..d76cad67 100644 --- a/AI/D1_GenerateMarkdown.py +++ b/AI/D1_GenerateMarkdown.py @@ -1,104 +1,139 @@ # -*- coding: utf-8 -*- import time from pathlib import Path -from typing import Iterator +from typing import Iterator, Optional + import dashscope from dashscope import Generation from dashscope.api_entities.dashscope_response import DashScopeAPIResponse -class TestDeepSeek: - # 模型版本常量 - R1 = "deepseek-r1" - V3 = "deepseek-v3" - # API密钥(建议从环境变量读取) +class MarkdownGenerator: + """Markdown教学大纲生成器""" + + # 固定配置项 + DEFAULT_TEMPLATE = Path(r"D:\dsWork\QingLong\AI\md-file\readme\default.md") + DEFAULT_OUTPUT_DIR = Path(r"D:\dsWork\QingLong\AI\md-file\readme") + MODEL_R1 = "deepseek-r1" API_KEY = "sk-01d13a39e09844038322108ecdbd1bbc" - @staticmethod - def get_system_prompt() -> str: - """读取系统提示文件""" - md_path = Path(r"D:\dsWork\QingLong\PptGenerator\md-file\readme\default.md") - if not md_path.exists(): - raise FileNotFoundError(f"提示文件不存在: {md_path}") - return md_path.read_text(encoding='utf-8') - - @classmethod - def call_with_stream(cls) -> Iterator[DashScopeAPIResponse]: - """流式调用API""" + def __init__( + self, + course_name: str, + output_path: Optional[Path] = None, + template_path: Optional[Path] = None + ): + """ + 初始化生成器 + + :param course_name: 课程名称(如:小学数学内角和) + :param output_path: 输出文件路径(可选) + :param template_path: 模板文件路径(可选) + """ + self.course_name = course_name + self.template_path = template_path or self.DEFAULT_TEMPLATE + self.output_path = output_path or self.DEFAULT_OUTPUT_DIR / f"{course_name}.md" + + self._validate_paths() + + def _validate_paths(self): + """路径验证""" + if not self.template_path.exists(): + raise FileNotFoundError(f"模板文件不存在: {self.template_path}") + + self.output_path.parent.mkdir(parents=True, exist_ok=True) + if not self.output_path.parent.is_dir(): + raise NotADirectoryError(f"无效的输出目录: {self.output_path.parent}") + + def _load_template(self) -> str: + """加载模板内容""" + return self.template_path.read_text(encoding='utf-8') + + def _generate_stream(self) -> Iterator[DashScopeAPIResponse]: + """流式生成内容""" system_prompt = ( - "返回的教案内容请严格按照指定的markdown语法格式返回,用来生成ppt。" - "需要注意:1、最开头的Title:..,Author: ... Date:... 不能省略掉,有用处。" - "2、第一级用#,第二级用##,第二级是独立的PPT一个页,每页中的数据必须有> 开头," - "如果是页面中的条目,必须用 - 开头,结果不要返回图片!请仔细阅读参考格式:" - ) + cls.get_system_prompt() + "请严格按照以下Markdown格式生成教学大纲:\n" + f"{self._load_template()}\n" + "注意:\n" + "1. 使用#/##标记标题\n" + "2. 每页内容以>开头\n" + "3. 列表项使用-标记\n" + ) - try: - return Generation.call( - model=cls.R1, - api_key=cls.API_KEY, - messages=[ - {"role": "system", "content": system_prompt}, - {"role": "user", "content": "请帮我生成一个小学数学内角和的教案,按标准格式输出。"} - ], - result_format='message', - stream=True, # 启用流式模式 - incremental_output=True # 启用增量输出 - ) - except Exception as e: - raise RuntimeError(f"API调用失败: {str(e)}") from e + return Generation.call( + model=self.MODEL_R1, + api_key=self.API_KEY, + messages=[ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": f"请生成《{self.course_name}》教学大纲"} + ], + result_format='message', + stream=True, + incremental_output=True + ) - @classmethod - def main(cls): - """主执行方法(带实时进度提示)""" - print("🔄 开始生成教案,请稍候...") + def run(self) -> bool: + """执行生成流程""" start_time = time.time() - last_update = start_time spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] - spinner_idx = 0 + content_buffer = [] try: - responses = cls.call_with_stream() - full_content = [] - has_content = False - - for response in responses: - current_time = time.time() - # 更新进度动画(每秒更新) - if current_time - last_update > 0.1: - print(f"\r{spinner[spinner_idx % 10]} 生成中 [{int(current_time - start_time)}s]", end="") - spinner_idx += 1 - last_update = current_time - - # 处理响应内容 + print(f"🚀 开始生成【{self.course_name}】教学大纲") + responses = self._generate_stream() + + for idx, response in enumerate(responses): + # 显示进度 + print(f"\r{spinner[idx % 10]} 生成中({int(time.time() - start_time)}秒)", end="") + if response.status_code == 200 and response.output: - chunk = response.output.choices[0].message.content - if chunk: - full_content.append(chunk) - if not has_content: - print("\n\n✅ 开始接收内容:") - has_content = True - print(chunk, end="", flush=True) # 实时显示内容 - - # 最终处理 - if full_content: - md_content = ''.join(full_content) - print(f"\n\n🎉 生成完成!总耗时: {int(time.time() - start_time)}秒") - - # 保存文件 - output_path = Path(r"D:\dsWork\QingLong\PptGenerator\md-file\readme\5.md") - output_path.parent.mkdir(parents=True, exist_ok=True) - output_path.write_text(md_content, encoding='utf-8') - print(f"💾 结果已保存至: {output_path}") - else: - print("\n⚠️ 未收到有效内容,请检查提示词和API配置") + if chunk := response.output.choices[0].message.content: + content_buffer.append(chunk) + if len(content_buffer) == 1: + print("\n\n📝 内容生成开始:") + print(chunk, end="", flush=True) + + # 保存结果 + if content_buffer: + self.output_path.write_text(''.join(content_buffer), encoding='utf-8') + print(f"\n\n✅ 生成成功!耗时 {int(time.time() - start_time)}秒") + print(f"📂 文件已保存至:{self.output_path}") + return True + return False except Exception as e: - print(f"\n\n❌ 发生错误: {str(e)}") - print("请参考文档:https://help.aliyun.com/zh/model-studio/developer-reference/error-code") - finally: - print("\n🔚 程序执行结束") + print(f"\n\n❌ 生成失败:{str(e)}") + return False + + +def generate_document( + course_name: str, + output_path: Optional[str] = None, + template_path: Optional[str] = None +): + """ + 生成文档入口函数 + + :param course_name: 课程名称 + :param output_path: 输出路径(可选) + :param template_path: 模板路径(可选) + """ + try: + generator = MarkdownGenerator( + course_name=course_name, + output_path=Path(output_path) if output_path else None, + template_path=Path(template_path) if template_path else None + ) + return generator.run() + except Exception as e: + print(f"❌ 初始化失败:{str(e)}") + return False if __name__ == "__main__": - dashscope.api_key = TestDeepSeek.API_KEY - TestDeepSeek.main() \ No newline at end of file + # 使用示例(实际使用时参数可写在此处) + dashscope.api_key = MarkdownGenerator.API_KEY + generate_document( + course_name="小学数学三角形内角和", + output_path=r"D:\dsWork\QingLong\AI\md-file\readme\5.md" + ) \ No newline at end of file