How to Create Custom Report Templates in ReportEngine: A Complete Guide
You can create custom report templates in ReportEngine by either adding Markdown files to the ReportEngine/report_template directory for automatic discovery or passing a raw Markdown string via the custom_template parameter to bypass auto-selection.
The bettafish repository provides a flexible ReportEngine that generates structured reports using Markdown-based templates. Understanding how to create custom report templates in ReportEngine allows you to control the visual and structural skeleton of every generated report, from section headings to overall layout.
Understanding ReportEngine's Template Architecture
Template Storage and Discovery
Templates are simple Markdown (.md) files stored under ReportEngine/report_template. The engine discovers these files through TemplateSelectionNode._get_available_templates in ReportEngine/nodes/template_selection_node.py (lines 26-44). This method walks the directory specified by self.template_dir, which defaults to Settings.TEMPLATE_DIR defined in ReportEngine/utils/config.py (line 59).
Each file is read, and _extract_template_description (lines 54-68) derives a short description from the filename to present to the LLM for selection.
Template Selection Logic
The central orchestration happens in ReportEngine/agent.py. The ReportAgent._select_template method (lines 914-918) checks if a custom_template argument is provided. If non-empty, it returns a dictionary with template_name="custom" and the supplied content, skipping the LLM-driven selection logic entirely.
Method 1: Creating Reusable Template Files
To create a permanent template that the LLM can auto-select, add a new Markdown file to the template directory. The engine treats these as first-class templates that can be automatically selected based on query context.
Create a file following this structure:
### **我的专项报告模板**
- **1.0 项目概览**
- 1.1 背景
- 1.2 目标
- **2.0 方法论**
- 2.1 数据来源
- 2.2 分析模型
- **3.0 结果与建议**
- 3.1 关键洞察
- 3.2 行动方案
Save this as ReportEngine/report_template/我的专项报告模板.md. Use a numeric heading hierarchy (e.g., ### 1.0 章节标题) so that parse_template_sections can recognize sections correctly. The engine automatically includes it in the candidate list shown to the LLM.
Method 2: Passing Custom Templates at Runtime
For ad-hoc layouts without modifying repository files, pass a raw Markdown string via the custom_template parameter.
Via Command Line Interface
The CLI entry point report_engine_only.py forwards the custom_template argument to the engine:
python report_engine_only.py --query "2024 市场趋势" \
--custom-template "$(cat my_template.md)"
Via Flask API
The HTTP API endpoint in ReportEngine/flask_interface.py accepts custom_template in the JSON payload:
import requests
import json
url = "http://localhost:5000/api/report"
payload = {
"query": "企业品牌声誉分析",
"custom_template": """### **企业品牌声誉报告模板**
- **1.0 报告概览**
- 1.1 品牌现状
- 1.2 受众情感
- **2.0 竞争对手对比**
- 2.1 关键指标
- 2.2 差距分析
- **3.0 行动建议**
- 3.1 媒体策略
- 3.2 危机预案"""
}
headers = {"Content-Type": "application/json"}
resp = requests.post(url, data=json.dumps(payload), headers=headers)
print(resp.json())
Via Python API
Use ReportAgent directly for programmatic control:
from ReportEngine.agent import ReportAgent
agent = ReportAgent()
custom_md = """
### **专项调研报告模板**
- **1.0 调研目标**
- 1.1 背景描述
- 1.2 关键问题
- **2.0 方法与数据**
- 2.1 数据来源
- 2.2 分析框架
- **3.0 发现与结论**
- 3.1 主要洞察
- 3.2 建议措施
"""
result = agent.generate_report(
query="AI 产业链趋势",
reports=["..."],
forum_logs="",
custom_template=custom_md,
save_report=False
)
print(result["html_content"])
How the Engine Processes Custom Templates
Once selected, templates are processed by ReportAgent._slice_template (lines 1003-1016 in agent.py). This method calls parse_template_sections to convert the Markdown into a list of TemplateSection objects.
These sections drive the subsequent layout, word-budget, and chapter-generation nodes, regardless of whether the template came from a file in ReportEngine/report_template or a custom string passed at runtime.
Summary
- Template files are Markdown documents stored in
ReportEngine/report_templatethat the LLM can auto-select based on query context. - Custom templates bypass auto-selection when passed as strings via the
custom_templateparameter in the CLI, Flask API, or Python API. - The selection logic resides in
ReportAgent._select_template(lines 914-918), while parsing happens in_slice_template(lines 1003-1016). - Both methods ultimately produce
TemplateSectionobjects that define the report structure.
Frequently Asked Questions
What file format should custom report templates use?
ReportEngine expects templates to be valid Markdown (.md) files. The engine parses headings (e.g., ### 1.0 报告摘要) to identify sections, so using a clear numeric hierarchy helps the parse_template_sections function correctly slice the template into chapters.
Can I use custom templates without modifying the repository files?
Yes. You can pass a raw Markdown string via the custom_template parameter when using the CLI (report_engine_only.py), the Flask API (ReportEngine/flask_interface.py), or the Python API (ReportAgent.generate_report). This bypasses the file-based discovery mechanism entirely.
How does the engine decide between auto-selected and custom templates?
The decision happens in ReportAgent._select_template at lines 914-918 of agent.py. If the custom_template argument is non-empty, the method immediately returns a dictionary with template_name="custom" and the provided content, skipping the LLM-driven selection logic that would otherwise query available templates from ReportEngine/report_template.
Where should I place template files for automatic discovery?
Place Markdown files in the ReportEngine/report_template directory. The default path is defined by Settings.TEMPLATE_DIR in ReportEngine/utils/config.py (line 59). The TemplateSelectionNode._get_available_templates method scans this directory, extracts descriptions from filenames, and presents the list to the LLM for selection.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →