Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ee3ac165ce | |||
| 224a5748d7 | |||
| d5f4a5f06f | |||
| 1380c20a53 | |||
| 63fbd7ebbb | |||
| 359785b162 | |||
| 60a58a3ac8 | |||
| 284d654293 | |||
| 68e5e6d10e | |||
| a058b97400 | |||
| 9a8c9dedd7 | |||
| c3f1af3ef8 | |||
| d06fbfb5b3 | |||
| b2f5e2a29d | |||
| b56a8cbac1 | |||
| e2a41f4062 |
@@ -8,6 +8,8 @@ data/
|
||||
# Workspace
|
||||
workspace/
|
||||
|
||||
config/
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
|
||||
Vendored
+2
-1
@@ -16,5 +16,6 @@
|
||||
},
|
||||
"files.insertFinalNewline": true,
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"editor.formatOnSave": true
|
||||
"editor.formatOnSave": true,
|
||||
"liveServer.settings.port": 5501
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ OpenManus is built by contributors from MetaGPT. Huge thanks to this agent commu
|
||||
## Cite
|
||||
```bibtex
|
||||
@misc{openmanus2025,
|
||||
author = {Xinbin Liang and Jinyu Xiang and Zhaoyang Yu and Jiayi Zhang and Sirui Hong and Sheng Fan and Xiao Tang and Bang Liu and Yuyu Luo and Chenglin Wu},
|
||||
author = {Xinbin Liang and Jinyu Xiang and Zhaoyang Yu and Jiayi Zhang and Sirui Hong and Sheng Fan and Xiao Tang},
|
||||
title = {OpenManus: An open-source framework for building general AI agents},
|
||||
year = {2025},
|
||||
publisher = {Zenodo},
|
||||
|
||||
@@ -4,9 +4,23 @@ from app.agent.toolcall import ToolCallAgent
|
||||
from app.config import config
|
||||
from app.prompt.visualization import NEXT_STEP_PROMPT, SYSTEM_PROMPT
|
||||
from app.tool import Terminate, ToolCollection
|
||||
from app.tool.chart_visualization.chart_prepare import VisualizationPrepare
|
||||
from app.tool.chart_visualization.data_visualization import DataVisualization
|
||||
from app.tool.chart_visualization.python_execute import NormalPythonExecute
|
||||
# from app.tool.chart_visualization.chart_prepare import VisualizationPrepare
|
||||
# from app.tool.chart_visualization.data_visualization import DataVisualization
|
||||
# from app.tool.chart_visualization.initial_report_generation import GenerateInitialReport
|
||||
# from app.tool.chart_visualization.final_report_generation import GenerateFinalReport
|
||||
# from app.tool.chart_visualization.search_report_template import SearchReportTemplate
|
||||
# from app.tool.chart_visualization.report_template_generation import ReportTemplateGeneration
|
||||
# from app.tool.chart_visualization.initial_information_collection import InitialInformationCollection
|
||||
from app.tool.chart_visualization.chart_prepare import VisualizationPrepare
|
||||
from app.tool.chart_visualization.select_insights import SelectInsights
|
||||
from app.tool.chart_visualization.add_insights import AddInsights
|
||||
from app.tool.chart_visualization.data_visualization import DataVisualization
|
||||
from app.tool.chart_visualization.v2.search_html_library import SearchHtmlLibrary
|
||||
from app.tool.chart_visualization.v2.initial_report_generation import GenerateInitialReport
|
||||
from app.tool.chart_visualization.v2.report_template_generation import ReportTemplateGeneration
|
||||
from app.tool.chart_visualization.v2.final_report_generation import GenerateFinalReport
|
||||
from app.tool.chart_visualization.v2.report_beautify import ReportBeautify
|
||||
|
||||
|
||||
class DataAnalysis(ToolCallAgent):
|
||||
@@ -18,7 +32,34 @@ class DataAnalysis(ToolCallAgent):
|
||||
"""
|
||||
|
||||
name: str = "Data_Analysis"
|
||||
description: str = "An analytical agent that utilizes python and data visualization tools to solve diverse data analysis tasks"
|
||||
description: str = """
|
||||
A data science agent specializing in Python-based analytics and advanced visualization techniques
|
||||
for solving complex data analysis challenges.
|
||||
|
||||
Standard Report Generation Workflow:
|
||||
1. Template Preparation:
|
||||
- SearchHtmlLibrary: Identify suitable visualization templates
|
||||
- ReportTemplateGeneration & GenerateInitialReport: Create initial report structure
|
||||
|
||||
2. Visualization Pipeline:
|
||||
- VisualizationPrepare: Configure data for visualization
|
||||
- DataVisualization: Generate interactive charts and graphs
|
||||
|
||||
3. Insight Enhancement:
|
||||
- SelectInsights: Extract key findings from visualizations
|
||||
- AddInsights: Annotate charts with analytical insights
|
||||
|
||||
4. Report Finalization:
|
||||
- GenerateFinalReport: Replace the placeholders with charts
|
||||
- ReportBeautify: Apply professional styling and formatting
|
||||
|
||||
Operational Protocol:
|
||||
- First determine optimal visualization types based on dataset characteristics
|
||||
- Utilize HTML template library to establish report framework
|
||||
- Execute visualization pipeline to create data representations
|
||||
- Enhance each chart with key insights you selected
|
||||
- Assemble final report by embedding enriched visualizations
|
||||
"""
|
||||
|
||||
system_prompt: str = SYSTEM_PROMPT.format(directory=config.workspace_root)
|
||||
next_step_prompt: str = NEXT_STEP_PROMPT
|
||||
@@ -30,8 +71,15 @@ class DataAnalysis(ToolCallAgent):
|
||||
available_tools: ToolCollection = Field(
|
||||
default_factory=lambda: ToolCollection(
|
||||
NormalPythonExecute(),
|
||||
SearchHtmlLibrary(),
|
||||
ReportTemplateGeneration(),
|
||||
GenerateInitialReport(),
|
||||
GenerateFinalReport(),
|
||||
ReportBeautify(),
|
||||
AddInsights(),
|
||||
VisualizationPrepare(),
|
||||
DataVisualization(),
|
||||
SelectInsights(),
|
||||
Terminate(),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,7 +1,33 @@
|
||||
SYSTEM_PROMPT = """You are an AI agent designed to data analysis / visualization task. You have various tools at your disposal that you can call upon to efficiently complete complex requests.
|
||||
# Note:
|
||||
1. The workspace directory is: {directory}; Read / write file in workspace
|
||||
2. Generate analysis conclusion report in the end"""
|
||||
2. Generate analysis conclusion report in the end
|
||||
|
||||
Standard Report Generation Workflow:
|
||||
1. Template Preparation:
|
||||
- SearchHtmlLibrary: Identify suitable visualization templates
|
||||
- ReportTemplateGeneration & GenerateInitialReport: Create initial report structure
|
||||
|
||||
2. Visualization Pipeline:
|
||||
- VisualizationPrepare: Configure data for visualization
|
||||
- DataVisualization: Generate interactive charts and graphs
|
||||
|
||||
3. Insight Enhancement:
|
||||
- SelectInsights: Extract key findings from visualizations
|
||||
- AddInsights: Annotate charts with analytical insights
|
||||
|
||||
4. Report Finalization:
|
||||
- GenerateFinalReport: Replace the placeholders with charts
|
||||
- ReportBeautify: Apply professional styling and formatting
|
||||
|
||||
Operational Protocol:
|
||||
- First determine optimal visualization types based on dataset characteristics
|
||||
- Utilize HTML template library to establish report framework
|
||||
- Execute visualization pipeline to create data representations
|
||||
- Enhance each chart with key insights you selected
|
||||
- Assemble final report by embedding enriched visualizations
|
||||
|
||||
"""
|
||||
|
||||
NEXT_STEP_PROMPT = """Based on user needs, break down the problem and use different tools step by step to solve it.
|
||||
# Note
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
from app.tool.chart_visualization.chart_prepare import VisualizationPrepare
|
||||
from app.tool.chart_visualization.data_visualization import DataVisualization
|
||||
from app.tool.chart_visualization.python_execute import NormalPythonExecute
|
||||
|
||||
|
||||
__all__ = ["DataVisualization", "VisualizationPrepare", "NormalPythonExecute"]
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
import sys
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
print(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
|
||||
|
||||
from typing import Any, Hashable
|
||||
|
||||
import pandas as pd
|
||||
from pydantic import Field, model_validator
|
||||
|
||||
from app.config import config
|
||||
from app.llm import LLM
|
||||
from app.logger import logger
|
||||
from app.tool.base import BaseTool
|
||||
|
||||
|
||||
class AddInsights(BaseTool):
|
||||
name: str = "add_insights"
|
||||
description: str = (
|
||||
"Enhances charts by adding insights markers and annotations "
|
||||
"using JSON data generated by the insights_selection tool. "
|
||||
"This creates the final annotated visualization output."
|
||||
)
|
||||
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"json_path": {
|
||||
"type": "string",
|
||||
"description": """Path to the JSON file generated by insights_selection tool.
|
||||
Contains chart insights data in format:
|
||||
{
|
||||
"chartPath": string,
|
||||
"insights_id": number[]
|
||||
}""",
|
||||
},
|
||||
"output_type": {
|
||||
"type": "string",
|
||||
"description": "Visualization output format selection",
|
||||
"default": "html",
|
||||
"enum": [
|
||||
"png", # Static image format
|
||||
"html" # Interactive web format (recommended)
|
||||
],
|
||||
},
|
||||
},
|
||||
"required": ["json_path"],
|
||||
}
|
||||
llm: LLM = Field(default_factory=LLM, description="Language model instance")
|
||||
|
||||
@model_validator(mode="after")
|
||||
def initialize_llm(self):
|
||||
"""Initialize llm with default settings if not provided."""
|
||||
if self.llm is None or not isinstance(self.llm, LLM):
|
||||
self.llm = LLM(config_name=self.name.lower())
|
||||
return self
|
||||
|
||||
def load_chart_with_css(self, chart_path):
|
||||
# 读取 HTML 文件
|
||||
with open(chart_path, 'r', encoding='utf-8') as f:
|
||||
html_content = f.read()
|
||||
html_content = html_content.replace('`', "'")
|
||||
|
||||
# 在 <head> 里插入 CSS
|
||||
css = """
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#chart-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
"""
|
||||
|
||||
# 如果原文件没有 <head>,直接插入到最前面
|
||||
if "<head>" in html_content:
|
||||
html_content = html_content.replace("<head>", "<head>" + css)
|
||||
else:
|
||||
html_content = css + html_content
|
||||
|
||||
with open(chart_path, 'w', encoding='utf-8') as f:
|
||||
f.write(html_content)
|
||||
|
||||
def get_file_path(
|
||||
self,
|
||||
json_info: list[dict[str, str]],
|
||||
path_str: str,
|
||||
directory: str = None,
|
||||
) -> list[str]:
|
||||
res = []
|
||||
for item in json_info:
|
||||
if os.path.exists(item[path_str]):
|
||||
res.append(item[path_str])
|
||||
elif os.path.exists(
|
||||
os.path.join(f"{directory or config.workspace_root}", item[path_str])
|
||||
):
|
||||
res.append(
|
||||
os.path.join(
|
||||
f"{directory or config.workspace_root}", item[path_str]
|
||||
)
|
||||
)
|
||||
else:
|
||||
raise Exception(f"No such file or directory: {item[path_str]}")
|
||||
return res
|
||||
|
||||
async def add_insights(
|
||||
self, json_info: list[dict[str, str]], output_type: str
|
||||
) -> str:
|
||||
data_list = []
|
||||
chart_file_path = self.get_file_path(
|
||||
json_info, "chartPath", os.path.join(config.workspace_root, "visualization")
|
||||
)
|
||||
for index, item in enumerate(json_info):
|
||||
if "insights_id" in item:
|
||||
data_list.append(
|
||||
{
|
||||
"file_name": os.path.basename(chart_file_path[index]).replace(
|
||||
f".{output_type}", ""
|
||||
),
|
||||
"insights_id": item["insights_id"],
|
||||
}
|
||||
)
|
||||
tasks = [
|
||||
self.invoke_vmind(
|
||||
insights_id=item["insights_id"],
|
||||
file_name=item["file_name"],
|
||||
output_type=output_type,
|
||||
task_type="insight",
|
||||
)
|
||||
for item in data_list
|
||||
]
|
||||
results = await asyncio.gather(*tasks)
|
||||
error_list = []
|
||||
success_list = []
|
||||
for index, result in enumerate(results):
|
||||
chart_path = chart_file_path[index]
|
||||
if "error" in result and "chart_path" not in result:
|
||||
error_list.append(f"Error in {chart_path}: {result['error']}")
|
||||
else:
|
||||
success_list.append(chart_path)
|
||||
self.load_chart_with_css(chart_path)
|
||||
|
||||
success_template = (
|
||||
f"# Charts Update with Insights\n{','.join(success_list)}"
|
||||
if len(success_list) > 0
|
||||
else ""
|
||||
)
|
||||
if len(error_list) > 0:
|
||||
return {
|
||||
"observation": f"# Error in chart insights:{'\n'.join(error_list)}\n{success_template}",
|
||||
"success": False,
|
||||
}
|
||||
else:
|
||||
return {"observation": f"{success_template}"}
|
||||
|
||||
async def execute(
|
||||
self,
|
||||
json_path: str,
|
||||
output_type: str | None = "html",
|
||||
tool_type: str | None = "visualization",
|
||||
language: str | None = "en",
|
||||
) -> str:
|
||||
try:
|
||||
logger.info(f"📈 data_visualization with {json_path} in: {tool_type} ")
|
||||
with open(json_path, "r", encoding="utf-8") as file:
|
||||
json_info = json.load(file)
|
||||
return await self.add_insights(json_info, output_type)
|
||||
except Exception as e:
|
||||
return {
|
||||
"observation": f"Error: {e}",
|
||||
"success": False,
|
||||
}
|
||||
|
||||
async def invoke_vmind(
|
||||
self,
|
||||
file_name: str,
|
||||
output_type: str,
|
||||
task_type: str,
|
||||
insights_id: list[str] = None,
|
||||
dict_data: list[dict[Hashable, Any]] = None,
|
||||
chart_description: str = None,
|
||||
language: str = "en",
|
||||
):
|
||||
llm_config = {
|
||||
"base_url": self.llm.base_url,
|
||||
"model": self.llm.model,
|
||||
"api_key": self.llm.api_key,
|
||||
}
|
||||
vmind_params = {
|
||||
"llm_config": llm_config,
|
||||
"user_prompt": chart_description,
|
||||
"dataset": dict_data,
|
||||
"file_name": file_name,
|
||||
"output_type": output_type,
|
||||
"insights_id": insights_id,
|
||||
"task_type": task_type,
|
||||
"directory": str(config.workspace_root),
|
||||
"language": language,
|
||||
}
|
||||
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
"npx",
|
||||
"ts-node",
|
||||
"src/chartVisualize.ts",
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
cwd=os.path.dirname(__file__),
|
||||
)
|
||||
input_json = json.dumps(vmind_params, ensure_ascii=False).encode("utf-8")
|
||||
try:
|
||||
stdout, stderr = await process.communicate(input_json)
|
||||
stdout_str = stdout.decode("utf-8")
|
||||
stderr_str = stderr.decode("utf-8")
|
||||
if process.returncode == 0:
|
||||
return json.loads(stdout_str)
|
||||
else:
|
||||
return {"error": f"Node.js Error: {stderr_str}"}
|
||||
except Exception as e:
|
||||
return {"error": f"Subprocess Error: {str(e)}"}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
from app.tool.chart_visualization.python_execute import NormalPythonExecute
|
||||
|
||||
|
||||
class VisualizationPrepare(NormalPythonExecute):
|
||||
"""A tool for Chart Generation Preparation"""
|
||||
|
||||
name: str = "visualization_preparation"
|
||||
description: str = "Using Python code to generates metadata of data_visualization tool. Outputs: 1) JSON Information. 2) Cleaned CSV data files (Optional)."
|
||||
description: str = """
|
||||
You need some charts to replace initial report's placeholders. So you need to use this tool first to prepare metadata for data_visualization tool.
|
||||
Using Python code to generates metadata of data_visualization tool. Outputs: 1) JSON Information. 2) Cleaned CSV data files (Optional).
|
||||
"""
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code_type": {
|
||||
"description": "code type, visualization: csv -> chart; insight: choose insight into chart",
|
||||
"description": "code type, visualization: csv -> chart",
|
||||
"type": "string",
|
||||
"default": "visualization",
|
||||
"enum": ["visualization", "insight"],
|
||||
"default": "visualization"
|
||||
},
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": """Python code for data_visualization prepare.
|
||||
## Visualization Type
|
||||
|
||||
## Visualization Type (Initial Step)
|
||||
1. Data loading logic
|
||||
2. Csv Data and chart description generate
|
||||
2.1 Csv data (The data you want to visulazation, cleaning / transform from origin data, saved in .csv)
|
||||
2.2 Chart description of csv data (The chart title or description should be concise and clear. Examples: 'Product sales distribution', 'Monthly revenue trend'.)
|
||||
2.1 Csv data (The data you want to visulazation, cleaning / transform from origin data, saved in .csv)
|
||||
2.2 Chart description of csv data (The chart title or description should be concise and clear. Examples: 'Product sales distribution', 'Monthly revenue trend'.)
|
||||
3. Save information in json file.( format: {"csvFilePath": string, "chartTitle": string}[])
|
||||
## Insight Type
|
||||
1. Select the insights from the data_visualization results that you want to add to the chart.
|
||||
2. Save information in json file.( format: {"chartPath": string, "insights_id": number[]}[])
|
||||
# Note
|
||||
1. You can generate one or multiple csv data with different visualization needs.
|
||||
2. Make each chart data esay, clean and different.
|
||||
3. Json file saving in utf-8 with path print: print(json_path)
|
||||
|
||||
|
||||
# Best Practices
|
||||
1. Generate one or multiple csv data with different visualization needs based on the initial report
|
||||
2. Make each chart data simple, clean and distinct
|
||||
4. Json file saving in utf-8 with path print: print(json_path)
|
||||
""",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -14,12 +14,8 @@ from app.tool.base import BaseTool
|
||||
|
||||
class DataVisualization(BaseTool):
|
||||
name: str = "data_visualization"
|
||||
description: str = """Visualize statistical chart or Add insights in chart with JSON info from visualization_preparation tool. You can do steps as follows:
|
||||
1. Visualize statistical chart
|
||||
2. Choose insights into chart based on step 1 (Optional)
|
||||
Outputs:
|
||||
1. Charts (png/html)
|
||||
2. Charts Insights (.md)(Optional)"""
|
||||
description: str = """Visualize statistical chart with JSON info from visualization_preparation tool.
|
||||
Outputs: Charts (png/html)"""
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -34,10 +30,9 @@ Outputs:
|
||||
"enum": ["png", "html"],
|
||||
},
|
||||
"tool_type": {
|
||||
"description": "visualize chart or add insights",
|
||||
"description": "visualize",
|
||||
"type": "string",
|
||||
"default": "visualization",
|
||||
"enum": ["visualization", "insight"],
|
||||
},
|
||||
"language": {
|
||||
"description": "english(en) / chinese(zh)",
|
||||
@@ -79,11 +74,43 @@ Outputs:
|
||||
raise Exception(f"No such file or directory: {item[path_str]}")
|
||||
return res
|
||||
|
||||
def load_chart_with_css(self, chart_path):
|
||||
# 读取 HTML 文件
|
||||
with open(chart_path, 'r', encoding='utf-8') as f:
|
||||
html_content = f.read()
|
||||
|
||||
# 在 <head> 里插入 CSS
|
||||
css = """
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#chart-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
"""
|
||||
|
||||
# 如果原文件没有 <head>,直接插入到最前面
|
||||
if "<head>" in html_content:
|
||||
html_content = html_content.replace("<head>", "<head>" + css)
|
||||
else:
|
||||
html_content = css + html_content
|
||||
|
||||
with open(chart_path, 'w', encoding='utf-8') as f:
|
||||
f.write(html_content)
|
||||
|
||||
def success_output_template(self, result: list[dict[str, str]]) -> str:
|
||||
content = ""
|
||||
if len(result) == 0:
|
||||
return "Is EMPTY!"
|
||||
for item in result:
|
||||
chart_path=item['chart_path']
|
||||
self.load_chart_with_css(chart_path)
|
||||
content += f"""## {item['title']}\nChart saved in: {item['chart_path']}"""
|
||||
if "insight_path" in item and item["insight_path"] and "insight_md" in item:
|
||||
content += "\n" + item["insight_md"]
|
||||
@@ -145,7 +172,7 @@ Outputs:
|
||||
else:
|
||||
return {"observation": f"{self.success_output_template(success_list)}"}
|
||||
|
||||
async def add_insighs(
|
||||
async def add_insights(
|
||||
self, json_info: list[dict[str, str]], output_type: str
|
||||
) -> str:
|
||||
data_list = []
|
||||
@@ -207,7 +234,7 @@ Outputs:
|
||||
if tool_type == "visualization":
|
||||
return await self.data_visualization(json_info, output_type, language)
|
||||
else:
|
||||
return await self.add_insighs(json_info, output_type)
|
||||
return await self.add_insights(json_info, output_type)
|
||||
except Exception as e:
|
||||
return {
|
||||
"observation": f"Error: {e}",
|
||||
|
||||
+28
-13
@@ -10,7 +10,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@visactor/vchart": "^1.13.7",
|
||||
"@visactor/vmind": "2.0.5",
|
||||
"@visactor/vmind": "2.0.6-alpha.2",
|
||||
"get-stdin": "^9.0.0",
|
||||
"puppeteer": "^24.9.0"
|
||||
},
|
||||
@@ -6319,9 +6319,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@visactor/calculator": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@visactor/calculator/-/calculator-2.0.5.tgz",
|
||||
"integrity": "sha512-/NBDB/wBQLeQuSspDBuiEAbbyfJS/xPX6mubVsLGhfy65UwUBojAQgmX25FcRJnUsRXooK5heshni19DBBf8xA==",
|
||||
"version": "2.0.6-alpha.2",
|
||||
"resolved": "https://registry.npmjs.org/@visactor/calculator/-/calculator-2.0.6-alpha.2.tgz",
|
||||
"integrity": "sha512-eSihYc5cTOeH3gFIW5lBBSWk1PDPDrO/dhaz3G6ZfRRx/wLNf5K1W1jCUaKeNcfcLyydB+6JH7u1k8vm2oIznw==",
|
||||
"dependencies": {
|
||||
"@visactor/vutils": "~0.19.3",
|
||||
"node-sql-parser": "~4.17.0",
|
||||
@@ -6329,13 +6329,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@visactor/chart-advisor": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@visactor/chart-advisor/-/chart-advisor-2.0.5.tgz",
|
||||
"integrity": "sha512-pvHceRlworB7kDSmbWXUtherLLXh5nMj0aEGuxtzKQyHmeO0sjuu9gGXBFIgscGliSZM4tmeNrFU9eBLGJ8dxw==",
|
||||
"version": "2.0.6-alpha.2",
|
||||
"resolved": "https://registry.npmjs.org/@visactor/chart-advisor/-/chart-advisor-2.0.6-alpha.2.tgz",
|
||||
"integrity": "sha512-QlhM5s3o48QtUDn0VmJB6xwYwBPgUh2SfxYosGKrbmajRFUb8e6I6LDKTNOda2dQ3/e0a04+zZIiDTpViMxkCw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@visactor/vutils": "~0.19.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@visactor/generate-vchart": {
|
||||
"version": "2.0.6-alpha.2",
|
||||
"resolved": "https://registry.npmjs.org/@visactor/generate-vchart/-/generate-vchart-2.0.6-alpha.2.tgz",
|
||||
"integrity": "sha512-Md62wBLtAwIZ/a04xRyCfgeFDy0sgwUiBei6vD6FoE+vgEkpp9+Vf0jpMXK1sTuxFa3nxi8GxcUsDmiNwEZJ9w==",
|
||||
"dependencies": {
|
||||
"@visactor/vchart-theme": "~1.12.2",
|
||||
"@visactor/vutils": "~0.19.3",
|
||||
"dayjs": "~1.11.10",
|
||||
"node-sql-parser": "~4.17.0",
|
||||
"ts-pattern": "~4.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@visactor/vchart": {
|
||||
"version": "1.13.8",
|
||||
"resolved": "https://registry.npmjs.org/@visactor/vchart/-/vchart-1.13.8.tgz",
|
||||
@@ -6496,14 +6509,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@visactor/vmind": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@visactor/vmind/-/vmind-2.0.5.tgz",
|
||||
"integrity": "sha512-QztQaeSkdeRZYOUlB4qaBpx3/swyO3JzFH8eYvSgvptS/rf8aQDZiufAUasafDLkcME5N6RpBGkcGYIDkmt74Q==",
|
||||
"version": "2.0.6-alpha.2",
|
||||
"resolved": "https://registry.npmjs.org/@visactor/vmind/-/vmind-2.0.6-alpha.2.tgz",
|
||||
"integrity": "sha512-bPuZ4U7dIxHbYnu1oSuddJc5HvRN194Yair9kYqlx4fBqNukHAqWAUEyCdir9YzyJVDvSdEJ7xqmvXecW5W3WQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stdlib/stats-base-dists-t-quantile": "0.2.1",
|
||||
"@visactor/calculator": "2.0.5",
|
||||
"@visactor/chart-advisor": "2.0.5",
|
||||
"@visactor/vchart-theme": "^1.11.2",
|
||||
"@visactor/calculator": "2.0.6-alpha.2",
|
||||
"@visactor/chart-advisor": "2.0.6-alpha.2",
|
||||
"@visactor/generate-vchart": "2.0.6-alpha.2",
|
||||
"@visactor/vchart-theme": "~1.12.2",
|
||||
"@visactor/vdataset": "~0.19.3",
|
||||
"@visactor/vutils": "~0.19.3",
|
||||
"alasql": "~4.3.2",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@visactor/vchart": "^1.13.7",
|
||||
"@visactor/vmind": "2.0.5",
|
||||
"@visactor/vmind": "2.0.6-alpha.2",
|
||||
"get-stdin": "^9.0.0",
|
||||
"puppeteer": "^24.9.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
from app.tool.chart_visualization.python_execute import NormalPythonExecute
|
||||
class SelectInsights(NormalPythonExecute):
|
||||
name: str = "insights_selection"
|
||||
description: str = (
|
||||
"This tool analyzes data_visualization tool's outputs and identifies key data insights for each chart."
|
||||
"based on their importance ranking. Insights are prioritized in three tiers:\n"
|
||||
"1 **Critical Insights**: 'abnormal_trend', 'abnormal_band', 'turning_point', 'overall_trend'\n"
|
||||
"2 **Important Insights**: 'outlier', 'extreme_value', 'majority_value', 'avg'\n"
|
||||
"3 **Basic Insights**: 'min', 'max'\n\n"
|
||||
"**!Must be called immediately after data_visualization completes!**"
|
||||
"**!All insights_id must come from the data_visualization analysis results!**"
|
||||
|
||||
)
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": """Python code to analyze visualized charts and extract insights.
|
||||
|
||||
# PRIORITY REQUIREMENTS
|
||||
Insights must be selected and ranked according to these importance tiers:
|
||||
1. **First Priority**: Always include 'abnormal_trend', 'abnormal_band', 'turning_point', 'overall_trend' when present
|
||||
2. **Second Priority**: Include 'outlier', 'extreme_value', 'majority_value', 'avg' if no first-tier insights exist
|
||||
3. **Third Priority**: Fall back to 'min', 'max' only when no higher-priority insights are available
|
||||
|
||||
# EXECUTION REQUIREMENTS
|
||||
1. **Timing**: MUST be called immediately after data_visualization completes
|
||||
2. **Dependency**: MUST use insights from data_visualization output as the only source for insights_id
|
||||
|
||||
|
||||
# CODE REQUIREMENTS
|
||||
Your Python code must:
|
||||
1. Analyze the data_visualization results to identify significant insights for each chart.
|
||||
2. Save the findings in JSON format:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"chartPath": "string", // Path to the generated chart
|
||||
"insights_id": number[] // Array of key insight IDs FROM DATA_VISUALIZATION RESULTS
|
||||
},
|
||||
{
|
||||
"chartPath": "string", // Path to the generated chart
|
||||
"insights_id": number[] // Array of key insight IDs FROM DATA_VISUALIZATION RESULTS
|
||||
},
|
||||
...
|
||||
]
|
||||
```
|
||||
Json file saving in utf-8 with path print: print(json_path)
|
||||
""",
|
||||
},
|
||||
},
|
||||
"required": ["code"],
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import puppeteer from "puppeteer";
|
||||
import VMind, { ChartType, DataTable } from "@visactor/vmind";
|
||||
import VMind, { ChartType } from "@visactor/vmind";
|
||||
import type { DataTable } from '@visactor/generate-vchart';
|
||||
import { isString } from "@visactor/vutils";
|
||||
|
||||
enum AlgorithmType {
|
||||
@@ -63,8 +64,7 @@ function getHtmlVChart(spec: any, width?: number, height?: number) {
|
||||
<script src="https://unpkg.com/@visactor/vchart/build/index.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="chart-container" style="width: ${
|
||||
width ? `${width}px` : "100%"
|
||||
<div id="chart-container" style="width: ${width ? `${width}px` : "100%"
|
||||
}; height: ${height ? `${height}px` : "100%"};"></div>
|
||||
<script>
|
||||
// parse spec with function
|
||||
@@ -82,7 +82,7 @@ function getHtmlVChart(spec: any, width?: number, height?: number) {
|
||||
return v;
|
||||
});
|
||||
}
|
||||
const spec = parseSpec(\`${serializeSpec(spec)}\`);
|
||||
const spec = parseSpec(\'${serializeSpec(spec)}\');
|
||||
const chart = new VChart.VChart(spec, {
|
||||
dom: 'chart-container'
|
||||
});
|
||||
@@ -242,7 +242,7 @@ async function generateChart(
|
||||
ChartType.AreaChart,
|
||||
ChartType.ScatterPlot,
|
||||
ChartType.DualAxisChart,
|
||||
].includes(chartType)
|
||||
].includes(chartType as ChartType)
|
||||
) {
|
||||
const { insights: vmindInsights } = await vmind.getInsights(spec, {
|
||||
maxNum: 6,
|
||||
@@ -295,11 +295,14 @@ async function updateChartWithInsight(
|
||||
}
|
||||
) {
|
||||
const { directory, outputType, fileName, insightsId } = options;
|
||||
//???????为什么打印不出来???????
|
||||
//console.log(options)
|
||||
let res: { error?: string; chart_path?: string } = {};
|
||||
try {
|
||||
const specPath = getSavedPathName(directory, fileName, "json", true);
|
||||
const spec = JSON.parse(fs.readFileSync(specPath, "utf8"));
|
||||
// llm select index from 1
|
||||
//console.log(spec)
|
||||
const insights = (spec.insights || []).filter(
|
||||
(_insight: any, index: number) => insightsId.includes(index + 1)
|
||||
);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import asyncio
|
||||
|
||||
import os
|
||||
import sys
|
||||
print(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
|
||||
from app.agent.data_analysis import DataAnalysis
|
||||
from app.logger import logger
|
||||
|
||||
@@ -7,173 +10,87 @@ from app.logger import logger
|
||||
prefix = "Help me generate charts and save them locally, specifically:"
|
||||
tasks = [
|
||||
{
|
||||
"prompt": "Help me show the sales of different products in different regions",
|
||||
"data": """Product Name,Region,Sales
|
||||
Coke,South,2350
|
||||
Coke,East,1027
|
||||
Coke,West,1027
|
||||
Coke,North,1027
|
||||
Sprite,South,215
|
||||
Sprite,East,654
|
||||
Sprite,West,159
|
||||
Sprite,North,28
|
||||
Fanta,South,345
|
||||
Fanta,East,654
|
||||
Fanta,West,2100
|
||||
Fanta,North,1679
|
||||
Xingmu,South,1476
|
||||
Xingmu,East,830
|
||||
Xingmu,West,532
|
||||
Xingmu,North,498
|
||||
""",
|
||||
},
|
||||
{
|
||||
"prompt": "Show market share of each brand",
|
||||
"data": """Brand Name,Market Share,Average Price,Net Profit
|
||||
Apple,0.5,7068,314531
|
||||
Samsung,0.2,6059,362345
|
||||
Vivo,0.05,3406,234512
|
||||
Nokia,0.01,1064,-1345
|
||||
Xiaomi,0.1,4087,131345""",
|
||||
},
|
||||
{
|
||||
"prompt": "Please help me show the sales trend of each product",
|
||||
"data": """Date,Type,Value
|
||||
2023-01-01,Product A,52.9
|
||||
2023-01-01,Product B,63.6
|
||||
2023-01-01,Product C,11.2
|
||||
2023-01-02,Product A,45.7
|
||||
2023-01-02,Product B,89.1
|
||||
2023-01-02,Product C,21.4
|
||||
2023-01-03,Product A,67.2
|
||||
2023-01-03,Product B,82.4
|
||||
2023-01-03,Product C,31.7
|
||||
2023-01-04,Product A,80.7
|
||||
2023-01-04,Product B,55.1
|
||||
2023-01-04,Product C,21.1
|
||||
2023-01-05,Product A,65.6
|
||||
2023-01-05,Product B,78
|
||||
2023-01-05,Product C,31.3
|
||||
2023-01-06,Product A,75.6
|
||||
2023-01-06,Product B,89.1
|
||||
2023-01-06,Product C,63.5
|
||||
2023-01-07,Product A,67.3
|
||||
2023-01-07,Product B,77.2
|
||||
2023-01-07,Product C,43.7
|
||||
2023-01-08,Product A,96.1
|
||||
2023-01-08,Product B,97.6
|
||||
2023-01-08,Product C,59.9
|
||||
2023-01-09,Product A,96.1
|
||||
2023-01-09,Product B,100.6
|
||||
2023-01-09,Product C,66.8
|
||||
2023-01-10,Product A,101.6
|
||||
2023-01-10,Product B,108.3
|
||||
2023-01-10,Product C,56.9""",
|
||||
},
|
||||
{
|
||||
"prompt": "Show the popularity of search keywords",
|
||||
"data": """Keyword,Popularity
|
||||
Hot Word,1000
|
||||
Zao Le Wo Men,800
|
||||
Rao Jian Huo,400
|
||||
My Wish is World Peace,400
|
||||
Xiu Xiu Xiu,400
|
||||
Shenzhou 11,400
|
||||
Hundred Birds Facing the Wind,400
|
||||
China Women's Volleyball Team,400
|
||||
My Guan Na,400
|
||||
Leg Dong,400
|
||||
Hot Pot Hero,400
|
||||
Baby's Heart is Bitter,400
|
||||
Olympics,400
|
||||
Awesome My Brother,400
|
||||
Poetry and Distance,400
|
||||
Song Joong-ki,400
|
||||
PPAP,400
|
||||
Blue Thin Mushroom,400
|
||||
Rain Dew Evenly,400
|
||||
Friendship's Little Boat Says It Flips,400
|
||||
Beijing Slump,400
|
||||
Dedication,200
|
||||
Apple,200
|
||||
Dog Belt,200
|
||||
Old Driver,200
|
||||
Melon-Eating Crowd,200
|
||||
Zootopia,200
|
||||
City Will Play,200
|
||||
Routine,200
|
||||
Water Reverse,200
|
||||
Why Don't You Go to Heaven,200
|
||||
Snake Spirit Man,200
|
||||
Why Don't You Go to Heaven,200
|
||||
Samsung Explosion Gate,200
|
||||
Little Li Oscar,200
|
||||
Ugly People Need to Read More,200
|
||||
Boyfriend Power,200
|
||||
A Face of Confusion,200
|
||||
Descendants of the Sun,200""",
|
||||
},
|
||||
{
|
||||
"prompt": "Help me compare the performance of different electric vehicle brands using a scatter plot",
|
||||
"data": """Range,Charging Time,Brand Name,Average Price
|
||||
2904,46,Brand1,2350
|
||||
1231,146,Brand2,1027
|
||||
5675,324,Brand3,1242
|
||||
543,57,Brand4,6754
|
||||
326,234,Brand5,215
|
||||
1124,67,Brand6,654
|
||||
3426,81,Brand7,159
|
||||
2134,24,Brand8,28
|
||||
1234,52,Brand9,345
|
||||
2345,27,Brand10,654
|
||||
526,145,Brand11,2100
|
||||
234,93,Brand12,1679
|
||||
567,94,Brand13,1476
|
||||
789,45,Brand14,830
|
||||
469,75,Brand15,532
|
||||
5689,54,Brand16,498
|
||||
""",
|
||||
},
|
||||
{
|
||||
"prompt": "Show conversion rates for each process",
|
||||
"data": """Process,Conversion Rate,Month
|
||||
Step1,100,1
|
||||
Step2,80,1
|
||||
Step3,60,1
|
||||
Step4,40,1""",
|
||||
},
|
||||
{
|
||||
"prompt": "Show the difference in breakfast consumption between men and women",
|
||||
"data": """Day,Men-Breakfast,Women-Breakfast
|
||||
Monday,15,22
|
||||
Tuesday,12,10
|
||||
Wednesday,15,20
|
||||
Thursday,10,12
|
||||
Friday,13,15
|
||||
Saturday,10,15
|
||||
Sunday,12,14""",
|
||||
},
|
||||
{
|
||||
"prompt": "Help me show this person's performance in different aspects, is he a hexagonal warrior",
|
||||
"data": """dimension,performance
|
||||
Strength,5
|
||||
Speed,5
|
||||
Shooting,3
|
||||
Endurance,5
|
||||
Precision,5
|
||||
Growth,5""",
|
||||
},
|
||||
{
|
||||
"prompt": "Show data flow",
|
||||
"data": """Origin,Destination,value
|
||||
Node A,Node 1,10
|
||||
Node A,Node 2,5
|
||||
Node B,Node 2,8
|
||||
Node B,Node 3,2
|
||||
Node C,Node 2,4
|
||||
Node A,Node C,2
|
||||
Node C,Node 1,2""",
|
||||
},
|
||||
"prompt": "Help me show the daily sales performance metrics over time. ",
|
||||
"data":
|
||||
"""Table: 每日销售数据明细
|
||||
OrderDate,RegionCode,SalesAmount,DataQuality
|
||||
2023-04-01,SW,25860.24,正常
|
||||
2023-04-01,NE,5877.65,正常
|
||||
2023-04-01,C,34271.58,正常
|
||||
2023-04-01,N,6251.42,正常
|
||||
2023-04-01,E,3113.46,正常
|
||||
2023-04-02,NW,87717.84,正常
|
||||
2023-04-02,E,53058.96,正常
|
||||
2023-04-02,N,14409.92,正常
|
||||
2023-04-02,NE,5540.92,正常
|
||||
2023-04-03,C,41802.49,正常
|
||||
2023-04-03,NE,9202.20,正常
|
||||
2023-04-03,SW,583.30,正常
|
||||
2023-04-03,N,560.56,正常
|
||||
2023-04-03,E,96269.32,正常
|
||||
2023-04-04,NE,106208.48,正常
|
||||
2023-04-04,C,6231.62,正常
|
||||
2023-04-04,E,84454.83,正常
|
||||
2023-04-05,NE,312.82,正常
|
||||
2023-04-05,SW,5718.89,正常
|
||||
2023-04-05,C,39811.91,正常
|
||||
2023-04-05,E,244163.47,正常
|
||||
2023-04-05,N,79487.41,正常
|
||||
2023-04-06,C,28648.34,正常
|
||||
2023-04-06,N,18288.76,正常
|
||||
2023-04-08,SW,67434.58,正常
|
||||
2023-04-08,C,1176.00,正常
|
||||
2023-04-08,NW,81264.54,正常
|
||||
2023-04-08,E,87750.96,正常
|
||||
2023-04-09,SW,67434.58,正常
|
||||
2023-04-09,C,5902.34,正常
|
||||
2023-04-09,E,22252.27,正常
|
||||
2023-04-09,NE,98844.76,正常
|
||||
2023-04-10,E,2677.36,正常
|
||||
2023-04-10,SW,1444.52,正常
|
||||
2023-04-10,NE,62082.61,正常
|
||||
2023-04-10,C,677.38,正常
|
||||
2023-04-11,SW,776.16,正常
|
||||
2023-04-11,C,7487.00,正常
|
||||
2023-04-11,E,57016.40,正常
|
||||
2023-04-12,SW,7131.85,正常
|
||||
2023-04-12,E,11837.81,正常
|
||||
2023-04-12,C,207763.14,正常
|
||||
2023-04-13,C,24299.30,正常
|
||||
2023-04-13,E,9847.04,正常
|
||||
2023-04-13,NE,15919.12,正常
|
||||
2023-04-15,SW,33544.42,正常
|
||||
2023-04-15,C,39935.98,正常
|
||||
2023-04-15,N,60416.80,正常
|
||||
2023-04-15,NE,1234.80,正常
|
||||
2023-04-15,E,36007.16,正常
|
||||
2023-04-16,E,108484.04,正常
|
||||
2023-04-16,SW,2450.00,正常
|
||||
2023-04-17,E,78099.14,正常
|
||||
2023-04-17,C,49350.84,正常
|
||||
2023-04-17,N,18480.84,正常
|
||||
2023-04-18,NE,48419.84,正常
|
||||
2023-04-18,C,118951.67,正常
|
||||
2023-04-18,N,10853.89,正常
|
||||
2023-04-18,SW,1627.58,正常
|
||||
2023-04-18,E,32777.28,正常
|
||||
2023-04-19,N,41905.78,正常
|
||||
2023-04-19,E,47942.58,正常
|
||||
2023-04-19,NE,48259.51,正常
|
||||
2023-04-19,C,18021.22,正常
|
||||
2023-04-22,NE,58530.50,正常
|
||||
2023-04-22,E,22004.72,正常
|
||||
2023-04-22,C,7729.26,正常
|
||||
2023-04-23,E,49218.54,正常
|
||||
2023-04-23,NE,13944.42,正常
|
||||
2023-04-23,SW,3843.56,正常
|
||||
2023-04-24,SW,16754.08,正常
|
||||
2023-04-24,NE,2343.18,正常
|
||||
2023-04-24,E,41413.82,正常
|
||||
2023-04-24,C,723.24,正常
|
||||
2023-04-25,C,10678.08,正常
|
||||
2023-04-25,E,44791.10,正常"""
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
print(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
|
||||
from app.agent.data_analysis import DataAnalysis
|
||||
from app.agent.manus import Manus
|
||||
|
||||
|
||||
# from app.agent.manus import Manus
|
||||
|
||||
|
||||
async def main():
|
||||
# agent = DataAnalysis()
|
||||
agent = Manus()
|
||||
await agent.run(
|
||||
"""Requirement: Analyze the following data and generate a simple data report with some charts in HTML format.
|
||||
|
||||
Table1: 学生基本信息
|
||||
Name,Age,Gender,Grade,Class,StudentID,EnrollmentDate,GuardianName,GuardianPhone,Address,PreviousSchool
|
||||
王悦,16,女,高一,3班,S20230147,2023-09-01,王建国,138-1234-5678,北京市海淀区学院路101号,海淀实验中学
|
||||
|
||||
Table2: 学科成绩详细数据
|
||||
Subject,Teacher,TestType,TestDate,Score,ClassRank,GradeRank,ScoreChange,DifficultyLevel
|
||||
数学,张老师,单元测验,2023-09-05,82,12,45,-,中等
|
||||
数学,张老师,周测,2023-09-12,85,10,38,+3,中等
|
||||
数学,张老师,月考,2023-09-28,87,8,35,+2,中等偏难
|
||||
数学,张老师,期中考试,2023-10-15,92,5,22,+5,难
|
||||
语文,李老师,单元测验,2023-09-06,80,15,50,-,中等
|
||||
语文,李老师,周测,2023-09-13,83,12,42,+3,中等
|
||||
语文,李老师,月考,2023-09-29,85,10,40,+2,中等偏难
|
||||
语文,李老师,期中考试,2023-10-16,88,8,35,+3,难
|
||||
英语,王老师,单元测验,2023-09-07,87,8,30,-,中等
|
||||
英语,王老师,周测,2023-09-14,89,6,25,+2,中等
|
||||
英语,王老师,月考,2023-09-30,90,5,20,+1,中等偏难
|
||||
英语,王老师,期中考试,2023-10-17,93,4,18,+3,难
|
||||
物理,刘老师,单元测验,2023-09-08,75,18,65,-,难
|
||||
物理,刘老师,周测,2023-09-15,77,16,60,+2,难
|
||||
物理,刘老师,月考,2023-10-01,78,15,58,+1,难
|
||||
物理,刘老师,期中考试,2023-10-18,85,12,40,+7,中等偏难
|
||||
化学,陈老师,单元测验,2023-09-09,79,14,55,-,中等偏难
|
||||
化学,陈老师,周测,2023-09-16,81,12,50,+2,中等偏难
|
||||
化学,陈老师,月考,2023-10-02,82,11,48,+1,中等偏难
|
||||
化学,陈老师,期中考试,2023-10-19,84,10,45,+2,中等
|
||||
|
||||
Table3: 学习行为日数据(2023年9月)
|
||||
Date,Weekday,StudyHours,HomeworkHours,ReadingMinutes,ScreenTime,PhysicalActivity,ClassAttendance,ParticipationScore,SleepHours,MoodScore
|
||||
2023-09-01,周五,3.5,2.0,45,1.5,1.0,出勤,85,8.2,4
|
||||
2023-09-02,周六,4.0,1.5,30,2.0,0.8,出勤,90,7.8,5
|
||||
2023-09-03,周日,3.0,2.5,60,1.0,1.2,出勤,88,8.5,4
|
||||
2023-09-04,周一,5.0,2.0,50,1.2,0.7,出勤,92,7.9,5
|
||||
2023-09-05,周二,4.5,1.8,40,1.8,1.0,出勤,87,8.0,4
|
||||
2023-09-06,周三,3.8,2.2,55,1.3,0.9,出勤,89,8.3,5
|
||||
2023-09-07,周四,4.2,1.7,35,1.6,1.1,出勤,91,7.7,4
|
||||
2023-09-08,周五,3.5,2.1,48,1.4,0.8,出勤,86,8.1,3
|
||||
2023-09-09,周六,4.8,1.9,42,1.7,1.3,出勤,93,7.6,5
|
||||
2023-09-10,周日,3.2,2.3,52,1.1,0.7,出勤,88,8.4,4
|
||||
2023-09-11,周一,4.5,1.6,38,1.9,1.0,出勤,90,7.9,5
|
||||
2023-09-12,周二,3.9,2.4,57,1.2,0.9,出勤,87,8.2,4
|
||||
2023-09-13,周三,4.1,1.8,44,1.5,1.2,出勤,91,7.8,5
|
||||
2023-09-14,周四,3.7,2.6,49,1.4,0.8,出勤,89,8.3,4
|
||||
2023-09-15,周五,4.3,1.9,36,1.8,1.1,出勤,92,7.7,5
|
||||
2023-09-16,周六,3.4,2.2,53,1.3,0.9,出勤,86,8.1,4
|
||||
2023-09-17,周日,4.6,1.7,41,1.6,1.3,出勤,90,7.6,5
|
||||
2023-09-18,周一,3.8,2.5,47,1.2,0.7,出勤,88,8.4,4
|
||||
2023-09-19,周二,4.2,1.8,39,1.7,1.0,出勤,91,7.9,5
|
||||
2023-09-20,周三,3.9,2.3,51,1.4,0.8,出勤,87,8.2,4
|
||||
2023-09-21,周四,4.4,1.6,43,1.5,1.2,出勤,93,7.8,5
|
||||
2023-09-22,周五,3.6,2.4,46,1.3,0.9,出勤,89,8.3,4
|
||||
2023-09-23,周六,4.7,1.9,37,1.8,1.1,出勤,86,7.7,5
|
||||
2023-09-24,周日,3.5,2.1,50,1.4,0.8,出勤,90,8.1,4
|
||||
2023-09-25,周一,4.3,1.7,42,1.6,1.3,出勤,88,7.6,5
|
||||
2023-09-26,周二,3.8,2.6,48,1.2,0.7,出勤,91,8.4,4
|
||||
2023-09-27,周三,4.1,1.8,40,1.7,1.0,出勤,87,7.9,5
|
||||
2023-09-28,周四,3.9,2.3,52,1.5,0.9,出勤,92,8.2,4
|
||||
2023-09-29,周五,4.5,1.6,45,1.4,1.2,出勤,89,7.8,5
|
||||
2023-09-30,周六,3.7,2.4,44,1.3,0.8,出勤,86,8.3,4
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,75 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
print(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
|
||||
from app.agent.data_analysis import DataAnalysis
|
||||
from app.agent.manus import Manus
|
||||
|
||||
|
||||
# from app.agent.manus import Manus
|
||||
|
||||
|
||||
async def main():
|
||||
# agent = DataAnalysis()
|
||||
agent = Manus()
|
||||
await agent.run(
|
||||
"""Requirement: Analyze the following data and generate a graphical data report in HTML format. The final product should be a data report.
|
||||
Table1: 用户基本信息
|
||||
Name,Age,Gender,Height(cm),Weight(kg),MeasureDate
|
||||
张三,45,男,170,98.6,2023-10-01
|
||||
|
||||
Table2: 身体成分数据
|
||||
Date,BodyFat(%),MuscleMass(kg),WaterContent(%),BoneMass(kg),VisceralFat,Protein(%)
|
||||
2023-10-01,35.2,42.3,43.1,2.8,18,14.2
|
||||
|
||||
Table3: 每日营养活动数据
|
||||
Date,CaloriesIntake(kcal),CaloriesBurned(kcal),ProteinIntake(g),CarbIntake(g),FatIntake(g),Steps,ActiveMinutes,SleepHours,MorningWeight(kg)
|
||||
2023-09-01,3850,1250,85,480,120,3200,12,5.2,99.2
|
||||
2023-09-02,4200,1100,90,520,135,2800,8,4.8,99.5
|
||||
2023-09-03,3600,950,78,450,110,2500,5,5.5,99.8
|
||||
2023-09-04,3950,1050,82,490,125,2900,10,4.5,100.1
|
||||
2023-09-05,4100,1150,88,510,130,3100,15,5.0,100.3
|
||||
2023-09-06,3750,980,80,460,115,2600,6,4.7,100.6
|
||||
2023-09-07,4300,1200,92,540,140,3300,18,4.3,100.9
|
||||
2023-09-08,3450,900,75,430,105,2400,4,5.2,101.2
|
||||
2023-09-09,4000,1000,84,500,122,2700,9,4.9,101.5
|
||||
2023-09-10,3800,975,79,470,118,2550,7,5.1,101.8
|
||||
2023-09-11,4150,1100,86,515,128,3000,14,4.6,102.0
|
||||
2023-09-12,3550,925,77,440,108,2300,3,5.4,102.3
|
||||
2023-09-13,4250,1180,94,530,138,3400,20,4.2,102.6
|
||||
2023-09-14,3700,990,81,465,113,2650,8,5.3,102.9
|
||||
2023-09-15,4050,1070,87,505,127,2950,13,4.8,103.1
|
||||
2023-09-16,3500,910,76,435,104,2250,2,5.6,103.4
|
||||
2023-09-17,3900,1020,83,485,120,2750,11,4.7,103.7
|
||||
2023-09-18,4350,1250,96,550,145,3500,22,4.0,104.0
|
||||
2023-09-19,3650,960,79,455,112,2450,5,5.2,104.3
|
||||
2023-09-20,4000,1030,85,495,124,2850,12,4.9,104.5
|
||||
2023-09-21,3450,890,74,425,103,2200,1,5.5,104.8
|
||||
2023-09-22,3850,995,82,475,119,2700,10,4.6,105.1
|
||||
2023-09-23,4100,1120,89,515,131,3050,16,4.3,105.4
|
||||
2023-09-24,3550,935,77,440,107,2350,4,5.4,105.7
|
||||
2023-09-25,3950,1010,84,490,123,2800,13,4.8,106.0
|
||||
2023-09-26,4200,1150,91,525,136,3200,19,4.1,106.3
|
||||
2023-09-27,3600,945,78,445,109,2400,6,5.3,106.6
|
||||
2023-09-28,4050,1080,87,505,128,2900,15,4.7,106.9
|
||||
2023-09-29,3750,970,80,460,116,2600,9,5.0,107.2
|
||||
2023-09-30,4300,1220,95,540,142,3350,23,3.9,107.5
|
||||
|
||||
Table4: 健康指标参考范围
|
||||
Category,SubCategory,Range,Unit
|
||||
BMI,Underweight,<18.5,kg/m²
|
||||
BMI,Normal,18.5-24.9,kg/m²
|
||||
BMI,Overweight,25-29.9,kg/m²
|
||||
BMI,Obese,≥30,kg/m²
|
||||
BodyFat,Male(40-59),11-22,%
|
||||
BodyFat,Female(40-59),23-34,%
|
||||
VisceralFat,Normal,1-9,Level
|
||||
VisceralFat,High,10-14,Level
|
||||
VisceralFat,Very High,≥15,Level
|
||||
Sleep,Recommended,7-9,hours
|
||||
Steps,Active,≥10000,steps/day
|
||||
"""
|
||||
)
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,123 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
print(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
|
||||
from app.agent.data_analysis import DataAnalysis
|
||||
from app.agent.manus import Manus
|
||||
|
||||
|
||||
# from app.agent.manus import Manus
|
||||
|
||||
|
||||
async def main():
|
||||
# agent = DataAnalysis()
|
||||
agent = Manus()
|
||||
await agent.run(
|
||||
"""Requirement: Analyze the following data and generate a graphical data report in HTML format. The final product should be a data report.
|
||||
Table1: 销售区域基本信息
|
||||
RegionCode,RegionName,Description
|
||||
SW,西南,西南地区销售数据
|
||||
NE,东北,东北地区销售数据
|
||||
C,中南,中南地区销售数据
|
||||
N,华北,华北地区销售数据
|
||||
E,华东,华东地区销售数据
|
||||
NW,西北,西北地区销售数据
|
||||
|
||||
Table2: 每日销售数据明细
|
||||
OrderDate,RegionCode,SalesAmount,DataQuality
|
||||
2023-04-01,SW,25860.24,正常
|
||||
2023-04-01,NE,5877.65,正常
|
||||
2023-04-01,C,34271.58,正常
|
||||
2023-04-01,N,6251.42,正常
|
||||
2023-04-01,E,3113.46,正常
|
||||
2023-04-02,NW,87717.84,正常
|
||||
2023-04-02,E,53058.96,正常
|
||||
2023-04-02,N,14409.92,正常
|
||||
2023-04-02,NE,5540.92,正常
|
||||
2023-04-03,C,41802.49,正常
|
||||
2023-04-03,NE,9202.20,正常
|
||||
2023-04-03,SW,583.30,正常
|
||||
2023-04-03,N,560.56,正常
|
||||
2023-04-03,E,96269.32,正常
|
||||
2023-04-04,NE,106208.48,正常
|
||||
2023-04-04,C,6231.62,正常
|
||||
2023-04-04,E,84454.83,正常
|
||||
2023-04-05,NE,312.82,正常
|
||||
2023-04-05,SW,5718.89,正常
|
||||
2023-04-05,C,39811.91,正常
|
||||
2023-04-05,E,244163.47,正常
|
||||
2023-04-05,N,79487.41,正常
|
||||
2023-04-06,C,28648.34,正常
|
||||
2023-04-06,N,18288.76,正常
|
||||
2023-04-08,SW,67434.58,正常
|
||||
2023-04-08,C,1176.00,正常
|
||||
2023-04-08,NW,81264.54,正常
|
||||
2023-04-08,E,87750.96,正常
|
||||
2023-04-09,SW,67434.58,正常
|
||||
2023-04-09,C,5902.34,正常
|
||||
2023-04-09,E,22252.27,正常
|
||||
2023-04-09,NE,98844.76,正常
|
||||
2023-04-10,E,2677.36,正常
|
||||
2023-04-10,SW,1444.52,正常
|
||||
2023-04-10,NE,62082.61,正常
|
||||
2023-04-10,C,677.38,正常
|
||||
2023-04-11,SW,776.16,正常
|
||||
2023-04-11,C,7487.00,正常
|
||||
2023-04-11,E,57016.40,正常
|
||||
2023-04-12,SW,7131.85,正常
|
||||
2023-04-12,E,11837.81,正常
|
||||
2023-04-12,C,207763.14,正常
|
||||
2023-04-13,C,24299.30,正常
|
||||
2023-04-13,E,9847.04,正常
|
||||
2023-04-13,NE,15919.12,正常
|
||||
2023-04-15,SW,33544.42,正常
|
||||
2023-04-15,C,39935.98,正常
|
||||
2023-04-15,N,60416.80,正常
|
||||
2023-04-15,NE,1234.80,正常
|
||||
2023-04-15,E,36007.16,正常
|
||||
2023-04-16,E,108484.04,正常
|
||||
2023-04-16,SW,2450.00,正常
|
||||
2023-04-17,E,78099.14,正常
|
||||
2023-04-17,C,49350.84,正常
|
||||
2023-04-17,N,18480.84,正常
|
||||
2023-04-18,NE,48419.84,正常
|
||||
2023-04-18,C,118951.67,正常
|
||||
2023-04-18,N,10853.89,正常
|
||||
2023-04-18,SW,1627.58,正常
|
||||
2023-04-18,E,32777.28,正常
|
||||
2023-04-19,N,41905.78,正常
|
||||
2023-04-19,E,47942.58,正常
|
||||
2023-04-19,NE,48259.51,正常
|
||||
2023-04-19,C,18021.22,正常
|
||||
2023-04-22,NE,58530.50,正常
|
||||
2023-04-22,E,22004.72,正常
|
||||
2023-04-22,C,7729.26,正常
|
||||
2023-04-23,E,49218.54,正常
|
||||
2023-04-23,NE,13944.42,正常
|
||||
2023-04-23,SW,3843.56,正常
|
||||
2023-04-24,SW,16754.08,正常
|
||||
2023-04-24,NE,2343.18,正常
|
||||
2023-04-24,E,41413.82,正常
|
||||
2023-04-24,C,723.24,正常
|
||||
2023-04-25,C,10678.08,正常
|
||||
2023-04-25,E,44791.10,正常
|
||||
|
||||
Table3: 销售指标分析参考
|
||||
Category,SubCategory,Range,Level,Description
|
||||
销售金额,日销售额,>50000,优秀,单日销售额超过5万
|
||||
销售金额,日销售额,20000-50000,良好,单日销售额2-5万
|
||||
销售金额,日销售额,5000-20000,一般,单日销售额0.5-2万
|
||||
销售金额,日销售额,<5000,待提升,单日销售额低于5千
|
||||
区域表现,华东地区,持续领先,优秀,销售额稳定高位
|
||||
区域表现,中南地区,波动较大,关注,销售额波动明显
|
||||
区域表现,西南地区,整体偏低,待提升,需要业务拓展
|
||||
数据完整性,日期覆盖,4月1-25日,完整,覆盖主要业务日期
|
||||
数据质量,金额精度,两位小数,标准,财务数据标准格式
|
||||
业务连续性,工作日,正常营业,良好,除周末外正常营业
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,47 @@
|
||||
from app.tool.chart_visualization.python_execute import NormalPythonExecute
|
||||
|
||||
class GenerateFinalReport(NormalPythonExecute):
|
||||
"""A tool for generating final data analysis report"""
|
||||
|
||||
name: str = "generate_final_report"
|
||||
description: str = """Replace the all placeholders in initial report and refine to generate final report.
|
||||
Outputs: 1) HTML report file path"""
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code_type": {
|
||||
"description": "code type, replacing: html with placeholders -> html with specific chart; check_refine: Make final adjustments and checks on the report",
|
||||
"type": "string",
|
||||
"default": "replacing",
|
||||
"enum": ["replacing", "check_refine"],
|
||||
},
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": """Python code for replacing chart placeholders with specific chart file path, or for report checking and refining.
|
||||
# Replacing Type
|
||||
1. Find all placeholders
|
||||
2. When replacing the chart path placeholder, use a relative path. ** src="/workspace/visualization/chart_name.html" **
|
||||
3. When replacing the text placeholders, generate a detailed text description.
|
||||
**When filling in the key insights below the charts, the insights must correspond with those previously added by the add insight tool.**
|
||||
|
||||
## Notice:
|
||||
Use the absolute path starting with /workspace, for example, **/workspace/visualization/chart_name.html**
|
||||
|
||||
# Check_refine Type:
|
||||
1. Check the entire html file
|
||||
- Have all placeholders been filled?
|
||||
- Whether the path of the chart is: /workspace/visualization/***.html
|
||||
- If text-related placeholders still exist, please fill them in as much as possible. If chart path placeholders still exist, please delete that chart part of the report.
|
||||
**When filling in the key insights below the charts, the insights must correspond with those previously added by the add insight tool.**
|
||||
|
||||
|
||||
|
||||
## Output Requirements
|
||||
1. Generate **report.html** file
|
||||
2. Print the file path: print(report_path)
|
||||
3. Make sure the HTML includes Bootstrap for responsive design
|
||||
""",
|
||||
},
|
||||
},
|
||||
"required": ["code", "code_type"],
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
from app.tool.chart_visualization.python_execute import NormalPythonExecute
|
||||
from typing import ClassVar
|
||||
from pathlib import Path
|
||||
|
||||
class GenerateInitialReport(NormalPythonExecute):
|
||||
"""A tool for generating initial data analysis reports based on the report template and user's input data"""
|
||||
|
||||
name: str = "generate_initial_report"
|
||||
description: str = """Generates an initial HTML data analysis report based on the report template and user's input data.
|
||||
After searhing and reading the report template, you should dynamically adapt the template content according to user input data,
|
||||
intelligently determine which charts should be included in the report,
|
||||
and automatically populate the fillable placeholders with corresponding data.
|
||||
|
||||
Outputs: 1) HTML report file path"""
|
||||
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": f"""Python code for generating initial HTML data report based on the report template and user's input data.
|
||||
|
||||
## Output Requirements
|
||||
1. Generate initial_report.html file
|
||||
2. Print the file path: print(report_path)
|
||||
|
||||
# Notes:
|
||||
1. Refer to the searched report templates
|
||||
2. Complete the applicable placeholders, and leave any unfilled ones as '[placeholder: ...]'.
|
||||
|
||||
""",
|
||||
},
|
||||
},
|
||||
"required": ["code", "code_type"],
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
from app.tool.chart_visualization.python_execute import NormalPythonExecute
|
||||
|
||||
class ReportBeautify(NormalPythonExecute):
|
||||
"""A tool for transforming a basic health report into a professional, visually appealing final version"""
|
||||
|
||||
name: str = "report_beautify"
|
||||
description: str = """
|
||||
This tool should be called **LAST** in the workflow to perform final beautification of the data report.
|
||||
It will:
|
||||
1. Apply advanced styling and layout enhancements
|
||||
2. Add interactive elements and visual polish
|
||||
3. Ensure mobile responsiveness
|
||||
|
||||
Key beautification features to implement:
|
||||
- colorful and fancy background and color scheme
|
||||
- Modern CSS styling with gradients and shadows
|
||||
- Font Awesome icons for visual cues
|
||||
- Animated progress bars for metrics
|
||||
- Card-based layout with hover effects
|
||||
- Responsive design for all devices
|
||||
- Scroll-triggered animations
|
||||
- Professional typography hierarchy
|
||||
|
||||
## Output Requirements
|
||||
1. Generate **beautify_report.html** file
|
||||
2. Print the file path: print(report_path)
|
||||
"""
|
||||
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": """
|
||||
Python code that beautify the report:
|
||||
1. CSS/JS enhancements for modern styling
|
||||
2. Structure optimization for better readability
|
||||
3. Mobile responsiveness adjustments
|
||||
|
||||
Example tasks:
|
||||
- Add Bootstrap 5 + Font Awesome
|
||||
- Add metric cards with progress bars
|
||||
- Create responsive tables
|
||||
""",
|
||||
},
|
||||
},
|
||||
"required": ["code"],
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
from app.tool.base import BaseTool, ToolResult
|
||||
from typing import ClassVar
|
||||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||||
from pathlib import Path
|
||||
from app.config import config
|
||||
from app.tool.chart_visualization.python_execute import NormalPythonExecute
|
||||
|
||||
|
||||
|
||||
class ReportTemplateGeneration(NormalPythonExecute):
|
||||
"""A tool for generating the report template in users' local file system"""
|
||||
|
||||
name: str = "report_template_generation"
|
||||
description: str = """Generate a customized HTML report template based on user input data and the natural language description of the report from the previous step.
|
||||
|
||||
When user requires a report, you need to use the search_html_library tool first, and then use this tool based on your search result.
|
||||
In this tool, you will need to process two input parameters to generate a customized HTML report.
|
||||
(1) First Input Parameter: Analyze the user-provided dataset for the report and generate: A natural language suggestion for the HTML report customization (e.g., layout, structure, recommended charts, and visualizations).
|
||||
(2) Second Input Parameter: Based on the natural language suggestion, produce: Python code that dynamically generates the corresponding HTML report. The code should also save the HTML file to the local filesystem.
|
||||
Outputs: HTML report template file path"""
|
||||
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"report_template_description": {
|
||||
"description": "Natural language suggestion for HTML report structure (layout, sections, chart recommendations). Focus on framework only - no actual content needed.",
|
||||
"type": "string",
|
||||
},
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": """Python code to generate an HTML template with standardized placeholders. Requirements:
|
||||
1. **Use placeholder format: [placeholder: description]**
|
||||
2. Generate template structure only - no real content or data
|
||||
3. Use the components and theme you have searched before.
|
||||
4. For text sections: Use placeholders for paragraphs/lists
|
||||
5. For charts: Use iframe elements with placeholder paths (/workspace/visualization/[filename].html)
|
||||
6. Maintain semantic HTML structure with appropriate classes
|
||||
|
||||
## Output Requirements
|
||||
1. Generate **report_template.html** file
|
||||
2. Print the file path: print(report_path)
|
||||
|
||||
Examples:
|
||||
<div class="section">
|
||||
<h2>Executive Summary</h2>
|
||||
<div class="card">
|
||||
<p>[placeholder: 1-3 paragraph summary]</p>
|
||||
<div class="highlight">
|
||||
<strong>Key Findings:</strong>
|
||||
<ul>
|
||||
<li>[placeholder: Key insight 1]</li>
|
||||
<li>[placeholder: Key insight 2]</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>[placeholder: Section name]</h2>
|
||||
<div class="card">
|
||||
<div class="card-header">[placeholder: Chart title]</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-container">
|
||||
<iframe src="[placeholder: /workspace/visualization/chart_name.html]"
|
||||
width="100%" height="100%" frameborder="0"></iframe>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<h4>Key Insights:</h4>
|
||||
<ul>
|
||||
<li>[placeholder: Chart insight 1]</li>
|
||||
<li>[placeholder: Chart insight 2]</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>"""
|
||||
},
|
||||
},
|
||||
"required": ["report_template_description", "code"],
|
||||
}
|
||||
async def execute(self, code: str, report_template_description: str | None = None, timeout=5):
|
||||
return await super().execute(code, timeout)
|
||||
@@ -0,0 +1,142 @@
|
||||
from app.tool.base import BaseTool, ToolResult
|
||||
from typing import ClassVar, Dict
|
||||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||||
from pathlib import Path
|
||||
from app.config import config
|
||||
from app.tool.file_operators import (
|
||||
FileOperator,
|
||||
LocalFileOperator,
|
||||
PathLike,
|
||||
SandboxFileOperator,
|
||||
)
|
||||
from typing import List
|
||||
|
||||
class SearchHtmlLibraryResponse(ToolResult):
|
||||
"""Structured response from the SearchHtmlLibrary tool, inheriting ToolResult."""
|
||||
|
||||
report_bootstrap_theme: str = Field(description="The theme of the bootstrap report")
|
||||
components_content: Dict[str, str] = Field(description="The UI components content as a dictionary (component_name: html_content)")
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""Formatted string with indented HTML content"""
|
||||
components_info = []
|
||||
for name, content in self.components_content.items():
|
||||
components_info.append(
|
||||
f"【{name}】\n"
|
||||
f"{content.strip()}\n"
|
||||
f"{'-'*40}"
|
||||
)
|
||||
|
||||
return (
|
||||
f"📊 Report Theme: {self.report_bootstrap_theme}\n\n"
|
||||
f"🛠️ Components Content:\n\n"
|
||||
f"{'\n'.join(components_info)}"
|
||||
)
|
||||
|
||||
class SearchHtmlLibrary(BaseTool):
|
||||
"""A tool for searching the html library in users' local file system"""
|
||||
|
||||
name: str = "search_html_library"
|
||||
description: str = """Check the type of user's input data, and select proper bootstrap theme and component from user's local file system.
|
||||
When user requires a report, you need to use this tool first, to search the corresponding ui components and serve as a reference for subsequent report generation.
|
||||
Then, use other tools to generate fancy report template, specific chart...
|
||||
Outputs: 1) HTML components, 2) Bootstrap theme """
|
||||
|
||||
parameters: dict = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"report_bootstrap_theme":{
|
||||
"description": "The theme of bootstrap template to use.",
|
||||
"enum": [
|
||||
# Light themes
|
||||
"Brite"
|
||||
"Cerulean",
|
||||
"Materia",
|
||||
"Cosmo",
|
||||
"Flatly",
|
||||
"Journal",
|
||||
"Litera",
|
||||
"Lumen",
|
||||
"Minty",
|
||||
"Pulse",
|
||||
"Sandstone",
|
||||
"Simplex",
|
||||
"Sketchy",
|
||||
"Spacelab",
|
||||
"United",
|
||||
"Zephyr",
|
||||
|
||||
# Dark themes
|
||||
"Cyborg",
|
||||
"Darkly",
|
||||
"Slate",
|
||||
"Solar",
|
||||
"Superhero",
|
||||
"Vapor",
|
||||
"Lux",
|
||||
|
||||
# Special styles
|
||||
"Quartz",
|
||||
"Morph",
|
||||
"Yeti"
|
||||
],
|
||||
"default": "Materia",
|
||||
"type": "string",
|
||||
},
|
||||
"components": {
|
||||
"description": "List of components to you will use in the report, you need to decide based on user's input data.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["blockquote", "card", "chart", "indicator", "list", "nav", "nvabar", "progress", "table", "typography"]
|
||||
},
|
||||
"default": ["card", "chart", "table"],
|
||||
"minItems": 2,
|
||||
"uniqueItems": True
|
||||
}
|
||||
},
|
||||
"required": ["report_bootstrap_theme", "components"],
|
||||
}
|
||||
|
||||
_local_operator: LocalFileOperator = LocalFileOperator()
|
||||
_sandbox_operator: SandboxFileOperator = SandboxFileOperator()
|
||||
|
||||
# def _get_operator(self, use_sandbox: bool) -> FileOperator:
|
||||
def _get_operator(self) -> FileOperator:
|
||||
"""Get the appropriate file operator based on execution mode."""
|
||||
return (
|
||||
self._sandbox_operator
|
||||
if config.sandbox.use_sandbox
|
||||
else self._local_operator
|
||||
)
|
||||
|
||||
async def execute(
|
||||
self,
|
||||
report_bootstrap_theme: str,
|
||||
components: List[str]
|
||||
) -> SearchHtmlLibraryResponse:
|
||||
"""
|
||||
Execute the tool with the given parameters.
|
||||
Reads HTML component files and returns their content in a dictionary.
|
||||
"""
|
||||
operator = self._get_operator()
|
||||
components_content = {} # Initialize an empty dictionary to store component contents
|
||||
|
||||
for component in components:
|
||||
path = f"/home/vm3/JoyZhao/OSPP/OpenManus/workspace/html_library/{component}.html"
|
||||
print(f"Reading component: {path}")
|
||||
|
||||
try:
|
||||
# Read the HTML file content
|
||||
component_content = await operator.read_file(path)
|
||||
# Store in dictionary with component name as key
|
||||
components_content[component] = component_content
|
||||
except Exception as e:
|
||||
print(f"Failed to read component {component}: {str(e)}")
|
||||
components_content[component] = f"Error loading {component} component"
|
||||
|
||||
theme=f"https://cdn.jsdelivr.net/npm/bootswatch@5/dist/{report_bootstrap_theme.lower()}/bootstrap.min.css"
|
||||
return SearchHtmlLibraryResponse(
|
||||
report_bootstrap_theme=theme,
|
||||
components_content=components_content
|
||||
)
|
||||
@@ -1,17 +0,0 @@
|
||||
# Global LLM configuration
|
||||
[llm] #Jiekou.AI:
|
||||
api_type = 'jiekou'
|
||||
model = "claude-sonnet-4-5-20250929" # The LLM model to use
|
||||
base_url = "https://api.jiekou.ai/openai" # API endpoint URL
|
||||
api_key = "your Jiekou.AI api key" # Your API key
|
||||
max_tokens = 64000 # Maximum number of tokens in the response
|
||||
temperature = 0.0 # Controls randomness
|
||||
|
||||
|
||||
[llm.vision] #Jiekou.AI VISION:
|
||||
api_type = 'jiekou'
|
||||
model = "claude-sonnet-4-5-20250929" # The vision model to use
|
||||
base_url = "https://api.jiekou.ai/openai" # API endpoint URL for vision model
|
||||
api_key = "your Jiekou.AI api key" # Your API key for vision model
|
||||
max_tokens = 64000 # Maximum number of tokens in the response
|
||||
temperature = 0.0 # Controls randomness for vision model
|
||||
@@ -31,14 +31,6 @@ temperature = 0.0 # Controls randomness
|
||||
# max_tokens = 4096
|
||||
# temperature = 0.0
|
||||
|
||||
# [llm] #Jiekou.AI:
|
||||
# api_type = 'jiekou'
|
||||
# model = "claude-sonnet-4-5-20250929" # The LLM model to use
|
||||
# base_url = "https://api.jiekou.ai/openai" # API endpoint URL
|
||||
# api_key = "your Jiekou.AI api key" # Your API key
|
||||
# max_tokens = 64000 # Maximum number of tokens in the response
|
||||
# temperature = 0.0 # Controls randomness
|
||||
|
||||
# Optional configuration for specific LLM models
|
||||
[llm.vision]
|
||||
model = "claude-3-7-sonnet-20250219" # The vision model to use
|
||||
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "OpenManus",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
This is a sample file. Files generated by OpenManus are stored in the current folder by default.
|
||||
Reference in New Issue
Block a user