Еволюція ботів з ШІ: використовуємо можливості агентів, моделей RAG і LLM
Вітаю, мене звати Демʼєн. Ця стаття є продуктом мого власного дослідження та синтезу знань про різноманітні інструменти для розробки ШІ-ботів. Вона слугує особистим довідником і має на меті описати шаблони високого рівня, конвеєри та архітектурні рішення, які широко використовуються у 2024 році.
Стаття розроблена, щоб збалансувати загальний технічний рівень, підходить для новачків у цій темі, одночасно заглиблюючись у теорію та надаючи реальні приклади та інструменти без необхідності стрибати в програмування. Цей структурований набір власних нотаток має бути достатньо вичерпним для технічно підкованих людей, які або не знайомі з предметом, або мають фрагментарні знання. Заздалегідь перепрошую за ламану мову, оскільки живу майже 10 років у Штатах.
Наразі у розробників є потужні інструменти для створення інтелектуальних ШІ-застосунків, включно з великими мовними моделями (LLM), конвеєрами (Pipelines) RAG, агентами та дизайнами ReAct. У цьому посібнику описано процес роботи з цими інструментами та підходами для створення ботів ШІ, які підвищують якість відповіді, одночасно зменшуючи витрати.
Нижче надані URL-посилання на додаткові ресурси; однак прошу проігнорувати їх під час першого читання, щоб зосередити вашу увагу. Вся необхідна інформація міститься в цій статті, тому наразі нема потреби відкривати ці посилання 😉.
Я пропоную розділити розробку ШІ загального призначення на дві основні частини:
- навчання моделі — створення нової або модифікація вже наявної;
- використання моделей — саме тут буде зосереджено основну увагу цієї статті, оскільки багато чого ми можемо зробити в цьому напрямку.
Навчання LLM: аналіз фінансової доцільності
Навчання нових LLM з нуля складне та дороге. Натомість ви можете досягти кращих результатів, розробляючи застосунки, які використовують дійсні моделі General-Pre-trained-Transformers (GPT) без їх модифікації. Цей підхід часто є економічно ефективнішим і усуває обмеження традиційних LLM, як-от обробка складної математики, останніх новин, комерційних даних або нових знань, які ще не були включені в модель, — ось тут на допомогу приходить RAG, але про це трохи пізніше.
Оптимізація надання додаткового контексту може ще більше зменшити витрати, і в цій статті досліджуватимуться шаблони для розробки застосунків, які ефективно використовують моделі LLM. Дотримуючись цих стратегій, ви можете покращити результати без необхідності тонкого налаштування чи навчання нових моделей.
Навчання маленьких моделей і використання загальних моделей, тонке налаштування
Перш ніж відкидати цей варіант як занадто складний і дорогий, дослідімо його на високому рівні. Створення ШІ-застосунку починається з вибору моделі. Ви можете розробити модель з нуля або використати вже наявні.
Щоб краще зрозуміти це, візуалізуйте графік нейронної мережі. Уявіть невелику нейронну мережу з вертикально вирівняними вузлами (колами): три зелені вузли ліворуч (вхідний шар), три набори з чотирьох синіх вузлів посередині (приховані шари) і два жовті вузли праворуч (вихідний шар). Ці вертикально вирівняні вузли називаються шарами. Сучасні LLM, на відміну від цього простого прикладу із пʼятьма шарами, мають значно більше вузлів, з’єднань і шарів.
Граф нейронної мережі з 5 шарами: один вхід ліворуч, 3 посередині та один вихід праворуч.
Машинне навчання (ML) і LLM працюють через низку рівнів і зв’язків. Значення у вхідному шарі впливають на наступний шар, доки останній прихований шар не створить результат. Приховані шари — саме тут відбувається велика частина «магії» — є найскладнішою та найменш зрозумілою частиною нейронних мереж.
Хоча ми можемо осягнути невеликі нейронні мережі, мільярди параметрів у великих моделях поза нашими можливостями. Ця складність створює «Вау-момент», коли, наприклад, зображення однієї літери, розбитого на менші фрагменти, обробляється моделлю для точної ідентифікації літери. Ми знаємо методи та інструменти для налаштування та маніпулювання цими прихованими шарами, тестування та вдосконалення моделі для покращення результатів.
Попри можливість відстеження активованих вузлів і з’єднань, процес дуже часто не має сенсу для людини, чому саме нейронна мережа та її активовані з’єднання з заданими налаштуваннями та «відбиток» активованих вузлів під час введення повертає, наприклад, «це кіт». Ми можемо бачити активовані вузли, з’єднання та їхні значення, але незрозуміло, чому цей «відбиток» дорівнює результату «це кіт».
Проте ми знаємо, що це працює. Наші поточні методи та інструменти дозволяють нам досягати виняткових результатів, навіть якщо основні процеси все ще є дещо таємничими.
Ви можете розробити невеликі спеціалізовані моделі для конкретних завдань, використовуючи загальні моделі як обгортки для виконання різних функцій. Тонке налаштування наявних моделей часто набагато дешевше, ніж навчання нових моделей з нуля. Попередньо навчені великі моделі забезпечують набагато кращу відправну точку майже для будь-якої проблеми машинного навчання порівняно з навчанням та ініціалізацією нової моделі. Цей підхід відомий як трансферне навчання.
Існують різні способи тонкого налаштування, залежно від того, чи хочете ви налаштувати модель Embeddings або «велику» модель Chat LLM. Для менших моделей, таких як Embeddings, цей процес недорогий. Однак для тонкого налаштування великих моделей із мільярдами параметрів потрібне спеціальне обладнання, яке може бути дуже затратним.
Щоб зменшити витрати, було розроблено кілька методів тонкого налаштування. Перший — «заморозити» модифікацію деяких вузлів та змінювати лише частку що не заморожена. І ще більш економічно ефективнішою є адаптація низького рангу (LoRA). Замість того, щоб змінювати всі або частину мільярдів параметрів, LoRA додає новий рівень до нейронної мережі. Альтернативи LoRA включають GaLore і DoRA.
Напрямки розробки та вдосконалення моделей
Розробку та вдосконалення LLM можна розділити на дві основні категорії:
- Масштабування: характеризується збільшенням кількості параметрів, розширенням місця для зберігання даних, інвестицій в більш потужне обладнання та більшими витратами.
- Підвищення якості: більш ефективне використання тих самих ресурсів шляхом реалізації кращих алгоритмів, більш розумної обробки навчальних даних і використання спеціалізованого, економічного апаратного забезпечення для кращої продуктивності.
Зрештою, ці підходи об’єднаються для оптимізації розробки моделі та результатів.
Типи моделей
Більшість моделей було розроблено з вузьким фокусом на тексті, зображеннях, аудіо чи відео. Спочатку текстові моделі могли обробляти лише одну, на приклад англійську мову, а моделі зображень могли надавати лише текстові описи до наданих зображень, та не могли на приклад генерувати зображення або навпаки.
Проте, зростає тенденція до об’єднання цих можливостей. Зараз багато текстових моделей підтримують кілька мов, включаючи мови програмування. Крім того, деякі моделі можуть одночасно працювати з текстом і зображеннями як на вхід (Decoding), так і на вихід (Encoding), це відомо як мультимодальні моделі.
Важливою новинкою, яку починають набувати моделі, є «Виклик функцій». Ця можливість змушує модель відповідати передбачуваним і строго відформатованим способом, дотримуючись попередньо визначених правил.
Наприклад, якщо попросити створити правильним форматом JSON, модель відповідатиме тільки так. Ця можливість покращує інтеграцію LLM з наявними застосунками, дозволяючи їм діяти як замінники людської логіки прийняття рішень для автоматизації та виклику різних функцій усередині додатка.
Loss Function
Під час тонкого налаштування моделі першим кроком є оцінка її продуктивності. Loss function або функція помилок вимірює, наскільки добре ваша модель повертає очікуваний результат. Він кількісно визначає різницю між прогнозованими результатами моделі та фактичними результатами.
Loss function загалом поділяється на два типи: класифікація та регресія.
Створення та налагодження нових моделей — це ще одна тема для обговорення, яка потребує зовсім інших навичок та інструментів аніж використання моделі. Попри те, що в цьому розділі наведено загальний огляд, ця стаття не буде зосереджена на тонкому налаштуванні моделей або створення нових моделей. Натомість ми досліджуватимемо, як працювати з наявними моделями, створюючи застосунки-обгортки навколо них, щоб підвищити якість без модифікації моделей.
Еволюція: v1.0
Технології розробки ботів ШІ, дизайни та архітектури швидко розвиваються, збільшуючи абстракцію в маніпулюванні даними та покращуючи якість результатів. Цей прогрес веде до більш схожих на якість людської відповіді та навіть краще.
Першим великим кроком стала розробка великих мовних моделей (LLM). Другий крок це створення застосунків Retrieval-Augmented Generation (RAG) навколо LLM для покращення відповідей шляхом додавання релевантної інформації як контекст, таким чином усуваючи слабкі сторони LLM за допомогою різних функцій та інструментів. Третій крок — це розширення RAG до Агентів, які можуть взаємодіяти з реальним світом і виконувати завдання за допомогою інструментів, а не просто відповідати на запитання в чаті.
На кожному з цих кроків існує гнучкість у тім, як саме створено ваш застосунок, що дозволяє експериментувати, та адаптувати його до задачі. Для спрощення я називатиму ці кроки версіями v1.0, v2.0, v2.5, v3.0 і v3.5. Хоча це не є офіційною термінологією, проте допоможе впорядкувати інформацію та структурувати цю статтю.
Inference: двигун, здатний запускати вашу модель що генерує результат. Не плутати із RAG-застосунком.
Serve: процес надання Inference як сервіса через API endpoint за протоколом HTTP.
Модель LLM: сприймайте це як папугу, здатного повторювати слова, переставляти їх або навіть відповідати на запитання. Це алгоритм нейронної мережі, який зберігається у вигляді файлу та виконується механізмом Inference. Коли модель виконується з вводом від користувача, вона може відповідати відповідним чином. LLM відрізняються своєю здатністю розуміння та генерування мови, отриманої шляхом вивчення статистичних зв’язків із документів під час навчального процесу.
RAG-застосунок — код, написаний найчастіше на python чи node.js. Він буде звертатись до inference-двигуна за допомогою API.
RAG: використання інструментів v2.0
LLM часто «галюцинують», дають неточні відповіді або просто чогось не знають. Ось чому було винайдено Retrieve Augment Generate (RAG) Pipeline: щоб направляти, перевіряти та вводити нову інформацію як контекст, що дозволяє досягти кращих результатів.
RAG можна називати «підхід», «методика», «Pipeline» або «шаблон», хоча я обмежусь термінами «RAG-застосунок» або «RAG-конвеєр», які буду використовувати як синоніми в цій статті. Якщо вам потрібно вставити посилання на оригінальні документи, LLM не здатна цього зробити, наприклад, подивіться на Bing/Copilot RAG, який не лише відповідає на ваше запитання, але й надає URL-посилання на документи, які він використав для створення кінцевої відповіді. LLM не знають комерційної інформації, останніх новин, знань, які не були включені в модель під час навчання. Ці недоліки можна виправити із допомогою RAG.
Цей шматок створений під впливом статті Олексія Гончара.
На зображенні вище ви можете побачити простий застосунок на основі RAG, який приймає запит користувача, витягує додатковий контекст, який має відношення до запиту, і передає LLM.
Вся суть конвеєра RAG полягає в тому, щоб досягнути маленьких, навіть крихітних покращень та накопичити їх якомога більше. Варто враховувати та перевіряти кожну дрібницю, яка покращує результат. Це ідея RAG. У 2024 році
LLM-моделі, як правило, краще відповідають на спрощені запитання та коли мають додатковий контекст для початкового запиту від користувача. І так, мабуть, буде ще протягом тривалого часу, якщо не завжди. RAG — це підхід, що постійно розвивається, і націлений на покращення якості застосунку, що використовує штучний інтелект, який маніпулює моделями, як останній крок поліруючи вихідний результат.
RAG може аугментувати LLM за допомогою:
- отримання релевантної інформації із зовнішніх джерел і збагачення контексту, наданого моделі, покращує відповідь, використовуючи наявні моделі без необхідності їхньої модифікації;
- використання шаблонів тексту з інструкцією чи підказкою примушують модель розкласти складні запити користувача на менші підзадачі.
LangChain: поєднання розробки та продуктиву, обробка даних
LangChain-фреймворк полегшує розробку, усуваючи необхідність запускати ресурсомісткі екземпляри баз даних, дозволяючи працювати безпосередньо з файлами бази даних. Виробничі середовища повинні використовувати запущені виділені застосунки бази даних, які взаємодіють через API з IP-адресою екземпляра БД, а не працюють безпосередньо з файлами бази даних. LangChain може генерувати та читати файли бази даних для розробки. У той час, як для виробництва ідеально використовувати повноцінний екземпляр бази даних. Звісно ж, у LangChain набагато більше застосувань.
Типи даних
Щоб додавати в контекст LLM за допомогою RAG релевантну корисну до запиту інформацію, вам доведеться по-різному опрацьовувати різні типи даних, по-різному їх зберігати та використовувати різні інструменти. Існує багато типів даних. Спочатку розберімось, які існують типи даних, а потім з інструментами, якими можна користуватись.
Високорівнево дані можуть бути: структуровані, неструктуровані та напівструктуровані. Попри те, що назва «Структурований» може здатися зрозумілою, вона не означає загального чи людського розуміння структури. Наприклад, файл TXT із книгою, яка добре відформатована з ідеальною структурою, вмістом або індексом сторінок і розділів ідеально форматування та з пронумерованими сторінками та чудовою граматикою і простотою розуміння для людини, цей файл НЕ є прикладом структурованих даних. У світі ІТ, з комп’ютерного погляду термін структурованих даних має дуже точне та конкретне значення.
Структуровані дані в ІТ означають табличний вигляд тексту, цей тип даних має принаймні одну таблицю із записами (рядками) і полями (стовпцями). Таблиця має відповідати певній схемі, тобто стовпці мають містити дані одного типу, а не просто випадковий текст, що зберігається в таблиці, наприклад, у стовпці із заголовком «Чистий дохід» кожен рядок має містити цифру, а не смайлик усміхненого обличчя. Приклади:
- таблиці (наприклад, XLSX, CSV, Google Sheets, LibreOffice Calc);
- реляційні бази даних такі як MySQL та PostgreSQL (SQL);
- бази даних ключ-значення, такі як Redis (велика одна таблиця з кількома стовпцями);
- якщо БД містить, скажімо, дані у форматі JSON, то ці дані є напівструктурованими. Якщо вона містить фрагменти тексту, то сам текст є неструктурованими даними.
Неструктуровані дані у світі ІТ також є дуже специфічним типом, наприклад: текстові документи та мультимедіа. Тобто, TXT-файли відносять до неструктурованих даних.
Текстові дані:
- текстові документи (наприклад, DOCX, RTF, TXT, ePub тощо);
- PDF-файли;
- файли HTML/вебсторінок.
Мультимедіа:
- зображення (наприклад, JPEG, PNG);
- аудіо, голос (наприклад, MP3, WAV);
- відео (наприклад, MP4, AVI).
Напівструктуровані дані:
- електронні листи мають певну структуру: заголовки, текст і вкладення;
- те саме з файлами JSON, XML і YAML;
- бази даних NoSQL: MongoDB (MQL), Cassandra (CQL), Neo4j (Cypher), Nebula (GQL, Cypher).
RAG і типи даних
Розуміння різноманітних типів даних і того, як вони зберігаються, визначатиме, як ваш RAG додаток може отримувати цю інформацію та як вона надаватиметься вашим моделям. В решті решт вам потрібен якийсь інструмент, який може витягти менші фрагменти інформації з вашого великого набору даних. Наприклад, структуровані дані має сенс зберігати в реляційних базах даних і витягувати за допомогою SQL.
Неструктуровані дані можуть бути занадто великими, і вам може знадобитися розділити їх на менші фрагменти, а потім зберегти та проіндексувати у векторній базі даних. Напівструктуровані дані можуть підтягуватись через API, CQL, MQL, GQL або Cypher.
Під час створення конвеєра RAG вам може знадобитися, щоб ваш застосунок використовував деякі інструменти, які передають маленькі фрагменти інформації контекстом у вашу модель.
Структуровані дані та інструменти даватимуть найкращі результати. Напівструктуровані будуть кращими порівняно з загальними інструментами семантичного пошуку, такими як векторна БД, та неструктурованими даними. Хоча більшість даних є неструктурованими, тому на практиці вам можуть знадобитися усі ці інструменти.
Приклад даних що в основному структуровані: уявіть, що ми маємо дані лікарні з наступними таблицями: будівлі лікарень та їх розташування; пацієнти, їх дата народження та група крові; лікарі з роком закінчення та фахом; візити із зазначенням дати, місця, суми рахунка, номера кабінету, лікаря, пацієнта, типу візиту, опису лікування, скарги; пацієнт також може залишити відгуки з іменем лікаря та назвою лікарні до візиту.
На перший погляд, ці дані повинні зберігатися в реляційній БД і відповідно витягуватися за допомогою інструментів SQL, що в принципі правильно. Але якщо ви помітили, у нас ще є також такі речі, як скарга та відгуки пацієнтів, які найкраще витягти й обробити за допомогою семантичного пошуку (векторна база даних). Семантичний пошук корисний, коли вам потрібно відповісти на питання про враження пацієнта, почуття, сприйняття, настрої або будь-яку іншу якісну інформацію.
Цей підхід не буде дієвим для відповідей на об’єктивні запитання, які містять математичні функції, такі як підрахунок, відсотки, агрегації або перелік фактів. Наприклад, якщо запит користувача: «Чи задоволені пацієнти своїм постачальником послуг?». У цьому випадку вам, ймовірно, знадобляться обидва: реляційна база даних для витягування об’єктивної інформації за допомогою SQL-запита, а також векторна база даних із семантичним пошуком для отримання якісних даних.
WrenAI — гідний уваги і зручний опенсорс-продукт для генерації Text-to-SQL. Можна запускати як локально, так і у вас в k8s. Має UI та API, через який можна робити запити та отримувати відповідь як із згенерованим SQL під ваш запит, так і витягнуті данні. Що дуже спрощує роботу із структурованими даними.
Фази RAG
RAG включає дві фази. У початківців часто виникає бажання поєднувати їх, що є поганою ідеєю, оскільки у продуктиві ви не хочете завантажувати гігабайти даних з кожним запитом користувача.
- Обробка, підготовка, індексування та розміщення інформації для зберігання в якійсь базі даних. Зазвичай це робиться розробниками одноразово, на вимогу або за розкладом.
- Ініціюється запитом користувача під час виконання. Отримання маленької частини релевантної інформації з БД, що супроводжуватиметься запитом користувача, для додаткового контексту.
Embeddings та векторні бази даних
Embeddings — це числове представлення будь-якої інформації. Вони дозволяють визначити схожість, забезпечити швидкий пошук, класифікацію кластеризацію/групування та рекомендації.
Уявіть собі цифрову бібліотеку з величезною колекцією (наш набір даних). Кожна книга представлена набором координат — числовим вектором, який відображає суть вмісту, жанру, стилю та інших особливостей книги за допомогою унікального «цифрового відбитка» для кожної книги.
Коли користувач шукає книгу, він вводить пошуковий запит. Пошукова система бібліотеки перетворює цей запит на координати, використовуючи той самий метод, що використовувався для всіх книг для пошуку в бібліотечній базі даних книг. Система шукає Embeddings книг, які найбільше схожі на Embeddings запиту від користувача. Потім користувачеві в результатах пошуку на основі початкового запиту рекомендуються книги з найбільш схожими Embeddings.
Іншим найпростішим прикладом використання може бути те, що ви шукаєте синонім слова. Embeddings може допомогти вам знайти схожі або «близькі» слова, але, звісно, така технологія може набагато більше. Семантичний пошук — дуже ефективний спосіб швидкого пошуку інформації, пов’язаної з вашим запитом, і саме так працює пошукова система Google.
Дозвольте мені навести інший приклад. Це буде зрозуміліше в порівнянні з тим, як люди дивляться на дані: уявіть, що ви шукаєте на карті міста поблизу Києва. Якщо комп’ютер знає координати {50°40’19"N, 30°36’78"W}
, то щоб знайти місто поблизу Києва, йому не потрібна карта, а лише список координат усіх інших міст! Серед міст ця точка {50°58’82"N, 30°43’29"W}
є найближчою — м. Вишгород. Зверніть увагу, наскільки близькі координати широти та довготи.
Тепер ми можемо ще один додатковий «вимір» із розміром міста за чисельністю населення, і якщо користувач запитує знайти найближче до Києва місто враховуючи населення, відповідь може бути іншою для даного запиту. Ми можемо додати більше «вимірів». За допомогою цього алгоритму комп’ютери можуть знайти схожість у телевізійних комедіях, одежу чи будь-чого. Науковою мовою це було б сформульовано як «Розміщення семантично подібних запитів близько один до одного у векторному просторі».
Embeddings — це дуже потужний інструмент для модифікації запиту користувача, та збагачення його релевантною інформацією шляхом розміщення запиту користувача до категорій, до яких він належить, і пошуку подібної інформації за допомогою спільних категорій з інших джерел. Гарним прикладом, коли треба використовувати в Embeddings, можуть бути щоденні новини, про які наша
Чому нам потрібно кодувати та представляти наш набір даних у перетвореному стані як Embeddings та перетворювати запит користувача у вектори, а потім шукати вектори замість простого пошуку в оригінальному наборі даних безпосередньо використовуючи запит? Тому що саме таким чином компʼютери швидше оброблюють та краще розуміють зв’язок між інформацією. Іншими словами, вектори або координати, видані Embeddings-моделлю до якогось тексту, які чисельно подібні, також є семантично подібними.
У першій фазі RAG підготовлює інформацію з нашого набору даних, розбиваючи на фрагменти, що перекриваються, і зберігає в базі даних (називається векторна БД) із закодованими числовими представленнями (векторами), щоб пізніше, у другій фазі, ви могли швидко отримати маленький шматок релевантної інформації як додатковий контекст для запиту користувача.
Embeddings кодують текст із нашого набору даних в індекс у першій фазі та зберігають їх у векторній базі даних. Потім у другій фазі запит користувача також кодується за допомогою тієї самої моделі Embeddings, а індекс із векторами, згенерований запитом користувача, використовується для пошуку та отримання фрагментів тексту з векторної БД, так само як працюють пошукові системи. Для кодування тексту з числовими представленнями (векторами) використовується модель Embeddings, яка зазвичай набагато менша, ніж LLM. На сьогодні практично всі Embeddings-моделі є деякими варіантами від моделі BERT.
Отримання релевантного контексту з векторної бази даних — не єдиний спосіб, ви можете отримати дані багатьма способами, з реляційної бази даних із таблиць або через API, такі як Google Maps або Yelp. Ви завжди можете скористатися векторною базою даних, якщо у вас немає інших, зручніших способів зберігання та отримання даних.
- what-is-embedding-and-what-can-you-do-with-it;
- getting-started-with-embeddings;
- learn-retrieval-augmented-generation;
- langchain_faiss_example.
Розбивка (Chunking)
Уявіть, що у нас є велика книга або навіть декілька книг, ми не можемо вставити всю книгу як контекст до LLM, але ми можемо вставити менший шматок фрагмента тексту з цієї книги. Коли ви зберігаєте свої дані в базі даних, ви хочете, щоб вони були розділені на частини, які будуть потім використані як контекст у вашому RAG-застосунку, оскільки контекст обмежений розміром запита LLM. З RAG будь-які деталі важливі для вдосконалення, навіть те, як ви розділяєте інформацію на фрагменти.
Ви можете просто розділити свій текст на фіксовану кількість символів, але яка тоді буде ця кількість? Окрім того, розбиваючи дані на фрагменти, можливо є сенс, щоб вони «перекривались», щоб не втратити важливу інформацію, тож потрібно також вирішити, наскільки великим буде це перекриття. Ви можете розглянути семантичне фрагментування, щоб розділити текст, можливо, на слова, речення, абзаци, розділи та підрозділи, щоб зберегти семантичну цілісність контекстуально релевантного вмісту, деякі алгоритми, здатні динамічно визначати точки зупинки значних відхилень у вмісті під час розділення великого блоку інформації на менші частини.
Існує більше ніж одна семантична розбивка. Дехто навіть пропонує автоматично генерувати короткий «змінний» або ж «рухомий» підсумок, який включає кілька попередніх фрагментів у поточний фрагмент для кожного фрагмента що може підвищити якість результату. Це те, що вам доведеться перевірити та самостійно визначити, що найкраще працює під вашу задачу.
Але для початку розгляньте «простий» підхід із фіксованою довжиною у 500 символів із перекриттям 100 символів і продовжуйте далі, оскільки вам можуть знадобитися набагато менші чи більші фрагменти або, можливо, семантичне фрагментування буде кращим для вашої конкретної задачі.
А потім спробуйте, наприклад, рекурсивний розділ символів. Зокрема, існують інструменти для динамічного фрагментування на основі типу файлу, наприклад unstructured.
- semantic-chunking-for-rag;
- chunking-strategies-optimization-for-retrieval-augmented-generation-rag;
- Levels_Of_Text_Splitting.
Векторна БД
Вектори або «координати» двовимірної карти можна зберігати у векторній базі даних, уявіть просту таблицю з довготою, широтою та назвою міста. Тепер уявіть, що у вас є три виміри в просторі, це будуть довгота, широта та висота з іменем, що дасть чотири стовпці. У математиці ви можете мати понад три виміри, скільки завгодно.
Наприклад, ви можете мати три виміри в просторі та один додатковий вимір населення міста та міської площі, таким чином ми отримаємо п’ять вимірів плюс назву міста, що складається з шести стовпців. Ці розміри можуть представляти різні характеристики міста чи будь-якої іншої сутності, наприклад слова. І ми можемо знайти схожість або «близькість» або подібність одного слова до іншого.
Оскільки слова можуть мати багато значень і використовуватися в різних контекстах, деякі слова можуть бути простими синонімами. Іншим прикладом може бути помилка в слові. Таким чином, векторна база даних може зберігати та знаходити близькість тексту з запитом користувача, перевіреної за набором даних векторів, і надавати результати фрагментів тексту, близьких до запиту користувача, які все одно будуть близькими навіть із помилкою.
Моделі Embeddings допомагають перетворити фрагменти нашого тексту на групу векторів і зберігати ці фрагменти з їхніми векторними представленнями у векторній базі даних. Коли модель Embeddings кодує ваш текст у вектори, вона виробляє «систему координат» в багатовимірному просторі, який є унікальним для цієї сигнатури моделі Embeddings.
Ось чому, якщо ви закодували ваші фрагменти інформації за допомогою однієї моделі Embeddings, ви зможете знайти схожі, тільки якщо ви використовуєте тут саму систему координат. Іншими словами, на практиці, якщо ви закодували купу файлів і зберегли їх у векторній БД за допомогою, скажімо, OpenAI text-embedding-ada-002 model, ви не можете закодувати запит користувача за допомогою будь-якої іншої моделі Embeddings для пошуку, бо це вже буде інша система координат.
Уявіть, що ви кодуєте щось за допомогою одного алгоритму шифрування, тоді ви повинні використовувати точно той самий алгоритм для його декодування, або якщо ви хочете керувати автомобілем, ви не можете взяти ключі з іншого автомобіля, так само, якби ви кодували дані за допомогою Embeddings-моделі та зберегли у векторній базі даних ви повинні використовувати ту саму модель Embeddings, щоб також кодувати запит користувача для отримання «сумісних» координат із вже збереженими у вашій векторній базі даних.
Насправді ви можете мати набагато більше, ніж п’ять вимірів, у вас можуть бути сотні чи навіть тисячі вимірів. Зазвичай чим більше, тим краще з погляду якості (хоча це не завжди так), з іншого боку, пошук найближчих подібностей із більшою кількістю вимірів потребує більше обчислювальних потужностей, а також споживає більше пам’яті. Різні векторні бази даних можуть дозволяти різну кількість підтримуваних вимірів і алгоритмів пошуку подібності.
Станом на 2024 року поточна таблиця лідерів із десяти найпопулярніших моделей Embeddings досягає 4096 вимірів. Кожна модель Embeddings може кодувати дані в різну кількість вимірів, тому вам потрібно переконатися, що ваша векторна база даних може зберегти згенеровану систему координат.
Приклад моделей Embeddings та кількості вимірів (координат).
Модель, кількість вимірів. Приклад для OpenAI:
- text-embedding-ada-002 — 1536;
- text-embedding-3-small — 1536;
- text-embedding-3-large — 3072.
Векторні бази даних і максимум вимірів, що підтримуються:
- Chroma — не має обмежень на кількість вимірів;
- Milvus — максимум 32 000;
- Weavite — максимум 65 000;
- Neo4j — максимум 4096.
Не так давно більшість LLM мали дуже короткий розмір контекстного вікна, але нещодавно він значно покращився завдяки стрибку з 4096 вхідних токенів до вражаючих 32 000, 128 000 або навіть більше. Дехто може подумати, що векторні бази даних більше не потрібні, хоча це дуже дискусійно, оскільки обробка 32 000 токенів тексту в LLM може коштувати значно більше, займати надто багато часу, і, що найважливіше, може сплутати LLM величезною кількістю інформації. Також моделі з великим вікном контексту зазвичай коштують дорожче за токен. Принаймні на даний момент LLM, як правило, краще відповідають із скороченою кількістю інформації, а менші фрагменти, додані до контексту, обчислюватимуться швидше та, ймовірно, дадуть кращі результати.
Дерево думок RAG: багатошарове міркування
Якщо LLM — перший крок, RAG — другий, то дерево думок — два з половиною на шляху уперед. Цей підхід передбачає генерування кількох рівнів інформації, міркувань, ланцюжків думок для отримання різних відповідей і оцінки їх відповідності до запиту.
То ж навіщо вам RAG? Щоб покращити якість результату, змусити LLM думати краще, поєднати результати кількох LLM, на виході отримати якіснішу відповідь.
Пам’ять: короткострокові та довгострокові міркування
Коротка пам’ять стосується безпосередньо повідомлень в історії розмов, тоді як довга памʼять охоплює всі попередні взаємодії із користувачем для персоналізації відповідей і використання зовнішніх джерел даних. Автономні агенти самі можуть вирішити, чи варто їм використовувати пам’ять.
Довгострокова памʼять: структуровані дані
Табличні дані можна зберігати в реляційній базі даних, тій як PostgreSQL, Oracle RDBMS, MySQL та інших. Подібно до векторів для отримання даних із БД ваш додаток має перетворювати запит користувача, але цього разу на мову SQL. Цей тип даних забезпечує, мабуть, найкращий можливий результат чим інші типи даних.
Конвертація запиту користувача Text-to-SQL наразі відносно проста задача якщо ви користуєтесь OpenAI GPT, є навіть моделі, які спеціально навчені лише наборам даних SQL, такі як sqlcoder, llama-3-sqlcoder, claude-3-opus, duckdb-nsql, starcoder2:15b-instruct, codeqwen:7b-chat та інші, які можна запускати на власних серверах локально, а також існують зручні інструменти, які допомагають створювати готові RAG pipelines для генерації SQL і отримання даних із вашої бази даних.
📌
Wren AI Text-to-SQL: UI та API, або Як спростити роботу з реляційними базами в застосунках RAG/Agent.
Агенти: багатофункціональний ансамбль інструментів v3.0
Агенти можуть взаємодіяти зі світом різними способами, тоді як RAG головним чином зосереджується на відповідях на запитання у форматі чату. На відміну від RAG, який дотримується більш жорсткого робочого процесу, агенти можуть використовувати кілька інструментів і вирішувати, використовувати їх чи взагалі пропустити. Агенти особливо корисні для завдань у цифровій сфері реального світу.
З погляду практики, важливо знати, що агенти покладаються на «виклики API функцій», і ваш механізм, що обслуговує inference, повинен мати можливість обробляти такі виклики API. Приклади Inference-двигунів, які підтримують виклик функцій, включають OpenAI, Ollama, LocalAI та xorbitsai/inference. Бібліотека LiteLLM дозволяє перевірити, чи підтримує ваш Inference-двигун виклик функцій. Крім того, сама модель повинна обробляти запити виклику функцій. Прикладами Inference-двигунів та моделей, які підтримують виклики функцій, є OpenAI/gpt-3.5-turbo, Mistral, LocalAI/llama3—8b-function-call-v0.2 та Ollama/mistral:v0.3.
Сприймайте агента як працівника, який може виконувати одне чи кілька завдань. Що робити, якщо вам потрібен більше одного працівника? Ви можете використовувати системи мультиагентних оркестраторів, такі як CrewAI (На базі з LangChain) або LangGraph, щоб розподіляти завдання між командою працівників для спільної роботи над вашим завданням.
- crewai;
- multi-agent-orchestration-conversations-using-autogen-crewai-and-langgraph;
- how-to-assemble-your-ultimate-ai-squad-with-crewai;
- create-a-blog-writer-multi-agent-system-using-crewai-and-ollama;
- crafting-custom-love-poems-with-crewai-agents;
- mistral-ai-function-calling-a-simple-example-with-code.
ReAct Агент: спрощення складних запитів v3.5
Розум і дія (Reason & Action, ReAct) просуває агентів трохи далі. Це загальний дизайн, ідея якого — змусити
ReAct спонукає LLM генерувати потік своїх міркувань і відображати хід дій. Це дозволяє системі динамічно розмірковувати для створення, утримування напрямку та коригування планів дій, а також забезпечує взаємодію із зовнішнім середовищем за допомогою доступних інструментів для включення контексту в розміркування. Ця техніка розбиває складні запитання на підзадачі, кожне з яких розглядається окремими інструментами, щоб надати кращу відповідь.
«Магічний соус» у структурі ReAct — це підказка в контексті запита до моделі, яка спонукає модель LLM використовувати наведений нижче процес мислення: запитання, дія, виконання дії та спостереження.
Answer the following questions as best you can. You have access to the following tools: {tools} Use the following format: Question: the input question you must answer Thought: you should always think about what to do Action: the action to take, should be one of [{tool_names}] Action Input: the input to the action Observation: the result of the action … (this Thought/Action/Action Input/Observation can repeat N times) Thought: I now know the final answer Final Answer: the final answer to the original input question Begin! Question: {input} Thought:{agent_scratchpad} There are three placeholders {tool}, {input}, and {agent_scratchpad} in this prompt. These will be replaced with the appropriate text before sending it to LLM.
Генератор тексту в код та його виконання: автономні агенти
Існують спеціальні моделі LLM, навчені створювати код, наприклад Codestral, Codex, Code Llama, Codet5-open-code, AI2SQL і Starcoder2. Деякі багатоагентні системи, такі як OpenDevin, Devika і Microsoft AutoGen, просунулися далі, виконуючи та навіть тестуючи згенерований код. Що, з одного боку, є потенційною проблемою безпеки. Але з іншого боку може значно покращити якість вашої відповіді.
LLMs можуть «галюцинувати», відповідаючи на запитання, пов’язані з новинами чи математикою, і коли працюють зі специфічними задачами аналізу даних із великою структурою даних. Вони можуть мати труднощі з гнучкістю для виконання різноманітних потреб користувачів. Хоча RAG може вирішити першу частину, математика залишається проблемою.
Наприклад, якщо модель запитають: «Скільки буде 1/3?», LLM не завжди може дати правильну відповідь, якщо вона спеціально не була навчена відповідати на такі запити. Навіть просунуті LLMs, все ще стикаються з проблемами точних числових розрахунків. Вони можуть дати приблизні відповіді, якщо тому не були навчені.
Text-to-Code Generator and Executor
Вирішуючи завдання, що вимагають точних обчислень, як-от перетворення градусів Фаренгейта в градуси Цельсія, великі LLM можуть надавати приблизні значення на основі своїх навчальних даних. Для точних обчислень кращим підходом було б надати завдання, щоб LLM створила фрагмент коду, наприклад, у Python, для виконання обчислень.
Після цього агент може запустити код і перевірити результат, використовуючи відомі правильні значення. Ця комбінація LLM та динамічно згенерованого коду забезпечує точні та надійні числові результати.
Можна піти ще далі абстрагуватись і створювати агентів під кожну задачу користувача автоматично замість того щоб статично їх намагатись зробити зазделегідь.
Аугментація Inference API
Незалежно від того, чи запускаєте ви свої моделі локально за допомогою таких інструментів, як Ollama, LocalAI, LM Studio, Jan, Llamafile, GPT4all, або через платні служби, такі як OpenAI, Azure OpenAI Service, Groq, Anthropic, MistralAI, Cohere, Google Vertex-AI, Replicate.com, або HuggingFace Text-Generation-Inference, ви скоро зрозумієте, що ці API відрізняються. Ці відмінності можуть варіюватися від невеликих нюансів до великих розбіжностей, навіть серед API, які заявляють про повну сумісність.
Наприклад, ви можете мати доступ до моделі text-embedding-ada-002 OpenAI і моделі text-embedding-ada-002 LocalAI, але вони абсолютно різні та несумісні з погляду кількості вимірів та створені векторні простори матимуть не сумісні системи координат. Навіть якщо API сумісні, вони рідко сумісні повністю на всі 100%.
Використання кількох моделей від різних служб може бути більш рентабельним. Ви можете запустити невелику модель локально для таких завдань, як генерування запитів Text-to-SQL, що зробить її недорогою, водночас вибравши модель Groq для LLM Chat і модель HuggingFace для Embeddings, щоб досягти кращої продуктивності та економічності.
Щоб користуватись усіма цими варіантами та спростити майбутні зміни, подумайте про впровадження рівня абстракції між вашим додатком та inference API, таким як, наприклад, LiteLLM. Цей підхід забезпечує гнучкість і масштабованість в міру розвитку ваших потреб.
Тестування RAG/Agent, контроль показників
Ви створите свій застосунок, але це ще не кінець. На цьому етапі ви можете зрозуміти, що існує дуже багато змінних, які вам може знадобитися налаштувати, і те, як ви налаштовуєте свій застосунок: розмір фрагментації, застосування різних інструментів для фрагментації різних типів даних, вибір розміру фрагментів, вибір з різних алгоритмів векторного пошуку, скільки перших результатів (Top-K) поверне ваша векторна база даних, вибір моделі чату LLM, вибір моделі Embeddings, яка створює різну кількість вимірів, якість prompt engineering та конкретні тімплейти із підказками та інструкцією, тип RAG, вибір інструментів для витягування ваших структурованих і напівструктурованих даних, кроки, які може виконувати ваш RAG, як працює пам’ять вашого RAG, чи пам’ятає він останні 10 повідомлень, чи лише їхній підсумок?
Усе це змінні, які впливають на якість, швидкість і ціну ваших результатів. Ви маєте протестувати ці параметри, та оцінити якість і швидкість вашого застосунку.
Оцінка якості
Оцінювання має важливе значення для виявлення та кількісної оцінки слабких місць вашого застосунку із ШІ, та надати напрям для вдосконалення результату. Щоб проілюструвати цю концепцію, давайте використаємо приклад із реального життя.
Пам’ятаєте, як ми фрагментували та зберегли фрагменти даних у векторній БД? Створімо сценарії для вашого застосунку на основі цього процесу. Ось як працює RAG: спочатку ви розділяєте текст на фрагменти та вставляєте ці фрагменти у свою векторну базу даних. Під час виконання із кожним запитом користувача ваш застосунок шукає ці фрагменти, щоб підставити їх у контекст вашої моделі Chat LLM.
Тепер зробімо це навпаки. Почніть із фрагментів і попросіть LLM створити запитання та відповіді на основі кожного фрагменту. Коли у вас є ці пари запитань і відповідей, збережіть їх. Цей процес одразу надав нам готові тестові сценарії. Далі почергово надсилайте лише запитання своєму застосунку та порівняйте відповіді з попередньо згенерованими відповідями.
Замість того, щоб покладатися на людей або платні послуги, ви можете використовувати локальні
Цей метод пропонує детальне розуміння продуктивності вашого застосунку з вашим набором даних. Фреймворки, такі як LangChain і LlamaIndex, мають вбудовані функції для таких базових перевірок. Крім того, такі інструменти, як фреймворк RAGas, бібліотека llmperf і служба LangSmith, можуть кількісно оцінити якість відповідей і виявити запитання без правильної відповіді, надаючи повну картину якості вашого застосунку.
Тема оцінки якості (визначення бенчмарків, реалізація процесу виміру і досягнення запланованих показників) часом займає не менше часу ніж весь інший процес.
З точки зору бізнесу краще хороша система валідації з поверх простого функціоналу ніж найкращі технології без належного контролю якості.
Хоча тут це описано двох абзацах, з яких може сформуватися хибна враження, не треба недооцінювати цей етап.
Швидкодія
Окрім якості, оцінка швидкості вашого застосунку теж має важливе значення. Обробка деяких відповідей займає занадто багато часу? Можливо, варто подумати, чи можна трохи знизити якість відповіді, щоб досягти двократного покращення швидкості. На приклад зменшивши кількість повернених фрагментів із векторної бази даних. Або навпаки, якщо швидкість менш релевантна, а ваша мета це максимізувати деталізацію та якість, можливо, за меншу вартість.
Існують інструменти порівняння швидкості, які допоможуть вам прийняти рішення, балансуючи швидкість, якість і вартість для оптимізації продуктивності вашого додатка.
Prompt Engineering
Якість контексту, отриманого через пошук Embeddings у вашій векторній базі даних, може не завжди бути ефективною для LLM Chat. Деякі моделі дотримуються інструкцій краще, ніж інші, і залежно від особливостей моделі певні підказки можуть працювати ефективно, а інші — ні. Тому вкрай важливо дібрати текст підказки та інструкцій, які найкраще підходять для вашої моделі LLM. Є спеціалізовані ресурси, які діляться прикладами підказок та інструкцій, які можуть бути ефективними.
Prompt flow є протилежністю захардкоженного тексту підказок та інструкцій для LLM. Він передбачає створення кількох різних підказок і варіантів, які можна під’єднати до LLM для різних сценаріїв, динамічно адаптуватися до запиту користувача, що в кінцевому підсумку забезпечує кращі результати.
Коли ви розробляєте ШІ-застосунок, важливо мати якийсь інструмент відстеження, який може показати вам потік даних у вашому додатку, який може пояснити ланцюжок думок, через які проходить ваш застосунок та LLM, даючи вам краще розуміння, чому ви отримуєте один результат, а не інший.
Наприклад, ваша векторна база даних може не повертати відповідну інформацію на ваш запит, що може бути причиною того, що ваш RAG/Agent не відповідає на ваші запитання правильно, тому важливо на етапі відлагодження бачити, як ваш застосунок реагує всередині, щоб покращити результати від вашої векторної бази даних та моделі.
- langfuse;
- smith.langchain.com;
- llm-prompt-engineering-for-beginners-what-it-is-and-how-to-get-started;
- the-modern-scientist/best-prompt-techniques-for-best-llm-responses.
Відгуки користувачів: для адаптації застосунку
Якщо ваш застосунок може оцінювати відгуки, ви можете збільшити якість та покращити взаємодію з користувачем, використовуючи такі реакції, як «подобається 👍» або «не подобається 👎» на відповідь. Крім того, якщо ви спілкуєтесь із чистими моделями, то можете помітити, що кожного разу, коли ви щось запитуєте, модель починає з чистого аркуша, немає жодної пам’яті, в них чиста амнезія. Тож RAG може допомогти виправити це, взявши до уваги відгук користувача із поточної історії розмови та додавши їх як контекст.
Локальне тестування за допомогою Docker Compose
Docker Compose дозволяє тестувати застосунок штучного інтелекту локально, маніпулюючи ним за допомогою змінних середовища. У багатьох проєктах, як-от LocalAI чи Ollama, майже повністю або частково використовують майже той самий API, що й OpenAI, що дозволяє запускати такі моделі, як Mistral або Llama локально, а потім легко перейти їх на ChatGPT.
Для початківців дуже простий та зручний продукт Flowise із UI для створення RAG та Агентів за допомогою drag-n-drop. Він дозволить краще закріпити та засвоїти описані принципи в цій статті та, що для багатьох важливо, візуалізувати pipeline застосунку. Будь-кому рекомендую почати вивчення RAG та Агентів саме із цього продукту. Він дозволяє використовувати як LangChain, так і Llamaindex-фреймворк. На жаль, не дуже підходить для продуктиву через брак багатьох функцій, як-от робота із Knowledge Graph, та зручність і простота роботи виливаються у брак глибоких налаштувань і усіх доступних можливостей, коли ви програмуєте код.
Розгортання: використання моделей та DevOps
Локальні моделі штучного інтелекту без графічного процесора чи спеціалізованого обладнання можуть відповідати із затримками, наприклад 1 хвилина, що може бути прийнятними для розробки. Якщо у вас є Apple Silicon (який використовує Metal GPU Framework) або ПК із графічними процесорами NVIDIA чи AMD, це може значно пришвидшити відповідь вашої моделі. Це також може бути стратегією для зниження ціни розробки вашого застосунку локально за допомогою докер-контейнерів і розгортання у виробничому середовищі, наприклад k8s чи пізніше, тому ви напевно захочете мати CI/CD, із такими GitOps-інструментами, як ArgoCD чи FluxCD, що може значно спростити цей процес.
Повертаючись до початку
Досконалості не існує, і якщо на цьому етапі вже все зроблено, ви можете повернутися до самого початку цієї статті: подумайте про навчання нових моделей для вашої конкретної задачі або зробіть тонкий тюнінг наявної моделі. І на цьому витку з новою моделлю ви, ймовірно, почнете краще розуміти, як покращити свій застосунок RAG/Agents ще раз... Так, коло життя. Або коло ШІ.
Резюме:
Розкладання запиту на простіші задачі та введення додаткового контексту, як правило, забезпечує кращі результати. Фреймворки LangChain & LlamaIndex мають на меті полегшити платформу для розробки RAG. Розуміючи та ефективно використовуючи конвеєри RAG і шаблони агентів, розробники можуть створювати адаптивні системи штучного інтелекту, які можуть виконувати дії в реальному світі, заточені на певні області та задачі.
Важливо розуміти свої дані та як з ними працювати. Тестування, оцінка, контрольні показники допомагають виміряти та покращити ваш застосунок. Аугментація API — важливий крок в правильному напрямку, щоб уникнути Vendor Lock-in та допомогти з локальними тестами та розробкою. Концепції RAG & Agents слугують платформою синергії між парадигмою ReAct, Embeddings, графом знань і LLM, що прокладає шлях для наступного покоління додатків із ШІ. Розуміння застосунку та продумані способи жонглювання вашими даними можуть знизити витрати.
Підтримка:
Якщо вам сподобалася ця стаття і ви хочете підтримати мене:
- Натисніть «Подобається 👍» та додайте «До обраного ⭐️» мою статтю; це допоможе мені.
- Слідкуйте за мною на DOU щоб отримувати останні статті.
- Поділіться цією статтею в соціальних мережах ➡️🌐
- Дайте відгук у коментарях нижче, навіть якщо це просте «дякую» — це допоможе мені розуміти, що моя робота була не марною.
- Якщо є помилки, скажіть де, а найголовніше як виправити, не претендую на роль всезнайки.
- Додайтесь до мого кола в LinkedIn та AI Sky Discord Server.
- Шукаю ентузіастів та однодумців, що знаються на Python і хотіли б втілити описані ідеї у життя, і, можливо, навіть зробити сумісний проєкт: Напишіть мені в LinkedIn. На разі працю над PoC який використовує описані принципи у цій статті. Буду радий поділитись своїми напрацюваннями і знаннями.
- Я готую статтю яка по великому рахунку використовує NLP для побудувати графу знань із вільного тексту, який зберігається у БД для того щоб потім бути використаним в Agentic RAG чатботі. Чи було би вам цікаво стати соовтором? Треба вичитати перевірити, виправити де не правильно, може оновити якщо щось застаріло чи додати нове. Це буде продовженням до цієї статті. Прошу написати мені персональне повідомлення LinkedIn / Discord якщо ви хочете по співпрацювати на цю тему.
233 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів