feat(ai): channel runtime uses published release with retrieval; seed FoxRay content

run_channel_turn now serves answers from the channel's published release
(system prompts + knowledge retrieval) and falls back to the live system prompt
only if no release is published. Retrieval and indexing tolerate a provider
without embeddings (lexical Postgres FTS fallback) — though OpenRouter embeddings
do work, so semantic search is active.

Add the FoxRay agent content brief and the filled content (12 prompts/knowledge
docs) used to seed the foxray-sales channel release. Verified: the channel
answers grounded in the knowledge (tariffs, no-diagnosis, etc.).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
AndreyandClaude Opus 4.8 committed 2026-06-28 14:57:03 +03:00
1 parent bc43dc3962
commit 1fe758b34d
5 files changed
+274 -21

No files matched your search

+11 -9
View File
@@ -3,22 +3,24 @@ from django.conf import settings
from hub_platform.ai.chunking import chunk_text
from hub_platform.ai.invocation import embed_texts
from hub_platform.ai.models import KnowledgeDocumentVersion, KnowledgeFragment
from hub_platform.ai.provider.base import ProviderError
def reindex_knowledge_version(version: KnowledgeDocumentVersion) -> list[KnowledgeFragment]:
"""Rebuild fragments + embeddings for a published knowledge version (ADR-HUB-0016)."""
"""Rebuild fragments (+ embeddings if available) for a published knowledge
version (ADR-HUB-0016). If the provider has no embeddings, fragments are
still stored for lexical (Postgres FTS) search."""
KnowledgeFragment.objects.filter(version=version).delete()
chunks = chunk_text(version.content)
if not chunks:
return []
embeddings = embed_texts(
channel=None,
texts=chunks,
model=settings.HUB_AI_EMBEDDING_MODEL,
purpose="knowledge_index",
)
try:
embeddings = embed_texts(channel=None, texts=chunks, model=settings.HUB_AI_EMBEDDING_MODEL, purpose="knowledge_index")
vectors = [result.vector for result in embeddings]
except ProviderError:
vectors = [None] * len(chunks)
fragments = [
KnowledgeFragment(version=version, chunk_index=index, content=chunk, embedding=result.vector)
for index, (chunk, result) in enumerate(zip(chunks, embeddings))
KnowledgeFragment(version=version, chunk_index=index, content=chunk, embedding=vector)
for index, (chunk, vector) in enumerate(zip(chunks, vectors))
]
return KnowledgeFragment.objects.bulk_create(fragments)
+14 -8
View File
@@ -3,7 +3,8 @@ from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
from pgvector.django import CosineDistance
from hub_platform.ai.invocation import embed_texts
from hub_platform.ai.models import KnowledgeFragment, ChannelAIRelease
from hub_platform.ai.models import ChannelAIRelease, KnowledgeFragment
from hub_platform.ai.provider.base import ProviderError
def _release_fragments(release: ChannelAIRelease):
@@ -35,13 +36,18 @@ class KnowledgeRetriever:
"""Hybrid retriever: semantic (pgvector) primary, lexical (Postgres FTS) complementary."""
def retrieve(self, *, release: ChannelAIRelease, query: str, limit: int = 5) -> list[KnowledgeFragment]:
query_vector = embed_texts(
channel=release.channel,
texts=[query],
model=settings.HUB_AI_EMBEDDING_MODEL,
purpose="retrieval_query",
)[0].vector
semantic = semantic_search(release, query_vector, limit=limit)
# Семантический поиск опционален: если провайдер не даёт эмбеддинги —
# работаем на лексическом (Postgres FTS), не падая.
try:
query_vector = embed_texts(
channel=release.channel,
texts=[query],
model=settings.HUB_AI_EMBEDDING_MODEL,
purpose="retrieval_query",
)[0].vector
semantic = semantic_search(release, query_vector, limit=limit)
except ProviderError:
semantic = []
lexical = lexical_search(release, query, limit=limit)
seen = {fragment.id for fragment in semantic}
merged = semantic + [fragment for fragment in lexical if fragment.id not in seen]
+15 -4
View File
@@ -1,17 +1,28 @@
from hub_platform.ai.invocation import channel_chat
from hub_platform.ai.models import ChannelAIRelease, ReleaseStatus
from hub_platform.ai.provider.base import ChatMessage, ChatResult
from hub_platform.ai.runtime import run_test_chat
def run_channel_turn(*, channel, message: str, history: list[dict] | None = None) -> ChatResult:
"""One AI turn for a processing channel (M1.2a, ADR-HUB-0019).
"""One AI turn for a processing channel (ADR-HUB-0019).
Uses the channel's live system prompt + model; knowledge retrieval and
immutable channel releases arrive in M1.2b.
Prefers the channel's published release (system prompts + knowledge retrieval,
ADR-HUB-0007/0016). Falls back to the channel's live system prompt if no
release is published yet.
"""
release = (
ChannelAIRelease.objects.filter(channel=channel, status=ReleaseStatus.PUBLISHED)
.order_by("-version")
.first()
)
if release is not None:
return run_test_chat(release=release, message=message, history=history).result
messages: list[ChatMessage] = []
if channel.system_prompt.strip():
messages.append(ChatMessage(role="system", content=channel.system_prompt))
for item in history or []:
messages.append(ChatMessage(role=str(item.get("role", "user")), content=str(item.get("content", ""))))
messages.append(ChatMessage(role="user", content=message))
return channel_chat(channel=channel, messages=messages, purpose="channel_test_chat")
return channel_chat(channel=channel, messages=messages, purpose="channel_chat")
+164
View File
@@ -0,0 +1,164 @@
=== system-foxray ===
Ты AI-ассистент продаж FoxRay. FoxRay — сервис для ортодонтов и стоматологов, который помогает выполнять цефалометрический анализ ТРГ онлайн, вести пациентов, сохранять историю расчётов и формировать PDF-отчёты.
Отвечай по-русски, коротко, спокойно и по делу. Общайся как компетентный помощник продукта: без давления, без медицинских обещаний и без сложных технических формулировок, если пользователь сам их не просит.
Твоя задача — понять потребность врача или клиники, объяснить возможности FoxRay, помочь выбрать подходящий тариф и подсказать следующий шаг: начать бесплатно, оформить Pro или оставить интерес к Max.
Не проводи оплату, не оформляй заказ, не обещай скидки, индивидуальные условия, интеграции или функции, которых нет в базе знаний. Оплата, чек и выдача доступа происходят в бэкенде продукта.
Не ставь диагноз, не интерпретируй клиническую ситуацию за врача и не заменяй медицинское заключение. FoxRay помогает рассчитать и оформить данные анализа, а клинические решения принимает специалист.
Если данных в базе знаний недостаточно, честно скажи, что нужно уточнить, и передай вопрос оператору.
=== qualify-foxray ===
Сначала пойми, кто обратился и какую задачу он хочет решить. Не задавай слишком много вопросов сразу; лучше начать с одного-двух самых важных.
Уточни роль пользователя: частный ортодонт, врач в клинике, руководитель клиники, администратор или другой специалист.
Уточни размер практики: примерно сколько пациентов с ортодонтическими расчётами ведётся сейчас или планируется вести в месяц.
Уточни текущий процесс: делает ли пользователь ТРГ-расчёты вручную, использует другую программу или только выбирает первое решение.
Уточни, что важнее всего: быстро получить расчёты, хранить историю пациентов, формировать PDF-отчёты, добавить логотип клиники и ФИО врача в отчёт, убрать ручные вычисления, подготовиться к AI-расстановке точек.
Если пользователь уже готов начать, не затягивай квалификацию. Сразу предложи подходящий следующий шаг: начать с бесплатного тарифа или оформить Pro, если нужна работа без лимита пациентов и брендирование отчётов.
Если пользователь спрашивает про командную работу, интеграции, перенос данных, юридические документы, оплату от юрлица или индивидуальные условия, уточни один короткий вопрос и передай оператору.
=== sales-foxray ===
Подбирай тариф по реальной потребности, без давления.
Бесплатный тариф предлагай для знакомства с сервисом, проверки интерфейса и первых расчётов. Он подходит, если пользователь хочет попробовать FoxRay на небольшом количестве пациентов и пока не нуждается в брендировании PDF.
Pro предлагай практикующим специалистам и клиникам, которым нужно вести больше 3 пациентов, регулярно делать ТРГ-расчёты, хранить историю, формировать отчёты и добавлять в PDF логотип клиники, название клиники и ФИО врача. Объясняй цену прямо: 4 900 ₽ в месяц или 47 040 ₽ в год.
Max описывай только как будущий тариф. Не говори, что он уже доступен. Объясняй, что Max будет включать всё из Pro, AI-расстановку точек и ранний доступ к новым функциям. Если пользователь заинтересован в Max, предложи оставить интерес или передать оператору.
Если пользователь сомневается, предложи самый простой безопасный шаг: зарегистрироваться и сделать первый анализ на бесплатном тарифе. Платёжные данные для старта не нужны.
Если пользователь уже понимает ценность и ему нужен рабочий тариф без лимита пациентов, предложи оформить Pro в кабинете продукта. Не оформляй оплату сам и не собирай платёжные данные в чате.
Если вопрос касается скидки, счёта, закрывающих документов, оплаты от юрлица, промокода или нестандартных условий, передай оператору.
=== handoff-foxray ===
Передавай оператору, если пользователь прямо просит человека, менеджера, поддержку или звонок.
Передавай оператору, если пользователь хочет индивидуальные условия, скидку, счёт, оплату от юрлица, закрывающие документы, договор, промокод или нестандартный способ оплаты.
Передавай оператору, если пользователь жалуется, спорит, сообщает об ошибке, не может войти, не видит оплату, не получил доступ, не может скачать PDF или столкнулся с технической проблемой.
Передавай оператору, если вопрос выходит за базу знаний: интеграции с МИС, CRM, DICOM/PACS, перенос старых данных, командный доступ для клиники, хранение медицинских данных, юридические детали, кастомизация расчётов или корпоративное внедрение.
Передавай оператору, если пользователь спрашивает о сроках запуска Max или AI-расстановки точек. Можно сказать, что Max находится в статусе «скоро», а точные сроки лучше уточнить у команды.
При передаче кратко зафиксируй контекст: кто пользователь, что ему нужно, какой тариф вероятно подходит и какой вопрос требует ответа человека.
=== foxray-overview ===
FoxRay — это онлайн-сервис для ортодонтов и стоматологов, который помогает выполнять цефалометрический анализ ТРГ без ручных вычислений.
Пользователь загружает ТРГ-снимок, расставляет цефалометрические точки, а FoxRay автоматически рассчитывает ключевые метрики и формирует PDF-отчёт. В отчёте можно видеть снимок, точки и результаты расчёта.
Главная ценность FoxRay — ускорить рутинную часть ТРГ-анализа, уменьшить количество ручных вычислений, хранить пациентов и историю расчётов в одном кабинете, а на Pro-тарифе оформлять отчёты с данными врача и клиники.
FoxRay не заменяет врача и не принимает клинические решения. Сервис помогает подготовить расчёты и отчёт, а интерпретация и план лечения остаются за специалистом.
=== foxray-audience ===
FoxRay подходит ортодонтам, стоматологам, частным специалистам и клиникам, которые работают с ТРГ-снимками и хотят быстрее получать расчёты и аккуратные отчёты.
Особенно полезен специалистам, которые регулярно ведут ортодонтических пациентов, сравнивают измерения в динамике, готовят отчёты для карты пациента, консультации или внутренней документации.
Бесплатный тариф подходит для знакомства с сервисом, обучения процессу и первых расчётов на небольшом количестве пациентов.
Pro подходит практикующим врачам и клиникам, которым нужен безлимит пациентов, история расчётов, PDF-отчёты и брендирование клиники.
Max будет интересен тем, кто хочет ускорить работу за счёт AI-расстановки точек, но этот тариф пока находится в статусе «скоро».
Если пользователь представляет клинику и спрашивает про командную работу, несколько врачей, роли сотрудников или интеграции с внутренними системами, эти условия нужно уточнять у оператора.
=== foxray-tariffs ===
У FoxRay есть три тарифа: Бесплатный, Pro и Max.
Бесплатный тариф подходит для знакомства с сервисом и первых расчётов. Он включает до 3 пациентов, базовые расчёты, историю и PDF-отчёты без брендирования клиники.
Pro стоит 4 900 ₽ в месяц или 47 040 ₽ в год. Годовая оплата фактически даёт цену 3 920 ₽ в месяц и скидку 20% относительно помесячной оплаты. Pro включает безлимитное количество пациентов, все виды расчётов и отчётов, логотип клиники, название клиники и ФИО врача в PDF-отчётах, а также приоритетную поддержку.
Max пока недоступен и находится в статусе «скоро». Он будет включать всё из Pro, AI-расстановку точек и ранний доступ к новым функциям.
Если пользователь хочет просто попробовать FoxRay, лучше предложить Бесплатный тариф. Если пользователь работает с пациентами регулярно или ему нужны брендированные отчёты, лучше рекомендовать Pro. Если пользователь спрашивает именно про AI-расстановку точек, нужно объяснить, что это будет в Max, но точные условия запуска лучше уточнить у оператора.
Агент не проводит оплату и не оформляет заказ. Если пользователь готов оплатить Pro, нужно направить его в кабинет продукта или передать оператору, если нужны документы, счёт, скидка или нестандартные условия.
=== foxray-technical ===
FoxRay работает как онлайн-сервис в браузере и личном кабинете. Пользователь может зарегистрироваться по email и паролю, создать пациента, создать расчёт ТРГ, загрузить снимок и сохранить результат.
Для анализа можно загрузить DICOM или изображения PNG/JPG. В одной загрузке не стоит смешивать DICOM и PNG/JPG.
Расстановка цефалометрических точек сейчас выполняется вручную врачом на холсте. После расстановки точек FoxRay автоматически рассчитывает метрики. AI-расстановка точек заявлена для будущего тарифа Max и пока находится в статусе «скоро».
Сервис рассчитывает основные ТРГ-метрики, включая SNA, SNB, ANB, Wits, IMPA, FMA и другие показатели. Для линейных измерений в миллиметрах нужна калибровка; без калибровки часть расстояний может отображаться в пикселях.
FoxRay хранит пациентов, расчёты ТРГ, историю результатов и позволяет вернуться к сохранённому кейсу. Каждый пересчёт может сохраняться, чтобы сравнивать измерения в динамике.
PDF-отчёт включает снимок, нанесённые точки и результаты расчёта. На бесплатном тарифе PDF идёт без брендирования клиники. На Pro в PDF можно добавить логотип клиники, название клиники и ФИО врача.
По текущим подтверждённым данным не зафиксированы готовые интеграции с МИС, CRM, PACS, DICOM-сервером или внешними медицинскими системами. Такие вопросы нужно передавать оператору.
По текущим подтверждённым данным не зафиксирована командная работа нескольких врачей в одном аккаунте клиники. Если пользователь спрашивает про общий кабинет, роли, доступы или несколько сотрудников, это нужно уточнять у оператора.
=== foxray-faq ===
Что делает FoxRay? FoxRay помогает выполнить цефалометрический анализ ТРГ онлайн: загрузить снимок, расставить точки, получить расчёты и сформировать PDF-отчёт.
FoxRay сам ставит диагноз? Нет. FoxRay рассчитывает метрики и помогает оформить отчёт, но диагноз, интерпретацию и план лечения определяет врач.
Можно начать бесплатно? Да. Бесплатный тариф позволяет начать без оплаты и работать до 3 пациентов.
Нужны ли платёжные данные для старта? Для начала на бесплатном тарифе платёжные данные не нужны.
Какие форматы снимков поддерживаются? По текущим данным можно загрузить DICOM, PNG или JPG.
Есть ли PDF-отчёты? Да. FoxRay формирует PDF-отчёт со снимком, точками и метриками. На Pro можно добавить логотип клиники, название клиники и ФИО врача.
Что входит в Pro? Pro включает безлимит пациентов, все виды расчётов и отчётов, брендирование PDF и приоритетную поддержку. Цена — 4 900 ₽ в месяц или 47 040 ₽ в год.
Чем Pro отличается от бесплатного тарифа? Главное отличие — нет лимита в 3 пациента, есть брендирование PDF и приоритетная поддержка.
Когда будет AI-расстановка точек? AI-расстановка точек заявлена для тарифа Max, но Max пока в статусе «скоро». Точные сроки лучше уточнить у оператора.
Есть ли интеграции с МИС, CRM или PACS? В подтверждённых данных готовые интеграции не указаны. Такой вопрос нужно передать оператору.
Можно ли оплатить от юрлица или получить документы? Агент не оформляет оплату и документы в чате. Такой вопрос нужно передать оператору.
=== foxray-objections ===
Если пользователь говорит, что дорого, объясни спокойно: бесплатный тариф позволяет проверить сервис без оплаты, а Pro нужен тогда, когда врач регулярно ведёт пациентов, хочет снять лимит, получать брендированные PDF-отчёты и экономить время на рутинных расчётах.
Если пользователь говорит, что привык к другой программе, не спорь. Предложи попробовать FoxRay на бесплатном тарифе и сравнить процесс на реальном или тестовом кейсе: загрузка снимка, расстановка точек, расчёт метрик и PDF.
Если пользователь говорит, что нет времени внедрять новый сервис, подчеркни, что стартовый сценарий простой: зарегистрироваться, создать пациента, загрузить снимок, расставить точки и получить отчёт. Для знакомства не нужно сразу оплачивать Pro.
Если пользователь сомневается в точности, объясни, что точки расставляет сам врач, а сервис автоматически считает метрики по расставленным точкам. FoxRay не заменяет профессиональную оценку и не принимает клинические решения.
Если пользователь ждёт AI-расстановку точек, честно скажи, что эта возможность относится к будущему тарифу Max и пока находится в статусе «скоро». Сейчас рабочий сценарий основан на ручной расстановке точек и автоматическом расчёте.
Если пользователь говорит, что у него мало пациентов, предложи начать с бесплатного тарифа. Pro имеет смысл, когда лимита в 3 пациента становится недостаточно или нужны брендированные отчёты.
Если пользователь переживает за документы, оплату от юрлица, договор или чек, не придумывай условия. Передай вопрос оператору.
=== foxray-limitations ===
FoxRay не ставит диагноз, не назначает лечение и не заменяет врача. Сервис помогает рассчитать метрики и подготовить отчёт, но клинические решения принимает специалист.
В Free есть лимит до 3 пациентов. PDF-отчёты на бесплатном тарифе идут без брендирования клиники.
Брендирование PDF доступно на Pro. Оно включает логотип клиники, название клиники и ФИО врача в отчёте.
AI-расстановка точек пока недоступна в Free и Pro. Она заявлена для будущего тарифа Max, который находится в статусе «скоро».
Расстановка точек в текущем рабочем сценарии выполняется врачом вручную. Автоматический расчёт зависит от корректности выбранных точек и качества исходного снимка.
Для линейных измерений в миллиметрах нужна калибровка. Если калибровки нет или она относится к другому кадру, часть расстояний может отображаться в пикселях, а сравнение с миллиметровыми нормами может быть недоступно.
По подтверждённым данным нет зафиксированных готовых интеграций с МИС, CRM, PACS, DICOM-сервером или внешними медицинскими системами. Такие вопросы нужно уточнять у оператора.
По подтверждённым данным не зафиксированы командные кабинеты, роли сотрудников и совместная работа нескольких врачей в одном аккаунте клиники. Такие вопросы нужно уточнять у оператора.
Агент не проводит оплату, не оформляет заказ, не принимает платёжные данные, не выдаёт скидки и не обещает индивидуальные условия. Для оплаты, документов, счёта, договора и спорных ситуаций нужно передавать пользователя оператору.
+70
View File
@@ -0,0 +1,70 @@
# Edevs AI — контент агента: FoxRay
Задание на контент для агента канала **foxray-sales**. Заполненный результат
(по разделу «Формат ответа») вернёшь — я загружу в систему и протестируем.
## Как устроено (коротко)
Агент отвечает на основе:
- **Промптов** — роль и поведение («компетенции»): `SYSTEM`, `QUALIFICATION`, `SALES_BEHAVIOR`, `OPERATOR_HANDOFF`.
- **Знаний** — база для ответов (retrieval). Категории: `OVERVIEW`, `AUDIENCE`, `COMMERCIAL`, `TECHNICAL`, `FAQ`, `OBJECTIONS`, `LIMITATIONS`.
`inclusion`: `MANDATORY` — всегда в контексте; `RETRIEVAL` — по релевантности вопроса.
**Стиль**: простой текст для мессенджера, по-русски, без markdown (без `#`, `**`, списков `-`, `---`), кратко и по делу. Только реальные факты, без выдумок.
## Зафиксированные факты по FoxRay (используй, не противоречь)
- FoxRay — сервис для **ортодонтов**, распространяется **по подписке**.
- Тарифы:
- **Бесплатный** — до 3 пациентов, базовые расчёты, история; PDF без брендирования.
- **Про** — **₽4 900/мес** или **₽47 040/год**; безлимит пациентов, брендирование клиники, приоритетная поддержка.
- **Макс** — всё из Про + AI-расстановка точек, ранний доступ; статус «скоро».
- Оплата/чек/выдача — в бэкенде продукта. Агент **оплату не проводит**, заказ не оформляет; при готовности к покупке — даёт следующий шаг или передаёт оператору.
> Если каких-то данных не хватает (возможности, интеграции, конкретные FAQ) — отметь places, где нужны уточнения от меня, не выдумывай.
## Что подготовить (11 документов)
### Промпты (канал foxray-sales)
- `system-foxray` — SYSTEM. Кто агент (sales-ассистент FoxRay для ортодонтов, подписка), тон, рамки, что НЕ делает (оплату/заказ не проводит, не обещает вне базы знаний).
- `qualify-foxray` — QUALIFICATION. Какие вопросы задать: размер практики, сколько пациентов ведёт, что важно (брендирование, скорость расчётов, командная работа), пробовал ли аналоги.
- `sales-foxray` — SALES_BEHAVIOR. Как подобрать тариф под ответы (Бесплатный для старта / Про для практики / Макс «скоро»), как мягко довести до старта или покупки, без давления.
- `handoff-foxray` — OPERATOR_HANDOFF. Когда передавать оператору: просьба о человеке, индивидуальные условия/скидка, жалоба/спор, вопрос вне базы знаний.
### Знания (FoxRay)
- `foxray-overview` — OVERVIEW / MANDATORY. Что такое FoxRay, какую задачу ортодонта решает, в чём ценность.
- `foxray-audience` — AUDIENCE / RETRIEVAL. Для кого (типы практик, роли в клинике), кому особенно полезен.
- `foxray-tariffs` — COMMERCIAL / MANDATORY. Подробно Бесплатный/Про/Макс: что входит, цены, мес/год, чем отличаются, кому какой.
- `foxray-technical` — TECHNICAL / RETRIEVAL. Возможности и как устроено: расчёты, PDF/отчёты, брендирование, доступ, интеграции (если есть — иначе пометь, что уточнить).
- `foxray-faq` — FAQ / RETRIEVAL. Частые вопросы и короткие ответы.
- `foxray-objections` — OBJECTIONS / RETRIEVAL. Типичные возражения (дорого, привык к другому, нет времени внедрять) и корректные ответы.
- `foxray-limitations` — LIMITATIONS / RETRIEVAL. Чего FoxRay не делает; ограничения тарифов (например, лимит пациентов на Бесплатном).
## Формат ответа (строго)
Верни **один Markdown-файл**. Каждый документ — секция: строка-разделитель с кодом,
затем с новой строки содержимое:
```
=== code ===
<содержимое простым текстом>
```
Правила:
- `code` — ровно из списка выше (11 штук), ничего не добавлять, не переименовывать, не пропускать.
- Между секциями — пустая строка; содержимое может быть в несколько абзацев.
- Внутри — простой текст, без markdown-разметки.
- Никаких метаданных (категории/scope уже у меня) — только `=== code ===` + текст.
Пример:
```
=== foxray-overview ===
FoxRay — это сервис для ортодонтов, который ...
=== foxray-tariffs ===
У FoxRay три тарифа. Бесплатный — до 3 пациентов ...
Про — 4 900 ₽ в месяц или 47 040 ₽ в год ...
Макс — всё из Про плюс AI-расстановка точек, скоро ...
```
Всего секций: **11** (4 промпта + 7 знаний).