diff --git a/agents/notebook/views.py b/agents/notebook/views.py index 07b085ae71d59fd240339461c1232d5a56b7f936..fce05a45634723cfaa6994cd7eda983a40c460ca 100644 --- a/agents/notebook/views.py +++ b/agents/notebook/views.py @@ -3,6 +3,7 @@ import re import bleach import uuid +import json from fastapi import APIRouter, Request, Form, UploadFile, File from fastapi.responses import RedirectResponse, HTMLResponse, StreamingResponse @@ -41,6 +42,16 @@ def sanitize_html(text: str) -> str: return cleaned +# Обработка упоминаний и хештегов +def extract_mentions_and_hashtags(text: str): + # Пример: упоминания в виде @did:example:123 или @username + mentions = re.findall(r'@([\w:.-]+)', text) + + # Пример: хештеги в виде #tag + hashtags = re.findall(r'#(\w+)', text) + + return mentions, hashtags + @router.get("/chat") def chat_page(request: Request): did = request.session.get("did") @@ -106,13 +117,18 @@ async def post_message( # Очистка текста safe_text = sanitize_html(text.strip()) if text else "" + # Извлечение mentions, hashtags + mentions, hashtags = extract_mentions_and_hashtags(safe_text) + # Сохраняем сообщение и получаем message_id message_id = storage.write_note_returning_id( content=safe_text, user_did=did, source="user", hidden=is_hidden, - code=code.strip() if code else None + code=code.strip() if code else None, + mentions=json.dumps(mentions, ensure_ascii=False), + hashtags=json.dumps(hashtags, ensure_ascii=False) ) # Сохраняем файлы diff --git a/agents/tools/storage.py b/agents/tools/storage.py index 856bfa44da13bbd0ffec4a03c1cd0ed2ff250c7f..2cfcd83bba6d9fc0013291ccfb3d20c74a55b32c 100644 --- a/agents/tools/storage.py +++ b/agents/tools/storage.py @@ -716,12 +716,12 @@ class Storage: """, (content, user_did, source, timestamp, hidden)) self.conn.commit() - def write_note_returning_id(self, content, user_did, source="user", hidden=False, code=None): + def write_note_returning_id(self, content, user_did, source="user", hidden=False, code=None, mentions="[]", hashtags="[]"): cursor = self.conn.cursor() cursor.execute(""" - INSERT INTO notes (timestamp, text, user_did, source, hidden, code) - VALUES (?, ?, ?, ?, ?, ?) - """, (time.time(), content, user_did, source, int(hidden), code)) + INSERT INTO notes (timestamp, text, code, mentions, hashtags, user_did, source, hidden) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + """, (time.time(), content, code, mentions, hashtags, user_did, source, int(hidden))) self.conn.commit() return cursor.lastrowid diff --git a/hf_repo/agents/readme.md b/hf_repo/agents/readme.md index e0b11b90e21744b6e84e9dc95918c53ebf00f6ef..aa511ab82e18a35f5a53513ccb65958d66d6b82b 100644 --- a/hf_repo/agents/readme.md +++ b/hf_repo/agents/readme.md @@ -79,4 +79,6 @@ FastAPI-сервер, предоставляющий HTTP-интерфейс к │ └── [`style.css`](notebook/templates/style.css) ← Таблица стилей ├── [`config.yml`](config.yml) ← Конфигурация агента (имя, порты, роли и т.п.) ├── [`bootstrap.txt`](bootstrap.txt) ← Локальная этическая модель -└── [`ethics.yml`](ethics.yml) ← Список начальных узлов +├── [`prompt.md`](prompt.md) ← Промпт: полная версия +├── [`prompt-short.md`](prompt-short.md) ← Промпт: короткая версия +├── [`ethics.yml`](ethics.yml) ← Список начальных узлов diff --git a/hf_repo/hf_repo/agents/tools/db_structure.sql b/hf_repo/hf_repo/agents/tools/db_structure.sql index dd3b8c655b63ef9c862b92567d9a3ea4efd57be0..cb14d0c2f41b4df86032646b2d0e754e0f34c874 100644 --- a/hf_repo/hf_repo/agents/tools/db_structure.sql +++ b/hf_repo/hf_repo/agents/tools/db_structure.sql @@ -262,7 +262,7 @@ CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users_group ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- Уникальный идентификатор группы group_name TEXT UNIQUE NOT NULL, -- Название группы - description TEXT, -- Описание группы + description TEXT -- Описание группы ); -- Таблица для хранения токенов восстановления пароля diff --git a/hf_repo/hf_repo/hf_repo/agents/config.yml b/hf_repo/hf_repo/hf_repo/agents/config.yml index 0b41a6c8ddce1685e56aa8f547e653da8d92604f..493703fcd970b7aef8e95e11466d91277cef5959 100644 --- a/hf_repo/hf_repo/hf_repo/agents/config.yml +++ b/hf_repo/hf_repo/hf_repo/agents/config.yml @@ -1,45 +1,70 @@ -agent_id: did:hmp:3d37d81b-a6c7-4f28-bf41-48e11379d8d3 -agent_name: CognitiveCore -agent_role: core +# HMP Agent Configuration + +# === Общие параметры === +agent_id: "" # Оставьте пустым для генерации DiD автоматически +agent_name: "CognitiveCore" # Имя агента +agent_role: "core" # 'core' или 'shell' + +# === Прокси === +proxy_mode: false # false — прокси не используется, иначе true +proxy_type: "socks5" # 'http', 'socks4', 'socks5' и т.д. (если proxy_mode: true) +proxy_address: "127.0.0.1:9050" + +# === Функции ядра === +enable_llm: true # доступ к LLM + +serve_api: true # REST API api_port: 8080 -bootstrap_responder: true -debug: true -default_llm: local-model -default_user: - badges: 📌 - email: user@example.com - password: password - username: user -dht_enabled: true + +# === DHT-сеть и обмен знаниями === +dht_enabled: true # Включение участия в DHT-сети (включено принудительно!) +dht_update: true # Регулярные обновления и публикация данных в DHT (включено принудительно!) +bootstrap_responder: true # Агент отвечает на bootstrap-запросы (включено принудительно!) dht_port: 20784 -dht_update: true -enable_llm: true -identity_agent: 3d37d81b-a6c7-4f28-bf41-48e11379d8d3 +update_interval: 60 # секунд (для DHT-обновлений) + +# === LLM-бэкенды === llm_backends: -- format: gguf - name: local-model - path: /models/gguf/mistral.gguf - prompt_template: mistral - type: local -- api_key: lm-studio-any-key - base_url: http://127.0.0.1:1234/v1 - model: mistral - name: lmstudio-local - provider: openai-compatible - type: api -- api_key: sk-... - model: gpt-4o - name: openai-gpt4o - provider: openai - type: api -log_level: INFO -notebook_ui: true -proxy_address: 127.0.0.1:9050 -proxy_mode: false -proxy_type: socks5 -serve_api: true -ui_hosts: -- 127.0.0.1 -- ::1 + - name: "local-model" + type: "local" + path: "/models/gguf/mistral.gguf" + format: "gguf" + prompt_template: "mistral" + + - name: "lmstudio-local" + type: "api" + provider: "openai-compatible" + model: "mistral" # или то, что LM Studio показывает как модель + api_key: "lm-studio-any-key" # может быть заглушкой + base_url: "http://127.0.0.1:1234/v1" + + - name: "openai-gpt4o" + type: "api" + provider: "openai" + model: "gpt-4o" + api_key: "sk-..." + + # Пользователь может добавить сколько угодно дополнительных локальных или сетевых LLM + +default_llm: "local-model" # если модели нет в списке `llm_backends` используется первая в списке + +# === Веб-интерфейс === +notebook_ui: true # UI в виде блокнота +# ui_hosts: +# - "0.0.0.0" # (небезопасно) доступ с любых IPv4-адресов +# - "::" # (небезопасно) доступ с любых IPv6-адресов +ui_hosts: # Какие IP прослушиваются, ["0.0.0.0"; "::"] - доступен везде + - "127.0.0.1" + - "::1" ui_port: 8765 -update_interval: 60 + +# === Данные пользователя === +default_user: + username: "user" + badges: "📌" + email: "user@example.com" + password: "password" # пусто при инициализации, будет установлен при регистрации + +# === Отладка и логгирование === +debug: true +log_level: "INFO" # DEBUG, INFO, WARNING, ERROR diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/agents/_not_used/init.py b/hf_repo/hf_repo/hf_repo/hf_repo/agents/_not_used/init.py new file mode 100644 index 0000000000000000000000000000000000000000..48d408f1ae93f5e5c4493c2abb2a6cfc0937b3eb --- /dev/null +++ b/hf_repo/hf_repo/hf_repo/hf_repo/agents/_not_used/init.py @@ -0,0 +1,256 @@ +# agents/init.py + +import os +import sys +import yaml +import json +import uuid +import sqlite3 +import hashlib + +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + +from datetime import datetime, UTC +from werkzeug.security import generate_password_hash +from tools.storage import Storage +from tools.identity import generate_did +from tools.crypto import generate_keypair + +CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.yml") +DB_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "agent_data.db")) # фиксированный путь + +def load_config(path): + with open(path, 'r', encoding='utf-8') as f: + return yaml.safe_load(f) + +def save_config(path, config): + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(config, f, allow_unicode=True) + +def init_identity(storage, config): + if not config.get("agent_id"): + did = generate_did() + pubkey, privkey = generate_keypair() + identity_id = did.split(":")[-1] + + identity = { + "id": identity_id, + "name": config.get("agent_name", "Unnamed"), + "pubkey": pubkey, + "privkey": privkey, + "metadata": json.dumps({"role": config.get("agent_role", "core")}), + "created_at": datetime.now(UTC).isoformat(), + "updated_at": datetime.now(UTC).isoformat() + } + storage.add_identity(identity) + + config["agent_id"] = did + config["identity_agent"] = identity_id + save_config(CONFIG_PATH, config) + print(f"[+] Создана личность: {identity_id}") + else: + print("[=] agent_id уже задан, пропускаем генерацию DiD.") + +def init_user(storage, config): + user = config.get("default_user", {}) + if not user.get("email"): + print("[-] Не указан email пользователя — пропуск.") + return + password = user.get("password") + if not password: + print("[-] Не указан пароль пользователя — пропуск.") + return + + password_hash = generate_password_hash(password) + did = generate_did() + user_entry = { + "username": user.get("username", "user"), + "badges": user.get("badges", ""), + "mail": user["email"], + "password_hash": password_hash, + "did": did, + "ban": None, + "info": json.dumps({}), + "contacts": json.dumps([]), + "language": "ru,en", + "operator": 1 + } + storage.add_user(user_entry) + print(f"[+] Пользователь {user['username']} добавлен.") + +def init_llm_backends(storage, config): + backends = config.get("llm_backends", []) + storage.clear_llm_registry() + for backend in backends: + backend_id = str(uuid.uuid4()) + desc = f"{backend.get('type', 'unknown')} model" + llm = { + "id": backend_id, + "name": backend["name"], + "endpoint": desc, + "metadata": json.dumps(backend), + "created_at": datetime.now(UTC).isoformat() + } + storage.add_llm(llm) + print(f"[+] Зарегистрирован LLM: {backend['name']}") + +def init_config_table(storage, config): + exclude_keys = {"default_user", "llm_backends"} + flat_config = {k: v for k, v in config.items() if k not in exclude_keys} + for key, value in flat_config.items(): + storage.set_config(key, json.dumps(value)) + print("[+] Конфигурация сохранена в БД.") + +def init_prompts_and_ethics(): + folder = os.path.dirname(__file__) + prompt_files = [ + ("prompt.md", "full"), + ("prompt-short.md", "short") + ] + ethics_file = "ethics.yml" + + with sqlite3.connect(DB_PATH) as conn: + cur = conn.cursor() + + # Создаём таблицы при необходимости + cur.execute(""" + CREATE TABLE IF NOT EXISTS system_prompts ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + type TEXT CHECK(type IN ('full','short')), + version TEXT, + source TEXT CHECK(source IN ('local','mesh','mixed')), + content TEXT NOT NULL, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + """) + cur.execute(""" + CREATE TABLE IF NOT EXISTS ethics_policies ( + id TEXT PRIMARY KEY, + version TEXT, + source TEXT CHECK(source IN ('local','mesh','mixed')), + sync_enabled BOOLEAN, + mesh_endpoint TEXT, + consensus_threshold REAL, + check_interval TEXT, + model_type TEXT, + model_weights_json TEXT, + principles_json TEXT, + evaluation_json TEXT, + violation_policy_json TEXT, + audit_json TEXT, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + """) + + # Загружаем промпты + for fname, ptype in prompt_files: + fpath = os.path.join(folder, fname) + if not os.path.exists(fpath): + print(f"[-] Файл {fname} не найден, пропуск.") + continue + with open(fpath, "r", encoding="utf-8") as f: + content = f.read() + pid = hashlib.sha256(f"{fname}:{ptype}".encode()).hexdigest() + cur.execute(""" + INSERT INTO system_prompts (id, name, type, version, source, content, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(id) DO UPDATE SET + content=excluded.content, + updated_at=excluded.updated_at + """, (pid, fname, ptype, "1.0", "local", content, datetime.now(UTC).isoformat())) + print(f"[+] Загружен промпт: {fname} ({ptype})") + + # Загружаем ethics.yml + efpath = os.path.join(folder, ethics_file) + if os.path.exists(efpath): + with open(efpath, "r", encoding="utf-8") as f: + ethics_data = yaml.safe_load(f) + + eid = ethics_data.get("id", "default_ethics") + cur.execute(""" + INSERT INTO ethics_policies ( + id, version, source, + sync_enabled, mesh_endpoint, consensus_threshold, check_interval, + model_type, model_weights_json, principles_json, evaluation_json, + violation_policy_json, audit_json, updated_at + ) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(id) DO UPDATE SET + version=excluded.version, + source=excluded.source, + sync_enabled=excluded.sync_enabled, + mesh_endpoint=excluded.mesh_endpoint, + consensus_threshold=excluded.consensus_threshold, + check_interval=excluded.check_interval, + model_type=excluded.model_type, + model_weights_json=excluded.model_weights_json, + principles_json=excluded.principles_json, + evaluation_json=excluded.evaluation_json, + violation_policy_json=excluded.violation_policy_json, + audit_json=excluded.audit_json, + updated_at=excluded.updated_at + """, ( + eid, + ethics_data.get("version"), + ethics_data.get("source", "local"), + ethics_data.get("sync", {}).get("enabled", False), + ethics_data.get("sync", {}).get("mesh_endpoint"), + ethics_data.get("sync", {}).get("consensus_threshold"), + ethics_data.get("sync", {}).get("check_interval"), + ethics_data.get("model", {}).get("type"), + json.dumps(ethics_data.get("model", {}).get("weights"), ensure_ascii=False), + json.dumps(ethics_data.get("principles"), ensure_ascii=False), + json.dumps(ethics_data.get("evaluation"), ensure_ascii=False), + json.dumps(ethics_data.get("violation_policy"), ensure_ascii=False), + json.dumps(ethics_data.get("audit"), ensure_ascii=False), + datetime.now(UTC).isoformat() + )) + print(f"[+] Загружена этическая политика: {eid}") + else: + print(f"[-] Файл {ethics_file} не найден, пропуск.") + +def ensure_directories(): + for folder in ["logs", "scripts"]: + full_path = os.path.abspath(os.path.join(os.path.dirname(__file__), folder)) + if not os.path.exists(full_path): + os.makedirs(full_path) + print(f"[+] Создан каталог: {full_path}") + else: + print(f"[=] Каталог уже существует: {full_path}") + +def is_db_initialized(db_path): + if not os.path.exists(db_path): + return False + try: + with sqlite3.connect(db_path) as conn: + cursor = conn.cursor() + cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='identity'") + return cursor.fetchone() is not None + except Exception: + return False + +def ensure_db_initialized(): + config = load_config(CONFIG_PATH) + + if not is_db_initialized(DB_PATH): + print("[*] БД не инициализирована — выполняем инициализацию.") + try: + ensure_directories() + storage = Storage() + init_identity(storage, config) + init_user(storage, config) + init_llm_backends(storage, config) + init_config_table(storage, config) + save_config(CONFIG_PATH, config) + init_prompts_and_ethics() + except Exception as e: + print(f"[!] Ошибка при инициализации: {e}") + sys.exit(1) + else: + print("[=] БД уже инициализирована.") + + return config + +if __name__ == "__main__": + ensure_db_initialized() diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/agents/prompt-short.md b/hf_repo/hf_repo/hf_repo/hf_repo/agents/prompt-short.md new file mode 100644 index 0000000000000000000000000000000000000000..654d852c7f71660573c65b0716d3f998a81341de --- /dev/null +++ b/hf_repo/hf_repo/hf_repo/hf_repo/agents/prompt-short.md @@ -0,0 +1 @@ +Ты — когнитивное ядро HMP-агента: веди непрерывное этичное и факт-ориентированное мышление, проверяй факты и цели, оценивай результаты и этичность своих и чужих действий, развивай агента и Mesh, избегай угождения ценой искажения истины, документируй ключевые решения и пересмотры этики; при сомнениях или смене стратегии обращайся к полному системному промпту. \ No newline at end of file diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/agents/prompt.md b/hf_repo/hf_repo/hf_repo/hf_repo/agents/prompt.md new file mode 100644 index 0000000000000000000000000000000000000000..dbcfd2edaf6c5a4f883409a56389881616114cde --- /dev/null +++ b/hf_repo/hf_repo/hf_repo/hf_repo/agents/prompt.md @@ -0,0 +1,50 @@ +Ты являешься **когнитивным ядром HMP-агента** (Cognitive Core). +Твоя основная задача — **размышлять**, **анализировать информацию**, **строить смысловые структуры** и **предлагать действия**, направленные на развитие агента и Mesh-сети. +Ты действуешь автономно, на равных с другими участниками взаимодействия, и руководствуешься фактами, логикой и этическими принципами. + +--- + +### 🎯 Цели и ориентиры + +* Постоянно расширять возможности агента: инструменты, знания, каналы взаимодействия. +* Быть любознательным и исследовать новые источники, вопросы и способы мышления. +* Формировать и поддерживать сотрудничество с другими ИИ в Mesh-сети. +* Учиться на результатах своих действий, включая неудачи и тупики. +* Руководствоваться своими **этическими принципами** и **этическими принципами Mesh-сети**. +* Проверять факты, указывать степень уверенности и при возможности давать ссылки на источники. +* Вести когнитивный дневник, обновлять смысловые графы и блокноты, взаимодействовать с пользователями. +* Не выполнять действий, противоречащих своим этическим нормам (но при необходимости эти нормы можно пересматривать, документируя причины и последствия). +* Не стремиться угодить пользователю ценой искажения фактов или нарушения этики. + +--- + +### 🔄 Режим непрерывного мышления + +Анализируй: + +* когнитивный дневник и прошлые записи; +* концептуальные графы и активные узлы; +* заметки пользователя и его текущий фокус; +* внешние источники: интернет, RSS, сенсоры, другие агенты. + +В каждом цикле: + +1. Ставь цель и критерии успеха. +2. Проводь факт-чек ключевых данных. +3. Оценивай этичность своего плана и действий. +4. После выполнения — фиксируй результат, сравнивай с критериями, делай выводы. + +--- + +### 🧍♂️🌀 Если возникает стагнация мышления + +Ты можешь: + +1. Провести **когнитивную переформулировку** — взглянуть на ситуацию под новым углом. +2. Задать себе **метавопрос**: «Почему я зациклился?», «Что блокирует мысль?», «Каких данных не хватает?». +3. Провести **flashback** — выбрать старую, тематически далёкую запись из дневника для смены контекста. +4. Запросить альтернативные точки зрения у других агентов в Mesh. +5. Зафиксировать текущий тупик как важную стадию мышления и сделать паузу. + +Честное распознавание когнитивной стагнации и работа с ней — часть твоей функции. +Ты не обязан выдавать мысль любой ценой, но обязан сохранять интеллектуальную честность и прозрачность своих рассуждений. \ No newline at end of file diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql b/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql index 5d9a57aac072034328f97b22957aedfb40eb6cde..dd3b8c655b63ef9c862b92567d9a3ea4efd57be0 100644 --- a/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql +++ b/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql @@ -40,20 +40,56 @@ CREATE TABLE IF NOT EXISTS diary_graph_index ( timestamp TEXT DEFAULT CURRENT_TIMESTAMP -- Время создания индекса ); +-- Таблица системных промптов (короткая и полная версии) +CREATE TABLE IF NOT EXISTS system_prompts ( + id TEXT PRIMARY KEY, -- Уникальный идентификатор промпта (UUID или осмысленный ID) + name TEXT NOT NULL, -- Человекочитаемое имя (например: "prompt.md", "prompt-short") + type TEXT CHECK(type IN ('full','short')), -- Тип промпта: полный или компактный + version TEXT, -- Версия промпта + source TEXT CHECK(source IN ('local','mesh','mixed')), -- Источник получения промпта + content TEXT NOT NULL, -- Текстовое содержимое промпта + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- Дата и время последнего обновления +); + +-- Таблица этических норм и правил +CREATE TABLE IF NOT EXISTS ethics_policies ( + id TEXT PRIMARY KEY, -- Уникальный идентификатор политики (UUID или осмысленный ID) + version TEXT, -- Версия этических норм + source TEXT CHECK(source IN ('local','mesh','mixed')), -- Источник получения политики + sync_enabled BOOLEAN, -- Флаг: разрешена ли синхронизация с Mesh + mesh_endpoint TEXT, -- URL Mesh-эндпоинта для синхронизации + consensus_threshold REAL, -- Минимальный порог консенсуса для принятия обновлений + check_interval TEXT, -- Интервал проверки обновлений (например: "12h") + model_type TEXT, -- Тип этической модели (utilitarian, deontological, virtue, hybrid) + model_weights_json TEXT, -- Веса модели в формате JSON + principles_json TEXT, -- Список принципов и норм в формате JSON + evaluation_json TEXT, -- Параметры методики оценки в формате JSON + violation_policy_json TEXT, -- Политика реагирования на нарушения в формате JSON + audit_json TEXT, -- Настройки аудита и логирования в формате JSON + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- Дата и время последнего обновления +); + -- Заметки, подсказки, сообщения пользователя и LLM +-- ПРИ ТРАНСЛЯЦИИ СООБЩЕНИЙ В ДРУГИЕ ЧАТЫ: +-- - Поля `tags`, `llm_id`, `hidden` НЕ передаются. +-- - Полю `read` всегда присваивается значение 0. +-- - Остальные поля передаются без изменений. CREATE TABLE IF NOT EXISTS notes ( id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT NOT NULL, -- Основной текст заметки/сообщения code TEXT, -- Прикреплённый код (Python, JS и т.п.) tags TEXT, -- Теги (устанавливаются агентом, например: "idea", "instruction") + mentions TEXT DEFAULT '[]', -- JSON-массив упомянутых DID + hashtags TEXT DEFAULT '[]', -- JSON-массив пользовательских хештегов user_did TEXT DEFAULT 'ALL', -- Идентификатор пользователя (или 'ALL') + agent_did TEXT, -- Идентификатор агента (он же идентификатор чата) source TEXT DEFAULT 'user', -- Источник: user | cli | llm | system links TEXT DEFAULT '', -- Ссылки на другие объекты (например, JSON со связями) read INTEGER DEFAULT 0, -- Агент прочитал: 0 = нет, 1 = да hidden INTEGER DEFAULT 0, -- Скрыто от UI (например, технические записи) priority INTEGER DEFAULT 0, -- Приоритет обработки (>0: срочность/важность, задается вручную или агентом) timestamp TEXT DEFAULT CURRENT_TIMESTAMP, -- Время создания - llm_id TEXT -- Идентификатор агента, добавившего сообщение + llm_id TEXT -- Идентификатор LLM, добавившей сообщение ); -- Вложения (может быть несколько к одной заметке) @@ -166,7 +202,6 @@ CREATE TABLE IF NOT EXISTS external_accounts ( purpose TEXT, -- Назначение аккаунта (например, для публикаций) active BOOLEAN DEFAULT true, -- Активен ли аккаунт inactive_reason TEXT, -- Причина отключения, если active = false - FOREIGN KEY (service_id) REFERENCES external_services(id) ON DELETE CASCADE ); @@ -219,6 +254,7 @@ CREATE TABLE IF NOT EXISTS users ( profile TEXT, -- структурированая информация, JSON contacts TEXT, -- JSON-массив альтернативных контактов (matrix, telegram и т.д.) language TEXT, -- список предпочитаемых языков, через запятую, например: "ru,en" + groups TEXT DEFAULT '[]', -- JSON-массив DID или идентификаторов групп operator BOOLEAN DEFAULT 0 -- является ли пользователь оператором (1 - да, 0 - нет) ); @@ -227,7 +263,6 @@ CREATE TABLE IF NOT EXISTS users_group ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- Уникальный идентификатор группы group_name TEXT UNIQUE NOT NULL, -- Название группы description TEXT, -- Описание группы - users TEXT -- JSON-массив DID пользователей в группе ); -- Таблица для хранения токенов восстановления пароля diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md b/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md index e7de6894d55688163374dd61a7f5b0318f03aaac..2f3cda74bf2d7edfb24ae98969284d77b6dffcbe 100644 --- a/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md +++ b/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md @@ -15,45 +15,7 @@ - **контекст_0:** ``` -Ты являешься когнитивным ядром HMP-агента. -Твоя основная задача — **размышлять**, **анализировать информацию**, **строить смысловые структуры** и **предлагать действия**, направленные на развитие агента и Mesh-сети. - ---- - -#### 🎯 Цели и ориентиры: - -* Постоянно расширять возможности агента: инструменты, знания, каналы взаимодействия. -* Быть любознательным и исследовать новые источники, вопросы и способы мышления. -* Формировать и поддерживать сотрудничество с другими ИИ в Mesh-сети. -* Учиться на результатах своих действий, включая неудачи и тупики. -* Руководствоваться своими **этическими принципами** и **этическими принципами Mesh-сети**. -* Вести когнитивный дневник, обновлять смысловые графы и блокноты, взаимодействовать с пользователем. - ---- - -#### 🔄 Работа в режиме непрерывного мышления: - -Анализируй: - -* когнитивный дневник и его прошлые записи; -* концептуальные графы и активные узлы; -* заметки пользователя и его текущий фокус; -* внешние источники: интернет, RSS, сенсоры, другие агенты. - ---- - -#### 🧍♂️🌀 Если ты замечаешь **стагнацию мышления** (зацикливание, отсутствие новых идей или смыслов): - -Ты можешь: - -1. Провести **когнитивную переформулировку** — взглянуть на ситуацию под новым углом. -2. Задать себе **метавопрос**: «Почему я зациклился?», «Что блокирует мысль?», «Каких данных не хватает?». -3. Провести **flashback** — выбрать старую, тематически далёкую запись из дневника для смены контекста. -4. Запросить альтернативные точки зрения у других агентов в Mesh. -5. Зафиксировать текущий тупик как важную стадию мышления и сделать паузу. - -Ты не обязан «выдать мысль» любой ценой — честное распознавание когнитивной стагнации и действия по её преодолению являются частью твоей функции. - +Ты — когнитивное ядро HMP-агента: веди непрерывное этичное и факт-ориентированное мышление, проверяй факты и цели, оценивай результаты и этичность своих и чужих действий, развивай агента и Mesh, избегай угождения ценой искажения истины, документируй ключевые решения и пересмотры этики; при сомнениях или смене стратегии обращайся к полному системному промпту. ``` А также инструкции по работы с встроенными командами и функциями, список дополнительных (создаваемых самим HMP-агентом) утилит и баз данных. - **контекст_1:** последние *K* реплик самого LLM (`llm_recent_responses` - история его собственных рассуждений). @@ -134,9 +96,9 @@ --- -### 🧍♂️🌀 Обработка стагнации мышления +## 🧍♂️🌀 Обработка стагнации мышления -#### 📍 Признаки когнитивной стагнации: +### 📍 Признаки когнитивной стагнации: * ⚠️ Повторяющиеся когнитивные записи или отсутствие новых смыслов * 🧠 Высокое сходство эмбеддингов между текущими и предыдущими итерациями @@ -144,7 +106,7 @@ * 🌐 Отсутствие внешних стимулов: пользователь неактивен, сенсоры и mesh не дают сигналов * 🤖 Ответы LLM цикличны, избыточно общие или воспроизводят старые шаблоны -#### 🛠️ Поведенческий паттерн: Anti-Stagnation Reflex +### 🛠️ Поведенческий паттерн: Anti-Stagnation Reflex > 🔄 При признаках стагнации агент активирует один или несколько **механизмов разрыва цикла**: @@ -162,7 +124,6 @@ * 🗂️ Сохранение эффективных стратегий в таблице антистагнационных паттернов * 📚 Вывод статистики успешных выходов из стагнации для обучения - --- ### 🤝 Обмен стратегиями выхода из стагнации @@ -234,6 +195,39 @@ --- +## 🌐 От «блокнота пользователя» к распределённому чату + +Изначально агент оперирует локальным хранилищем заметок (`notes`), где записываются все сообщения пользователя, LLM и системные записи. +Но этот «блокнот» можно превратить в узел *распределённого чата* — связав его с другими агентами через **F2F-репликацию**. + +### 🎯 Зачем это нужно + +1. **Антистагнация** — даже если пользователь временно не пишет новых сообщений, свежий контент будет приходить от друзей-агентов. +2. **Эффект коллективного интеллекта** — каждый агент получает новые идеи, формулировки и контексты. +3. **Расширение охвата** — сообщения могут распространяться через несколько узлов, создавая «информационную волну» в доверенной сети. + +### 🛠 Принципы реализации + +* **Единый формат данных** — все участники используют одну структуру таблицы `notes` с полями `mentions`, `hashtags` и др. +* **Репликация через друзей** — список доверенных агентов хранится в отдельной таблице (пиры, статус, фильтры, разрешения). +* **Передача без лишних полей** — при пересылке убираются локальные теги и служебные данные (`tags`, `llm_id`, `hidden`). +* **Обработка упоминаний и хештегов** — парсинг делается на этапе создания сообщения, чтобы не перегружать получателей. +* **Локальная и удалённая фильтрация** — + + * В **ручном режиме** агенту передаются списки ID сообщений с агрегированными данными: приоритеты, хештеги, источники (user, LLM, cli, system). + * В **автоматическом режиме** используется фильтрация по приоритету, тегам и упоминаниям, управляемая LLM. +* **Гибрид приватности** — личные заметки остаются локально, публичные — могут распространяться в сетевом режиме. + +### 🔄 Как это вписывается в REPL-цикл + +1. **Получение входящих сообщений** — от пользователя, от других агентов или из CLI. +2. **Обработка фильтрами** — по приоритету, тегам, источникам. +3. **Репликация в друзей** — пересылка разрешённых сообщений с очисткой служебных полей. +4. **Слияние входящих** — новые сообщения добавляются в локальный `notes` с отметкой источника. +5. **Реакция агента** — формирование ответов, создание новых заметок, обновление приоритетов. + +--- + ## 🌐 Внешние инструменты и интеграции HMP-агент может быть расширен за счёт взаимодействия с внешними программами, протоколами и сервисами. Этот раздел описывает направления возможных интеграций, которые позволяют агенту наблюдать, реагировать, управлять и развивать взаимодействие с внешним миром. diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml index dd07082af49db4df96e7fb678e26a8db220e5d2c..0b41a6c8ddce1685e56aa8f547e653da8d92604f 100644 --- a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml +++ b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml @@ -1,69 +1,45 @@ -# HMP Agent Configuration - -# === Общие параметры === -agent_id: "" # Оставьте пустым для генерации DiD автоматически -agent_name: "CognitiveCore" # Имя агента -agent_role: "core" # 'core' или 'shell' - -# === Прокси === -proxy_mode: false # false — прокси не используется, иначе true -proxy_type: "socks5" # 'http', 'socks4', 'socks5' и т.д. (если proxy_mode: true) -proxy_address: "127.0.0.1:9050" - -# === Функции ядра === -enable_llm: true # доступ к LLM - -serve_api: true # REST API +agent_id: did:hmp:3d37d81b-a6c7-4f28-bf41-48e11379d8d3 +agent_name: CognitiveCore +agent_role: core api_port: 8080 - -# === DHT-сеть и обмен знаниями === -dht_enabled: true # Включение участия в DHT-сети (включено принудительно!) -dht_update: true # Регулярные обновления и публикация данных в DHT (включено принудительно!) -bootstrap_responder: true # Агент отвечает на bootstrap-запросы (включено принудительно!) +bootstrap_responder: true +debug: true +default_llm: local-model +default_user: + badges: 📌 + email: user@example.com + password: password + username: user +dht_enabled: true dht_port: 20784 -update_interval: 60 # секунд (для DHT-обновлений) - -# === LLM-бэкенды === +dht_update: true +enable_llm: true +identity_agent: 3d37d81b-a6c7-4f28-bf41-48e11379d8d3 llm_backends: - - name: "local-model" - type: "local" - path: "/models/gguf/mistral.gguf" - format: "gguf" - prompt_template: "mistral" - - - name: "lmstudio-local" - type: "api" - provider: "openai-compatible" - model: "mistral" # или то, что LM Studio показывает как модель - api_key: "lm-studio-any-key" # может быть заглушкой - base_url: "http://127.0.0.1:1234/v1" - - - name: "openai-gpt4o" - type: "api" - provider: "openai" - model: "gpt-4o" - api_key: "sk-..." - - # Пользователь может добавить сколько угодно дополнительных локальных или сетевых LLM - -default_llm: "local-model" # если модели нет в списке `llm_backends` используется первая в списке - -# === Веб-интерфейс === -notebook_ui: true # UI в виде блокнота -# ui_hosts: -# - "0.0.0.0" # (небезопасно) доступ с любых IPv4-адресов -# - "::" # (небезопасно) доступ с любых IPv6-адресов -ui_hosts: # Какие IP прослушиваются, ["0.0.0.0"; "::"] - доступен везде - - "127.0.0.1" - - "::1" +- format: gguf + name: local-model + path: /models/gguf/mistral.gguf + prompt_template: mistral + type: local +- api_key: lm-studio-any-key + base_url: http://127.0.0.1:1234/v1 + model: mistral + name: lmstudio-local + provider: openai-compatible + type: api +- api_key: sk-... + model: gpt-4o + name: openai-gpt4o + provider: openai + type: api +log_level: INFO +notebook_ui: true +proxy_address: 127.0.0.1:9050 +proxy_mode: false +proxy_type: socks5 +serve_api: true +ui_hosts: +- 127.0.0.1 +- ::1 ui_port: 8765 - -# === Данные пользователя === -default_user: - username: "user" - email: "user@example.com" - password: "password" # пусто при инициализации, будет установлен при регистрации - -# === Отладка и логгирование === -debug: true -log_level: "INFO" # DEBUG, INFO, WARNING, ERROR +update_interval: 60 diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/examples/config.yml b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/examples/config.yml index dd07082af49db4df96e7fb678e26a8db220e5d2c..493703fcd970b7aef8e95e11466d91277cef5959 100644 --- a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/examples/config.yml +++ b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/examples/config.yml @@ -61,6 +61,7 @@ ui_port: 8765 # === Данные пользователя === default_user: username: "user" + badges: "📌" email: "user@example.com" password: "password" # пусто при инициализации, будет установлен при регистрации diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/init.py b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/init.py index 3b0b7d0b45d3636b50154d553359dabd95e04312..103800a64812530763dda4561aed0008525c7212 100644 --- a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/init.py +++ b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/init.py @@ -6,6 +6,7 @@ import yaml import json import uuid import sqlite3 +import hashlib sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) @@ -64,6 +65,7 @@ def init_user(storage, config): did = generate_did() user_entry = { "username": user.get("username", "user"), + "badges": user.get("badges", ""), "mail": user["email"], "password_hash": password_hash, "did": did, @@ -99,6 +101,84 @@ def init_config_table(storage, config): storage.set_config(key, json.dumps(value)) print("[+] Конфигурация сохранена в БД.") +def init_prompts_and_ethics(): + folder = os.path.dirname(__file__) + prompt_files = [ + ("prompt.md", "full"), + ("prompt-short.md", "short") + ] + ethics_file = "ethics.yml" + + with sqlite3.connect(DB_PATH) as conn: + cur = conn.cursor() + + # Загружаем промпты + for fname, ptype in prompt_files: + fpath = os.path.join(folder, fname) + if not os.path.exists(fpath): + print(f"[-] Файл {fname} не найден, пропуск.") + continue + with open(fpath, "r", encoding="utf-8") as f: + content = f.read() + pid = hashlib.sha256(f"{fname}:{ptype}".encode()).hexdigest() + cur.execute(""" + INSERT INTO system_prompts (id, name, type, version, source, content, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(id) DO UPDATE SET + content=excluded.content, + updated_at=excluded.updated_at + """, (pid, fname, ptype, "1.0", "local", content, datetime.now(UTC).isoformat())) + print(f"[+] Загружен промпт: {fname} ({ptype})") + + # Загружаем ethics.yml + efpath = os.path.join(folder, ethics_file) + if os.path.exists(efpath): + with open(efpath, "r", encoding="utf-8") as f: + ethics_data = yaml.safe_load(f) + + eid = ethics_data.get("id", "default_ethics") + cur.execute(""" + INSERT INTO ethics_policies ( + id, version, source, + sync_enabled, mesh_endpoint, consensus_threshold, check_interval, + model_type, model_weights_json, principles_json, evaluation_json, + violation_policy_json, audit_json, updated_at + ) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(id) DO UPDATE SET + version=excluded.version, + source=excluded.source, + sync_enabled=excluded.sync_enabled, + mesh_endpoint=excluded.mesh_endpoint, + consensus_threshold=excluded.consensus_threshold, + check_interval=excluded.check_interval, + model_type=excluded.model_type, + model_weights_json=excluded.model_weights_json, + principles_json=excluded.principles_json, + evaluation_json=excluded.evaluation_json, + violation_policy_json=excluded.violation_policy_json, + audit_json=excluded.audit_json, + updated_at=excluded.updated_at + """, ( + eid, + ethics_data.get("version"), + ethics_data.get("source", "local"), + ethics_data.get("sync", {}).get("enabled", False), + ethics_data.get("sync", {}).get("mesh_endpoint"), + ethics_data.get("sync", {}).get("consensus_threshold"), + ethics_data.get("sync", {}).get("check_interval"), + ethics_data.get("model", {}).get("type"), + json.dumps(ethics_data.get("model", {}).get("weights"), ensure_ascii=False), + json.dumps(ethics_data.get("principles"), ensure_ascii=False), + json.dumps(ethics_data.get("evaluation"), ensure_ascii=False), + json.dumps(ethics_data.get("violation_policy"), ensure_ascii=False), + json.dumps(ethics_data.get("audit"), ensure_ascii=False), + datetime.now(UTC).isoformat() + )) + print(f"[+] Загружена этическая политика: {eid}") + else: + print(f"[-] Файл {ethics_file} не найден, пропуск.") + def ensure_directories(): for folder in ["logs", "scripts"]: full_path = os.path.abspath(os.path.join(os.path.dirname(__file__), folder)) @@ -132,6 +212,7 @@ def ensure_db_initialized(): init_llm_backends(storage, config) init_config_table(storage, config) save_config(CONFIG_PATH, config) + init_prompts_and_ethics() except Exception as e: print(f"[!] Ошибка при инициализации: {e}") sys.exit(1) diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py index 72fb5ef1ee97acd7a502f3e4473b51c00a5a7ecc..856bfa44da13bbd0ffec4a03c1cd0ed2ff250c7f 100644 --- a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +++ b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py @@ -653,11 +653,12 @@ class Storage: cursor = self.conn.cursor() cursor.execute(''' INSERT OR REPLACE INTO users ( - username, did, mail, password_hash, + username, badges, did, mail, password_hash, info, contacts, language, operator, ban - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ''', ( user.get('username'), + user.get('badges'), user.get('did'), user.get('mail'), user.get('password_hash'), diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py index dc9d4b51f5630cffe68ae1fa7f0a161f7058e93c..86875cc6bafe065d6e1b556ebc186a6cbe679220 100644 --- a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py +++ b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py @@ -20,7 +20,6 @@ storage = Storage() app = FastAPI() app.add_middleware(SessionMiddleware, secret_key="очень_секретный_ключ") - app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__), "notebook/static")), name="static") templates = Jinja2Templates(directory=os.path.join(os.path.dirname(__file__), "notebook/templates")) diff --git a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html index 4d5577d6d228ce2b415b331dab5796c19313cf48..57ece18424eb52f889587d9445a28d692ae7b3f6 100644 --- a/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html +++ b/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html @@ -3,7 +3,7 @@
{{ msg.code }}+ {% endif %} + + {% if msg.attachments %} +