fd-cn-report 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.4
2
+ Name: fd-cn-report
3
+ Version: 0.2.0
4
+ Summary: Chinese financial report MCP server — 31 Shenwan industry AI rule system, outline extraction, AI structured extraction, Elasticsearch store + search, industry rules dashboard
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: fastmcp>=2.0
7
+ Requires-Dist: sqlalchemy>=2.0
8
+ Requires-Dist: python-dotenv>=1.0
9
+ Requires-Dist: httpx>=0.27
10
+ Requires-Dist: pypdf>=4.0
11
+ Requires-Dist: jsonschema>=4.0
12
+ Requires-Dist: elasticsearch>=8.0
13
+ Requires-Dist: akshare>=1.13
14
+ Requires-Dist: pandas>=2.0
15
+ Requires-Dist: pymupdf>=1.28.0
16
+ Requires-Dist: lxml>=4.9
@@ -0,0 +1,460 @@
1
+ # fd-cn-report
2
+
3
+ MCP server for Chinese financial reports — 31 申万 L1 industry AI rule system,
4
+ outline extraction, AI structured extraction, Elasticsearch store + search,
5
+ and interactive rules dashboard.
6
+
7
+ ## Industry Rules System
8
+
9
+ **21,698 LLM rules** covering **31 申万 L1 industries** with per-section extraction
10
+ instructions generated from real annual report PDFs. Each rule maps an indicator
11
+ to its exact section position in the periodic report.
12
+
13
+ ### Coverage
14
+
15
+ | 章节 | 内容 | 说明 |
16
+ |------|------|------|
17
+ | 资产负债表 | 全部科目 (112+ rules) | 从合并资产负债表提取 |
18
+ | 利润表 | 全部科目 (130+ rules) | 从合并利润表提取 |
19
+ | 现金流量表 | 全部科目 (42+ rules) | 从合并现金流量表提取 |
20
+ | 管理层讨论 | 主营业务分析、成本、产销量、研发 | 从实际报告第三节提取 |
21
+ | 主要财务指标 | ROE、EPS、毛利率、分季度数据 | 从第二节提取 |
22
+ | 报表附注/重要事项 | 关联交易、担保、诉讼、资产减值 | 从第六节+第十节附注提取 |
23
+ | 股东信息 | 前十大股东、持股变动、分红 | 从第七节提取 |
24
+ | 公司治理 | 董事会、高管薪酬 | 从第四节提取 |
25
+ | 环境 | 排污、碳排放、能源消耗 | 从第五节提取 |
26
+
27
+ ### Industry-Specific Rules
28
+
29
+ 6 industries have industry-specific rules on top of the universal set:
30
+
31
+ | 行业 | 特有指标 | 来源 |
32
+ |------|---------|------|
33
+ | 银行 | 不良率、净息差、资本充足率、贷款五级分类 | 工商银行年报 |
34
+ | 房地产 | 合同负债、存货-开发成本、土储、销售面积 | 保利发展年报 |
35
+ | 电力设备 | 在建工程、产能利用率、应收账款 | 宁德时代年报 |
36
+ | 医药生物 | 研发费用、销售费用、在研管线、无形资产 | 恒瑞医药年报 |
37
+ | 非银金融 | 保费收入、赔付支出、偿付能力、新业务价值 | 中国平安年报 |
38
+ | 农林牧渔 | 存货-消耗性生物资产 | 隆平高科年报 |
39
+
40
+ ### Rule Generation Pipeline
41
+
42
+ Rules are generated from real annual report PDFs via parallel LLM calls:
43
+
44
+ ```bash
45
+ # Generate rules for all 31 industries from real reports
46
+ python scripts/generate_rules_from_real_reports.py --max-concurrent 5
47
+
48
+ # Single industry
49
+ python scripts/generate_rules_from_real_reports.py --industry 801120
50
+
51
+ # Run industry-specific sections only
52
+ python scripts/generate_rules_from_real_reports.py --industry 801780 --llm-only
53
+ ```
54
+
55
+ ### Dashboard
56
+
57
+ Interactive web UI to browse, filter, and search all 21,698 rules:
58
+
59
+ ```bash
60
+ # CLI
61
+ python scripts/industry_rules_dashboard.py
62
+ # or
63
+ fd-cn-report
64
+
65
+ # MCP tool
66
+ open_industry_rules_dashboard(port=8888)
67
+ ```
68
+
69
+ Features:
70
+ - **Industry filter** — dropdown with all 31 申万 L1 industries
71
+ - **Module filter** — filter by balance_sheet, income_statement, etc.
72
+ - **Keyword search** — indicator name, section, instruction text
73
+ - **Sortable columns** — click header to sort
74
+ - **Pagination** — 50 rules per page
75
+ - **Color-coded tags** — module type visualization
76
+ - **Real-time stats** — filtered count, industry count, module count
77
+
78
+ ---
79
+
80
+ ## Tools (44 MCP tools)
81
+
82
+ | Layer | Tool | Description |
83
+ |-------|------|-------------|
84
+ | **Company API** | `get_company` | Resolve ticker/name → company entry |
85
+ | | `list_filings` | List CNINFO disclosures by form/category + year |
86
+ | | `get_filing` | One announcement's metadata + PDF URL |
87
+ | | `get_financials` | Income/balance/cashflow via akshare |
88
+ | | `get_financial_statements` | 三大报表 as text from the annual-report PDF |
89
+ | | `get_section` | `(ticker, year, section)` → section text |
90
+ | | `list_report_types` | Browse CNINFO disclosure category catalog |
91
+ | | `get_special_report` | Special-type report (招股说明书, 收购报告书, …) |
92
+ | **HK Stock** | `get_hk_company` | Resolve HK stock by ticker/name |
93
+ | | `list_hk_filings` | List HKEX filings |
94
+ | | `get_hk_financials` | HK financial statements |
95
+ | | `get_hk_section` | HK report section extraction |
96
+ | **Official-website (SSE/SZSE/BSE)** | `get_sse_company` | Resolve SSE-listed company by 6-digit ticker |
97
+ | | `list_sse_filings` | List SSE disclosures from sse.com.cn |
98
+ | | `get_sse_section` | SSE annual-report section extraction |
99
+ | | `get_sse_interaction` | 上证e互动 investor Q&A |
100
+ | | `get_szse_company` | Resolve SZSE-listed company by 6-digit ticker |
101
+ | | `list_szse_filings` | List SZSE disclosures from szse.cn |
102
+ | | `get_szse_section` | SZSE annual-report section extraction |
103
+ | | `get_szse_interaction` | 互动易 investor Q&A |
104
+ | | `get_bse_company` | Resolve BSE-listed company by 6-digit ticker |
105
+ | | `list_bse_filings` | List BSE disclosures (BSE-native, CNINFO fallback) |
106
+ | | `get_bse_section` | BSE annual-report section extraction |
107
+ | **Official-website (CSRC)** | `list_csrc_filings` | List CSRC regulatory announcements |
108
+ | | `get_csrc_ipo_review` | CSRC IPO (首发) review status |
109
+ | | `get_csrc_merger_review` | CSRC 并购重组 review status |
110
+ | | `list_csrc_enforcement` | CSRC enforcement actions |
111
+ | **Ministry statistics** | `list_ministries` | List supported ministry stat sources |
112
+ | | `get_ministry_stat` | Ministry stats page -> HTML tables |
113
+ | | `get_nbs_stat` | NBS macro statistic by indicator code |
114
+ | **PDF / AI / ES** | `list_outline` | Parse 目录 from report URL or PDF path |
115
+ | | `extract_section` | Body text by exact title / regex / ordinal |
116
+ | | `ai_extract` | LLM-structured extraction over section text |
117
+ | | `index_records` | Bulk index records into ES |
118
+ | | `search_reports` | BM25 + filter search with highlights |
119
+ | | `delete_index` | Drop `cnreport-{year}` index |
120
+ | **Cache** | `list_cache` | List cached reports |
121
+ | | `clear_cache` | Evict cached reports |
122
+ | **Indicators** | `list_indicators` | Browse indicator rule set |
123
+ | | `get_indicator` | One indicator's value |
124
+ | | `extract_indicators` | All applicable indicators in one pass |
125
+ | | `extract_indicators_by_position` | CSV-driven extraction |
126
+ | | `extract_indicators_batch` | Batch concurrent extraction |
127
+ | **Dashboard** | `open_industry_rules_dashboard` | Start the rules web dashboard |
128
+
129
+ ## Typical Chain
130
+
131
+ ```python
132
+ # 1. Resolve company → 2. find latest annual → 3. pull MD&A → 4. LLM-extract revenue table
133
+
134
+ co = get_company("600519")
135
+ # {"stock_code": "600519", "name": "贵州茅台", "org_id": "gssh0600519", "exchange": "sse", ...}
136
+
137
+ filings = list_filings("600519", form="年度报告", year=2023, limit=3)
138
+ # [{"announcement_id": "1219730876", "pdf_url": "http://static.cninfo.com.cn/.../*.PDF", ...}]
139
+
140
+ sec = get_section("600519", year=2023, section="管理层讨论与分析")
141
+ # {"text": "<full MD&A body>", "pdf_url": "...", "outline_entry": {...}, ...}
142
+
143
+ records = ai_extract(
144
+ text=sec["text"],
145
+ schema={"type": "object", "properties": {
146
+ "segment": {"type": "string"},
147
+ "revenue_2023": {"type": "string"},
148
+ }, "required": ["segment", "revenue_2023"]},
149
+ )
150
+ # {"records": [{"segment": "茅台酒", "revenue_2023": "139,989,000,000"}, ...]}
151
+ ```
152
+
153
+ ## Special Report Types
154
+
155
+ CNINFO exposes dozens of disclosure categories beyond the four periodic reports
156
+ (招股说明书, 增发, 业绩预告, 收购报告书, 股权激励, …). Browse the catalog, then list or
157
+ retrieve by category:
158
+
159
+ ```python
160
+ catalog = list_report_types()
161
+ # {"groups": [{"name": "定期报告", "categories": [...]}, {"name": "融资", ...}, ...], "count": 26}
162
+
163
+ list_report_types(group="融资")
164
+ # {"group": "融资", "categories": [{name: "首发", code: "category_sf_szsh", ...}, ...], "count": 6}
165
+
166
+ filings = list_filings("600519", category="首发", limit=3)
167
+
168
+ sec = get_special_report("600519", category="首发", section="募集资金运用")
169
+ ```
170
+
171
+ ## 三大报表 (Three Major Financial Statements)
172
+
173
+ `get_financials` returns akshare's structured numeric tables. `get_financial_statements`
174
+ pulls the three major statement sections **as text** from the PDF:
175
+
176
+ ```python
177
+ stmts = get_financial_statements("600519", year=2023)
178
+ # {
179
+ # "stock_code": "600519", "company_name": "贵州茅台", "year": 2023,
180
+ # "form": "年度报告", "pdf_url": "...", "cached": False,
181
+ # "statements": {
182
+ # "income_statement": {"title": "2、 合并利润表", "outline_entry": {...}, "char_count": 4521, "text": "..."},
183
+ # "balance_sheet": {"title": "1、 合并资产负债表", ...},
184
+ # "cashflow": {"title": "3、 合并现金流量表", ...},
185
+ # },
186
+ # "missing": [],
187
+ # }
188
+ ```
189
+
190
+ ## Report Cache
191
+
192
+ Every report fetch goes through an on-disk cache under `.cache/reports/`.
193
+ First fetch downloads PDF + extracts text + outline; subsequent fetches read from disk.
194
+
195
+ ```python
196
+ list_cache()
197
+ # {"cache_dir": ".../.cache/reports", "count": 2, "entries": [...]}
198
+
199
+ clear_cache() # evict everything
200
+ clear_cache(stock_code="600519") # evict one company
201
+ clear_cache(stock_code="600519", year=2023) # evict one company + year
202
+ ```
203
+
204
+ ## Indicators
205
+
206
+ The indicator engine profiles each company, filters applicable rules, and
207
+ routes each indicator to akshare / report-section / computed / external.
208
+
209
+ ```python
210
+ # Preview → pull one → pull all → CSV
211
+ list_indicators(company="工商银行") # rules applicable to 工商银行
212
+ get_indicator("资本充足率", "工商银行", 2023) # one value
213
+ extract_indicators("工商银行", 2023) # all applicable, one PDF fetch
214
+ extract_indicators("工商银行", 2023,
215
+ indicators=["资本充足率","不良率"]) # subset
216
+ extract_indicators("工商银行", 2023, extractor_mode="python") # LLM-free
217
+ extract_indicators_by_position("工商银行", 2023) # CSV-driven
218
+ ```
219
+
220
+ Multi-form support (年度报告 / 半年度报告 / 第一季度报告 / 第三季度报告):
221
+
222
+ ```python
223
+ extract_indicators_by_position("工商银行", 2023, form="第一季度报告")
224
+ extract_indicators("贵州茅台", 2023, form="半年度报告")
225
+ ```
226
+
227
+ ### Concurrency
228
+
229
+ ```python
230
+ extract_indicators("工商银行", 2023, concurrency=4) # explicit cap
231
+ extract_indicators("工商银行", 2023, concurrency=1) # sequential
232
+
233
+ # Batch: multi-company concurrent extraction
234
+ extract_indicators_batch([("601398", 2023), ("600519", 2023)],
235
+ concurrency=2, extract_concurrency=4)
236
+ # → {"results": {"601398_2023": {...}, ...}, "failures": [...], "concurrency": 2}
237
+ ```
238
+
239
+ ### Section Cache
240
+
241
+ LLM responses are persisted to disk, keyed by `(pdf_url, section_key, period, rules_hash)`.
242
+ Subsequent runs reuse cached records. Set `LLM_SECTION_CACHE=off` to disable.
243
+
244
+ ## Standalone CLIs
245
+
246
+ ```bash
247
+ # Full engine extraction
248
+ python scripts/extract_indicators.py 601398 --year 2023 \
249
+ [--rules indicator_rules.json] [--extractor auto|llm|python] \
250
+ [--indicators 资本充足率,不良率] [--out-dir ./out]
251
+
252
+ # CSV-driven extraction
253
+ python scripts/extract_indicators_by_position.py 601398 --year 2023 \
254
+ [--csv docs/indicators_position.csv] [--extractor auto|llm|python] \
255
+ [--form 年度报告|半年度报告|第一季度报告|第三季度报告]
256
+
257
+ # Multi-year extraction
258
+ python scripts/extract_indicators_multiyear.py 601398 2023 2024
259
+
260
+ # Industry rules dashboard
261
+ python scripts/industry_rules_dashboard.py [port]
262
+ # or: fd-cn-report
263
+
264
+ # Generate industry rules from real reports
265
+ python scripts/generate_rules_from_real_reports.py
266
+
267
+ # Check industry coverage
268
+ python scripts/check_industry_coverage.py
269
+
270
+ # Seed industry rules
271
+ python scripts/seed_industry_rules.py
272
+ ```
273
+
274
+ ## HK Stock Support
275
+
276
+ ```python
277
+ get_hk_company("00700") # → 腾讯控股
278
+ list_hk_filings("00700", year=2023) # → HKEX filings
279
+ get_hk_financials("00700") # → financial statements
280
+ get_hk_section("00700", year=2023, section="管理层讨论与分析")
281
+ ```
282
+
283
+ ## Official-website datasources (SSE / SZSE / BSE)
284
+
285
+ Direct, primary-source disclosure paths complementing CNINFO. Each exchange
286
+ client resolves a 6-digit ticker locally (no network) and lists disclosures
287
+ from the exchange's own site. BSE falls back to CNINFO when its own API is
288
+ thin, tagging each row with `source: "bse" | "cninfo"`. Section extraction
289
+ reuses the same outline pipeline as CNINFO/HK.
290
+
291
+ ```python
292
+ # SSE (上交所) - 600/601/603/605/688/900 codes
293
+ get_sse_company("600519")
294
+ list_sse_filings("600519", year=2023) # -> sse.com.cn disclosures
295
+ get_sse_section("600519", year=2023, section="管理层讨论与分析")
296
+ get_sse_interaction("600519") # -> 上证e互动 Q&A
297
+
298
+ # SZSE (深交所) - 000/001/002/003/300/301 codes
299
+ get_szse_company("000001")
300
+ list_szse_filings("000001", year=2023) # -> szse.cn disclosures
301
+ get_szse_section("000001", year=2023, section="管理层讨论与分析")
302
+ get_szse_interaction("000001") # -> 互动易 Q&A (irm.cninfo.com.cn)
303
+
304
+ # BSE (北交所) - 430xxx / 83xxxx / 87xxxx / 88xxxx / 920xxx codes
305
+ get_bse_company("835185")
306
+ list_bse_filings("835185", year=2023) # -> BSE-native, else CNINFO fallback
307
+ get_bse_section("835185", year=2023, section="管理层讨论与分析") # result carries `source`
308
+ ```
309
+
310
+ > **Endpoints are undocumented.** SSE (`query.sse.com.cn`), SZSE
311
+ > (`www.szse.cn/api`), BSE (`www.bse.cn`), and the Q&A hosts
312
+ > (`sns.sseinfo.com`, `irm.cninfo.com.cn`) expose no official API contract and
313
+ > shift over time. Clients are thin, retry 429/5xx, and bypass proxy env
314
+ > (`trust_env=False`). Run `CNREPORT_SELFCHECK_LIVE=1 uv run python selfcheck.py`
315
+ > to ping each endpoint - 4xx/5xx are flagged per source without failing the
316
+ > suite. Name-fragment resolution is not supported by these clients; resolve the
317
+ > name via `get_company` (CNINFO) first, then pass the 6-digit code.
318
+
319
+ ## CSRC regulatory data (证监会)
320
+
321
+ CSRC regulatory data CNINFO/exchanges do not cover: announcements, IPO / 并购重组
322
+ review status, and enforcement. HTML-parsed with `lxml`; endpoints undocumented.
323
+
324
+ ```python
325
+ list_csrc_filings(begin_date="2024-01-01") # -> regulatory announcements
326
+ get_csrc_ipo_review("贵州茅台") # -> IPO review status row
327
+ get_csrc_merger_review("某科技股份公司") # -> M&A review status row
328
+ list_csrc_enforcement() # -> administrative-penalty actions
329
+ ```
330
+
331
+ ## Ministry statistics (部级部门)
332
+
333
+ Structured economic/financial statistics from ministry-level departments,
334
+ complementing `fd-cn-gov`'s catalog-archive scraping with *data* queries. NBS
335
+ has a JSON API; the others publish HTML tables. Results are TTL-cached under
336
+ `.cache/stats/`. Base URLs reuse `fd-cn-gov`'s registry when importable.
337
+
338
+ ```python
339
+ list_ministries() # -> [{id, label, en, transport, base}, ...]
340
+ get_nbs_stat("A0201") # -> NBS GDP series {period: value} (dbcode="hgnd" annual)
341
+ get_ministry_stat("gacc") # -> GACC trade page parsed into HTML tables
342
+ get_ministry_stat("pboc", limit=20) # -> PBoC monetary tables
343
+ # Supported ids: nbs mof pboc safe gacc nfra
344
+ ```
345
+
346
+ > Ministry stat-page paths and CSRC URLs are best-guess and **undocumented** -
347
+ > verify live via `CNREPORT_SELFCHECK_LIVE=1 uv run python selfcheck.py`.
348
+ > Corrections are one-line edits in `ministry_stats_client._MINISTRIES` /
349
+ > `csrc_client._URLS`.
350
+
351
+ ## Setup
352
+
353
+ ```bash
354
+ uv sync # installs akshare, pypdf, fastmcp, ...
355
+ uv run python server.py # FastMCP over stdio
356
+ ```
357
+
358
+ Self-check (no network):
359
+
360
+ ```bash
361
+ uv run python selfcheck.py # DB + outline + company API + special reports
362
+ uv run python selfcheck_cache.py # report cache + three-statements extraction
363
+ ```
364
+
365
+ Tests (offline):
366
+
367
+ ```bash
368
+ uv run --with pytest python -m pytest test_cnreport.py -v -p no:logfire
369
+ ```
370
+
371
+ ## Configuration
372
+
373
+ CNINFO and akshare are **keyless**. Other tools need env vars in `.env`:
374
+
375
+ | Var | Used by | Required? |
376
+ |-----|---------|-----------|
377
+ | `LLM_API_KEY`, `LLM_BASE_URL`, `LLM_MODEL` | `ai_extract`, rule generation | Yes for AI |
378
+ | `ES_URL` (+ optional `ES_API_KEY` or `ES_USERNAME`/`ES_PASSWORD`) | `index_records`, `search_reports`, `delete_index` | Yes for ES |
379
+ | `DAAS_DATABASE_URL` | provenance writes, rules storage | Defaults to `daas.db` |
380
+ | `CNREPORT_CACHE_DIR` | report cache | Defaults to `.cache/reports/` |
381
+
382
+ ## Architecture
383
+
384
+ ```
385
+ fd-cn-report/
386
+ ├── server.py # FastMCP server (@app.tool registrations)
387
+ ├── cninfo_client.py # CNINFO API (keyless lookup + query)
388
+ ├── hk_stock_client.py # HK stock API (akshare + HKEX)
389
+ ├── financials_client.py # akshare financial statements (lazy)
390
+ ├── cnreport_tools.py # Pure helpers (outline, extract, LLM, ES)
391
+ ├── report_cache.py # On-disk PDF + text + outline cache
392
+ ├── llm_section_cache.py # LLM response section cache
393
+
394
+ ├── indicators_client.py # Rules engine (load, profile, route, extract)
395
+ ├── indicators_extractors.py # Pluggable Python extractors
396
+ ├── indicators_models.py # Pydantic extraction models
397
+ ├── indicators_csv_migration.py # CSV → JSON rule migration
398
+ ├── report_section_map.py # Section alias expansion + matching
399
+
400
+ ├── rules_db.py # Rules database (SQLite via SQLAlchemy)
401
+ ├── rules_models.py # Pydantic rule models
402
+ ├── rules_skills.py # LLM rule generation + validation
403
+ ├── cnreport_models.py # ORM models (LlmRule, ScriptRule)
404
+ ├── cnreport_database.py # Database connection management
405
+
406
+ ├── industry_taxonomy.py # 申万 L1 industry taxonomy
407
+ ├── industry_coverage.py # Coverage checks for industry rules
408
+
409
+ ├── docs/
410
+ │ ├── industry_taxonomy.json # 31 industry taxonomy
411
+ │ ├── industry_indicator_baseline.json # Baseline indicators per industry
412
+ │ ├── indicators_position.csv # Indicator catalog (CSV source)
413
+ │ └── indicators-methodology.md # Rendered methodology
414
+
415
+ ├── scripts/
416
+ │ ├── industry_rules_dashboard.py # Web dashboard (CLI + MCP)
417
+ │ ├── generate_rules_from_real_reports.py # Per-industry rule generation
418
+ │ ├── generate_all_industry_rules.py # LLM rule generation
419
+ │ ├── seed_industry_rules.py # Universal rule seeding
420
+ │ ├── seed_missing_industry_rules.py # Industry-specific seeding
421
+ │ ├── extract_indicators.py # Standalone extraction CLI
422
+ │ ├── extract_indicators_by_position.py # CSV-driven extraction CLI
423
+ │ ├── extract_indicators_multiyear.py # Multi-year batch extraction
424
+ │ ├── check_industry_coverage.py # Coverage validation
425
+ │ ├── migrate_indicators_csv.py # CSV → DB migration
426
+ │ └── rules_dashboard.py # indicator_rules.json editor
427
+
428
+ └── .cache/reports/ # Downloaded PDFs + extracted text + outlines
429
+ ```
430
+
431
+ ## Adding a New Industry
432
+
433
+ 1. Add to `docs/industry_taxonomy.json`:
434
+ ```json
435
+ {"industry": "801xxx", "label": "行业名称", "report_kinds": ["annual-report", "interim-report", "quarterly-report"]}
436
+ ```
437
+
438
+ 2. Add baseline indicators to `docs/industry_indicator_baseline.json`:
439
+ ```json
440
+ {"cn/801xxx/listed/annual-report": ["资产总计", "营业收入", "净利润", ...]}
441
+ ```
442
+
443
+ 3. Add representative company to `scripts/generate_rules_from_real_reports.py`:
444
+ ```python
445
+ "801xxx": ("600xxx", "代表公司", "行业名称"),
446
+ ```
447
+
448
+ 4. Define industry-specific sections:
449
+ ```python
450
+ "801xxx": [("section_name", "keyword", "keyword2", "guidance"), ...],
451
+ ```
452
+
453
+ 5. Generate rules:
454
+ ```bash
455
+ python scripts/generate_rules_from_real_reports.py --industry 801xxx
456
+ ```
457
+
458
+ ## License
459
+
460
+ MIT