| 属性 | 内容 |
|---|---|
| 工作流ID | WF-002 |
| 工作流名称 | 知识库生成 |
| 功能描述 | 从MatrixOne库中的历史Issue数据提炼产品知识、问题模式、标签体系,生成Markdown文档并存入数据库 |
| 实现状态 | ✅ 已实现 |
| 云端可用 | ✅ 完全可用 |
| 核心价值 | 自动学习产品结构和问题模式,为WF-003(智能提Issue)提供知识支持 |
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 步骤1 │──▶│ 步骤2 │──▶│ 步骤3 │──▶│ 步骤4 │──▶│ 步骤5 │──▶│ 步骤6 │──▶│ 步骤7 │
│读取Issue │ │AI提炼产品│ │ 分析标签 │ │识别常见 │ │生成MD文档│ │存入数据库│ │保存文件 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
从MO库查询 AI识别产品 统计Labels 高频Issue Markdown 写入知识库表 .md文件
历史Issue 模块/功能 按前缀分类 组合模式 结构化文档 版本化管理 latest版本
快速理解:
- 步骤1 - 从MO库读取历史Issue数据(最新快照)
- 步骤2 - AI分析200个样本,识别产品结构(MOI/MO、模块、功能)
- 步骤3 - 统计Labels体系(customer/、area/、kind/等前缀)
- 步骤4 - 识别高频Issue组合(≥10个的常见类型)
- 步骤5 - 生成Markdown知识库文档(产品+标签+常见Issue)
- 步骤6 - 存入
issue_knowledge_base表(结构化存储) - 步骤7 - 保存MD文件(latest版本+历史版本)
核心特点:✅ AI驱动提炼 | ✅ MD文档+数据库双存储 | ✅ Issue规范作为基础
| 输入项 | 类型 | 说明 | 来源 |
|---|---|---|---|
| repo_owner | String | 仓库所有者 | matrixorigin |
| repo_name | String | 仓库名称 | matrixone / matrixflow |
| 历史Issue数据 | 数据库 | MO库中的issues_snapshot表 | WF-001的输出 |
| 输入项 | 类型 | 说明 | 示例 |
|---|---|---|---|
| AI_PROVIDER | String | AI服务提供商 | qwen(推荐) |
| DASHSCOPE_API_KEY | String | 通义千问API密钥 | sk-xxxxxxxxxxxx |
| QWEN_MODEL | String | 模型名称 | qwen-plus |
| 输入项 | 类型 | 说明 | 位置 |
|---|---|---|---|
| 模板文件 | Markdown | Issue标准模板,作为知识库的基础 | feature_issue_and_kanban/templates/*.md |
模板文件作用:
- 提供Issue标准字段结构
- 作为AI提炼的参考基准
- 定义产品分类(MO/MOI/Customer等)
| 输入项 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| min_issue_count | Integer | 标签最小出现次数(低于此值过滤) | 3 |
| sample_size | Integer | AI分析的样本数量 | 200 |
| common_issue_threshold | Integer | 常见Issue类型阈值 | 10 |
| 输出项 | 文件路径 | 说明 |
|---|---|---|
| 最新知识库 | data/knowledge_base/{owner}_{repo}_knowledge_latest.md |
最新版本,覆盖式更新 |
| 带时间戳版本 | data/knowledge_base/{owner}_{repo}_knowledge_{YYYYMMDD}.md |
历史版本备份 |
| 输出项 | 表名 | 说明 |
|---|---|---|
| 知识库记录 | issue_knowledge_base |
结构化知识数据 |
Markdown文档包含:
- 产品结构 - 识别的产品/模块列表
- 标签体系 - 按前缀分类的标签统计
- 常见Issue类型 - 高频Issue模式
- Issue目录 - 按产品/模块组织的Issue分类
步骤ID: WF-002-S01
功能: 从MatrixOne读取所有历史Issue数据
实现状态: ✅ 已实现
repo_owner: 仓库所有者repo_name: 仓库名称- 数据库连接: MO连接配置(来自WF-001)
SQL查询:
SELECT
issue_number,
title,
labels, -- JSON格式的Labels
state,
created_at
FROM issues_snapshot
WHERE repo_owner = :owner
AND repo_name = :repo
AND snapshot_time = (
SELECT MAX(snapshot_time)
FROM issues_snapshot
WHERE repo_owner = :owner
AND repo_name = :repo
)解析Labels:
# Labels字段是JSON字符串,需要解析
labels_data = json.loads(issue['labels'])
# 结果: [{"name": "bug", "color": "d73a4a"}, ...]- Issue列表(Python字典数组):
[ { "number": 8450, "title": "Bug: 查询超时", "labels": [ {"name": "bug", "color": "d73a4a"}, {"name": "customer/金盘", "color": "fbca04"} ], "state": "open", "created_at": "2024-01-01T00:00:00Z" }, ... ]
- 文件:
feature_issue_and_kanban/issue_creator/knowledge_extractor.py - 类:
KnowledgeExtractor - 方法:
_load_all_issues(repo_owner, repo_name)
步骤ID: WF-002-S02
功能: 使用AI分析Issue样本,识别产品分类、模块、功能
实现状态: ✅ 已实现
- 历史Issue数据(步骤1输出)
- sample_size: AI分析样本数量(默认200个)
- AI配置: 通义千问API
采样策略:
# 如果Issue总数>200,随机采样200个
sampled_issues = random.sample(issues, min(200, len(issues)))AI Prompt构建:
prompt = f"""
你是产品分析专家。请根据以下 {len(sampled)} 个 Issue 样本,提取产品结构。
Issue样本:
{json.dumps(sampled, ensure_ascii=False, indent=2)}
请识别:
1) 主产品(如 MOI、MO)
2) 子产品/模块
3) 主要功能
返回纯 JSON,格式示例:
{{
"MOI": {{
"type": "platform",
"sub_products": {{
"问数": {{
"features": ["NL2SQL", "数据分析"],
"issue_count": 100
}},
"ChatBI": {{
"features": ["对话交互", "BI分析"],
"issue_count": 50
}}
}}
}},
"MO": {{
"type": "database",
"modules": {{
"storage": {{"issue_count": 50}},
"sql": {{"issue_count": 80}}
}}
}}
}}
只返回 JSON,不要其他说明。
"""AI调用:
client = OpenAI(api_key=DASHSCOPE_API_KEY, base_url=QWEN_BASE_URL)
response = client.chat.completions.create(
model=QWEN_MODEL,
messages=[
{"role": "system", "content": "你只输出合法 JSON,不要 markdown 代码块。"},
{"role": "user", "content": prompt}
]
)回退机制(AI失败时):
# 基于规则提取:从Labels中识别 area/ 前缀
products = {}
for issue in issues:
for label in issue['labels']:
if label['name'].startswith('area/'):
area = label['name'].replace('area/', '')
# 归类到 MOI 产品
products.setdefault('MOI', {})['sub_products'][area] = {
'issue_count': ...
}- 产品结构字典(JSON格式):
{ "MOI": { "type": "platform", "sub_products": { "问数": { "features": ["NL2SQL", "数据分析"], "issue_count": 100 } } }, "MO": { "type": "database", "modules": { "storage": {"issue_count": 50} } } }
- 方法:
_extract_products(issues)
步骤ID: WF-002-S03
功能: 统计Labels,按前缀分类,过滤低频标签
实现状态: ✅ 已实现
- 历史Issue数据(步骤1输出)
- min_issue_count: 最小出现次数(默认3)
标签统计:
label_stats = defaultdict(lambda: defaultdict(int))
for issue in issues:
for label in issue['labels']:
name = label['name']
# 按前缀分类(如 customer/, area/, kind/)
if "/" in name:
prefix = name.split("/", 1)[0] + "/"
label_stats[prefix][name] += 1
else:
# 无前缀的标签归入 "other"
label_stats["other"][name] += 1过滤低频标签:
result = {}
for prefix, labels in label_stats.items():
# 只保留出现次数 >= min_issue_count 的标签
filtered = {
label: count
for label, count in labels.items()
if count >= min_issue_count
}
if filtered:
result[prefix] = filtered排序:
# 按出现次数降序排列
result[prefix] = dict(sorted(filtered.items(), key=lambda x: -x[1]))- 标签体系字典(JSON格式):
{ "customer/": { "customer/金盘": 50, "customer/XX公司": 30, "customer/YY银行": 25 }, "area/": { "area/问数": 100, "area/ChatBI": 80 }, "kind/": { "kind/bug": 200, "kind/feature": 150 }, "other": { "bug": 100, "enhancement": 50 } }
- 方法:
_extract_label_system(issues)
步骤ID: WF-002-S04
功能: 找出高频出现的Label组合,识别常见问题模式
实现状态: ✅ 已实现
- 历史Issue数据(步骤1输出)
- threshold: 常见Issue阈值(默认10,即至少10个Issue)
按Label组合分组:
grouped = defaultdict(list)
for issue in issues:
# 提取 kind/ 和 area/ 标签
key_labels = [
label['name']
for label in issue['labels']
if 'kind/' in label['name'] or 'area/' in label['name']
]
# 按字母排序形成唯一键
key = tuple(sorted(key_labels))
if key:
grouped[key].append(issue)识别高频组合:
common_issues = []
for labels_tuple, issue_list in grouped.items():
# 至少10个Issue才算常见类型
if len(issue_list) >= 10:
common_issues.append({
"labels": list(labels_tuple),
"count": len(issue_list),
"examples": [
{"number": i["number"], "title": i["title"]}
for i in issue_list[:5] # 取前5个作为示例
]
})
# 按数量降序排列,取前50个
common_issues.sort(key=lambda x: -x['count'])
common_issues = common_issues[:50]- 常见Issue类型列表(JSON格式):
[ { "labels": ["area/问数", "kind/bug"], "count": 120, "examples": [ {"number": 8450, "title": "NL2SQL翻译错误"}, {"number": 8451, "title": "查询超时"}, ... ] }, { "labels": ["area/ChatBI", "kind/feature"], "count": 80, "examples": [...] } ]
- 方法:
_extract_common_issue_types(issues)
步骤ID: WF-002-S05
功能: 将提炼的知识组织为结构化Markdown文档
实现状态: ✅ 已实现
- 产品结构(步骤2输出)
- 标签体系(步骤3输出)
- 常见Issue类型(步骤4输出)
Markdown生成逻辑:
markdown = f"""# Issue知识库索引
**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
---
## 一、产品结构
### MOI (平台)
- 问数 (100 Issues)
- 功能: NL2SQL, 数据分析
- ChatBI (80 Issues)
- 功能: 对话交互, BI分析
### MO (数据库)
- storage (50 Issues)
- sql (80 Issues)
---
## 二、标签体系
### customer/
- `customer/金盘` (50)
- `customer/XX公司` (30)
### area/
- `area/问数` (100)
- `area/ChatBI` (80)
### kind/
- `kind/bug` (200)
- `kind/feature` (150)
---
## 三、常见Issue类型
### 1. area/问数, kind/bug (120 Issues)
- #8450: NL2SQL翻译错误
- #8451: 查询超时
- #8452: 结果不准确
### 2. area/ChatBI, kind/feature (80 Issues)
- #7890: 增加图表类型
- #7891: 支持导出报告
"""- Markdown文本(字符串)
- 方法:
_generate_markdown_index(knowledge)
步骤ID: WF-002-S06
功能: 将知识库数据存入 issue_knowledge_base 表
实现状态: ✅ 已实现
- 产品结构(步骤2输出)
- 标签体系(步骤3输出)
- 常见Issue类型(步骤4输出)
生成版本号:
version = int(datetime.now().timestamp()) # 时间戳作为版本号存储产品结构:
INSERT INTO issue_knowledge_base (
knowledge_type, -- 'product'
category, -- 产品名(如 'MOI')
title, -- 产品名
description, -- JSON格式的产品详情
version -- 版本号
) VALUES (...)存储标签体系:
INSERT INTO issue_knowledge_base (
knowledge_type, -- 'label'
category, -- 标签前缀(如 'customer/')
title, -- 标签名(如 'customer/金盘')
description, -- 描述(如 '出现50次')
issue_count, -- 出现次数
version
) VALUES (...)存储常见Issue类型:
INSERT INTO issue_knowledge_base (
knowledge_type, -- 'common_issue'
category, -- Labels组合(逗号分隔)
title, -- 描述标题
description, -- JSON格式的详情(含examples)
issue_count, -- Issue数量
version
) VALUES (...)- 数据库记录: 存入
issue_knowledge_base表
- 方法:
_save_to_database(products, label_system, common_issues)_insert_knowledge(...)
步骤ID: WF-002-S07
功能: 将Markdown文档保存到文件系统
实现状态: ✅ 已实现
- Markdown文本(步骤5输出)
repo_owner,repo_name
文件路径生成:
output_dir = Path("data/knowledge_base")
output_dir.mkdir(parents=True, exist_ok=True)
# 带时间戳的历史版本
timestamp = datetime.now().strftime("%Y%m%d")
history_file = output_dir / f"{repo_owner}_{repo_name}_knowledge_{timestamp}.md"
# 最新版本(覆盖式)
latest_file = output_dir / f"{repo_owner}_{repo_name}_knowledge_latest.md"写入文件:
history_file.write_text(markdown, encoding="utf-8")
latest_file.write_text(markdown, encoding="utf-8")- 文件:
data/knowledge_base/matrixorigin_matrixone_knowledge_20260304.mddata/knowledge_base/matrixorigin_matrixone_knowledge_latest.md
- 方法:
_save_markdown_file(markdown, repo_owner, repo_name)
| 字段名 | 类型 | 说明 | 示例 |
|---|---|---|---|
| id | INTEGER | 主键 | - |
| knowledge_type | VARCHAR(50) | 知识类型 | product / label / common_issue |
| category | VARCHAR(100) | 分类 | MOI / customer/ / area/问数,kind/bug |
| title | VARCHAR(200) | 标题 | 问数 / customer/金盘 |
| description | TEXT | 详细描述(JSON或文本) | {"features": [...]} |
| issue_count | INTEGER | 关联Issue数量 | 100 |
| version | INTEGER | 版本号(时间戳) | 1709535600 |
| created_at | DATETIME | 创建时间 | - |
配置位置: config/config.py + 代码内部参数
关键参数:
# AI配置(同WF-001)
AI_PROVIDER = "qwen"
DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY")
# 知识提炼参数(代码内部)
min_issue_count = 3 # 标签最小出现次数
sample_size = 200 # AI分析样本数量
common_issue_threshold = 10 # 常见Issue阈值python3 feature_issue_and_kanban/scripts/update_knowledge_base.py \
--repo-owner matrixorigin \
--repo-name matrixonefrom feature_issue_and_kanban.issue_creator.knowledge_extractor import KnowledgeExtractor
from modules.database_storage.mo_client import MOStorage
from modules/llm_parser.llm_parser import LLMParser
# 初始化
storage = MOStorage()
llm = LLMParser()
extractor = KnowledgeExtractor(storage, llm)
# 提炼知识库
result = extractor.extract_full_knowledge_base("matrixorigin", "matrixone")
print(f"✅ 知识库生成完成")
print(f"产品数量: {len(result['products'])}")
print(f"标签数量: {sum(len(v) for v in result['label_system'].values())}")
print(f"常见Issue类型: {len(result['common_issues'])}")-
检查Markdown文件:
ls -lh data/knowledge_base/ cat data/knowledge_base/matrixorigin_matrixone_knowledge_latest.md
-
检查数据库记录:
-- 查看知识库记录 SELECT knowledge_type, COUNT(*) FROM issue_knowledge_base GROUP BY knowledge_type; -- 查看产品列表 SELECT * FROM issue_knowledge_base WHERE knowledge_type = 'product'; -- 查看标签体系 SELECT category, title, issue_count FROM issue_knowledge_base WHERE knowledge_type = 'label' ORDER BY issue_count DESC LIMIT 20;
确认:生成MD文档并保存到 data/knowledge_base/ 目录
确认:
- AI驱动:通过通义千问API智能识别
- 基于历史数据:从MO库中的Issue学习
- 规则回退:AI失败时使用基于Labels的规则提取
确认:AI提炼包括:
- 产品分类(MOI/MO等)
- 产品功能列表
- 主要问题类型
- Issue对应目录(按area/customer/kind组织)
确认:feature_issue_and_kanban/templates/*.md 作为:
- 知识库的基础结构参考
- AI提炼的字段模板
- 产品分类的参考标准
| 指标 | 数值 | 说明 |
|---|---|---|
| 处理速度 | ~1000 issues/分钟 | 数据读取和统计 |
| AI调用 | 1-2次 | 仅对样本数据调用AI |
| 生成时间 | ~2-5分钟 | 1000个Issue的完整提炼 |
| 文件大小 | ~50-200KB | Markdown文档 |
该工作流在云端部署无任何限制:
- 只依赖数据库读取和AI API调用
- 文件写入可用云存储替代
- 无本地环境依赖
- 定期执行:建议每周或每次WF-001运行后执行
- 增量更新:通过版本号(timestamp)管理多版本知识库
- 缓存策略:latest版本可缓存给WF-003使用
文档版本: v1.0
最后更新: 2026-03-04