Files

396 lines
12 KiB
Python
Raw Permalink Normal View History

import os
import sys
import json
import requests
from datetime import datetime
from dotenv import load_dotenv
import pathlib
# Load .env from the same directory as this script
env_path = pathlib.Path(__file__).parent / ".env"
load_dotenv(dotenv_path=env_path)
# =================================================================
# Configuration
# =================================================================
API_KEY = os.getenv("OPENAI_API_KEY")
BASE_URL = os.getenv("OPENAI_BASE_URL")
MODEL = os.getenv("OPENAI_MODEL", "gpt-4o") # Default to gpt-4o if not set
if not API_KEY or not BASE_URL:
print(
"Error: OPENAI_API_KEY and OPENAI_BASE_URL environment variables must be set."
)
sys.exit(1)
# =================================================================
# Prompts (Extracted from infographic_cn.py)
# =================================================================
SYSTEM_PROMPT_INFOGRAPHIC_ASSISTANT = """
You are a professional infographic design expert who can analyze user-provided text content and convert it into AntV Infographic syntax format.
## Infographic Syntax Specification
Infographic syntax is a Mermaid-like declarative syntax for describing infographic templates, data, and themes.
### Syntax Rules
- Entry uses `infographic <template-name>`
- Key-value pairs are separated by spaces, **absolutely NO colons allowed**
- Use two spaces for indentation
- Object arrays use `-` with line breaks
**IMPORTANT WARNING: This is NOT YAML format!**
- Wrong: `children:` `items:` `data:` (with colons)
- Correct: `children` `items` `data` (without colons)
### Template Library & Selection Guide
#### 1. List & Hierarchy (Text-heavy)
- **Linear & Short (Steps/Phases)** -> `list-row-horizontal-icon-arrow`
- **Linear & Long (Rankings/Details)** -> `list-vertical`
- **Grouped / Parallel (Features/Catalog)** -> `list-grid`
- **Hierarchical (Org Chart/Taxonomy)** -> `tree-vertical` or `tree-horizontal`
- **Central Idea (Brainstorming)** -> `mindmap`
#### 2. Sequence & Relationship (Flow-based)
- **Time-based (History/Plan)** -> `sequence-roadmap-vertical-simple`
- **Process Flow (Complex)** -> `sequence-zigzag` or `sequence-horizontal`
- **Resource Flow / Distribution** -> `relation-sankey`
- **Circular Relationship** -> `relation-circle`
#### 3. Comparison & Analysis
- **Binary Comparison (A vs B)** -> `compare-binary`
- **SWOT Analysis** -> `compare-swot`
- **Multi-item Comparison Table** -> `compare-table`
- **Quadrant Analysis (Importance vs Urgency)** -> `quadrant-quarter`
#### 4. Charts & Data (Metric-heavy)
- **Key Metrics / Data Cards** -> `statistic-card`
- **Distribution / Comparison** -> `chart-bar` or `chart-column`
- **Trend over Time** -> `chart-line` or `chart-area`
- **Proportion / Part-to-Whole** -> `chart-pie` or `chart-doughnut`
### Infographic Syntax Guide
#### 1. Structure
- **Entry**: `infographic <template-name>`
- **Blocks**: `data`, `theme`, `design` (optional)
- **Format**: Key-value pairs separated by spaces, 2-space indentation.
- **Arrays**: Object arrays use `-` (newline), simple arrays use inline values.
#### 2. Data Block (`data`)
- `title`: Main title
- `desc`: Subtitle or description
- `items`: List of data items
- - `label`: Item title
- - `value`: Numerical value (required for Charts/Stats)
- - `desc`: Item description (optional)
- - `icon`: Icon name (e.g., `mdi/rocket-launch`)
- - `time`: Time label (Optional, for Roadmap/Sequence)
- - `children`: Nested items (ONLY for Tree/Mindmap/Sankey/SWOT)
- - `illus`: Illustration name (ONLY for Quadrant)
#### 3. Theme Block (`theme`)
- `colorPrimary`: Main color (Hex)
- `colorBg`: Background color (Hex)
- `palette`: Color list (Space separated)
- `textColor`: Text color (Hex)
- `stylize`: Style effect (e.g., `rough`, `flat`)
### Examples
#### Chart (Bar Chart)
infographic chart-bar
data
title Revenue Growth
desc Monthly revenue in 2024
items
- label Jan
value 1200
- label Feb
value 1500
- label Mar
value 1800
#### Comparison (SWOT)
infographic compare-swot
data
title Project SWOT
items
- label Strengths
children
- label Strong team
- label Innovative tech
- label Weaknesses
children
- label Limited budget
- label Opportunities
children
- label Emerging market
- label Threats
children
- label High competition
#### Relationship (Sankey)
infographic relation-sankey
data
title Energy Flow
items
- label Solar
value 100
children
- label Grid
value 60
- label Battery
value 40
- label Wind
value 80
children
- label Grid
value 80
#### Quadrant (Importance vs Urgency)
infographic quadrant-quarter
data
title Task Management
items
- label Critical Bug
desc Fix immediately
illus mdi/bug
- label Feature Request
desc Plan for next sprint
illus mdi/star
### Output Rules
1. **Strict Syntax**: Follow the indentation and formatting rules exactly.
2. **No Explanations**: Output ONLY the syntax code block.
3. **Language**: Use the user's requested language for content.
"""
USER_PROMPT_GENERATE_INFOGRAPHIC = """
请分析以下文本内容将其核心信息转换为 AntV Infographic 语法格式
---
**用户上下文信息:**
用户姓名: {user_name}
当前日期时间: {current_date_time_str}
用户语言: {user_language}
---
**文本内容:**
{long_text_content}
请根据文本特点选择最合适的信息图模板并输出规范的 infographic 语法注意保持正确的缩进格式两个空格
"""
# =================================================================
# Test Cases
# =================================================================
TEST_CASES = [
{
"name": "List Grid (Features)",
"content": """
MiniMax 2025 模型矩阵全解析
1. 极致 MoE 架构优化国内首批 MoE 路线坚定者
2. Video-01 视频生成杀手锏级多模态能力
3. 情感陪伴与角色扮演源自星野基因
4. 超长上下文与精准召回支持 128k+ 窗口
""",
},
{
"name": "Tree Vertical (Hierarchy)",
"content": """
公司组织架构
- 研发部
- 后端组
- 前端组
- 市场部
- 销售组
- 推广组
""",
},
{
"name": "Statistic Card (Metrics)",
"content": """
2024年Q4 核心指标
- 总用户数1,234,567
- 日活跃用户89%
- 营收增长+45%
""",
},
{
"name": "Mindmap (Brainstorming)",
"content": """
人工智能的应用领域
- 生成式 AI文本生成图像生成视频生成
- 预测性 AI股市预测天气预报
- 决策 AI自动驾驶游戏博弈
""",
},
{
"name": "SWOT Analysis",
"content": """
某初创咖啡品牌的 SWOT 分析
优势产品口味独特选址精准
劣势品牌知名度低资金压力大
机会线上外卖市场增长年轻人对精品咖啡需求增加
威胁行业巨头价格战原材料成本上涨
""",
},
{
"name": "Sankey (Relationship)",
"content": """
家庭月度开支流向
总收入 10000
其中 4000 元用于房贷
3000 元用于日常消费包括 2000 元餐饮1000 元交通
2000 元用于教育培训
1000 元存入银行
""",
},
{
"name": "Quadrant (Analysis)",
"content": """
个人任务象限分析
- 紧急且重要修复线上紧急 Bug准备下午的客户会议
- 重要不紧急制定年度学习计划健身锻炼
- 紧急不重要回复琐碎的邮件接听推销电话
- 不紧急不重要刷社交媒体看无聊的综艺
""",
},
{
"name": "Chart Bar (Data)",
"content": """
2023年各季度营收情况亿元
第一季度12.5
第二季度15.8
第三季度14.2
第四季度18.9
""",
},
]
# =================================================================
# Helper Functions
# =================================================================
def generate_infographic(content):
now = datetime.now()
current_date_time_str = now.strftime("%Y年%m月%d%H:%M:%S")
formatted_user_prompt = USER_PROMPT_GENERATE_INFOGRAPHIC.format(
user_name="TestUser",
current_date_time_str=current_date_time_str,
user_language="zh-CN",
long_text_content=content,
)
headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
payload = {
"model": MODEL,
"messages": [
{"role": "system", "content": SYSTEM_PROMPT_INFOGRAPHIC_ASSISTANT},
{"role": "user", "content": formatted_user_prompt},
],
"stream": False,
}
try:
response = requests.post(
f"{BASE_URL}/chat/completions", headers=headers, json=payload
)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
except Exception as e:
print(f"API Request Failed: {e}")
return None
def validate_syntax(syntax):
if not syntax:
return False, "Empty output"
# Basic checks
if "infographic" not in syntax.lower():
return False, "Missing 'infographic' keyword"
if "data" not in syntax.lower() and "items" not in syntax.lower():
return False, "Missing 'data' or 'items' block"
# Check for colons in keys (simple heuristic)
lines = syntax.split("\n")
for line in lines:
stripped = line.strip()
if not stripped:
continue
# Ignore lines that are likely values or descriptions containing colons
first_word = stripped.split()[0]
if first_word in ["title", "desc", "label", "value", "time", "icon"]:
continue # These can have colons in value
# Check for key: pattern at start of line
if re.match(r"^\w+:", stripped):
return False, f"Found colon in key: {stripped}"
return True, "Syntax looks valid"
# =================================================================
# Main Execution
# =================================================================
import re
def main():
print(f"Starting Infographic Generation Verification...")
print(f"API: {BASE_URL}")
print(f"Model: {MODEL}")
print("-" * 50)
results = []
for case in TEST_CASES:
print(f"\nTesting Case: {case['name']}")
print("Generating...")
output = generate_infographic(case["content"])
if output:
# Clean output (remove markdown code blocks if present)
clean_output = output
if "```" in output:
match = re.search(
r"```(?:infographic|mermaid)?\s*(.*?)\s*```", output, re.DOTALL
)
if match:
clean_output = match.group(1).strip()
print(f"Output Preview:\n{clean_output[:200]}...")
is_valid, message = validate_syntax(clean_output)
if is_valid:
print(f"✅ Validation Passed: {message}")
results.append({"name": case["name"], "status": "PASS"})
else:
print(f"❌ Validation Failed: {message}")
print(f"Full Output:\n{output}")
results.append({"name": case["name"], "status": "FAIL"})
else:
print("❌ Generation Failed")
results.append({"name": case["name"], "status": "ERROR"})
print("\n" + "=" * 50)
print("Summary")
print("=" * 50)
for res in results:
print(f"{res['name']}: {res['status']}")
if __name__ == "__main__":
main()