refactor: 重构项目结构和文件组织

- 将文档文件移动到docs目录下分类存放
- 将测试文件移动到tests目录
- 将工具脚本移动到tools目录
- 更新README中的文件路径说明
- 删除重复和过时的文件
- 优化项目目录结构,提升可维护性
This commit is contained in:
ben
2025-08-22 16:52:17 +08:00
parent 51576ebb6f
commit 76306f2c8e
48 changed files with 4439 additions and 146 deletions

161
engines/celestial_map.py Normal file
View File

@@ -0,0 +1,161 @@
# celestial_map.py
import networkx as nx
import matplotlib.pyplot as plt
class CelestialMap:
"""
基于“差序格局”思想,构建一个描绘产业链上下游“引力关系”的图模型。
“差序格局”是中国社会学家费孝通提出的概念,指社会关系像水波纹一样,
由自己这个中心推出去,一层层地变淡。
在这个模型中:
- 恒星 (Star): 代表产业链的核心或最上游的公司/板块,是引力中心。
- 行星 (Planet): 代表与核心紧密相关的公司/板块,围绕恒星运转。
- 卫星 (Satellite): 代表更下游或关联度更弱的公司/板块,围绕行星运转。
引力 (Gravity): 代表实体间的影响力或情绪传导强度,距离越远,引力越弱。
"""
def __init__(self):
self.graph = nx.DiGraph()
def add_entity(self, name, entity_type, **kwargs):
"""
添加一个天体实体。
:param name: 实体名称 (e.g., 'NVIDIA')
:param entity_type: 实体类型 ('star', 'planet', 'satellite')
:param kwargs: 其他属性 (e.g., market_cap, sector)
"""
self.graph.add_node(name, entity_type=entity_type, **kwargs)
def establish_influence(self, source, target, gravity_strength=1.0, relationship_type='supply_chain'):
"""
在两个实体间建立影响关系(引力)。
差序格局的体现:引力强度(gravity_strength)默认为1.0
当从恒星 -> 行星 -> 卫星传递时,可以通过计算路径权重来体现引力的衰减。
:param source: 施加影响的实体名称
:param target: 受到影响的实体名称
:param gravity_strength: 基础引力强度 (1.0 / 距离)
:param relationship_type: 关系类型 (e.g., 'supply_chain', 'competitor', 'capital')
"""
if source not in self.graph:
raise ValueError(f"Source entity '{source}' not found in the map.")
if target not in self.graph:
raise ValueError(f"Target entity '{target}' not found in the map.")
# 使用 1/gravity_strength 作为边的权重,模拟距离
# 强引力 = 低权重 = 短距离
distance = 1.0 / gravity_strength
self.graph.add_edge(source, target, weight=distance, relationship=relationship_type)
def get_influence_path(self, start_node, end_node):
"""
计算两个实体间的最短(最强)影响路径。
:param start_node: 路径起点
:param end_node: 路径终点
:return: 路径节点列表和总路径长度(总距离)
"""
try:
path = nx.shortest_path(self.graph, source=start_node, target=end_node, weight='weight')
length = nx.shortest_path_length(self.graph, source=start_node, target=end_node, weight='weight')
return path, length
except nx.NetworkXNoPath:
return None, float('inf')
def get_downstream_entities(self, start_node, max_depth=None):
"""
获取一个实体的所有下游受影响实体。
:param start_node: 起点实体
:param max_depth: 搜索的最大深度(层级)
:return: 下游实体列表
"""
if start_node not in self.graph:
return []
return list(nx.dfs_preorder_nodes(self.graph, source=start_node, depth_limit=max_depth))
def visualize(self, layout='spring'):
"""
将星图可视化。
"""
pos = None
if layout == 'spring':
pos = nx.spring_layout(self.graph, k=0.9)
elif layout == 'kamada_kawai':
pos = nx.kamada_kawai_layout(self.graph)
elif layout == 'circular':
pos = nx.circular_layout(self.graph)
else:
pos = nx.spring_layout(self.graph)
node_colors = []
for node in self.graph.nodes(data=True):
if node[1]['entity_type'] == 'star':
node_colors.append('yellow')
elif node[1]['entity_type'] == 'planet':
node_colors.append('skyblue')
elif node[1]['entity_type'] == 'satellite':
node_colors.append('lightgreen')
else:
node_colors.append('gray')
edge_labels = nx.get_edge_attributes(self.graph, 'relationship')
plt.figure(figsize=(14, 10))
nx.draw(self.graph, pos, with_labels=True, node_size=3000, node_color=node_colors, font_size=10, font_weight='bold', arrowsize=20)
nx.draw_networkx_edge_labels(self.graph, pos, edge_labels=edge_labels, font_color='red')
plt.title("Celestial Map of Industry Influence (差序格局)")
plt.show()
if __name__ == '__main__':
# --- 示例构建一个AI芯片产业链的“差序格局”图 ---
# 1. 初始化星图
industry_map = CelestialMap()
# 2. 添加实体 (恒星、行星、卫星)
industry_map.add_entity('NVIDIA', 'star', sector='Semiconductors')
industry_map.add_entity('TSMC', 'planet', sector='Manufacturing')
industry_map.add_entity('ASML', 'planet', sector='Equipment')
industry_map.add_entity('Supermicro', 'planet', sector='Servers')
industry_map.add_entity('Apple', 'satellite', sector='Consumer Electronics')
industry_map.add_entity('Tesla', 'satellite', sector='Automotive')
industry_map.add_entity('OpenAI', 'satellite', sector='AI Research')
# 3. 建立影响关系 (引力)
# 恒星 -> 行星 (强引力)
industry_map.establish_influence('NVIDIA', 'TSMC', gravity_strength=0.9, relationship_type='chip_design')
industry_map.establish_influence('NVIDIA', 'Supermicro', gravity_strength=0.8, relationship_type='hardware_demand')
industry_map.establish_influence('ASML', 'TSMC', gravity_strength=0.9, relationship_type='euv_machines')
# 行星 -> 卫星 (中等引力)
industry_map.establish_influence('TSMC', 'Apple', gravity_strength=0.7, relationship_type='chip_supply')
industry_map.establish_influence('Supermicro', 'OpenAI', gravity_strength=0.6, relationship_type='server_supply')
industry_map.establish_influence('NVIDIA', 'Tesla', gravity_strength=0.5, relationship_type='ai_chip_supply') # 直接影响
# 4. 分析与查询
print("--- 情绪传导路径分析 ---")
path, total_distance = industry_map.get_influence_path('ASML', 'Apple')
if path:
print(f"'ASML''Apple' 的最强影响路径: {' -> '.join(path)}")
# 总距离越大,代表关系越疏远,影响力衰减越多
print(f"总影响距离 (1/gravity): {total_distance:.2f}")
path, total_distance = industry_map.get_influence_path('NVIDIA', 'OpenAI')
if path:
print(f"'NVIDIA''OpenAI' 的最强影响路径: {' -> '.join(path)}")
print(f"总影响距离 (1/gravity): {total_distance:.2f}")
print("\n--- 下游影响范围查询 ---")
downstream = industry_map.get_downstream_entities('NVIDIA', max_depth=2)
print(f"'NVIDIA' 在两层关系内的所有下游影响实体: {downstream}")
# 5. 可视化
industry_map.visualize(layout='kamada_kawai')

121
engines/cycle_models.py Normal file
View File

@@ -0,0 +1,121 @@
# cycle_models.py
from abc import ABC, abstractmethod
from typing import Dict, Any, List
class CycleModel(ABC):
"""
周期模型抽象基类 (Abstract Base Class)。
定义了所有市场周期、板块轮动或生命周期模型的统一接口。
确保上层应用如FSM可以调用周期分析功能而无需关心其具体实现
(例如,是十二长生、二十四节气还是美林投资时钟)。
"""
@abstractmethod
def get_current_stage(self, data: Dict[str, Any]) -> str:
"""
根据输入数据,判断当前处于哪个周期阶段。
:param data: 包含用于分析的数据的字典 (e.g., economic indicators, price momentum).
:return: 当前周期阶段的名称。
"""
pass
@abstractmethod
def get_stage_characteristics(self, stage: str) -> Dict[str, Any]:
"""
获取特定阶段的特征描述或建议策略。
:param stage: 阶段名称。
:return: 包含该阶段特征描述的字典。
"""
pass
@abstractmethod
def get_all_stages(self) -> List[str]:
"""
返回模型中所有阶段的有序列表。
:return: 包含所有阶段名称的列表。
"""
pass
class TwelveStagesOfLifeCycleModel(CycleModel):
"""
十二长生周期模型的具体实现。
该模型将事物的生命周期分为十二个阶段,用于描述板块轮动或个股的生命周期。
"""
def __init__(self):
self._stages = [
"长生", "沐浴", "冠带", "临官", "帝旺",
"", "", "", "", "", "", ""
]
self._characteristics = {
"长生": {"description": "新生,事物初生,潜力巨大。", "strategy": "关注,少量试探"},
"沐浴": {"description": "萌芽,成长初期,易受挫折。", "strategy": "谨慎观察,识别风险"},
"冠带": {"description": "成型,初步获得社会承认。", "strategy": "逐步建仓"},
"临官": {"description": "高速增长,事业有成。", "strategy": "持有并加仓"},
"帝旺": {"description": "顶峰,达到全盛时期。", "strategy": "警惕风险,考虑减仓"},
"": {"description": "衰退,开始走下坡路。", "strategy": "逐步卖出"},
"": {"description": "问题暴露,盈利能力减弱。", "strategy": "清仓"},
"": {"description": "明显下滑,失去活力。", "strategy": "避免接触"},
"": {"description": "估值塌陷,被市场遗忘。", "strategy": "观望,等待转机"},
"": {"description": "市场失忆,完全被忽视。", "strategy": "观望"},
"": {"description": "潜伏,新一轮周期的孕育。", "strategy": "研究,寻找新催化剂"},
"": {"description": "建仓期,主力资金开始布局。", "strategy": "少量布局,等待信号"}
}
def get_current_stage(self, data: Dict[str, Any]) -> str:
"""
模拟根据市场数据判断当前所处的“十二长生”阶段。
在真实实现中,这里会是一个复杂的量化模型。
"""
# 模拟逻辑:简单地根据一个随机分数来确定阶段
# score 范围 0-11
mock_score = data.get("mock_score", 0)
stage_index = int(mock_score) % len(self._stages)
return self._stages[stage_index]
def get_stage_characteristics(self, stage: str) -> Dict[str, Any]:
"""
获取指定“十二长生”阶段的特征和策略建议。
"""
return self._characteristics.get(stage, {"description": "未知阶段", "strategy": ""})
def get_all_stages(self) -> List[str]:
"""
返回所有十二长生阶段。
"""
return self._stages
# --- 示例:如何使用解耦的周期模型 ---
if __name__ == '__main__':
import random
# 上层应用如FSM依赖于抽象的 CycleModel
def analyze_market_cycle(model: CycleModel, market_data: Dict[str, Any]):
current_stage = model.get_current_stage(market_data)
characteristics = model.get_stage_characteristics(current_stage)
print(f"当前市场周期分析 (模型: {model.__class__.__name__}):")
print(f" - 所处阶段: 【{current_stage}")
print(f" - 阶段描述: {characteristics['description']}")
print(f" - 建议策略: {characteristics['strategy']}")
# 运行时,传入一个具体的周期模型实例
twelve_stages_model = TwelveStagesOfLifeCycleModel()
# 模拟不同的市场数据
for i in range(3):
# 在真实场景中,这里会是真实的经济或市场数据
simulated_market_data = {"mock_score": random.randint(0, 11)}
analyze_market_cycle(twelve_stages_model, simulated_market_data)
print("-" * 50)
# 如果未来要添加“美林投资时钟”模型,只需实现一个新的类,
# 上层应用 analyze_market_cycle 的代码完全不需要修改。
# class MerrillClockModel(CycleModel):
# ...
# merrill_model = MerrillClockModel()
# analyze_market_cycle(merrill_model, real_economic_data)

108
engines/market_fsm.py Normal file
View File

@@ -0,0 +1,108 @@
# market_fsm.py
from typing import Dict, Any
from mythology import MythologyEngine, DaoistMythologyEngine
from cycle_models import CycleModel, TwelveStagesOfLifeCycleModel
class MarketFSM:
"""
一个简化的市场分析有限状态机 (FSM)。
本 FSM 演示了如何通过抽象基类来调用外部的“神话引擎”和“周期模型”,
从而实现了核心逻辑与具体实现(如道家神话、十二长生模型)的解耦。
"""
def __init__(self, mythology_engine: MythologyEngine, cycle_model: CycleModel):
"""
FSM 在初始化时,注入所需引擎的抽象实例。
它不关心传入的是哪个具体的神话引擎或周期模型。
"""
if not isinstance(mythology_engine, MythologyEngine):
raise TypeError("mythology_engine must be a subclass of MythologyEngine")
if not isinstance(cycle_model, CycleModel):
raise TypeError("cycle_model must be a subclass of CycleModel")
self.mythology_engine = mythology_engine
self.cycle_model = cycle_model
self.current_state = "Idle"
self.context: Dict[str, Any] = {}
print(f"--- FSM 已启动 ---")
print(f"世界观: {self.mythology_engine.get_system_narrative()}")
print(f"周期模型: {self.cycle_model.__class__.__name__}")
print("-" * 50)
def run_analysis(self, market_data: Dict[str, Any]):
"""
执行一次完整的市场分析流程。
"""
print(f"\n【状态: {self.current_state}】-> [开始分析] -> 【状态: Collecting】")
self.current_state = "Collecting"
self._collect_data(market_data)
print(f"\n【状态: {self.current_state}】-> [分析周期] -> 【状态: CycleAnalysis】")
self.current_state = "CycleAnalysis"
self._analyze_cycle()
print(f"\n【状态: {self.current_state}】-> [生成报告] -> 【状态: Reporting】")
self.current_state = "Reporting"
self._generate_report()
print(f"\n【状态: {self.current_state}】-> [完成] -> 【状态: Idle】")
self.current_state = "Idle"
print("\n--- 分析流程结束 ---")
def _collect_data(self, market_data: Dict[str, Any]):
"""
模拟数据收集阶段。
"""
actor = self.mythology_engine.get_actor_name('collector')
metaphor = self.mythology_engine.get_process_metaphor('multi_agent_debate')
print(f"执行者: [{actor}]")
print(f"动作: [{metaphor}]")
self.context['market_data'] = market_data
print("数据收集完成。")
def _analyze_cycle(self):
"""
分析市场周期阶段。
"""
current_stage = self.cycle_model.get_current_stage(self.context['market_data'])
self.context['cycle_stage'] = current_stage
print(f"周期模型分析完成,当前阶段为: 【{current_stage}")
def _generate_report(self):
"""
生成最终报告。
"""
actor = self.mythology_engine.get_actor_name('synthesizer')
metaphor = self.mythology_engine.get_process_metaphor('final_decision')
stage = self.context['cycle_stage']
characteristics = self.cycle_model.get_stage_characteristics(stage)
print(f"执行者: [{actor}]")
print(f"动作: [{metaphor}]")
print("\n--- 最终分析报告 ---")
print(f"市场周期阶段: {stage}")
print(f"阶段特征: {characteristics.get('description', 'N/A')}")
print(f"建议策略: {characteristics.get('strategy', 'N/A')}")
print("--- 报告结束 ---")
if __name__ == '__main__':
# 1. 在系统启动时,选择并实例化具体的引擎和模型
daoist_mythology = DaoistMythologyEngine()
twelve_stages_cycle = TwelveStagesOfLifeCycleModel()
# 2. 将实例注入到 FSM 中
# FSM 只依赖于抽象,不关心具体实现
fsm = MarketFSM(
mythology_engine=daoist_mythology,
cycle_model=twelve_stages_cycle
)
# 3. 运行 FSM
# 模拟的市场数据
simulated_data = {"mock_score": 4} # 模拟处于“帝旺”阶段
fsm.run_analysis(simulated_data)

View File

@@ -0,0 +1,145 @@
# monster_stock_scanner.py
import random
from typing import List, Dict, Any
class Dragon:
"""
龙生九子,子子不同。
定义所有龙子的基础接口。
"""
def __init__(self, name: str, description: str):
self.name = name
self.description = description
def analyze(self, context: Dict[str, Any]) -> Dict[str, Any]:
"""
每条龙子根据自身的神通,对市场进行分析。
:param context: 包含分析所需信息的字典。
:return: 包含分析结果的字典。
"""
raise NotImplementedError("每个龙子都必须实现自己的 analyze 方法。")
class Bixi(Dragon):
"""
赑屃 (Bìxì),龙之长子,好负重,为“天时”。
负责识别宏观层面的结构性压力。
"""
def __init__(self):
super().__init__("赑屃", "识别宏观结构性压力")
def analyze(self, context: Dict[str, Any]) -> Dict[str, Any]:
"""
模拟分析宏观经济指标,以判断是否存在结构性压力。
在真实实现中这里会调用经济数据API如FRED, World Bank
"""
print(f"【天时 - {self.name}】正在分析宏观经济大盘...")
# 模拟宏观指标
mock_interest_rate = random.uniform(0.01, 0.05)
mock_inflation_rate = random.uniform(0.01, 0.03)
mock_gdp_growth = random.uniform(-0.01, 0.02)
# 规则当利率和通胀较高且GDP增长乏力时认为存在结构性压力。
pressure_score = (mock_interest_rate + mock_inflation_rate) - mock_gdp_growth
is_pressure = pressure_score > 0.05
print(f"分析完成:利率={mock_interest_rate:.2%}, 通胀={mock_inflation_rate:.2%}, GDP增长={mock_gdp_growth:.2%}")
print(f"宏观压力分数: {pressure_score:.3f}. {'存在结构性压力' if is_pressure else '宏观环境稳定'}")
return {
"has_structural_pressure": is_pressure,
"macro_pressure_score": pressure_score
}
class Fuxi(Dragon):
"""
负屃 (Fùxì),龙之八子,好斯文,为“地利”。
负责计算个股受到的多主题挤压分数。
"""
def __init__(self):
super().__init__("负屃", "计算个股的多主题挤压分数")
def analyze(self, context: Dict[str, Any]) -> Dict[str, Any]:
"""
模拟分析个股,判断其是否受到多个热门主题的共同驱动。
在真实实现中这里会使用NLP分析新闻、研报并结合知识图谱。
"""
stock_symbol = context.get("stock_symbol")
if not stock_symbol:
raise ValueError("需要提供股票代码 (stock_symbol) 进行分析。")
print(f"\n【地利 - {self.name}】正在分析个股 '{stock_symbol}' 的主题挤压...")
# 模拟热门主题
hot_themes = ["AI芯片", "新能源汽车", "量子计算", "生物医药", "数字孪生"]
# 模拟个股关联的主题
stock_related_themes = random.sample(hot_themes, random.randint(1, 3))
# 规则:关联的主题越多,挤压分数越高。
squeeze_score = len(stock_related_themes) / len(hot_themes)
print(f"分析完成:'{stock_symbol}' 关联的主题: {stock_related_themes}")
print(f"多主题挤压分数: {squeeze_score:.2f}")
return {
"related_themes": stock_related_themes,
"theme_squeeze_score": squeeze_score
}
def monster_stock_scanner(stock_symbol: str):
"""
“妖股扫描器” - 双龙合璧策略。
结合“天时”(宏观压力)与“地利”(个股主题),寻找潜在的“妖股”。
“妖股”的定义:在宏观承压的环境下,依然受到多个强大主题驱动的个股。
这种股票可能因为其强大的叙事性而走出独立行情。
"""
print(f"--- 启动妖股扫描器,目标: {stock_symbol} ---")
# 初始化龙子
bixi = Bixi()
fuxi = Fuxi()
# 1. 分析天时
macro_context = {}
macro_analysis = bixi.analyze(macro_context)
# 2. 分析地利
stock_context = {"stock_symbol": stock_symbol}
stock_analysis = fuxi.analyze(stock_context)
# 3. 监听“人和”(催化剂)- 此处简化
# 在真实系统中嘲风Chaofeng会监听实时新闻、社交媒体等。
has_catalyst = random.choice([True, False])
print(f"\n【人和 - 嘲风】监听中... {'发现关键催化剂!' if has_catalyst else '未发现明显催化剂。'}")
# 4. 综合决策
is_monster_stock = (
macro_analysis["has_structural_pressure"] and
stock_analysis["theme_squeeze_score"] >= 0.5 and
has_catalyst
)
print("\n--- 扫描结论 ---")
if is_monster_stock:
print(f"✅ 结论: '{stock_symbol}' 具备妖股潜力!")
print(" - 天时: 宏观环境承压,资金寻求确定性。")
print(f" - 地利: 受到 {len(stock_analysis['related_themes'])} 个热门主题的强力驱动。")
print(" - 人和: 出现关键催化剂。")
else:
print(f"❌ 结论: '{stock_symbol}' 当前不符合妖股特征。")
if not macro_analysis["has_structural_pressure"]:
print(" - 原因: 宏观环境稳定,市场风险偏好较高,难以形成抱团。")
if stock_analysis["theme_squeeze_score"] < 0.5:
print(" - 原因: 个股主题驱动力不足,缺乏想象空间。")
if not has_catalyst:
print(" - 原因: 缺少引爆市场的催化剂。")
if __name__ == '__main__':
# 扫描一个示例股票
monster_stock_scanner("TSLA")
print("\n" + "="*50 + "\n")
monster_stock_scanner("GOOGL")

112
engines/mythology.py Normal file
View File

@@ -0,0 +1,112 @@
# mythology.py
from abc import ABC, abstractmethod
from typing import Dict, Any
class MythologyEngine(ABC):
"""
神话引擎抽象基类 (Abstract Base Class)。
定义了所有神话体系映射的统一接口确保上层应用如FSM
可以无差别地调用,实现核心逻辑与文化叙事的解耦。
"""
@abstractmethod
def get_actor_name(self, component: str) -> str:
"""
根据技术组件名称,获取其在神话体系中对应的角色名称。
:param component: 技术组件的标识符 (e.g., 'refiner', 'verifier').
:return: 神话角色的名称 (e.g., '太上老君', '灵宝道君').
"""
pass
@abstractmethod
def get_process_metaphor(self, process: str) -> str:
"""
根据技术流程名称,获取其在神话体系中的隐喻。
:param process: 技术流程的标识符 (e.g., 'external_fetch').
:return: 神话流程的隐喻 (e.g., '撒豆成兵').
"""
pass
@abstractmethod
def get_system_narrative(self) -> str:
"""
获取整个系统的世界观或宏大叙事。
:return: 描述系统哲学的字符串。
"""
pass
class DaoistMythologyEngine(MythologyEngine):
"""
道家“封神”神话引擎的具体实现。
将“太公心易”系统的组件和流程映射到道家和封神演义的神话体系中。
"""
def __init__(self):
self._actor_map: Dict[str, str] = {
# FSM States / Core Components
'collector': '聚仙楼',
'divergence_handler': '白虎观会议',
'refiner': '太上老君',
'verifier': '灵宝道君',
'synthesizer': '元始天尊',
'actuator': '打神鞭',
# Agent Roles
'macro_analyst': '铁拐李',
'strategist': '汉钟离',
'sentiment_analyst': '张果老',
'compliance_checker': '曹国舅',
}
self._process_map: Dict[str, str] = {
'multi_agent_debate': '八仙论道',
'refinement_process': '兜率宫炼丹',
'external_verification': '撒豆成兵',
'final_decision': '元始决断',
'async_webhook_call': '元神出窍',
}
self._narrative = "本系统是一个道法自然、洞察万象的AI智能决策生态名为“太公心易”。"
def get_actor_name(self, component: str) -> str:
"""
获取道家神话体系中的角色名称。
"""
return self._actor_map.get(component, "未知神祇")
def get_process_metaphor(self, process: str) -> str:
"""
获取道家神话体系中的流程隐喻。
"""
return self._process_map.get(process, "混沌演化")
def get_system_narrative(self) -> str:
"""
返回“太公心易”系统的宏大叙事。
"""
return self._narrative
# --- 示例:如何使用解耦的引擎 ---
if __name__ == '__main__':
# 上层应用可以声明它需要一个 MythologyEngine而无需关心具体实现
def describe_system_component(engine: MythologyEngine, component: str, process: str):
actor = engine.get_actor_name(component)
metaphor = engine.get_process_metaphor(process)
print(f"组件 '{component}' 由 [{actor}] 负责,其核心流程 '{process}' 被称为 [{metaphor}]。")
# 在运行时,我们可以传入任何一个具体的引擎实例
daoist_engine = DaoistMythologyEngine()
print(f"系统世界观: {daoist_engine.get_system_narrative()}")
print("-" * 50)
describe_system_component(daoist_engine, 'refiner', 'refinement_process')
describe_system_component(daoist_engine, 'verifier', 'external_verification')
# 如果未来要切换到希腊神话,只需实现一个 GreekMythologyEngine 即可,
# 上层应用 describe_system_component 的代码完全不需要修改。
# class GreekMythologyEngine(MythologyEngine):
# ...
# greek_engine = GreekMythologyEngine()
# describe_system_component(greek_engine, 'refiner', 'refinement_process')