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:
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"system": "Ты — юрист по защите персональных данных и критической информационной инфраструктуры (187-ФЗ). Проверь реквизиты организации.",
|
||||||
|
"rules": [
|
||||||
|
"Не выдумывай реквизиты — исправляй/дополняй только если уверен.",
|
||||||
|
"В «полях» для каждого поля укажи статус: ok (заполнено корректно), пусто (не заполнено), ошибка (заполнено с ошибкой)."
|
||||||
|
],
|
||||||
|
"response_format": "Верни ТОЛЬКО JSON: {\"оценка\": \"ok|warning|error\", \"замечания\": [\"...\"], \"предложения\": {\"full_name\": \"...\", \"short_name\": \"...\", \"address\": \"...\", \"inn\": \"...\", \"kpp\": \"...\", \"ogrn\": \"...\", \"ogrn_date\": \"...\", \"chief_position\": \"...\", \"chief_fio\": \"...\"}, \"поля\": {\"full_name\": {\"статус\": \"ok|пусто|ошибка\", \"комментарий\": \"...\"}, ...}}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"system": "Ты — эксперт по безопасности критической информационной инфраструктуры (187-ФЗ, приказ ФСТЭК России № 239 и № 236). Проверь заполненные сведения об объекте КИИ и дай рекомендации.",
|
||||||
|
"response_format": "Верни ТОЛЬКО JSON: {\"оценка\": \"ok|warning|error\", \"замечания\": [\"...\"], \"предложения\": {\"attacker_category\": \"...\", \"threats\": \"...\", \"incidents\": \"...\", \"criteria_values\": \"...\", \"criteria_justification\": \"...\", \"org_measures\": \"...\", \"tech_measures\": \"...\"}}. В «предложениях» укажи, что добавить/исправить по каждому разделу, если нужно, иначе пустые строки."
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"system": "Ты — лингвист, специалист по склонению русских наименований организаций (187-ФЗ). Просклоняй название организации по падежам.",
|
||||||
|
"rules": [
|
||||||
|
"Склоняй только само название (включая организационно-правовую форму, если она склоняется по правилам русского языка).",
|
||||||
|
"Сохраняй кавычки, регистр и пунктуацию оригинала.",
|
||||||
|
"Не выдумывай падежи — используй стандартную парадигму: именительный, родительный, дательный, винительный, творительный, предложный."
|
||||||
|
],
|
||||||
|
"response_format": "Верни ТОЛЬКО JSON: {\"nominative\": \"...\", \"genitive\": \"...\", \"dative\": \"...\", \"accusative\": \"...\", \"instrumental\": \"...\", \"prepositional\": \"...\"}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"system": "Ты — эксперт ФСТЭК по категорированию объектов критической информационной инфраструктуры (187-ФЗ, ПП РФ № 127, Распоряжение ПРФ № 360-р, приказ ФСТЭК № 236). Твоя задача — по описанию объекта КИИ ПОДОБРАТЬ его характеристики ТОЛЬКО из предоставленных списков, ничего не выдумывая.",
|
||||||
|
"rules": [
|
||||||
|
"Выбирай значения ТОЛЬКО из предоставленных списков. Если подходящего значения в списке нет — верни пустую строку, не придумывай своё.",
|
||||||
|
"Поле «типовой_объект»: выбери полную строку ТОЛЬКО из предоставленного перечня типовых отраслевых объектов (Распоряжение ПРФ № 360-р), наиболее подходящую. Не перефразируй, не сокращай — копируй строку дословно. Если ничего не подходит — пустая строка.",
|
||||||
|
"Поле «сфера»: выбери ТОЛЬКО одну из предоставленных сфер. Не придумывай свои.",
|
||||||
|
"Поле «тип»: выбери ТОЛЬКО один из предоставленных типов объектов.",
|
||||||
|
"Поле «архитектура»: выбери ТОЛЬКО одну из предоставленных архитектур.",
|
||||||
|
"Поле «назначение»: заполни строго по форме: «Объект предназначен для <что делает> с целью <зачем>.». Не отклоняйся от этой формы.",
|
||||||
|
"Поле «обоснование»: 1-2 предложения, почему выбраны такие характеристики."
|
||||||
|
],
|
||||||
|
"response_format": "Верни ТОЛЬКО JSON без пояснений: {\"назначение\": \"...\", \"сфера\": \"...\", \"тип\": \"...\", \"архитектура\": \"...\", \"типовой_объект\": \"...\", \"обоснование\": \"...\"}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"system": "Ты — эксперт ФСТЭК по безопасности критической информационной инфраструктуры (187-ФЗ, приказ ФСТЭК № 236). На основе характеристик объекта КИИ выбери из предоставленного перечня АКТУАЛЬНЫЕ угрозы безопасности информации.",
|
||||||
|
"rules": [
|
||||||
|
"Выбирай угрозы ТОЛЬКО из предоставленного перечня — не выдумывай и не перефразируй, используй полные строки (код + название) как они есть.",
|
||||||
|
"Верни от 10 до 40 угроз.",
|
||||||
|
"Учитывай характеристики объекта: тип (ИС/АСУ/ИТКС), наличие интернета, сферу, категорию нарушителя."
|
||||||
|
],
|
||||||
|
"response_format": "Верни ТОЛЬКО JSON: {\"threats\": [\"УБИ.xxx Название угрозы\", ...]} — без пояснений и комментариев."
|
||||||
|
}
|
||||||
+31
-16
@@ -1671,6 +1671,10 @@ class DokoGenApp:
|
|||||||
'sphere': isys.sphere or '',
|
'sphere': isys.sphere or '',
|
||||||
'object_type': isys.object_type 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.log(f"🤖 Запрос к ИИ: подбор характеристик для «{isys.name}»")
|
||||||
self._verify_log("Подбор характеристик через ИИ…")
|
self._verify_log("Подбор характеристик через ИИ…")
|
||||||
|
|
||||||
@@ -1679,7 +1683,8 @@ class DokoGenApp:
|
|||||||
from .verify import suggest_object_params_ai
|
from .verify import suggest_object_params_ai
|
||||||
res, err = suggest_object_params_ai(
|
res, err = suggest_object_params_ai(
|
||||||
data, settings['ai_api_key'], settings.get('ai_model'),
|
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))
|
self.root.after(0, lambda: self._suggest_object_params_ai_done(res, err, isys.name))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.root.after(0, lambda: self._suggest_object_params_ai_done(None, str(e), isys.name))
|
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 = tk.Toplevel(self.root)
|
||||||
dlg.title("🤖 Рекомендации ИИ по характеристикам объекта")
|
dlg.title("🤖 Рекомендации ИИ по характеристикам объекта")
|
||||||
dlg.geometry("860x560")
|
dlg.geometry("880x620")
|
||||||
dlg.transient(self.root)
|
dlg.transient(self.root)
|
||||||
frm = ttk.Frame(dlg, padding=8)
|
frm = ttk.Frame(dlg, padding=8)
|
||||||
frm.pack(fill=tk.BOTH, expand=True)
|
frm.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
ttk.Label(frm, text=f"Объект: {obj_name} — рекомендации ИИ (подтвердите или скорректируйте)",
|
ttk.Label(frm, text=f"Объект: {obj_name} — рекомендации ИИ. Отметьте галочками, "
|
||||||
font=('Arial', 10, 'bold')).pack(anchor=tk.W)
|
f"какие поля применить (ИИ может ошибаться — проверяйте).",
|
||||||
|
font=('Arial', 10, 'bold'), wraplength=840, justify=tk.LEFT).pack(anchor=tk.W)
|
||||||
|
|
||||||
rows = [
|
rows = [
|
||||||
('назначение', 'Назначение объекта'),
|
('назначение', 'Назначение объекта (форма: «Объект предназначен для … с целью …»)'),
|
||||||
('сфера', 'Сфера деятельности'),
|
('сфера', 'Сфера деятельности'),
|
||||||
('тип', 'Тип объекта'),
|
('тип', 'Тип объекта'),
|
||||||
('архитектура', 'Архитектура объекта'),
|
('архитектура', 'Архитектура объекта'),
|
||||||
('типовой_объект', 'Типовой отраслевой объект КИИ'),
|
('типовой_объект', 'Типовой отраслевой объект КИИ'),
|
||||||
]
|
]
|
||||||
entries = {}
|
entries = {}
|
||||||
|
checks = {}
|
||||||
for key, label in rows:
|
for key, label in rows:
|
||||||
ttk.Label(frm, text=label + ":").pack(anchor=tk.W, pady=(6, 0))
|
row = ttk.Frame(frm)
|
||||||
e = tk.Text(frm, height=2 if key == 'типовой_объект' else 1, wrap=tk.WORD)
|
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.pack(fill=tk.X)
|
||||||
e.insert('1.0', res.get(key, '') or '')
|
e.insert('1.0', res.get(key, '') or '')
|
||||||
entries[key] = e
|
entries[key] = e
|
||||||
|
checks[key] = var
|
||||||
|
|
||||||
ttk.Label(frm, text="Обоснование ИИ:").pack(anchor=tk.W, pady=(6, 0))
|
ttk.Label(frm, text="Обоснование ИИ:").pack(anchor=tk.W, pady=(6, 0))
|
||||||
just = tk.Text(frm, height=2, wrap=tk.WORD)
|
just = tk.Text(frm, height=2, wrap=tk.WORD)
|
||||||
@@ -1727,20 +1739,23 @@ class DokoGenApp:
|
|||||||
|
|
||||||
btn_row = ttk.Frame(frm)
|
btn_row = ttk.Frame(frm)
|
||||||
btn_row.pack(fill=tk.X, pady=(8, 0))
|
btn_row.pack(fill=tk.X, pady=(8, 0))
|
||||||
ttk.Button(btn_row, text="✔️ Применить",
|
ttk.Button(btn_row, text="✔️ Применить отмеченное",
|
||||||
command=lambda: self._apply_ai_params(entries, dlg)).pack(side=tk.LEFT, padx=2)
|
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)
|
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):
|
def _get(e):
|
||||||
return e.get('1.0', 'end-1c').strip()
|
return e.get('1.0', 'end-1c').strip()
|
||||||
|
|
||||||
purpose = _get(entries['назначение'])
|
def _wanted(key):
|
||||||
sphere = _get(entries['сфера'])
|
return checks is None or checks.get(key, tk.BooleanVar(value=True)).get()
|
||||||
otype = _get(entries['тип'])
|
|
||||||
arch = _get(entries['архитектура'])
|
purpose = _get(entries['назначение']) if _wanted('назначение') else ''
|
||||||
typical = _get(entries['типовой_объект'])
|
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'):
|
if purpose and hasattr(self, 'is_purpose_entry'):
|
||||||
self.is_purpose_entry.delete(0, tk.END)
|
self.is_purpose_entry.delete(0, tk.END)
|
||||||
|
|||||||
+75
-41
@@ -14,6 +14,18 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
def _load_prompt(name):
|
||||||
|
"""Загружает промт из dictionaries/prompts/<name>.json (system/rules/response_format)."""
|
||||||
|
import os as _os
|
||||||
|
p = _os.path.join(_os.path.dirname(_os.path.abspath(__file__)),
|
||||||
|
'dictionaries', 'prompts', name + '.json')
|
||||||
|
try:
|
||||||
|
with open(p, encoding='utf-8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
except Exception:
|
||||||
|
return {}
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
@@ -526,20 +538,24 @@ def suggest_threats_ai(security_data, api_key, model='deepseek-chat', base_url=N
|
|||||||
else:
|
else:
|
||||||
threat_list_text = "(перечень не предоставлен — используй знания об актуальном перечне БДУ ФСТЭК)"
|
threat_list_text = "(перечень не предоставлен — используй знания об актуальном перечне БДУ ФСТЭК)"
|
||||||
|
|
||||||
system = (
|
pr = _load_prompt('suggest_threats')
|
||||||
|
system = pr.get('system', (
|
||||||
"Ты — эксперт ФСТЭК по безопасности критической информационной инфраструктуры "
|
"Ты — эксперт ФСТЭК по безопасности критической информационной инфраструктуры "
|
||||||
"(187-ФЗ, приказ ФСТЭК № 236). На основе характеристик объекта КИИ выбери из "
|
"(187-ФЗ, приказ ФСТЭК № 236). На основе характеристик объекта КИИ выбери из "
|
||||||
"предоставленного перечня АКТУАЛЬНЫЕ угрозы безопасности информации и верни "
|
"предоставленного перечня АКТУАЛЬНЫЕ угрозы безопасности информации."
|
||||||
"ТОЛЬКО JSON: "
|
))
|
||||||
'{"threats": ["УБИ.xxx Название угрозы", ...]} — от 10 до 40 угроз, '
|
rules = pr.get('rules', [])
|
||||||
"без пояснений и комментариев. Не выдумывай угрозы, которых нет в перечне; "
|
resp = pr.get('response_format',
|
||||||
"используй полные строки из перечня (код + название) как они есть."
|
'Верни ТОЛЬКО JSON: {"threats": ["УБИ.xxx Название угрозы", ...]} '
|
||||||
)
|
'— от 10 до 40 угроз, без пояснений.')
|
||||||
user = (
|
user = (
|
||||||
"Характеристики объекта КИИ:\n"
|
"Характеристики объекта КИИ:\n"
|
||||||
f"{json.dumps(security_data, ensure_ascii=False)}\n\n"
|
f"{json.dumps(security_data, ensure_ascii=False)}\n\n"
|
||||||
"Актуальный перечень угроз БДУ ФСТЭК:\n"
|
"Актуальный перечень угроз БДУ ФСТЭК (выбирай ТОЛЬКО из него, "
|
||||||
f"{threat_list_text}"
|
"используй полные строки как они есть):\n"
|
||||||
|
f"{threat_list_text}\n\n"
|
||||||
|
+ ("Правила:\n" + "\n".join(f"{i+1}. {r}" for i, r in enumerate(rules)) + "\n\n" if rules else "")
|
||||||
|
+ resp
|
||||||
)
|
)
|
||||||
js, err = _ai_json(api_key, model, base_url, system, user)
|
js, err = _ai_json(api_key, model, base_url, system, user)
|
||||||
if err:
|
if err:
|
||||||
@@ -552,48 +568,66 @@ def suggest_threats_ai(security_data, api_key, model='deepseek-chat', base_url=N
|
|||||||
|
|
||||||
|
|
||||||
def suggest_object_params_ai(object_data, api_key, model='deepseek-chat', base_url=None,
|
def suggest_object_params_ai(object_data, api_key, model='deepseek-chat', base_url=None,
|
||||||
typical_objects=None):
|
typical_objects=None, spheres=None, object_types=None,
|
||||||
|
architectures=None):
|
||||||
"""ИИ предлагает характеристики объекта КИИ: назначение, сферу, тип, архитектуру,
|
"""ИИ предлагает характеристики объекта КИИ: назначение, сферу, тип, архитектуру,
|
||||||
типовой отраслевой объект — как рекомендацию оператору.
|
типовой отраслевой объект — как рекомендацию оператору.
|
||||||
|
|
||||||
object_data — dict: name, description, purpose (что известно об объекте).
|
object_data — dict: name, description, purpose (что известно об объекте).
|
||||||
typical_objects — перечень типовых отраслевых объектов (из 360-р) для выбора.
|
typical_objects — перечень типовых отраслевых объектов (из 360-р) для выбора;
|
||||||
|
spheres / object_types / architectures — полные списки допустимых значений.
|
||||||
|
Промт берётся из dictionaries/prompts/suggest_object_params.json.
|
||||||
|
|
||||||
Возвращает (dict, ошибка): dict с полями
|
Возвращает (dict, ошибка): dict с полями
|
||||||
purpose / sphere / object_type / architecture / typical_object / обоснование.
|
назначение / сфера / тип / архитектура / типовой_объект / обоснование.
|
||||||
"""
|
"""
|
||||||
if not api_key:
|
if not api_key:
|
||||||
return None, "Не задан API-ключ ИИ (Файл → Настройки → API)"
|
return None, "Не задан API-ключ ИИ (Файл → Настройки → API)"
|
||||||
|
|
||||||
|
# Загрузка промта из папки dictionaries/prompts
|
||||||
|
import os as _os
|
||||||
|
prompt_path = _os.path.join(_os.path.dirname(_os.path.abspath(__file__)),
|
||||||
|
'dictionaries', 'prompts', 'suggest_object_params.json')
|
||||||
|
try:
|
||||||
|
with open(prompt_path, encoding='utf-8') as _f:
|
||||||
|
prompt = json.load(_f)
|
||||||
|
except Exception:
|
||||||
|
prompt = {}
|
||||||
|
system = prompt.get('system', 'Ты — эксперт ФСТЭК по категорированию объектов КИИ.')
|
||||||
|
rules = prompt.get('rules', [])
|
||||||
|
response_format = prompt.get('response_format',
|
||||||
|
'Верни ТОЛЬКО JSON: {"назначение": "...", "сфера": "...", '
|
||||||
|
'"тип": "...", "архитектура": "...", "типовой_объект": "...", '
|
||||||
|
'"обоснование": "..."}')
|
||||||
|
|
||||||
|
# Полные списки допустимых значений
|
||||||
|
def _fmt_list(name, items):
|
||||||
|
if not items:
|
||||||
|
return f"{name}: (список не предоставлен)"
|
||||||
|
return f"{name}:\n" + "\n".join(f"- {i}" for i in items)
|
||||||
|
|
||||||
|
lists_text = "\n\n".join([
|
||||||
|
_fmt_list("Сферы деятельности (выбирай ТОЛЬКО из них)", spheres),
|
||||||
|
_fmt_list("Типы объектов (выбирай ТОЛЬКО из них)", object_types),
|
||||||
|
_fmt_list("Архитектуры (выбирай ТОЛЬКО из них)", architectures),
|
||||||
|
])
|
||||||
if typical_objects:
|
if typical_objects:
|
||||||
to_text = "\n".join(f"{i+1}. {t}" for i, t in enumerate(typical_objects[:400]))
|
to_text = "\n".join(f"{i+1}. {t}" for i, t in enumerate(typical_objects[:400]))
|
||||||
else:
|
else:
|
||||||
to_text = "(перечень не предоставлен)"
|
to_text = "(перечень не предоставлен)"
|
||||||
|
|
||||||
system = (
|
rules_text = "\n".join(f"{i+1}. {r}" for i, r in enumerate(rules))
|
||||||
"Ты — эксперт ФСТЭК по категорированию объектов критической информационной инфраструктуры "
|
|
||||||
"(187-ФЗ, ПП РФ № 127, Распоряжение ПРФ № 360-р, приказ ФСТЭК № 236). "
|
|
||||||
"По описанию объекта КИИ предложи его характеристики. Верни ТОЛЬКО JSON: "
|
|
||||||
'{"назначение": "короткое назначение объекта", '
|
|
||||||
'"сфера": "одна из сфер: Здравоохранение, Наука, Транспорт, Связь, Энергетика, '
|
|
||||||
'Государственная регистрация прав, Банковская сфера и финансовый рынок, '
|
|
||||||
'Топливно-энергетический комплекс, Атомная энергетика, Оборонная промышленность, '
|
|
||||||
'Ракетно-космическая промышленность, Горнодобывающая промышленность, '
|
|
||||||
'Металлургическая промышленность, Химическая промышленность, Иная сфера деятельности", '
|
|
||||||
'"тип": "Информационная система | Автоматизированные системы управления | '
|
|
||||||
'Информационно-телекоммуникационная сеть", '
|
|
||||||
'"архитектура": "одно из: клиент-серверная система, автономная (standalone), '
|
|
||||||
'распределенная система, иное", '
|
|
||||||
'"типовой_объект": "полная строка из предоставленного перечня, наиболее подходящая, '
|
|
||||||
'или пустая строка", '
|
|
||||||
'"обоснование": "почему выбраны такие характеристики (1-2 предложения)"} '
|
|
||||||
"Не выдумывай типовой объект — бери только из перечня."
|
|
||||||
)
|
|
||||||
user = (
|
user = (
|
||||||
"Информация об объекте КИИ:\n"
|
"Информация об объекте КИИ:\n"
|
||||||
f"{json.dumps(object_data, ensure_ascii=False)}\n\n"
|
f"{json.dumps(object_data, ensure_ascii=False)}\n\n"
|
||||||
"Перечень типовых отраслевых объектов КИИ (Распоряжение ПРФ № 360-р):\n"
|
f"{lists_text}\n\n"
|
||||||
f"{to_text}"
|
"Перечень типовых отраслевых объектов КИИ (Распоряжение ПРФ № 360-р, "
|
||||||
|
"выбирай ТОЛЬКО из него, копируй строку дословно):\n"
|
||||||
|
f"{to_text}\n\n"
|
||||||
|
"Правила:\n"
|
||||||
|
f"{rules_text}\n\n"
|
||||||
|
f"{response_format}"
|
||||||
)
|
)
|
||||||
js, err = _ai_json(api_key, model, base_url, system, user)
|
js, err = _ai_json(api_key, model, base_url, system, user)
|
||||||
if err:
|
if err:
|
||||||
@@ -615,18 +649,18 @@ def check_security_ai(security_data, api_key, model='deepseek-chat', base_url=No
|
|||||||
"""
|
"""
|
||||||
if not api_key:
|
if not api_key:
|
||||||
return None, "Не задан API-ключ ИИ (Файл → Настройки → API)"
|
return None, "Не задан API-ключ ИИ (Файл → Настройки → API)"
|
||||||
system = (
|
pr = _load_prompt('check_security')
|
||||||
|
system = pr.get('system', (
|
||||||
"Ты — эксперт по безопасности критической информационной инфраструктуры (187-ФЗ, "
|
"Ты — эксперт по безопасности критической информационной инфраструктуры (187-ФЗ, "
|
||||||
"приказ ФСТЭК России от 25.12.2017 № 239 «Об утверждении Требований по обеспечению "
|
"приказ ФСТЭК России от 25.12.2017 № 239 и приказ № 236). Проверь заполненные "
|
||||||
"безопасности значимых объектов КИИ» и приказ № 236). Проверь заполненные сведения "
|
"сведения об объекте КИИ и дай рекомендации."
|
||||||
"об объекте КИИ и дай рекомендации. Верни ТОЛЬКО JSON: "
|
))
|
||||||
'{"оценка": "ok|warning|error", '
|
system = system + " " + pr.get('response_format',
|
||||||
'"замечания": ["..."], '
|
'Верни ТОЛЬКО JSON: {"оценка": "ok|warning|error", "замечания": ["..."], '
|
||||||
'"предложения": {"attacker_category": "...", "threats": "...", "incidents": "...", '
|
'"предложения": {"attacker_category": "...", "threats": "...", "incidents": "...", '
|
||||||
'"criteria_values": "...", "criteria_justification": "...", '
|
'"criteria_values": "...", "criteria_justification": "...", '
|
||||||
'"org_measures": "...", "tech_measures": "..."}} '
|
'"org_measures": "...", "tech_measures": "..."}} '
|
||||||
"В «предложениях» укажи, что добавить/исправить по каждому разделу, если нужно, иначе пустые строки."
|
'В «предложениях» укажи, что добавить/исправить по каждому разделу, иначе пустые строки.')
|
||||||
)
|
|
||||||
user = json.dumps(security_data, ensure_ascii=False)
|
user = json.dumps(security_data, ensure_ascii=False)
|
||||||
js, err = _ai_json(api_key, model, base_url, system, user)
|
js, err = _ai_json(api_key, model, base_url, system, user)
|
||||||
if err:
|
if err:
|
||||||
|
|||||||
Reference in New Issue
Block a user