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 信息图.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 ` - 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 ` - **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()