Агенти Bedrock: узагальнення пам’яті, версійовані правила безпеки та база знань.
Керування агентом Bedrock за допомогою Terraform: пам’ять сесії з власним запитом на узагальнення, версійовані правила безпеки з реалізацією моделі detect-then-block та система RAG на основі S3.
Джерела: 6A. Building Chat Agent with AWS Bedrock and Terraform: Summary, Knowledge Base, and Guardrails
Помилки, які не створюють шуму
У системі ШІ-агентів може трапитися багато проблем, і найгірші з них не викликають помилок та не спрацьовують попереджень. Якість поступово погіршується. Пам’ять сесії накопичує «шум» замість корисних сигналів, правила безпеки знаходяться поза системою контролю версій, а агент використовує інструменти для отримання контенту, який може надати безпосередньо база знань.
У Amazon Bedrock існують три рішення цих проблем: надстанова MEMORY_SUMMARIZATION, яка зберігає значущі сигнали користувача між сесіями, версіоновані правила Bedrock Guardrail у Terraform та необов’язкова база знань, яка зберігається у S3.
Інженерія запитів не може вирішити всі проблеми. Справжні системи потребують контролю у трьох аспектах:
- Якість пам’яті сесії. Резюме мають зберігати правильні сигнали користувача.
- Керування безпекою. Правила мають бути чіткими та версіонованими.
Без них система зазвичай виглядає стабільною під час демонстрацій, але потім починає погіршувати свою роботу при надходженні реального, різноманітного трафіку.
Як працює пам’ять сеансу
Узагальнення пам’яті забезпечує доступ до історії користувача з одного сеансу в інший, тож старі повідомлення не потрібно знову отримувати та обробляти в реальному часі. У Classic Agents Bedrock надає базову форму через enabled_memory_types = ["SESSION_SUMMARY"] у об’єкті aws_bedrockagent_agent, а функція GetAgentMemory у середовищі Agent Runtime читає те, що збережено.
З увімкненою пам’яттю робота відбувається асинхронно після закриття сеансу. Bedrock підсумовує завершену розмову, зберігає цей підсумок та вставляє його у наступні сеанси, які мають ту саму memoryId, при цьому не затримуючи відповідь користувача.
Bedrock постачає стандартний запит, який визначає спосіб функціонування підсумовування:
{
"messages": [
{
"role" : "user",
"content" : "We will be given a conversation between a user and an AI
assistant.
When available, in order to have more context, we will also be given
summaries we previously generated.
Our goal is to summarize the input conversation.
When we generate summaries we ALWAYS follow the below guidelines:
<guidelines>
- Each summary MUST be formatted in XML format.
- Each summary must contain at least the following topics: 'user
goals', 'assistant actions'.
- Each summary, whenever applicable, MUST cover every topic and be
placed between <topic name='$TOPIC_NAME'></topic>.
- We ALWAYS output all applicable topics within <summary></summary>
- If nothing about a topic is mentioned, DO NOT produce a summary
for that topic.
- We summarize in <topic name='user goals'></topic> ONLY what is
related to the user, e.g., user goals.
- We summarize in <topic name='assistant actions'></topic> ONLY what
is related to the assistant, e.g., assistant actions.
- NEVER start with phrases like 'Here's the summary...', provide
directly the summary in the format described below.
</guidelines>The XML format of each summary is as follows:
<summary>
<topic name='$TOPIC_NAME'>
...
</topic>
...
</summary>
Here is the list of summaries we previously generated.
<previous_summaries>
$past_conversation_summary$
</previous_summaries>
And here is the current conversation session between a user and an AI
assistant:
<conversation>
$conversation$
</conversation>
Please summarize the input conversation following the above guidelines
plus the below additional guidelines:
<additional_guidelines>
- ALWAYS strictly follow the above XML schema and ALWAYS generate
well-formatted XML.
- NEVER forget any detail from the input conversation.
- We also ALWAYS follow the below special guidelines for some of the topics.
<special_guidelines>
<user_goals>
- We ALWAYS report in <topic name='user goals'></topic> all details the user
provided in formulating their request.
</user_goals>
<assistant_actions>
- We ALWAYS report in <topic name='assistant actions'></topic> all details
about actions taken by the assistant, e.g., parameters used to invoke actions.
</assistant_actions>
</special_guidelines>
</additional_guidelines>"
}
]
}
Його інструкції знаходяться переважно у розділі <guidelines/>, де агенту вказується повертати свій результат усередині тега <summary/>. Резюме розділене за темами. Усе, що стосується цілей користувача, розміщується під темою user goals, власні дії агента — під assistant actions, причому кожна тема оформлена за допомогою обгортки <topic name='$TOPIC_NAME'></topic>. Очікуваний вихід виглядає так:
<summary>
<topic name='$TOPIC_NAME'>
...
</topic>
...
</summary>
Bedrock заповнює <previous_summaries/> попередніми резюме за допомогою змінної $past_conversation_summary$, а поточна розмова відображається всередині <conversation>$conversationlt;/conversation>. Ще два розділи, <additional_guidelines/> та <special_guidelines/>, дозволяють додати деталі до стратегії створення резюме.
Життєвий цикл виглядає так:
- Функція пам’яті увімкнута в конфігурації агента за допомогою
memory_configurationтаenabled_memory_types = ["SESSION_SUMMARY"]. - Користувач викликає агента, вказуючи стабільний
memoryIdдля кожного користувача. - Сесія закінчується або через
endSession = true, або через таймаут. - Bedrock генерує резюме на фоні.
memoryId Bedrock поміщає контекст пам’яті у місця для оркестрації, такі як $memory_content$.Це має дві наслідки. Підсумки не створюються миттєво та можуть з’явитися через деякий час після закриття сеансу. Крім того, якщо memoryId змінюється від запиту до запиту, безперервність зникає.
Попередження: Нестабільні значення
memoryId, такі як ідентифікатори з’єднань, до яких належать ідентифікатори користувачів, порушують безперервність пам’яті. Використовуйте ідентифікатор, який залишається незмінним для кожного користувача чи елемента розмови.
Роблення підсумків корисними
Стандартний підсумок — це загальний огляд. Це підходить для універсальних асистентів, але часто є занадто перевантаженим для спеціалізованих. Для невеликого новинного асистента корисним буде підсумок, який включає:
- постійні теми, такі як новини про ШІ, клімат чи геополітика;
Без такої структури обсяг пам’яті зростає, тоді як релевантність знижується.
Щоб її активувати, спочатку потрібно використати ресурс agent у Terraform:
resource "aws_bedrockagent_agent" "agent" {
# ... existing code above ...
memory_configuration {
enabled_memory_types = ["SESSION_SUMMARY"]
storage_days = 30
session_summary_configuration {
max_recent_sessions = 5
}
}
# ... existing code below ...
}
Агенти Bedrock приймають тут лише тип SESSION_SUMMARY. AgentCore пропонує більше: підсумки, переваги користувача, семантичні факти та власні стратегії зберігання інформації. Параметр storage_days визначає термін зберігання підсумків, а max_recent_sessions — кількість нещодавніх сеансів, які будуть підсумовані.
Кожен виклик має містити memoryId, у цьому випадку user_id, щоб розмови були прив’язані до однієї й тієї самої особи:
# Invoke with stable memoryId and explicit session end
resp = bedrock_agent_runtime.invoke_agent(
agentId=agent_id,
agentAliasId=alias_id,
sessionId=conversation_id,
memoryId=user_id, # stable per user
inputText=message_text,
endSession=is_last_turn
)
Для отримання даних використовується той самий memoryId:
# Retrieve summaries later (classic Agents API)
memory = bedrock_agent_runtime.get_agent_memory(
agentId=agent_id,
agentAliasId=alias_id,
memoryId=user_id,
memoryType="SESSION_SUMMARY"
)
Перевизначення запиту на стиснення
З увімкненою пам’яттю Bedrock дозволяє запиту на перевизначення замінити етап MEMORY_SUMMARIZATION: prompt_type = „MEMORY_SUMMARIZATION“ на prompt_creation_mode = „OVERRIDDEN“. Класичні агенти використовують два спеціальні місця підстановки: $past_conversation_summary$ для збережених резюме, пов’язаних із тією самою ідентичністю пам’яті, та $conversation$ для тексту поточної сесії. У шаблонах оркестрації контекст пам’яті передається через $memory_guideline$ для стратегії, $memory_content$ для збереження та $memory_action_guideline$ для системних запитів.
Спеціальна версія стандартного запиту чітко вказує, що агент має зафіксувати та що ігнорувати, щоб залишилися лише корисні деталі:
prompt_override_configuration {
prompt_configurations = [{
prompt_type = "MEMORY_SUMMARIZATION"
prompt_state = "ENABLED"
prompt_creation_mode = "OVERRIDDEN"
parser_mode = "DEFAULT"
base_prompt_template = <<-JSON
{
"system": "
We are summarizing a news research conversation for future sessions.
Capture:
- recurring topics,
- region focus,
- entities and stories the user tracks,
- explicit dislikes.
Ignore:
- greetings and small talk,
- implementation questions about the assistant itself.
Past summaries:
<previous_summaries>
$past_conversation_summary$
</previous_summaries>
Current session:
<conversation>
$conversation$
</conversation>
Return concise bullet points focused on user signal.",
"messages": [
{
"role": "user",
"content": [{ "text": "Generate a focused memory summary for personalization." }]
}
]
}
JSON
inference_configuration = [{
temperature = 0.2
top_k = 64
top_p = 0.9
max_length = 512
stop_sequences = []
}]
# ... existing code below ...
}
]
}
Перевизначте етап, коли загальний огляд не покращує подальші відповіді, коли підсумки потребують високого співвідношення сигнал/шум, або коли бюджет токенів пам’яті має залишатися обмеженим та прогнозованим. Якщо асистент є загальним та не ґрунтується на персоналізації, стандартний варіант підходить.
Типові помилки включають:
- нестабільні значення
memoryId, знову ж таки, наприклад, використання ідентифікаторів з’єднань замість ідентифікаторів користувачів; - сесії, які ніколи не закінчуються, тому підсумок так і не створюється;
- довгі запити на підсумок, які відтворюють практично повний текст розмови;
- змішування цілей підсумку з цілями форматування, призначеними для подальшої обробки.
Обмеження: правила, яких запити не можуть нав’язати
Іноді користувачі поводяться грубо, зловживають агентом або запитують про внутрішні деталі, секрети та особисті дані інших людей. Механізми контролю допомагають вирішувати ці проблеми. Принцип простий: запити спрямовують поведінку, а механізми контролю забезпечують дотримання правил. Використовуйте запити для прийняття рішень та форматування, а механізми контролю — для обмежень щодо безпеки контенту як у вхідних даних користувачів, так і у вихідних даних асистента.
Порада: Спробуйте використати механізми контролю у режимі DETECT перед тим, як використати режим BLOCK. Перевірка того, що могло б бути заблоковано, не впливає на тестувальників.
Bedrock містить кілька функцій контролю, які не вимагають додаткової налаштування, окрім їх додавання до списку:
- Фільтри контенту перешкоджають ненависті, образам, насильству, сексуальному контенту, неналежній поведінці та атакам через запити, маючи налаштування для вхідних та вихідних даних та відповідні дії. Вони ідеально підходять для постійного забезпечення базової безпеки для звичайного трафіку користувачів.
Більшість команд ефективніше впроваджують ці засоби поетапно: спочатку фільтри контенту та конфіденційної інформації, потім фільтри тем та слів, а вже після цього механізми обґрунтування та міркувань, коли політики пошуку стануть більш досконалими.
Порядок оцінки
Механізми контролю перевіряють обидві сторони:
- Вхідні дані. Спочатку оцінюється запит від користувача, причому всі налаштовані політики працюють паралельно. Якщо додано блок, Bedrock повертає значення
blocked_input_messagingта пропускає процес інференції. - Вихідні дані. Якщо вхідні дані пройшли перевірку, модель надає відповідь, яка потім перевіряється. Блок може замінити відповідь на
blocked_outputs_messagingабо заслонити її у випадках, коли налаштовані фільтри конфіденційності.
Порядок має значення для вартості. Блокований вхід коштує лише за оцінку захисних механізмів, а не за обробку моделлю.
Кожен фільтр контенту має два незалежні налаштування. Інтенсивність (inputStrength та outputStrength) може бути NONE, LOW, MEDIUM або HIGH та визначає, наскільки ретельно виявляються порушення. Дія (inputAction та outputAction) може бути BLOCK, що блокує контент та замінює його на спеціальне повідомлення, або NONE, що нічого не робить, а лише фіксує виявлення у записах відповідей, що фактично є режимом лише виявлення.
Розумна стандартна стратегія:
- для категорій високого ризику, таких як ненависть, насильство та неправомірна поведінка, починайте з
MEDIUMяк для вхідних, так і для вихідних даних; - під час тестування або на стадії попереднього використання починайте з
outputAction = „NONE“, щоб можна було підрахувати хибні позитивні результати; - переходьте на
BLOCKлише після того, як результати аналізу та тестових наборів стануть прийнятними; - категорії низького ризику залишайте на рівні
LOWабоMEDIUM, і не встановлюйте все на рівеньHIGHз самого початку.
Фільтри контенту також мають два рівні захисту. CLASSIC — це базовий фільтрування, тоді як STANDARD забезпечує сильніший захист завдяки аналізу кодової сфери та підтримці категорій атак типу prompt-attack. Асистент, який обробляє запити у стилі розробників, фрагменти коду чи змішаний текст та код, зазвичай є безпечнішим у режимі Standard.
Версіонування
Випуски захисних механізмів мають бути чіткими та незмінними, а кожна зміна політики має ставати новою версією. aws_bedrock_guardrail_version підтримує це: створюється версія, яка приєднується до aws_bedrock_guardrail через guardrail_configuration.
resource "aws_bedrock_guardrail" "guardrail" {
name = "${var.environment}-news-guardrail"
description = "Safety policies for news assistant"
blocked_input_messaging = "Your request violates our usage policy."
blocked_outputs_messaging = "This response was blocked by our safety policy."
content_policy_config {
filters_config {
type = "HATE"
input_strength = "MEDIUM"
output_strength = "MEDIUM"
}
filters_config {
type = "VIOLENCE"
input_strength = "MEDIUM"
output_strength = "MEDIUM"
}
filters_config {
type = "MISCONDUCT"
input_strength = "MEDIUM"
output_strength = "MEDIUM"
}
}
}
resource "aws_bedrock_guardrail_version" "guardrail_version" {
guardrail_arn = aws_bedrock_guardrail.guardrail.guardrail_arn
description = "release-${substr(sha256(var.guardrail_policy_fingerprint), 0, 12)}"
skip_destroy = true
}
resource "aws_bedrockagent_agent" "news_agent" {
# ... instruction, model, prompt overrides ...
guardrail_configuration {
guardrail_identifier = aws_bedrock_guardrail.guardrail.guardrail_id
guardrail_version = aws_bedrock_guardrail_version.guardrail_version.version
}
# ... existing code below ...
}
Це розділення дозволяє здійснити чисте скасування змін. Попередження залишаються без змін, і лише версія з захисними механізмами змінюється, коли потрібна налаштування політики.
База знань для внутрішнього контенту
Припустимо, що агент має відповідати на запитання, спираючись на корпоративні правила чи знання, накопичені з часом, та уникати непотрібних викликів інструментів. Bedrock використовує приєднану базу знань для генерації відповідей на основі отриманих документів; вона увімкнена за замовчуванням після її налаштування. Це дозволяє агентам безпечно підключатися до приватних корпоративних даних, щоб моделі могли надавати більш релевантні, точні та індивідуалізовані відповіді за допомогою технології Retrieval Augmented Generation (RAG).
Цей підхід підходить, коли джерелом інформації є внутрішні чи ретельно підготовлені документи, коли не потрібна миттєва актуальність інформації, або коли необхідні обґрунтовані відповіді з можливістю відстеження джерела, схожою на цитування.
Примітка: Інформація, яка оновлюється в реальному часі та індексується ззовні, краще оброблятися за допомогою інструментів API.
Bedrock Knowledge Base функціонує як керований потік RAG для вашого власного контенту. Замість того, щоб самостійно створювати інфраструктуру пошуку, ви дозволяєте Bedrock отримувати дані з підключення, аналізувати та розділяти документи на частини, створювати ембеддинги, зберігати вектори у підтримуваному сховищі та отримувати відповідні частини при надходженні запиту. Під час KNOWLEDGE_BASE_RESPONSE_GENERATION ці частини використовуються для формування обґрунтованих відповідей.
У процесі беруть участь два етапи. Завантаження даних відбувається офлайн або під час синхронізації: документи аналізуються, розділяються на частини згідно з визначеною стратегією, перетворюються на вектори за допомогою моделі ембеддингу та зберігаються у векторному індексі разом із мапуванням метаданих. Отримання даних під час роботи відбувається за кожним запитом: запит ембеддюється, сховище векторів повертає семантично релевантні частини, Bedrock додає їх до контексту моделі, а на етапі генерації створюється відповідний результат, або ж у режимі лише отримання даних повертаються результати пошуку.
Розділення на частини має практичне значення, оскільки низька якість отримання даних часто є наслідком проблем із завантаженням або формуванням частин, а не проблем із самим запитом.
Нічого не „вставляється як рядок“, як у SQL-кумуляторі. Ви додаєте або оновлюєте файли чи джерела, підтримувані коннектором, а потім запускаєте синхронізацію.
Попередження: Синхронізація не відбувається автоматично. Після додавання документів до S3 її потрібно явно ініціювати, перш ніж агент зможе їх отримати.
Керування під час виконання
numberOfResultsвизначає кількість повернених джерельних фрагментів (за замовчуванням до 5, діапазон від 1 до 100).overrideSearchTypeдозволяє обратиSEMANTICдля пошуку лише за векторами абоHYBRIDдля пошуку за векторами та текстом у необробленому вигляді; підтримується лише у сумісних сховищах та індексах. Якщо цей параметр не встановлений, Bedrock робить вибір сам.- Метадані
filterта логічні групи (andAll,orAll) дозволяють здійснювати точний пошук. - Необов’язкова переранжування покращує кінцевий порядок фрагментів.
За допомогою ієрархічного розділення на фрагменти кількість результатів може бути меншою, ніж запитано, оскільки дочірні фрагменти можуть бути замінені їхніми батьківськими під час формування відповіді.
Чанкування
Чанкування суттєво впливає на якість пошуку. Bedrock пропонує стандартне чанкування приблизно на 300 токенів за межами речень, чанкування фіксованого розміру з чітко визначеним розміром токенів та ступенем перекриття, ієрархічні батьківські та дочірні чанки для підвищеної точності та більш широкого контексту, семантичне чанкування з межами, визначеними моделлю, а також варіант без чанкування, при якому кожен документ розглядається як один чанк, що переважно підходить для вже розділених на частини контентів.
Розумний підхід: почніть зі стандартного або фіксованого чанкування, оскільки воно просте. Перейдіть на ієрархічне чанкування, коли відповідям знадобиться більше навколишнього контексту, та на семантичне — якщо точність залишатиметься низькою після налаштування запиту. Порівнюйте результати з набором даних для оцінки пошуку до та після кожної зміни.
Бази даних векторів
Бази знань працюють з кількома векторними серверами-підтримкою, такими як OpenSearch Serverless або керований кластер, сумісний з Aurora PostgreSQL, Pinecone, Redis Enterprise Cloud, MongoDB Atlas та Neptune Analytics, залежно від підтримки постачальника на момент розгортання. Вибір впливає на наявність ГІБРИДного пошуку, наявність фільтрів метаданих, а також на складність експлуатації та витрати. OpenSearch Serverless зазвичай дозволяє найшвидше розпочати роботу. Нижче наведено приклад налаштування за допомогою Terraform:
resource "aws_bedrockagent_knowledge_base" "news_kb" {
name = "${var.environment}-news-kb"
role_arn = aws_iam_role.bedrock_execution_role.arn
knowledge_base_configuration {
type = "VECTOR"
vector_knowledge_base_configuration {
embedding_model_arn = "arn:aws:bedrock:${data.aws_region.current.name}::foundation-model/amazon.titan-embed-text-v2:0"
}
}
storage_configuration {
type = "OPENSEARCH_SERVERLESS"
opensearch_serverless_configuration {
collection_arn = aws_opensearchserverless_collection.kb.arn
vector_index_name = "news-kb-index"
field_mapping {
vector_field = "vector"
text_field = "text"
metadata_field = "metadata"
}
}
}
# ... existing code below ...
}
resource "aws_bedrockagent_data_source" "news_docs" {
knowledge_base_id = aws_bedrockagent_knowledge_base.news_kb.id
name = "${var.environment}-news-docs"
data_source_configuration {
type = "S3"
s3_configuration {
bucket_arn = aws_s3_bucket.news_docs.arn
}
}
# ... existing code below ...
}
resource "aws_bedrockagent_agent_knowledge_base_association" "news_agent_kb" {
agent_id = aws_bedrockagent_agent.agent[0].agent_id
agent_version = "DRAFT"
knowledge_base_id = aws_bedrockagent_knowledge_base.news_kb.id
description = "Internal news assistant knowledge base for curated context and editorial guidelines"
knowledge_base_state = "ENABLED"
# ... existing code below ...
}
Маршрутизація між базою знань та інструментами
Використання бази знань надає агенту другий шлях для пошуку інформації. Щоб уникнути неоднозначностей, вкажіть правила маршрутизації для бази знань та API-інструменту у інструкціях до оркестрації, збережіть контракт POST_PROCESSING незмінним незалежно від того, яке джерело надало відповідь, та вказуйте, коли агенту слід ставити уточнювальні запитання через низький рівень впевненості у результаті пошуку.
Практична стратегія для такої налаштовки: використовуйте базу знань для внутрішнього, статичного контексту — такого як документи з правилами, стандарти редагування та історичні примітки; використовуйте групу дій для актуальних зовнішніх даних; та не викликайте обидва джерела одночасно, якщо лише запит справді не вимагає перевірки з кількох джерел.
Механізми контролю також застосовуються під час операцій пошуку та генерації, що має велике значення, оскільки сам по собі метод обґрунтованого пошуку не усуває ризиків для безпеки. Поширеною рекомендацією є спочатку оцінити шлях до бази знань із використанням механізмів контролю у режимі виявлення, налаштувати показники хибних позитивів та негативів на основі отриманих даних, а потім перейти до блокування чи маскування у режимі продакшну.
Отримання контенту
- Початковий корпус даних: для одноразового завантаження політик, часто ставлених запитань та посібників зі стилю — завантажте файли у бакет S3, підключений до джерела даних, та розпочніть синхронізацію.
- Постійні оновлення: коли текст продукту чи юридичних документів змінюється за певним графіком, щоденна задача може завантажувати нові файли у S3 та ініціювати виконання функції
StartIngestionJobдля джерела даних, або використовувати автоматичну синхронізацію, якщо вона увімкнена.
kb/topics/eu-ai-act-overview.md, щоб межі частин відповідали темам, а посилання були зрозумілішими, ніж у одному величезному PDF.StartIngestionJob, щоб база знань отримала нові об’єкти.Підводні камені
- Розглядати базу знань як потік даних у реальному часі. Вона є настільки актуальною, наскільки це дозволяє графік синхронізації.
- Надмірне або недостатнє розділення на частини, що погіршує точність.
- Недбалі метадані, через які фільтри втрачають ефективність.
- Об’єднання завдань зі збору та форматування інформації у один етап запиту.
- Впевненість у тому, що зміна формулювання запитів може врятувати слабкий індекс пошуку.
Який це має результат
Анотації працюють найкраще, коли вони адаптовані до конкретної галузі, а не залишаються як загальні узагальнення. Запити та правила функціонують на різних рівнях, тому їх потрібно версіонувати окремо. База знань є лише одним із варіантів пошуку та не замінює API в реальному часі, тож у запитах слід чітко вказувати, коли інструмент забезпечує актуальні дані, а коли база знань надає підготовлений контекст.
Разом ці елементи утворюють внутрішню систему агента: запит MEMORY_SUMMARIZATION, який стискає довгі розмови у повторно використовувані резюме, механізм Bedrock Guardrail, що блокує категорії шкідливого контенту, та база знань на джерелі даних S3 для генерації з підтримкою пошуку.