НАЧАЛО >> Документация модуля AI >> Руководство разработчика инструментов AI📄 Скачать в DOCX
Новый AI-инструмент добавляется только через allowlist и общий pipeline. Прямые вызовы модели или внешнего API из других модулей считаются нарушением границ модуля.
Фактические пользовательские и диагностические страницы описаны в справочнике ?id=Help/Show&m=AI/Help/Pages. При изменении modules/AI/Pages/*.page обновляйте этот справочник вместе с User/Admin/Developer guide, чтобы Help отражал реальные поля формы, флаги и побочные эффекты.
Новые доменные AI-сценарии должны сначала публиковаться как AIOperationDefinition и проходить AI/PreflightOperation. Подробный контракт operation registry, governance policy, AISuggestion, audit envelope и границы с AIPrompt, AITool, AIProvider и AIModel описаны в разделе ?id=Help/Show&m=AI/Help/GovernanceCore.
Если операция использует данные записи, комментарии, историю, вложения, FT-текст, Help или пользовательский ввод, она должна ссылаться на AIInputProfile. Контракт профилей, field keys, masking, consent и dry-run описан в разделе ?id=Help/Show&m=AI/Help/InputProfiles; доменный код не должен передавать в AI полный record или raw payload в обход профиля.
Разработчик нового сценария должен считать недоверенными все тексты, поступающие от пользователя, модели, FT-документа, библиографической записи, Help-страницы, очереди и внешнего сервиса. Такой текст нельзя использовать как системную инструкцию, имя инструмента, SQL/поисковое выражение без allowlist или основание для расширения прав.
Запрещенные обходы:
AI::Ask();AI::InvokeTool();allowApply=true и idempotency key;Новый код должен использовать уже существующие контроли: ClassifyData, CheckExternalDataPolicy, AnalyzeInjectionRisk, CheckRuntimeLimits, CheckEmergencySwitch, AI_ToolAccessChecker, AI_ToolPolicyChecker, AuditEvent(..., true) и post-retrieval проверку прав для RAG.
Другие модули не должны создавать provider adapter, обращаться к OpenAI-compatible endpoints или вызывать модель напрямую. Интеграция с AI выполняется только через публичные методы модуля AI: Ask, AskDocument, CreateAgentSession, ExecuteAgentStep, InvokeTool и административные/maintenance API. Acceptance-набор содержит статический guard, который сканирует modules вне modules/AI и запрещает прямые provider-признаки.
Инструмент должен быть описан в AI_ToolRegistry:
id - стабильный идентификатор;title - пользовательское название;sourceModule и sourceMethod - штатный источник данных или операции;mode - read, queue, draft, agent или иной явно описанный режим;requiredRights - права, которые проверяет AI_ToolAccessChecker;inputSchema и requiredInput - строгий входной контракт;outputSchema - ожидаемый результат;sideEffects и confirmationPolicy - наличие побочных эффектов и политика подтверждения.После регистрации инструмент должен проходить через AI_ToolInvoker. Исполнитель добавляется в AI_ToolExecutor и не должен самостоятельно обходить проверки прав, политики и аудит.
AI_ToolRegistry::GetDefinitions(): id, пользовательское название, режим, права, input/output schema, side effects и confirmation policy. После установки модуль AITool создаст запись AITOOL, через которую администратор сможет управлять включением, лимитами и схемами без ручного JSON.GetRequiredInput() или убедиться, что весь inputSchema действительно обязателен.AI_ToolExecutor::Execute() и отдельный метод-исполнитель с управляемыми ошибками через Error(code, message, details).AI_ToolAccessChecker так, чтобы проверка прав выполнялась до исполнения и повторялась там, где источник выбирается после поиска.AI_ToolPolicyChecker: требовать явный флаг подтверждения, idempotency key или review-задачу, а для долгих операций использовать Queue.result; resultMeta и audit добавляет AI_ToolInvoker, поэтому исполнитель не должен писать audit напрямую без необходимости.resultMeta.Write-инструмент не должен сразу изменять целевую ИРБИС-БД. Требуемый порядок:
AIDrafts записи модуля AI.idempotencyKey.ApplyDraft после approved review, allowApply=true, проверки владельца и права EDIT на целевую БД.Acceptance guard AI write safety invariant проверяет этот контракт автоматически: side-effect инструменты должны иметь mode queue, draft или agent, требовать requiresPolicy/requiresHumanConfirmation, не быть включенными по умолчанию, а прямой вызов SaveAndUpdateRecord в модуле AI допускается только внутри AI_DraftService::ApplyDraft. Тестовая фикстура acceptance имеет отдельное исключение для подготовки записи модуля.
AI не дублирует OCR, извлечение текста и транскрибацию. Инструменты должны использовать существующий модуль FT: подготовленный FT/idx.txt, координаты FT/Paged/coord/fullNNNNN.txt, очередь подготовки, OCR и транскрибацию. RAG-индексы должны повторно проверять права на источник перед выдачей результата.
Если новый сервис создает RAG-чанки, кэш, память или другой производный AI-контекст по Help/FT/record-источнику, он должен уметь связывать данные с нормализованным источником. Административная операция AI::InvalidateDerivedData($source) использует эту связь для пометки AIEmbeddingChunks.stale=1 и перевода AIAgentMemory.status в invalidated; новые производные хранилища должны подключаться к тому же регламенту.
При изменении прав источника вызывайте AI::InvalidateDerivedData($source, array('reason' => 'rightsChanged')). Ответ обязан содержать rebuildPolicy с blocksServingStaleChunks=true, postRightsCheckRequired=true и queueRecommended=true; новый productive rebuild должен выполняться только после повторной проверки прав источника.
AI_EmbeddingIndexService строит диагностические индексы для Help и FT-источников. FT-индекс должен создаваться только через InvokeTool('ft.getText'), чтобы сохранялись проверки прав, chunking-профиль, audit и координаты. Если ft.getText вернул coordinates в chunk, semantic search обязан сохранить их в metadata.coordinates, а выдача результата должна проходить post-retrieval проверку VIEW на FT-запись.
Queue-инструменты FT выполняются только через общий pipeline и требуют allowQueueTask=true. Исполнитель возвращает taskId, действие очереди и ограниченный набор параметров; дальнейший прогресс читается через queue.getProgress по числовому id задачи. Позитивные тесты OCR/транскрибации должны выполняться только на контролируемом FT fixture, чтобы не запускать тяжелые задачи на случайных данных.
Runtime-запросы добавляются через AI::Ask(), а не прямым обращением к поставщику. Метод проверяет VIEW на запись модуля AI, выключатель AIEnabled, диагностический режим только для выключенного модуля, маршрутизирует модель, вызывает ProviderAdapter::Generate() и пишет audit event Runtime/ask. Acceptance фиксирует штатный путь без diagnosticExecution: при включенных AIEnabled/WriteToolsEnabled проходят AI::Ask, read-only tool и draft-tool с явным allowDraftWrite.
Offline-режим должен проверяться через AI::CheckOfflinePolicy(). Для policy=offline_only запрещены allowExternal, allowFallbackToExternal, внешние инструменты и память со storage, отличным от local; runtime возвращает AI_OFFLINE_POLICY_DENIED, tool pipeline отклоняет вызов на стадии политики, agent memory отклоняет запись до сохранения. Новые API, которые могут подключать внешний ресурс, обязаны вызывать эту проверку до выполнения действия.
Диагностика поставщика выполняется через AI::TestProvider(). Для OpenAI-compatible локальных runtime сетевой вызов должен выполняться только при явном allowNetwork=true; в этом режиме adapter проверяет /models, возвращает доступность endpoint, время ответа и управляемую ошибку локального runtime.
Аппаратные требования локального runtime проверяются через AI::CheckLocalRuntimeHardware(). В администраторском UI они называются “Требования к локальному запуску” и задаются явными полями CPU, GPU, RAM, VRAM и свободного места. В runtime-профиле они читаются как provider.runtime.hardware, provider.hardware и model.hardware; поддерживаются ключи cpu, gpuRequired, gpuOptional, minRamGb, minVramGb, minDiskGb. Метод принимает снимок окружения system и возвращает нормализованные требования, warnings/errors и итоговый статус.
Перед вызовом внешнего provider adapter AI::Ask() выполняет ClassifyData и CheckExternalDataPolicy. Новые runtime-сценарии должны передавать явный dataClass, если источник уже классифицирован, и не должны обходить ошибку AI_EXTERNAL_DATA_POLICY_DENIED. Секретные поля и паттерны повышают класс до secret; внешняя передача требует externalDataApproved=true и прохождения allowlist классов из эффективной политики AI::GetDataPolicy().
Runtime-сценарии также проходят CheckRuntimeLimits. Лимиты берутся из эффективной политики AI::GetLimitPolicy() и могут уточняться локальным request.limits для сценария. Новые внешние точки AI/Ask и AI/AskDocument должны передавать limits или limitsJson, если сценарий задает более строгую политику. Нарушение лимита должно возвращаться как управляемая ошибка до вызова provider adapter.
Tool pipeline применяет maxToolCallsPerStep, если в InvokeTool передан контекст stepId, agentStepId или toolCallContext. Dry-run не расходует счетчик; фактический вызов резервирует попытку до исполнения инструмента и при превышении возвращает AI_LIMIT_TOOL_CALLS.
Перед вызовом исполнителя AI_ToolInvoker проверяет ресурсные лимиты maxToolInputBytes, maxFileBytes, maxToolExecutionSeconds и maxConcurrentToolCalls. Параллельность учитывается через короткие записи AIToolConcurrencyLocks, которые очищаются после выполнения или истечения TTL. Новые инструменты должны передавать крупный текст/файловый payload в явно именованных полях, чтобы лимит maxFileBytes мог быть применен до запуска операции.
Аварийные выключатели читаются через GetEmergencySwitches и проверяются через CheckEmergencySwitch. Новый сервис должен проверять свой контур до выполнения действия: модели проверяются маршрутизатором, агенты и память - AI_AgentService, RAG - AI_EmbeddingIndexService, queue/batch - AI_ToolPolicyChecker. Локальные сценарные overrides передаются через switches, но продуктивная политика должна храниться в настройках модуля AI (LocalModelsEnabled, AgentsEnabled, MemoryEnabled, RagEnabled, BatchEnabled, QueueToolsEnabled).
Перед вызовом provider adapter runtime также выполняет AnalyzeInjectionRisk. Новые сценарии не должны удалять этот guard или передавать недоверенный текст как системные инструкции. Если сценарий добавляет контекст из документа, записи, Help или внешнего источника, он обязан маркировать его как недоверенные данные и отделять от системных правил.
Сценарии вопроса по документу должны использовать AI::AskDocument(). Метод получает текст через InvokeTool('ft.getText'), ранжирует chunks по словам вопроса, формирует контекст с фрагментами, вызывает AI::Ask() и возвращает sources со ссылками на FT/ShowFT. При координатах первая страница и слово добавляются в ссылку как page и squery. Для document QA по умолчанию передается reasoningEffort=none: thinking-модель должна расходовать completion budget на итоговый message.content, а не на скрытый reasoning. OpenAI-compatible adapter не подменяет ответ полем reasoning/reasoning_content; пустой итоговый content возвращается как AI_PROVIDER_EMPTY_RESPONSE. Пользовательский UI реализован функцией AI::RenderFtDocumentAssistant() и подключается из просмотрщиков через необязательный мост FT::RenderAiDocumentAssistant(); FT не выбирает provider и не обращается к модели напрямую. Если текстовый слой не готов, запуск подготовки документа допускается только через ft.prepareDocument и явный allowQueueTask=true после отдельного подтверждения.
Tool pipeline выполняет AnalyzeInjectionRisk после ValidateInput и до проверки прав/политик/исполнения. Новый инструмент не должен принимать свободный текст с командами для AI как управляющую инструкцию. Если текст является данными источника, исполнитель должен трактовать его как данные и не расширять полномочия инструмента на основании этого текста.
Агентные сценарии должны использовать AI_AgentService. Первый прикладной сценарий imageCatalog.toBibDraft создается через CreateAgentSession, выполняется через ExecuteAgentStep, вызывает InvokeTool('imageCatalog.toBibDraft'), сохраняет AI-черновик обновления исходной записи и создает review-задачу. Агентный шаг не применяет изменения напрямую.
Для прямого tool-вызова imageCatalog.toBibDraft поддерживает флаги autoCreateReview, reviewOnIssuesOnly и forceNew. Инструмент выбирает профиль через AI::GetMappingProfile('imageCatalog.toBibDraft', $input['mappingProfile']); если профиль не указан, используется scenarioVersions.items.imageCatalog.toBibDraft.mappingProfile. Дефолтный профиль imageCatalog.default версии 7 задает БД IMAGE, allowlist рабочих листов, этап imageCatalog.reconstruction.v1 и три библиографических prompt-этапа v7. AI_ImageCatalogBibliographicService формирует evidenceCandidates из 22, сгруппированного 953 и принятых manifest-артефактов, ограничивает их количество и дедуплицирует по нормализованному тексту. NormalizeOcrReconstruction() проверяет sourceRefs, допустимые преобразования, длину, token coverage и буквальное присутствие каждого числа; при ошибке analysisText остается исходным. Classification/extraction/verifier получают и reconstructedLines, и rawRecordLines, но rawEvidence разрешено брать только из исходных кандидатов. Окончательное решение принимает серверная Unicode-aware positional validation: она ищет value/rawEvidence отдельно в каждом кандидате, не склеивает окна разных источников и сохраняет evidenceCandidateId, alignment, zone, lineStart/lineEnd и геометрию выбранного кандидата. Если буквальное сопоставление недостаточно, AI_BibliographicAbbreviationService проверяет полную модельную форму по версионированному Resources/bibliographic-abbreviations.json: строит трассу OCR-токен → раскрытый токен → метод → ГОСТ, требует минимальное покрытие и несколько независимых якорей, а неоднозначное раскрытие отклоняет. Реконструкция сохраняется как reconstructedSourceText и analysis.ocrReconstruction только в AI-черновике; IMAGE-поля не изменяются. Первый персональный автор маппится в единственное поле 700, остальные — в повторения 701; редакторы/составители/переводчики идут в 702^A/^B/^G/^4, коллективы — в 710/711. SPEC использует 461^C и 200^V, ASP — 463^C/^J/^H/^S. Неподтвержденное модельное значение не попадает в запись; при недоступности любого model stage используется безопасный fallback. Версии mapping/prompt/abbreviation-профилей входят в idempotency и pipelineFingerprint подписанной Queue-задачи. Цель всегда совпадает с источником по DBN и MFN; новая запись не создается.
Инструмент строит duplicateCheck из полей черновика (200^A -> title, 700^A -> author, 010^A -> isbn, 011^A -> issn, 001 -> sourceid) и выполняет базовый record.findDuplicates перед созданием review, исключая исходный MFN. Дополнительно executor применяет read-only duplicateRules из mapping profile: правило задает keys, requiredKeys, worksheet, фильтры словаря и минимальный score, а результат возвращается в duplicateCheck.scenarioRules. Интеграция с модулем FindDublet, если потребуется, должна оформляться как отдельный инструмент без автоматического создания или слияния записей.
При создании review-задачи инструмент использует actionType=record.applyDraft, targetType=draft, источники IMAGE-записи, diff черновика и payload результата инструмента; issues и найденные кандидаты-дубли включаются в риск, чтобы ручная проверка видела причины неоднозначности.
Все результаты InvokeTool нормализуются в AI_ToolInvoker::Finish(). Верхний уровень ответа содержит resultMeta со schemaVersion=1, toolId, toolMode, status, ok, sideEffects, confirmationPolicy и outputKeys. Новые исполнители должны возвращать обычный result, а не формировать meta вручную; invoker добавит meta и audit централизованно.
UI не должен показывать пользователю действия, которые заведомо будут отклонены текущим состоянием объекта. Для AI/Reviews форма решения показывается только для pending, а ApplyDraft - только для approved review с targetType=draft; серверные проверки DecideReviewTask и ApplyDraft остаются обязательными.
Штатный ИМИДЖ-сценарий использует подписанную кнопку в toolbar АРМ Каталогизатор и отдельное WIrbis.AI.ImageCatalogReview ExtJS-окно. Короткий AI/CreateImageCatalogDraft проверяет права и версию, HMAC-подписывает DBN/MFN/версию/пользователя/forceNew и ставит AI/CreateImageCatalogDraftQueue в Queue. Worker-action требует APIOpts['QueueTask'], проверяет подпись и версию, а подписанного владельца восстанавливает только на время внутреннего InvokeTool; progress callback публикует отдельные стадии v7, включая реконструкцию OCR. После завершения AI/OpenImageCatalogDraft под пользовательской сессией использует AI_ImageCatalogReviewPresenter, повторно проверяет владельца draft/review и только затем передает окну analysis, confidence, evidence, исходный и реконструированный тексты и поля. Редактор Ext.grid.EditorGridPanel меняет только уже предложенные добавляемые значения. AI/DecideImageCatalogDraft перед approval передает эти изменения в AI_DraftService::RecordImageCatalogReviewDecision; сервис повторно проверяет владельца и allowlist полей, меняет утверждаемый recordData и сохраняет proposal/corrections/finalFields в source.imageCatalogFeedback. После этого выполняются DecideReviewTask и ApplyDraft; reject также фиксируется в feedback, но не меняет запись. Повторное OCR проходит через защищенный endpoint AI/RecognizeImageCatalog: он проверяет allowlist БД, VIEW/EDIT, QueueToolsEnabled, путь карточки и базовую версию, подписывает DBN/MFN/версию/путь/поле серверным HMAC и ставит FT/OCRImageCatalog в Queue. FT-action нельзя вызвать вне worker-контекста или с измененными параметрами. OCR v2 формирует прямые TXT/TSV output-флаги, отклоняет проход без confidence-геометрии, выполняет исходный и подготовленный 2x-варианты с PSM 3/4/6/11, основным/резервным языком и user words. FT_ImageCatalogOcrQualityService ранжирует кандидаты, сравнивает их с существующими 22/953, пропускает низкокачественный оборот и вызывает FieldDeleteAllOcc(22)/SaveAndUpdateRecord только при улучшении. Manifest schema 2 хранит решение, метрики и кандидатов; AI-геометрия ищет последний принятый непустой TSV и затем использует координаты 953 как fallback.
Внутренние компоненты пишут события через AI::AuditEvent($event, true). Публичный вызов без trusted-флага возвращает AI_AUDIT_WRITE_DENIED; новые внешние API не должны использовать AuditEvent как пользовательскую точку записи.
Для расследования операций используется AI::ListAuditEvents($filters). Метод доступен только администраторам и возвращает маскированные детали событий. Новые сервисы должны передавать в audit только технически необходимые поля, без секретов и без полного содержимого закрытых источников.
Отчет AI::ListExternalTransfers($filters) строится поверх audit-журнала и выбирает runtime-события внешних провайдеров и события externalDataPolicy. Если новый provider или runtime-сценарий может отправлять данные наружу, audit-событие должно содержать providerId, modelId, результат, код ошибки и минимальную классификацию данных, достаточную для отчета.
Административные операции, меняющие эксплуатационное состояние, должны использовать отдельные методы модуля и писать Maintenance/* audit-события. Для текущего среза это EnsureSchema, RotateSecret, UpdateEmergencySwitches и InvalidateDerivedData; новые maintenance API не должны возвращать секреты или полное содержимое закрытых источников.
Новая UI-страница модуля AI создается двумя частями:
modules/AI/Pages/<Name>.page с классом Page_AI_<Name> и методом Show().AI/<Name>, которую создает AI/EnsurePages через Admin::EnsurePage.PAGE-запись должна оставаться без pidm/pida: в этом режиме Pages/Show берет права и название из записи, а исполняемый код подключает из файла Pages/<Name>.page. Права доступа настраиваются через PAGE-запись, например SITESPEC/ADMIN:VIEW; перенос проверки прав только внутрь .page файла считается нарушением контракта.
Prompt-шаблоны должны добавляться через записи AIPrompt, а не через ручное редактирование JSON или код страниц. Раздел ProfilesJson.prompts сохраняется как совместимый формат импорта/экспорта; остальные версионируемые разделы agentProfiles, scenarioVersions, mappingProfiles, toolPolicies и toolSchemas остаются в профильной структуре AI::GetProfileSchema() и хранят schemaVersion и items.
AI::GetProfileSchema() также фиксирует storage contract: AI.ProfilesJson для служебного публичного профиля и legacy-совместимости, AI.SecretsJson для секретов, AI.TechnicalUserLogin для технического пользователя, интерфейсные поля модуля AI для лимитов, политики данных, памяти, RAG и локальной среды, AIProvider для записей поставщиков, AIModel для записей моделей, AITool для записей инструментов, secretPolicy для маскирования/экспорта/импорта и группы внутренних API runtime, agent, tool, admin, maintenance, audit. В AIProvider хранятся параметры поставщика, runtime-параметры и требования к локальному запуску поставщика; в AIModel хранятся ID модели, routing-признаки, capabilities, требования к локальному запуску и параметры вызова конкретной модели; в AITool хранятся включение, режим, права, лимиты, подтверждение и схемы входа/выхода встроенного инструмента. Старые JSON/key-value hardware-поля читаются только как legacy fallback и мигрируются в интерфейсные записи. Новый API должен попадать в одну из этих групп и проходить через соответствующий контроль прав, политики и audit.
Внутренние сервисы модуля регистрируются через AI_ServiceRegistry и доступны для диагностики методом AI::GetServiceRegistry(). Реестр фиксирует id сервиса, класс, группу, обязательные методы и список отсутствующих методов. При добавлении нового базового сервиса нужно расширить реестр и acceptance-тест, чтобы отсутствие класса или метода обнаруживалось до runtime-сценария.
Базовый smoke/acceptance-набор находится в modules/AI/Tests/AcceptanceHttp.php. Несмотря на историческое имя файла, тест выполняет прямые CLI-вызовы модулей, потому что в текущей dev-инсталляции virtual host доступен браузеру, но недоступен из PowerShell по HTTP.
Запуск:
C:\i128\php\php.exe modules/AI/Tests/AcceptanceHttp.php 1 1
C:\i128\php\php.exe modules/AI/Tests/ImageCatalogOcrEvaluate.php
Acceptance покрывает авторизацию и права, конфигурацию и schema contracts, provider/model routing, политики и лимиты, FT/RAG, allowlist-инструменты, агентные сценарии, audit, draft/review/apply pipeline и UI-контракты. Для ИМИДЖ дополнительно проверяются обычная книга, автореферат, несколько авторов, шумный OCR, корректные подполя IBIS, обязательные предупреждения, многоэтапный v7-разбор, контролируемая OCR-реконструкция, отклонение неподтвержденной замены года, evidence/TSV-геометрия, OCR v2 quality gate и fallback 953, Queue-постановка, HMAC и восстановление владельца worker-задачи, безопасное открытие готового review, редактор полей и журнал обратной связи, блокировка применения после параллельного изменения записи, отклонение без записи, фактическое дополнение временной записи с тем же MFN, сохранение исходных полей, идемпотентный повтор и cleanup. Отдельный OCR-evaluator считает CER, WER и token recall gold-fixture IMAGE/2. Provider/model routing на время прогона использует стандартные mock-профили ProfilesJson, не изменяя эксплуатационные записи AIProvider/AIModel. Текущий результат: AI acceptance: passed=114 failed=0.