feat: ИИ-проверка объекта по частям (временные файлы вход/выход по блокам)

This commit is contained in:
2026-08-05 01:33:43 +04:00
parent d376a28184
commit b3ae4c22cf
2 changed files with 123 additions and 0 deletions
+79
View File
@@ -1066,6 +1066,8 @@ class DokoGenApp:
command=self._auto_fill_security_click).pack(side=tk.LEFT, padx=2)
ttk.Button(sec_main_btns, text="🤖 Проверить безопасность через ИИ",
command=self._check_security_ai).pack(side=tk.LEFT, padx=2)
ttk.Button(sec_main_btns, text="🧩 Проверить объект по частям (ИИ)",
command=self._check_object_partial_click).pack(side=tk.LEFT, padx=2)
ttk.Label(sec_main_btns,
text="Подбор по данным объекта — как рекомендация, оператор подтверждает.",
foreground='gray').pack(side=tk.LEFT, padx=8)
@@ -3507,6 +3509,83 @@ class DokoGenApp:
self._verify_log("🤖 Проверка категорий ИИ завершена")
self.log("🤖 Проверка категорий ИИ завершена")
def _check_object_partial_click(self):
"""🧩 ИИ-проверка всего объекта по частям: каждый блок — отдельный запрос,
данные и ответы ИИ пишутся во временную папку (dokogen_ai_*)."""
if self._current_is_idx is None:
messagebox.showinfo("Проверка", "Сначала выберите объект КИИ в списке слева")
return
settings = load_api_settings()
if not settings.get('ai_api_key'):
messagebox.showwarning("Настройки", "Не задан API-ключ ИИ.\nМеню «Файл → Настройки»")
return
self._collect_company()
self._collect_is()
c = self.model
isys = self.model.information_systems[self._current_is_idx]
blocks = [
{'name': 'Реквизиты организации', 'prompt': 'check_company',
'data': {'full_name': c.full_name, 'short_name': c.short_name, 'address': c.address,
'inn': c.inn, 'kpp': c.kpp, 'ogrn': c.ogrn, 'ogrn_date': c.ogrn_date,
'chief_position': c.chief_position, 'chief_fio': c.chief_fio}},
{'name': 'Характеристики объекта КИИ', 'prompt': 'suggest_object_params',
'data': {'name': isys.name, 'description': isys.description, 'purpose': isys.purpose,
'sphere': isys.sphere, 'object_type': isys.object_type,
'architecture': isys.architecture, 'typical_object': isys.typical_object,
'net_category': isys.net_category, 'net_purpose': isys.net_purpose}},
{'name': 'Безопасность (нарушитель, угрозы, меры)', 'prompt': 'check_security',
'data': {'name': isys.name, 'description': isys.description, 'category': isys.category,
'sphere': isys.sphere, 'attacker_category': isys.attacker_category,
'attacker_level': isys.attacker_level, 'attacker_types': isys.attacker_types,
'threats': isys.threats, 'incidents': isys.incidents,
'org_measures': isys.org_measures, 'tech_measures': isys.tech_measures}},
{'name': 'Категории значимости (ПП 127)', 'prompt': 'check_criteria',
'data': {'name': isys.name, 'description': isys.description, 'category': isys.category,
'sphere': isys.sphere, 'object_type': isys.object_type,
'criteria_values': isys.criteria_values,
'criteria_justification': isys.criteria_justification}},
{'name': 'Средства защиты (СЗИ)', 'prompt': 'suggest_defense',
'data': {'name': isys.name, 'category': isys.category, 'sphere': isys.sphere,
'threats': isys.threats,
'defense_tools': list(self.defense_tools_listbox.get(0, tk.END)) or []}},
]
self._verify_log(f"🧩 ИИ-проверка объекта «{isys.name}» по частям ({len(blocks)} блоков)…")
self.log(f"🧩 ИИ-проверка объекта «{isys.name}» по частям: {len(blocks)} блоков")
def _run():
try:
from .verify import check_object_partial
res, err = check_object_partial(
blocks, settings['ai_api_key'], settings.get('ai_model'),
settings.get('ai_base_url'))
self.root.after(0, lambda: self._check_object_partial_done(res, err, isys.name))
except Exception as e:
self.root.after(0, lambda: self._check_object_partial_done(None, str(e), isys.name))
threading.Thread(target=_run, daemon=True).start()
def _check_object_partial_done(self, res, err, obj_name):
if err:
self._verify_log(f"{err}")
self.log(f"❌ Проверка объекта по частям: {err}")
return
if not res:
self._verify_log("❌ ИИ не вернул результат")
return
lines = [f"🧩 ИИ-проверка объекта «{obj_name}» по частям", ""]
for r in res:
status = "" if r.get('ok') else ""
lines.append(f"{status} {r['name']}")
if r.get('files', {}).get('out'):
lines.append(f" ответ ИИ: {r['files']['out']}")
lines.append("")
lines.append("Полные ответы ИИ по каждому блоку — во временных файлах выше.")
lines.append("Рекомендации применяются по кнопкам разделов (по галочкам).")
self._show_security_ai_result(lines)
self._verify_log("🧩 Проверка объекта по частям завершена")
self.log("🧩 Проверка объекта по частям завершена")
def _select_from_defense_list(self):
"""Выбор СЗИ из JSON словаря."""
import json