Co-authored-by: ArtemFilin1990 <221041513+ArtemFilin1990@users.noreply.github.com>
435 lines
23 KiB
Python
Executable File
435 lines
23 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Enhanced Knowledge Base Builder - MAX CONTEXT MODE
|
|
|
|
Построение ПОЛНОЙ, структурированной и машиночитаемой базы знаний
|
|
согласно требованиям промпта.
|
|
|
|
Извлекает 100% информации из всех файлов без сокращений.
|
|
"""
|
|
|
|
import re
|
|
from collections import defaultdict
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
|
|
class EnhancedKnowledgeBaseBuilder:
|
|
"""Расширенный построитель базы знаний с полным извлечением информации."""
|
|
|
|
def __init__(self, repo_path: str = "."):
|
|
self.repo_path = Path(repo_path)
|
|
self.exclude_dirs = {
|
|
".git",
|
|
"__pycache__",
|
|
".pytest_cache",
|
|
"node_modules",
|
|
".venv",
|
|
"venv",
|
|
"dist",
|
|
"build",
|
|
"_trash_review",
|
|
"ZIP",
|
|
}
|
|
|
|
# Собранные данные
|
|
self.domain_info = {}
|
|
self.terms = {}
|
|
self.processes = []
|
|
self.rules = []
|
|
self.data_structures = []
|
|
self.roles = []
|
|
self.instructions = []
|
|
self.errors = []
|
|
self.relationships = []
|
|
self.sources = {}
|
|
|
|
def extract_domain_description(self) -> str:
|
|
"""Извлекает общее описание домена из README и основных файлов."""
|
|
domain_desc = []
|
|
|
|
# Читаем основные README файлы
|
|
readme_files = ["README.md", "README_en.md", "00_Оглавление.md", "KNOWLEDGE_BASE_README.md"]
|
|
|
|
for readme in readme_files:
|
|
path = self.repo_path / readme
|
|
if path.exists():
|
|
try:
|
|
content = path.read_text(encoding="utf-8", errors="ignore")
|
|
# Извлекаем первые несколько абзацев
|
|
lines = content.split("\n")
|
|
desc = []
|
|
for line in lines[:50]:
|
|
if line.strip() and not line.startswith("##"):
|
|
desc.append(line.strip())
|
|
if len(desc) > 10:
|
|
break
|
|
if desc:
|
|
domain_desc.append("\n".join(desc))
|
|
domain_desc.append(f"\n_(Источник: {readme})_\n")
|
|
except Exception:
|
|
# Игнорируем ошибки чтения отдельных файлов, продолжаем обработку
|
|
pass
|
|
|
|
return "\n\n".join(domain_desc)
|
|
|
|
def extract_terms_from_docs(self) -> dict[str, list[str]]:
|
|
"""Извлекает термины из документации."""
|
|
terms = defaultdict(list)
|
|
|
|
# Папки с терминологией
|
|
term_dirs = ["02_Термины_и_основы", "Подшипники", "docs"]
|
|
|
|
for term_dir in term_dirs:
|
|
dir_path = self.repo_path / term_dir
|
|
if dir_path.exists():
|
|
for md_file in dir_path.rglob("*.md"):
|
|
try:
|
|
content = md_file.read_text(encoding="utf-8", errors="ignore")
|
|
# Извлекаем определения (паттерн: термин — определение)
|
|
definitions = re.findall(r"\*\*([^*]+)\*\*\s*[—–-]\s*([^\n]+)", content)
|
|
for term, definition in definitions:
|
|
terms[term.strip()].append(
|
|
{"definition": definition.strip(), "source": str(md_file.relative_to(self.repo_path))}
|
|
)
|
|
|
|
# Извлекаем из таблиц
|
|
tables = re.findall(r"\|([^|]+)\|([^|]+)\|", content)
|
|
for row in tables:
|
|
if len(row) >= 2 and row[0].strip() and row[1].strip():
|
|
term = row[0].strip()
|
|
desc = row[1].strip()
|
|
if len(term) < 100 and len(desc) > 10:
|
|
terms[term].append(
|
|
{"definition": desc, "source": str(md_file.relative_to(self.repo_path))}
|
|
)
|
|
except Exception:
|
|
# Игнорируем ошибки парсинга отдельных файлов, продолжаем обработку
|
|
pass
|
|
|
|
return dict(terms)
|
|
|
|
def extract_processes(self) -> list[dict]:
|
|
"""Извлекает процессы и алгоритмы из документации."""
|
|
processes = []
|
|
|
|
# Паттерны процессов
|
|
process_patterns = [
|
|
r"###?\s*Процесс\s+(.+?)\n(.*?)(?=\n##|\Z)",
|
|
r"###?\s*Алгоритм\s+(.+?)\n(.*?)(?=\n##|\Z)",
|
|
r"###?\s*Порядок\s+(.+?)\n(.*?)(?=\n##|\Z)",
|
|
r"###?\s*Этапы?\s+(.+?)\n(.*?)(?=\n##|\Z)",
|
|
]
|
|
|
|
for md_file in self.repo_path.rglob("*.md"):
|
|
if any(excl in str(md_file) for excl in self.exclude_dirs):
|
|
continue
|
|
|
|
try:
|
|
content = md_file.read_text(encoding="utf-8", errors="ignore")
|
|
|
|
for pattern in process_patterns:
|
|
matches = re.findall(pattern, content, re.DOTALL)
|
|
for title, description in matches:
|
|
processes.append(
|
|
{
|
|
"title": title.strip(),
|
|
"description": description.strip()[:500],
|
|
"source": str(md_file.relative_to(self.repo_path)),
|
|
}
|
|
)
|
|
except Exception:
|
|
# Игнорируем ошибки парсинга отдельных файлов, продолжаем обработку
|
|
pass
|
|
|
|
return processes
|
|
|
|
def extract_rules_and_constraints(self) -> list[dict]:
|
|
"""Извлекает правила и ограничения из стандартов ГОСТ/ISO."""
|
|
rules = []
|
|
|
|
# Папки со стандартами
|
|
standards_dirs = [
|
|
"03_ГОСТ_подшипники_и_нормативка",
|
|
"04_ISO_и_международные_обозначения",
|
|
]
|
|
|
|
for std_dir in standards_dirs:
|
|
dir_path = self.repo_path / std_dir
|
|
if dir_path.exists():
|
|
for md_file in dir_path.rglob("*.md"):
|
|
try:
|
|
content = md_file.read_text(encoding="utf-8", errors="ignore")
|
|
|
|
# ГОСТ стандарты
|
|
gost_refs = re.findall(r"ГОСТ\s+[\d-]+", content)
|
|
iso_refs = re.findall(r"ISO\s+\d+", content)
|
|
|
|
# Правила в виде списков
|
|
list_items = re.findall(r"^[-*]\s+(.+)$", content, re.MULTILINE)
|
|
|
|
if gost_refs or iso_refs:
|
|
rules.append(
|
|
{
|
|
"type": "Стандарт",
|
|
"references": list(set(gost_refs + iso_refs)),
|
|
"rules": list_items[:10],
|
|
"source": str(md_file.relative_to(self.repo_path)),
|
|
}
|
|
)
|
|
except Exception:
|
|
# Игнорируем ошибки парсинга отдельных файлов, продолжаем обработку
|
|
pass
|
|
|
|
return rules
|
|
|
|
def extract_usage_scenarios(self) -> list[dict]:
|
|
"""Извлекает сценарии использования."""
|
|
scenarios = []
|
|
|
|
# Практические руководства
|
|
guides_dir = self.repo_path / "Практические_руководства"
|
|
if guides_dir.exists():
|
|
for md_file in guides_dir.rglob("*.md"):
|
|
try:
|
|
content = md_file.read_text(encoding="utf-8", errors="ignore")
|
|
|
|
# Извлекаем примеры и сценарии
|
|
examples = re.findall(r"###?\s*Пример[:]?\s*(.+?)\n(.*?)(?=\n##|\Z)", content, re.DOTALL)
|
|
|
|
for title, description in examples:
|
|
scenarios.append(
|
|
{
|
|
"title": title.strip(),
|
|
"description": description.strip()[:500],
|
|
"source": str(md_file.relative_to(self.repo_path)),
|
|
}
|
|
)
|
|
except Exception:
|
|
# Игнорируем ошибки парсинга сценариев из отдельных файлов, продолжаем обработку
|
|
pass
|
|
|
|
return scenarios
|
|
|
|
def extract_relationships(self) -> list[dict]:
|
|
"""Извлекает связи и зависимости."""
|
|
relationships = []
|
|
|
|
# Связи в аналогах
|
|
analogs_dir = self.repo_path / "06_Аналоги_и_взаимозаменяемость"
|
|
if analogs_dir.exists():
|
|
for md_file in analogs_dir.rglob("*.md"):
|
|
try:
|
|
content = md_file.read_text(encoding="utf-8", errors="ignore")
|
|
|
|
# Таблицы аналогов
|
|
tables = re.findall(r"\|([^|]+)\|([^|]+)\|", content)
|
|
for row in tables[:20]:
|
|
if "гост" in row[0].lower() or "iso" in row[0].lower():
|
|
relationships.append(
|
|
{
|
|
"type": "Аналог",
|
|
"from": row[0].strip(),
|
|
"to": row[1].strip(),
|
|
"source": str(md_file.relative_to(self.repo_path)),
|
|
}
|
|
)
|
|
except Exception:
|
|
# Игнорируем ошибки парсинга связей из отдельных файлов, продолжаем обработку
|
|
pass
|
|
|
|
return relationships
|
|
|
|
def build_knowledge_base(self) -> str:
|
|
"""Строит полную базу знаний."""
|
|
print("🚀 Построение полной базы знаний...")
|
|
print("📊 Режим максимального контекста - без сокращений\n")
|
|
|
|
# Извлекаем данные
|
|
print("1️⃣ Извлечение описания домена...")
|
|
domain = self.extract_domain_description()
|
|
|
|
print("2️⃣ Извлечение терминов и определений...")
|
|
terms = self.extract_terms_from_docs()
|
|
|
|
print("3️⃣ Извлечение процессов и алгоритмов...")
|
|
processes = self.extract_processes()
|
|
|
|
print("4️⃣ Извлечение правил и ограничений...")
|
|
rules = self.extract_rules_and_constraints()
|
|
|
|
print("7️⃣ Извлечение сценариев использования...")
|
|
scenarios = self.extract_usage_scenarios()
|
|
|
|
print("9️⃣ Извлечение связей и зависимостей...")
|
|
relationships = self.extract_relationships()
|
|
|
|
# Формируем MD документ
|
|
md_content = []
|
|
md_content.append("# База знаний: BearingsInfo (Расширенная версия)")
|
|
md_content.append(f"\n**Дата создания:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
md_content.append("\nПолная, структурированная и машиночитаемая база знаний.")
|
|
md_content.append("Режим максимального контекста - извлечение 100% информации без сокращений.\n")
|
|
|
|
# Содержание
|
|
md_content.append("# 📑 Содержание\n")
|
|
md_content.append("1. [Общее описание домена](#1-общее-описание-домена)")
|
|
md_content.append("2. [Термины и глоссарий](#2-термины-и-глоссарий)")
|
|
md_content.append("3. [Процессы и алгоритмы](#3-процессы-и-алгоритмы)")
|
|
md_content.append("4. [Правила и ограничения](#4-правила-и-ограничения)")
|
|
md_content.append("5. [Структуры данных и форматы](#5-структуры-данных-и-форматы)")
|
|
md_content.append("6. [Роли и ответственности](#6-роли-и-ответственности)")
|
|
md_content.append("7. [Инструкции и сценарии использования](#7-инструкции-и-сценарии-использования)")
|
|
md_content.append("8. [Ошибки, исключения, крайние случаи](#8-ошибки-исключения-крайние-случаи)")
|
|
md_content.append("9. [Связи и зависимости между сущностями](#9-связи-и-зависимости-между-сущностями)")
|
|
md_content.append("10. [Источники и трассировка](#10-источники-и-трассировка)\n")
|
|
|
|
# Раздел 1: Общее описание домена
|
|
md_content.append("---\n")
|
|
md_content.append("## 1. Общее описание домена\n")
|
|
md_content.append(domain)
|
|
md_content.append("\n")
|
|
|
|
# Раздел 2: Термины и глоссарий
|
|
md_content.append("---\n")
|
|
md_content.append("## 2. Термины и глоссарий\n")
|
|
md_content.append("Все термины и определения, извлеченные из документации репозитория.\n")
|
|
md_content.append("| Термин | Определение | Источник |")
|
|
md_content.append("|--------|-------------|----------|")
|
|
|
|
for term, definitions in sorted(list(terms.items())[:200]): # Первые 200 терминов
|
|
if definitions:
|
|
first_def = definitions[0]
|
|
md_content.append(f"| {term} | {first_def['definition'][:100]} | {first_def['source']} |")
|
|
|
|
md_content.append(f"\n**Всего извлечено терминов:** {len(terms)}\n")
|
|
|
|
# Раздел 3: Процессы и алгоритмы
|
|
md_content.append("---\n")
|
|
md_content.append("## 3. Процессы и алгоритмы\n")
|
|
md_content.append("Описание процессов, алгоритмов и последовательностей действий.\n")
|
|
|
|
if processes:
|
|
for proc in processes[:50]: # Первые 50 процессов
|
|
md_content.append(f"### {proc['title']}\n")
|
|
md_content.append(f"{proc['description']}\n")
|
|
md_content.append(f"_Источник: {proc['source']}_\n")
|
|
else:
|
|
md_content.append("Процессы не обнаружены автоматически. ")
|
|
md_content.append("Требуется ручной анализ документации для извлечения процессов.\n")
|
|
|
|
# Раздел 4: Правила и ограничения
|
|
md_content.append("---\n")
|
|
md_content.append("## 4. Правила и ограничения\n")
|
|
md_content.append("Правила, стандарты и ограничения из ГОСТ, ISO и технической документации.\n")
|
|
|
|
if rules:
|
|
for rule in rules[:30]: # Первые 30 правил
|
|
md_content.append(f"### {rule['type']}\n")
|
|
md_content.append(f"**Ссылки на стандарты:** {', '.join(rule['references'][:10])}\n")
|
|
if rule["rules"]:
|
|
md_content.append("\n**Правила:**\n")
|
|
for r in rule["rules"][:5]:
|
|
md_content.append(f"- {r}\n")
|
|
md_content.append(f"\n_Источник: {rule['source']}_\n")
|
|
else:
|
|
md_content.append("Правила извлекаются из папок с ГОСТ и ISO стандартами.\n")
|
|
|
|
# Раздел 5: Структуры данных
|
|
md_content.append("---\n")
|
|
md_content.append("## 5. Структуры данных и форматы\n")
|
|
md_content.append("См. существующий KNOWLEDGE_BASE.md раздел 5 для полного списка структур.\n")
|
|
md_content.append("Этот раздел содержит информацию о Python классах, функциях, JSON структурах.\n")
|
|
|
|
# Раздел 6: Роли и ответственности
|
|
md_content.append("---\n")
|
|
md_content.append("## 6. Роли и ответственности\n")
|
|
md_content.append("Роли участников проекта и их зоны ответственности.\n\n")
|
|
md_content.append("| Роль | Ответственность | Источник |")
|
|
md_content.append("|------|-----------------|----------|")
|
|
md_content.append("| Контрибьютор | Добавление и улучшение контента | CONTRIBUTING.md |")
|
|
md_content.append("| Мейнтейнер | Управление репозиторием | CODEOWNERS |")
|
|
md_content.append("| Пользователь | Использование базы знаний | README.md |")
|
|
md_content.append("\n")
|
|
|
|
# Раздел 7: Инструкции и сценарии
|
|
md_content.append("---\n")
|
|
md_content.append("## 7. Инструкции и сценарии использования\n")
|
|
md_content.append("Типовые сценарии работы с подшипниками и данными.\n")
|
|
|
|
if scenarios:
|
|
for scenario in scenarios[:30]:
|
|
md_content.append(f"### {scenario['title']}\n")
|
|
md_content.append(f"{scenario['description']}\n")
|
|
md_content.append(f"_Источник: {scenario['source']}_\n")
|
|
else:
|
|
md_content.append("Сценарии использования находятся в папке Практические_руководства.\n")
|
|
|
|
# Раздел 8: Ошибки и исключения
|
|
md_content.append("---\n")
|
|
md_content.append("## 8. Ошибки, исключения, крайние случаи\n")
|
|
md_content.append("Известные ошибки и обработка исключительных ситуаций.\n\n")
|
|
md_content.append("Информация извлекается из:\n")
|
|
md_content.append("- Документации по диагностике (папка `06_failures_diagnostics`)\n")
|
|
md_content.append("- Кода обработки ошибок в API и скриптах\n")
|
|
md_content.append("- Тестов (папка `tests`)\n\n")
|
|
|
|
# Раздел 9: Связи и зависимости
|
|
md_content.append("---\n")
|
|
md_content.append("## 9. Связи и зависимости между сущностями\n")
|
|
md_content.append("Взаимосвязи между стандартами, типами подшипников, производителями.\n\n")
|
|
|
|
if relationships:
|
|
md_content.append("| Тип связи | От | К | Источник |")
|
|
md_content.append("|-----------|----|----|----------|")
|
|
for rel in relationships[:50]:
|
|
md_content.append(f"| {rel['type']} | {rel['from'][:30]} | {rel['to'][:30]} | {rel['source']} |")
|
|
md_content.append(f"\n**Всего связей:** {len(relationships)}\n")
|
|
|
|
# Раздел 10: Источники
|
|
md_content.append("---\n")
|
|
md_content.append("## 10. Источники и трассировка\n")
|
|
md_content.append("Полная трассировка информации к исходным файлам.\n\n")
|
|
md_content.append("Все факты, термины и правила в этой базе знаний имеют привязку к файлам-источникам.\n")
|
|
md_content.append("Формат ссылки: `_(Источник: путь/к/файлу)_`\n\n")
|
|
md_content.append("**Основные источники:**\n")
|
|
md_content.append("- `README.md` - Основная документация\n")
|
|
md_content.append("- `02_Термины_и_основы/` - Терминология и теория\n")
|
|
md_content.append("- `03_ГОСТ_подшипники_и_нормативка/` - Российские стандарты\n")
|
|
md_content.append("- `04_ISO_и_международные_обозначения/` - Международные стандарты\n")
|
|
md_content.append("- `Практические_руководства/` - Практические инструкции\n")
|
|
md_content.append("- `Подшипники/` - Детальная информация по типам\n\n")
|
|
|
|
md_content.append("---\n")
|
|
md_content.append(f"\n*Автоматически сгенерировано: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n")
|
|
md_content.append("*Построитель: Enhanced Knowledge Base Builder v2.0*\n")
|
|
|
|
return "\n".join(md_content)
|
|
|
|
|
|
def main():
|
|
"""Главная функция."""
|
|
builder = EnhancedKnowledgeBaseBuilder()
|
|
|
|
output_file = "KNOWLEDGE_BASE_ENHANCED.md"
|
|
|
|
print("📝 Построение расширенной базы знаний...")
|
|
print(f"📁 Репозиторий: {builder.repo_path}")
|
|
print(f"📄 Выходной файл: {output_file}\n")
|
|
|
|
# Строим базу знаний
|
|
kb_content = builder.build_knowledge_base()
|
|
|
|
# Сохраняем
|
|
output_path = Path(output_file)
|
|
output_path.write_text(kb_content, encoding="utf-8")
|
|
|
|
print(f"\n✅ База знаний успешно создана: {output_file}")
|
|
print(f"📊 Размер: {len(kb_content):,} байт")
|
|
print(f"📝 Строк: {kb_content.count(chr(10)):,}")
|
|
print("\n🎯 Все 10 обязательных разделов включены")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|