feat: папка dictionaries/prompts — словари промтов для каждой ИИ-кнопки

- prompts/suggest_object_params.json: жёсткие правила подбора характеристик —
  выбирать ТОЛЬКО из предоставленных списков (сферы/типы/архитектуры/
  типовые объекты), ничего не выдумывать; назначение строго по форме
  «Объект предназначен для … с целью …»; типовой объект — дословно из 360-р
- prompts/suggest_threats.json, check_security.json, check_company.json,
  declension.json — промты для остальных ИИ-кнопок
- verify.py: _load_prompt() + подключение промтов в suggest_object_params_ai,
  suggest_threats_ai, check_security_ai; ИИ получает полные списки
  (spheres/object_types/architectures) и выбирает из них
- ui.py: окно рекомендаций ИИ — галочки у каждого поля, применяются
  только отмеченные (ИИ может ошибаться в архитектуре — оператор решает)
This commit is contained in:
2026-08-04 23:32:58 +04:00
parent acb7aeaa64
commit e4e7bb444a
7 changed files with 149 additions and 57 deletions
+31 -16
View File
@@ -1671,6 +1671,10 @@ class DokoGenApp:
'sphere': isys.sphere or '',
'object_type': isys.object_type or '',
}
# Полные списки допустимых значений — ИИ выбирает ТОЛЬКО из них
spheres = list(self.is_sphere_combo['values']) if hasattr(self, 'is_sphere_combo') else []
object_types = list(self.is_object_type_combo['values']) if hasattr(self, 'is_object_type_combo') else []
architectures = list(self.is_architecture_combo['values']) if hasattr(self, 'is_architecture_combo') else []
self.log(f"🤖 Запрос к ИИ: подбор характеристик для «{isys.name}»")
self._verify_log("Подбор характеристик через ИИ…")
@@ -1679,7 +1683,8 @@ class DokoGenApp:
from .verify import suggest_object_params_ai
res, err = suggest_object_params_ai(
data, settings['ai_api_key'], settings.get('ai_model'),
settings.get('ai_base_url'), typical_objects=typical_list)
settings.get('ai_base_url'), typical_objects=typical_list,
spheres=spheres, object_types=object_types, architectures=architectures)
self.root.after(0, lambda: self._suggest_object_params_ai_done(res, err, isys.name))
except Exception as e:
self.root.after(0, lambda: self._suggest_object_params_ai_done(None, str(e), isys.name))
@@ -1697,28 +1702,35 @@ class DokoGenApp:
dlg = tk.Toplevel(self.root)
dlg.title("🤖 Рекомендации ИИ по характеристикам объекта")
dlg.geometry("860x560")
dlg.geometry("880x620")
dlg.transient(self.root)
frm = ttk.Frame(dlg, padding=8)
frm.pack(fill=tk.BOTH, expand=True)
ttk.Label(frm, text=f"Объект: {obj_name} — рекомендации ИИ (подтвердите или скорректируйте)",
font=('Arial', 10, 'bold')).pack(anchor=tk.W)
ttk.Label(frm, text=f"Объект: {obj_name} — рекомендации ИИ. Отметьте галочками, "
f"какие поля применить (ИИ может ошибаться — проверяйте).",
font=('Arial', 10, 'bold'), wraplength=840, justify=tk.LEFT).pack(anchor=tk.W)
rows = [
('назначение', 'Назначение объекта'),
('назначение', 'Назначение объекта (форма: «Объект предназначен для … с целью …»)'),
('сфера', 'Сфера деятельности'),
('тип', 'Тип объекта'),
('архитектура', 'Архитектура объекта'),
('типовой_объект', 'Типовой отраслевой объект КИИ'),
]
entries = {}
checks = {}
for key, label in rows:
ttk.Label(frm, text=label + ":").pack(anchor=tk.W, pady=(6, 0))
e = tk.Text(frm, height=2 if key == 'типовой_объект' else 1, wrap=tk.WORD)
row = ttk.Frame(frm)
row.pack(fill=tk.X, pady=(6, 0))
var = tk.BooleanVar(value=True)
cb = ttk.Checkbutton(row, text=label, variable=var)
cb.pack(anchor=tk.W)
e = tk.Text(frm, height=2 if key in ('типовой_объект', 'назначение') else 1, wrap=tk.WORD)
e.pack(fill=tk.X)
e.insert('1.0', res.get(key, '') or '')
entries[key] = e
checks[key] = var
ttk.Label(frm, text="Обоснование ИИ:").pack(anchor=tk.W, pady=(6, 0))
just = tk.Text(frm, height=2, wrap=tk.WORD)
@@ -1727,20 +1739,23 @@ class DokoGenApp:
btn_row = ttk.Frame(frm)
btn_row.pack(fill=tk.X, pady=(8, 0))
ttk.Button(btn_row, text="✔️ Применить",
command=lambda: self._apply_ai_params(entries, dlg)).pack(side=tk.LEFT, padx=2)
ttk.Button(btn_row, text="✔️ Применить отмеченное",
command=lambda: self._apply_ai_params(entries, dlg, checks)).pack(side=tk.LEFT, padx=2)
ttk.Button(btn_row, text="Отмена", command=dlg.destroy).pack(side=tk.LEFT, padx=2)
def _apply_ai_params(self, entries, dlg):
"""Применить рекомендации ИИ к полям объекта."""
def _apply_ai_params(self, entries, dlg, checks=None):
"""Применить рекомендации ИИ к полям объекта (только отмеченные галочками)."""
def _get(e):
return e.get('1.0', 'end-1c').strip()
purpose = _get(entries['назначение'])
sphere = _get(entries['сфера'])
otype = _get(entries['тип'])
arch = _get(entries['архитектура'])
typical = _get(entries['типовой_объект'])
def _wanted(key):
return checks is None or checks.get(key, tk.BooleanVar(value=True)).get()
purpose = _get(entries['назначение']) if _wanted('назначение') else ''
sphere = _get(entries['сфера']) if _wanted('сфера') else ''
otype = _get(entries['тип']) if _wanted('тип') else ''
arch = _get(entries['архитектура']) if _wanted('архитектура') else ''
typical = _get(entries['типовой_объект']) if _wanted('типовой_объект') else ''
if purpose and hasattr(self, 'is_purpose_entry'):
self.is_purpose_entry.delete(0, tk.END)