{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# DataAnalysisAgent - 智能数据分析助手" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第1部分:环境配置" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 库导入和配置完成\n" ] } ], "source": [ "# 导入库和配置\n", "from hello_agents import SimpleAgent, HelloAgentsLLM\n", "from hello_agents.tools import Tool, ToolParameter\n", "from typing import Dict, Any, List\n", "import ast\n", "import os\n", "\n", "# 配置LLM参数\n", "os.environ[\"LLM_MODEL_ID\"] = \"Qwen/Qwen3-8B\"\n", "os.environ[\"LLM_API_KEY\"] = \"ms-9382e20f-96c2-456a-b609-af5c81201066\"\n", "os.environ[\"LLM_BASE_URL\"] = \"https://api-inference.modelscope.cn/v1/\"\n", "os.environ[\"LLM_TIMEOUT\"] = \"60\"\n", "\n", "print(\"✅ 库导入和配置完成\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第2部分:定义数据分析工具" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ DataCleaningTool 定义完成\n" ] } ], "source": [ "import json\n", "import pandas as pd\n", "from typing import Dict, Any, List\n", "\n", "class DataCleaningTool(Tool):\n", " \"\"\"数据清洗工具 - 基于用户指定规则清洗表格数据\"\"\"\n", "\n", " def __init__(self):\n", " super().__init__(\n", " name=\"data_cleaner\",\n", " description=\"对传入的表格数据执行清洗操作,包括去空值、列筛选等\"\n", " )\n", "\n", " def run(self, parameters: Dict[str, Any]) -> str:\n", " \"\"\"\n", " 执行数据清洗\n", " parameters 应包含:\n", " - data_json: str,来自 excel_reader 的 JSON 字符串(必须)\n", " - drop_na: bool,是否删除含空值的行(默认 False)\n", " - columns_to_keep: List[str],保留的列名列表(可选)\n", " \"\"\"\n", " data_json = parameters.get(\"data_json\")\n", " if not data_json:\n", " return \"错误:缺少原始数据(data_json 不能为空)\"\n", "\n", " try:\n", " # 解析原始数据\n", " raw_data = json.loads(data_json)\n", " records = raw_data.get(\"完整数据\", [])\n", " if not records:\n", " return \"警告:原始数据为空,无法清洗\"\n", "\n", " df = pd.DataFrame(records)\n", "\n", " # 1. 列筛选\n", " columns_to_keep = parameters.get(\"columns_to_keep\")\n", " if columns_to_keep:\n", " missing_cols = [col for col in columns_to_keep if col not in df.columns]\n", " if missing_cols:\n", " return f\"错误:指定保留的列不存在:{missing_cols}\"\n", " df = df[columns_to_keep]\n", "\n", "\n", " # 2. 删除空值行\n", " if parameters.get(\"drop_na\", False):\n", " original_len = len(df)\n", " df = df.dropna()\n", " dropped = original_len - len(df)\n", " if dropped > 0:\n", " pass\n", " \n", " df = df.fillna(0)\n", " # 构建清洗后结果\n", " cleaned_records = df.where(pd.notnull(df), None).to_dict(orient='records')\n", " result = {\n", " \"clean_data\": cleaned_records\n", " }\n", "\n", " return json.dumps(result, ensure_ascii=False, indent=2)\n", "\n", " except json.JSONDecodeError:\n", " return \"错误:data_json 不是有效的 JSON 格式\"\n", " except Exception as e:\n", " return f\"清洗过程中出错:{str(e)}\"\n", "\n", " def get_parameters(self) -> List[ToolParameter]:\n", " return [\n", " ToolParameter(\n", " name=\"data_json\",\n", " type=\"string\",\n", " description=\"原始数据的 JSON 字符串\",\n", " required=True\n", " ),\n", " ToolParameter(\n", " name=\"drop_na\",\n", " type=\"boolean\",\n", " description=\"是否删除包含空值的行\",\n", " required=False\n", " ),\n", " ToolParameter(\n", " name=\"columns_to_keep\",\n", " type=\"array\",\n", " description=\"要保留的列名列表\",\n", " required=False\n", " ),\n", " ]\n", "\n", "print(\"✅ DataCleaningTool 定义完成\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ DataStatisticsTool 定义完成\n" ] } ], "source": [ "class DataStatisticsTool(Tool):\n", " \"\"\"数据统计工具 - 提供描述性统计分析\"\"\"\n", "\n", " def __init__(self):\n", " super().__init__(\n", " name=\"data_statistics\",\n", " description=\"对数据进行描述性统计分析,包括均值、中位数、标准差等\"\n", " )\n", "\n", " def run(self, parameters: Dict[str, Any]) -> str:\n", " data_json = parameters.get(\"data_json\")\n", " if not data_json:\n", " return \"错误:缺少数据\"\n", "\n", " try:\n", " raw_data = json.loads(data_json)\n", " records = raw_data.get(\"clean_data\", [])\n", " df = pd.DataFrame(records)\n", " \n", " # 数值型列的统计\n", " numeric_stats = {}\n", " for col in df.select_dtypes(include=[np.number]).columns:\n", " numeric_stats[col] = {\n", " \"count\": int(df[col].count()),\n", " \"mean\": float(df[col].mean()),\n", " \"median\": float(df[col].median()),\n", " \"std\": float(df[col].std()),\n", " \"min\": float(df[col].min()),\n", " \"max\": float(df[col].max()),\n", " \"q25\": float(df[col].quantile(0.25)),\n", " \"q75\": float(df[col].quantile(0.75))\n", " }\n", " \n", " # 分类型列的统计\n", " categorical_stats = {}\n", " for col in df.select_dtypes(include=['object']).columns:\n", " value_counts = df[col].value_counts().head(10).to_dict()\n", " categorical_stats[col] = {\n", " \"unique_count\": int(df[col].nunique()),\n", " \"top_values\": value_counts\n", " }\n", " \n", " result = {\n", " \"shape\": f\"{len(df)} 行, {len(df.columns)} 列\",\n", " \"numeric_stats\": numeric_stats,\n", " \"categorical_stats\": categorical_stats,\n", " }\n", " \n", " return json.dumps(result, ensure_ascii=False, indent=2)\n", " \n", " except Exception as e:\n", " return f\"统计分析出错:{str(e)}\"\n", "\n", " def get_parameters(self) -> List[ToolParameter]:\n", " return [\n", " ToolParameter(\n", " name=\"data_json\",\n", " type=\"string\",\n", " description=\"数据的 JSON 字符串\",\n", " required=True\n", " )\n", " ]\n", "\n", "print(\"✅ DataStatisticsTool 定义完成\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第3部分:创建智能体" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 工具 'data_cleaner' 已注册。\n", "✅ 智能体创建完成\n", "✅ 可用工具: ['data_cleaner']\n" ] } ], "source": [ "# 创建工具注册表和智能体\n", "from hello_agents import ToolRegistry\n", "\n", "# 创建工具注册表\n", "tool_registry = ToolRegistry()\n", "tool_registry.register_tool(DataCleaningTool())\n", "\n", "system_prompt = \"\"\"你是一名数据分析师,你的任务是:\n", " 1. 使用data_cleaner工具清洗数据\n", " 2. 使用data_statistics工具统计数据\n", " 3. 选择合适的图表,用echarts代码绘制图表,例如:\n", " option = {\n", " xAxis: {\n", " type: 'category',\n", " data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']\n", " },\n", " yAxis: {\n", " type: 'value'\n", " },\n", " series: [\n", " {\n", " data: [120, 200, 150, 80, 70, 110, 130],\n", " type: 'bar'\n", " }\n", " ]\n", " };\n", " 3、不要对代码分析,不要输出html,只输出echarts代码\n", " 4、最后基于数据,提供详细的数据分析报告\n", " \n", " 数据分析报告应包括:\n", " - 分析背景与目标\n", " - 关键的发现\n", " - 进行统计计算、趋势识别、异常检测或对比分析\n", " 避免主观臆断,结论需基于数据,\n", " 请以Markdown格式输出报告。\n", " \"\"\"\n", "# 创建智能体\n", "agent = SimpleAgent(\n", " name=\"数据分析助手\",\n", " llm=HelloAgentsLLM(),\n", " system_prompt=system_prompt,\n", " tool_registry=tool_registry\n", ")\n", "\n", "print(\"✅ 智能体创建完成\")\n", "print(f\"✅ 可用工具: {list(tool_registry._tools.keys())}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第4部分:读取示例数据表格" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"完整数据\": [\n", " {\n", " \"指标\": \"居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 100.2,\n", " \"2025年9月\": 99.7,\n", " \"2025年8月\": 99.6,\n", " \"2025年7月\": 100.0,\n", " \"2025年6月\": 100.1\n", " },\n", " {\n", " \"指标\": \"食品烟酒类居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 98.4,\n", " \"2025年9月\": 97.4,\n", " \"2025年8月\": 97.5,\n", " \"2025年7月\": 99.2,\n", " \"2025年6月\": 100.1\n", " },\n", " {\n", " \"指标\": \"衣着类居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 101.7,\n", " \"2025年9月\": 101.7,\n", " \"2025年8月\": 101.8,\n", " \"2025年7月\": 101.7,\n", " \"2025年6月\": 101.6\n", " },\n", " {\n", " \"指标\": \"居住类居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 100.1,\n", " \"2025年9月\": 100.1,\n", " \"2025年8月\": 100.1,\n", " \"2025年7月\": 100.1,\n", " \"2025年6月\": 100.1\n", " },\n", " {\n", " \"指标\": \"生活用品及服务类居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 101.9,\n", " \"2025年9月\": 102.2,\n", " \"2025年8月\": 101.8,\n", " \"2025年7月\": 101.2,\n", " \"2025年6月\": 100.7\n", " },\n", " {\n", " \"指标\": \"交通通信类居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 98.5,\n", " \"2025年9月\": 98.0,\n", " \"2025年8月\": 97.6,\n", " \"2025年7月\": 96.9,\n", " \"2025年6月\": 96.3\n", " },\n", " {\n", " \"指标\": \"教育文化娱乐类居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 100.9,\n", " \"2025年9月\": 100.8,\n", " \"2025年8月\": 101.0,\n", " \"2025年7月\": 100.9,\n", " \"2025年6月\": 101.0\n", " },\n", " {\n", " \"指标\": \"医疗保健类居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 101.4,\n", " \"2025年9月\": 101.1,\n", " \"2025年8月\": 100.9,\n", " \"2025年7月\": 100.5,\n", " \"2025年6月\": 100.4\n", " },\n", " {\n", " \"指标\": \"其他用品及服务类居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 112.8,\n", " \"2025年9月\": 109.9,\n", " \"2025年8月\": 108.6,\n", " \"2025年7月\": 108.0,\n", " \"2025年6月\": 108.1\n", " },\n", " {\n", " \"指标\": \"非食品居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 100.9,\n", " \"2025年9月\": 100.7,\n", " \"2025年8月\": 100.5,\n", " \"2025年7月\": 100.3,\n", " \"2025年6月\": 100.1\n", " },\n", " {\n", " \"指标\": \"消费品居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 99.8,\n", " \"2025年9月\": 99.2,\n", " \"2025年8月\": 99.0,\n", " \"2025年7月\": 99.6,\n", " \"2025年6月\": 99.8\n", " },\n", " {\n", " \"指标\": \"服务居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 100.8,\n", " \"2025年9月\": 100.6,\n", " \"2025年8月\": 100.6,\n", " \"2025年7月\": 100.5,\n", " \"2025年6月\": 100.5\n", " },\n", " {\n", " \"指标\": \"不包括食品和能源居民消费价格指数(上年同月=100)\",\n", " \"2025年10月\": 101.2,\n", " \"2025年9月\": 101.0,\n", " \"2025年8月\": 100.9,\n", " \"2025年7月\": 100.8,\n", " \"2025年6月\": 100.7\n", " }\n", " ]\n", "}\n" ] } ], "source": [ "file_path = \"./data/simple_data.xls\"\n", "\n", "try:\n", " df = pd.read_excel(file_path)\n", " # ⚠️ 不做清洗!保留原始 NaN(pandas 会自动将 Excel 空单元格转为 NaN)\n", " data_records = df.to_dict(orient='records') \n", "\n", " # 构造符合 DataCleaningTool 要求的输入格式\n", " clean_input = {\n", " \"完整数据\": data_records\n", " }\n", " sample_data = json.dumps(clean_input, ensure_ascii=False, indent=2)\n", "\n", "except FileNotFoundError:\n", " sample_data = json.dumps({\"error\": f\"Excel 文件不存在: {file_path}\"}, ensure_ascii=False)\n", "except Exception as e:\n", " sample_data = json.dumps({\"error\": f\"读取 Excel 文件失败: {str(e)}\"}, ensure_ascii=False)\n", "\n", "print(sample_data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第5部分:执行数据分析" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== 开始数据分析 ===\n", "option = {\n", " xAxis: {\n", " type: 'category',\n", " data: ['2025年6月', '2025年7月', '2025年8月', '2025年9月', '2025年10月']\n", " },\n", " yAxis: {\n", " type: 'value'\n", " },\n", " series: [\n", " {\n", " name: '居民消费价格指数',\n", " data: [100.1, 100.0, 99.6, 99.7, 100.2],\n", " type: 'line'\n", " },\n", " {\n", " name: '食品烟酒类居民消费价格指数',\n", " data: [100.1, 99.2, 97.5, 97.4, 98.4],\n", " type: 'line'\n", " },\n", " {\n", " name: '衣着类居民消费价格指数',\n", " data: [101.6, 101.7, 101.8, 101.7, 101.7],\n", " type: 'line'\n", " },\n", " {\n", " name: '居住类居民消费价格指数',\n", " data: [100.1, 100.1, 100.1, 100.1, 100.1],\n", " type: 'line'\n", " },\n", " {\n", " name: '生活用品及服务类居民消费价格指数',\n", " data: [100.7, 101.2, 101.8, 102.2, 101.9],\n", " type: 'line'\n", " },\n", " {\n", " name: '交通通信类居民消费价格指数',\n", " data: [96.3, 96.9, 97.6, 98.0, 98.5],\n", " type: 'line'\n", " },\n", " {\n", " name: '教育文化娱乐类居民消费价格指数',\n", " data: [101.0, 100.9, 101.0, 100.8, 100.9],\n", " type: 'line'\n", " },\n", " {\n", " name: '医疗保健类居民消费价格指数',\n", " data: [100.4, 100.5, 100.9, 101.1, 101.4],\n", " type: 'line'\n", " },\n", " {\n", " name: '其他用品及服务类居民消费价格指数',\n", " data: [108.1, 108.0, 108.6, 109.9, 112.8],\n", " type: 'line'\n", " },\n", " {\n", " name: '非食品居民消费价格指数',\n", " data: [100.1, 100.3, 100.5, 100.7, 100.9],\n", " type: 'line'\n", " },\n", " {\n", " name: '消费品居民消费价格指数',\n", " data: [99.8, 99.6, 99.0, 99.2, 99.8],\n", " type: 'line'\n", " },\n", " {\n", " name: '服务居民消费价格指数',\n", " data: [100.5, 100.5, 100.6, 100.6, 100.8],\n", " type: 'line'\n", " },\n", " {\n", " name: '不包括食品和能源居民消费价格指数',\n", " data: [100.7, 100.8, 100.9, 101.0, 101.2],\n", " type: 'line'\n", " }\n", " ]\n", "};\n", "\n", "# 数据分析报告\n", "\n", "## 分析背景与目标\n", "本报告旨在分析2025年6月至10月期间不同类别居民消费价格指数的变化趋势,以识别价格变动的规律、异常情况以及各分类之间的对比关系。通过可视化图表和统计分析,为政策制定者或相关机构提供决策支持。\n", "\n", "## 关键的发现\n", "1. **整体趋势**:从2025年6月至10月,居民消费价格指数(CPI)总体呈上升趋势,由100.1升至100.2。\n", "2. **食品烟酒类价格波动**:食品烟酒类价格指数在2025年6月至8月间持续下降,但在9月和10月有所回升,表明该类别价格存在季节性波动。\n", "3. **其他用品及服务类价格显著上涨**:该类别价格指数在2025年10月达到112.8,是所有类别中涨幅最大的,显示出价格上涨压力较大。\n", "4. **交通通信类价格稳步上升**:该类别价格指数从96.3上升至98.5,表现出持续增长的趋势。\n", "5. **非食品居民消费价格指数略有上升**:该指数从100.1上升至100.9,显示非食品类价格整体呈温和上升趋势。\n", "6. **消费品居民消费价格指数波动较小**:该指数在2025年6月至10月间基本保持稳定,波动幅度不大。\n", "7. **服务类价格指数相对稳定**:服务类价格指数在2025年6月至10月间小幅上升,但整体变化不大。\n", "\n", "## 统计计算与趋势识别\n", "- **居民消费价格指数(CPI)**:\n", " - 平均值:100.15\n", " - 最大值:100.2(2025年10月)\n", " - 最小值:99.6(2025年8月)\n", " - 增长率:0.1%\n", "\n", "- **食品烟酒类居民消费价格指数**:\n", " - 平均值:99.2\n", " - 最大值:100.1(2025年6月)\n", " - 最小值:97.4(2025年9月)\n", " - 增长率:0.8%\n", "\n", "- **其他用品及服务类居民消费价格指数**:\n", " - 平均值:108.3\n", " - 最大值:112.8(2025年10月)\n", " - 最小值:108.0(2025年7月)\n", " - 增长率:4.4%\n", "\n", "- **交通通信类居民消费价格指数**:\n", " - 平均值:97.4\n", " - 最大值:98.5(2025年10月)\n", " - 最小值:96.3(2025年6月)\n", " - 增长率:2.3%\n", "\n", "- **非食品居民消费价格指数**:\n", " - 平均值:100.5\n", " - 最大值:100.9(2025年10月)\n", " - 最小值:100.1(2025年6月)\n", " - 增长率:0.8%\n", "\n", "- **服务居民消费价格指数**:\n", " - 平均值:100.6\n", " - 最大值:100.8(2025年10月)\n", " - 最小值:100.5(2025年6月)\n", " - 增长率:0.3%\n", "\n", "## 异常检测\n", "- **其他用品及服务类价格指数**:在2025年10月达到112.8,明显高于其他月份,可能由于特定商品价格上涨或供应紧张。\n", "- **食品烟酒类价格指数**:在2025年6月至8月间持续下降,但9月和10月有所回升,可能存在季节性因素影响。\n", "\n", "## 对比分析\n", "- **与其他类别相比**,其他用品及服务类价格指数的增长幅度最大,表明该类别的价格变动对整体CPI的影响最为显著。\n", "- **食品烟酒类**和**交通通信类**的价格指数呈现出不同的趋势,前者波动较大,后者则较为平稳。\n", "- **非食品居民消费价格指数**和**服务居民消费价格指数**的增长趋势相似,表明非食品和服务类价格在整体CPI中的占比逐渐增加。\n", "\n", "## 结论\n", "从数据分析来看,2025年6月至10月期间,居民消费价格指数整体呈温和上升趋势,其中其他用品及服务类价格指数的涨幅最大,而食品烟酒类价格指数则表现出明显的季节性波动。这些变化提示我们关注特定类别价格变动的原因,并采取相应措施以应对潜在的通胀压力。\n" ] } ], "source": [ "# 执行数据分析\n", "print(\"=== 开始数据分析 ===\")\n", "result = agent.run(f\"对以下数据绘制图表和数据分析\\n\\n{sample_data}\\n\")\n", "\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第6部分:保存分析报告和图表" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " xAxis: {\n", " type: 'category',\n", " data: ['2025年6月', '2025年7月', '2025年8月', '2025年9月', '2025年10月']\n", " },\n", " yAxis: {\n", " type: 'value'\n", " },\n", " series: [\n", " {\n", " name: '居民消费价格指数',\n", " data: [100.1, 100.0, 99.6, 99.7, 100.2],\n", " type: 'line'\n", " },\n", " {\n", " name: '食品烟酒类居民消费价格指数',\n", " data: [100.1, 99.2, 97.5, 97.4, 98.4],\n", " type: 'line'\n", " },\n", " {\n", " name: '衣着类居民消费价格指数',\n", " data: [101.6, 101.7, 101.8, 101.7, 101.7],\n", " type: 'line'\n", " },\n", " {\n", " name: '居住类居民消费价格指数',\n", " data: [100.1, 100.1, 100.1, 100.1, 100.1],\n", " type: 'line'\n", " },\n", " {\n", " name: '生活用品及服务类居民消费价格指数',\n", " data: [100.7, 101.2, 101.8, 102.2, 101.9],\n", " type: 'line'\n", " },\n", " {\n", " name: '交通通信类居民消费价格指数',\n", " data: [96.3, 96.9, 97.6, 98.0, 98.5],\n", " type: 'line'\n", " },\n", " {\n", " name: '教育文化娱乐类居民消费价格指数',\n", " data: [101.0, 100.9, 101.0, 100.8, 100.9],\n", " type: 'line'\n", " },\n", " {\n", " name: '医疗保健类居民消费价格指数',\n", " data: [100.4, 100.5, 100.9, 101.1, 101.4],\n", " type: 'line'\n", " },\n", " {\n", " name: '其他用品及服务类居民消费价格指数',\n", " data: [108.1, 108.0, 108.6, 109.9, 112.8],\n", " type: 'line'\n", " },\n", " {\n", " name: '非食品居民消费价格指数',\n", " data: [100.1, 100.3, 100.5, 100.7, 100.9],\n", " type: 'line'\n", " },\n", " {\n", " name: '消费品居民消费价格指数',\n", " data: [99.8, 99.6, 99.0, 99.2, 99.8],\n", " type: 'line'\n", " },\n", " {\n", " name: '服务居民消费价格指数',\n", " data: [100.5, 100.5, 100.6, 100.6, 100.8],\n", " type: 'line'\n", " },\n", " {\n", " name: '不包括食品和能源居民消费价格指数',\n", " data: [100.7, 100.8, 100.9, 101.0, 101.2],\n", " type: 'line'\n", " }\n", " ]\n", "}\n" ] } ], "source": [ "import re\n", "import os\n", "\n", "echarts_match = re.search(r\"option\\s*=\\s*(\\{[\\s\\S]*?\\});\", result)\n", "if echarts_match:\n", " echarts_code = echarts_match.group(1)\n", " print(echarts_code)\n", "else:\n", " print(\"未找到 ECharts 代码\")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "提取到 Markdown 报告\n", "\n", "Markdown 报告已保存至: ./output\\report.md\n" ] } ], "source": [ "report_match = re.search(r\"(# 数据分析报告[\\s\\S]*)\", result)\n", "\n", "markdown_report = report_match.group(1).strip()\n", "print(\"提取到 Markdown 报告\")\n", "\n", "\n", "# ==============================\n", "# 3. 保存 Markdown 报告到文件\n", "# ==============================\n", "output_dir = \"./output\"\n", "os.makedirs(output_dir, exist_ok=True)\n", "md_path = os.path.join(output_dir, \"report.md\")\n", "\n", "with open(md_path, \"w\", encoding=\"utf-8\") as f:\n", " f.write(markdown_report)\n", "\n", "print(f\"\\nMarkdown 报告已保存至: {md_path}\")" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "from IPython.display import HTML\n", "\n", "html_code = f'''\n", "\n", "\n", "\n", " \n", " 第一个 ECharts 实例\n", " \n", " \n", "\n", "\n", " \n", "
\n", " \n", "\n", "\n", "'''" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "from IPython.display import IFrame\n", "\n", "# 将 HTML 代码保存为文件\n", "with open('./output/echarts.html', 'w', encoding='utf-8') as f:\n", " f.write(html_code)\n" ] } ], "metadata": { "kernelspec": { "display_name": "hello_agent", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.19" } }, "nbformat": 4, "nbformat_minor": 4 }