Practical notes: Як я перетворив свою фотогалерею на автономного AI-агента
Покрокова інструкція з Practical notes: Як я перетворив свою фотогалерею на автономного AI-агента: контракти, перевірки та шаблони коду для команд, які використовують цю модель.
У цьому посібнику детально описано шлях від сировини до функціональної системи для проекту: «Як я перетворив свою галерею фотографій на автономного AI-агента — Повний посібник». Основна увага приділяється конкретним крокам виконання, чітким перевіркам та коду, який можна просто додати до репозиторію, не намагаючись здогадатися про його призначення. На етапі огляду необхідно визначити вхідні дані, виконавця кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись зрозуміти прихований стан системи. Краще використовувати невеликі, тестовані одиниці коду замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну структуру обробки даних.
Вступ
Під час виконання етапу введення спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте безповідомного часткового виконання завдань. Робіть перевірки після дорогих кроків. Система повернення до виконання не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор намагається виконати наступний етап.
Чому традиційний пошук фотографій не працює
Під час роботи над етапом «Чому традиційний пошук фото?» спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-версії до спільних середовищ. Робіть контрольні пункти після дорогих кроків. Система повторного запуску не повинна знову стягувати плату за один і той самий виклик ШІ, якщо оператор перезапускає пізнішу ланку.
Підхід з альбомами не функціонує в реальних умовах
Під час роботи над етапом «The album approach collapses» спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Зберігайте конфігурацію окремо від коду додатку. Файли середовища, бази секретних даних та флаги функцій мають знаходитися в одному місці, щоб оператори могли їх перевіряти, не читаючи весь код. Створюйте контрольні точки після дорогих операцій. Система відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізнішу операцію. Під час роботи над етапом «The album approach collapses» спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Віддавайте перевагу малим, тестованим одиницям коду перед величезними скриптами. Якщо якась операція зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану структуру обробки даних.
Пошук за ключовими словами — це не все
Пошук за ключовими словами ефективний лише тоді, коли його розглядають як вимірювану площину. Зафіксуйте один ідеальний приклад виконання, один випадок невдачі та примітки щодо скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Зберігайте структуру графа простою та типованою. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
Пошук у хмарній галереї: корисно, але з витратами
Пошук у галереї Cloud gallery найкраще функціонує, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад, один випадок невдачі та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.
Справжня проблема: відсутнє семантичне розуміння
Справжня проблема полягає у тому, що жоден етап не функціонує найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють відновлення роботи після перерв. Справжня проблема полягає у тому, що жоден етап не функціонує найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.
Концепція: семантичний пошук, пояснений просто
На етапі семантичного пошуку The Concept необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви для результатів роботи, визначте критерії успіху та не допускайте мовчазного часткового завершення. Вимагайте людського схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення елементів під час компіляції не є гарантією повноти бізнес-процесу.
Яке місце посідає мова?
Для етапу «Звідки береться мова» необхідно визначити вхідні дані, виконавця кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-середовища до спільних. Встановлюйте людське схвалення для кроків, які витрачають гроші або змінюють дані в продакшені. Підключення під час компіляції не є гарантією повності бізнес-функціоналу.
Вибір правильних інструментів (та чому це зайняло тижні)
На етапі вибору правильних інструментів необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Конфігурацію слід тримати окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевірити, не читаючи весь алгоритм. Аутентифікуватися слід біля шлюзу, а переавторизація — на рівні обробки даних. Один лише токен не є межею окремого тенантства. На етапі вибору правильних інструментів необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану систему обробки.
CLIP ViT-B/32 через FastEmbed — очі системи
Під час роботи з етапом CLIP ViT-B 32 через FastEmbed спочатку складіть контракт: необхідні вхідні дані, сигнал про успіх та що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте беззвучного часткового виконання завдань. Вимірюйте рівень відтворення інформації на фіксованому наборі запитань перед налаштуванням підказок. Часта зміна підказок рідко допомагає покращити ефективність пошуку.
from fastembed import ImageEmbeddingModel, TextEmbeddingModel
# Loaded once, reused forever
image_model = ImageEmbeddingModel.from_pretrained("Qdrant/clip-ViT-B-32-vision")
text_model = TextEmbeddingModel.from_pretrained("Qdrant/clip-ViT-B-32-text")
# After embedding:
image_vector = embed_image("sunset_photo.jpg") # shape: (512,)
query_vector = embed_text("beautiful sunset") # shape: (512,)
# Cosine similarity — just a dot product on normalised vectors
similarity = np.dot(image_vector, query_vector)
# If image is a sunset → similarity ≈ 0.85 (strong match)
# If image is food → similarity ≈ 0.15 (weak match)
Qdrant Edge — пам’ять
Під час роботи з етапом пам’яті Qdrant Edge спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Відображення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-середовища до спільних. Створюйте контрольні точки після дорогих кроків. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізніший етап.
from qdrant_edge import(
Distance,
EdgeConfig,
EdgeShard,
EdgeVectorParams,
)
config = EdgeConfig(
vectors={
VECTOR_NAME: EdgeVectorParams(
size=EMBED_DIM,
distance=Distance.Cosine
)
}
)
_shard = EdgeShard.create(path=str(SHARD_DIR), config=config)
Об’єднання всього воєдино
Під час роботи на етапі «Об’єднання всього» спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь алгоритм. Робіть контрольні пункти після дорогих кроків. Функція відновлення не повинна знову стягувати плату за той самий виклик LLM, коли оператор перезапускає пізніший етап. Під час роботи на етапі «Об’єднання всього» спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану систему обробки даних.
OpenClaw — мозок
Етап обробки даних OpenClaw працює найкраще, коли його розглядають як вимірювану поверхню. Запишіть один ідеальний результат, один випадок невдачі та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Зберігайте стан графа у вигляді простих структур з чіткими типами даних. Вкладені структури приховують інформацію про те, який вузол заповнив певне поле, що ускладнює продовження роботи після перерв.
Налаштування середовища
Етап налаштування середовища працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний результат, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних середовищ. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.
Крок 1: Клонуйте репозиторій та створіть віртуальне середовище
Етап 1: Клонування сцени працює найкраще, коли її розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол записав яке поле, і ускладнюють продовження роботи після перерв. Етап 1: Клонування сцени працює найкраще, коли її розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.
# Clone the repo
git clone https://github.com/vatsala-singh/AI-Powered-Photo-Search-and-Tagging-Agent.git
cd AI-Powered-Photo-Search-and-Tagging-Agent
# Create and activate virtual environment
python -m venv .venv
source .venv/bin/activate # Mac/Linux
# .venv\Scripts\activate # Windows
Етап 2: Встановлення залежностей
На другому кроці під час встановлення етапу необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви артефактів, визначте критерії успіху та не допускайте беззвучного часткового завершення. Вимагайте людського схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення під час компіляції не є гарантією повноти бізнес-процесу.
pip install -r requirements.txt
Крок 3: Зрозуміти структуру проекту
На етапі 3 «Розуміння» необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні. Встановлюйте людське схвалення для кроків, які витрачають гроші або змінюють дані в продакшені. Підключення під час компіляції не є гарантією повноти бізнес-функціоналу.
AI-Powered-Photo-Search-and-Tagging-Agent/
│
├── main.py # FastAPI app + OpenClaw agent entry point
├── config.py # All configurable parameters in one place
├── requirements.txt
│
├── pipeline/
│ ├── embedder.py # CLIP embedding logic (image + text)
│ └── indexer.py # Batch photo processing and indexing
│
├── store/
│ └── qdrant_client.py # Qdrant Edge setup and collection management
│
├── tools/
│ ├── search.py # Semantic search tool
│ ├── tag.py # Zero-shot auto-tagging tool
│ ├── duplicates.py # Near-duplicate detection tool
│ └── albums.py # Smart album grouping tool
│
├── test/
│ ├── embedder_test.py
│ ├── indexer_test.py
│ ├── search_test.py
│ └── qdrant_edge_client_test.py
│
└── qdrant-edge-data/ # Auto-created at runtime
├── storage/ # Qdrant's internal shard data
├── models/ # Cached CLIP model weights
└── photos/ # Collection data
Крок 4: Швидкий огляд config.py
На етапі „Короткий огляд“ кроку 4 необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Конфігурацію слід тримати окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь алгоритм. Необхідно передбачити людське схвалення для операцій, які спричиняють витрати грошей чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повноти бізнес-функцій. На етапі „Короткий огляд“ кроку 4 необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Краще використовувати невеликі, тестовані одиниці коду замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну ієрархію операцій.
# config.py
CLIP_IMAGE_MODEL = "Qdrant/clip-ViT-B-32-vision"
CLIP_TEXT_MODEL = "Qdrant/clip-ViT-B-32-text"
EMBEDDING_DIM = 512 # CLIP ViT-B/32 output dimension
COLLECTION_NAME = "photos"
QDRANT_PATH = "./qdrant-edge-data"
BATCH_SIZE = 32 # Images per indexing batch
TOP_K = 10 # Default search results returned
TAG_THRESHOLD = 0.20 # Min similarity score for a tag to apply
DUPLICATE_THRESHOLD = 0.97 # Min similarity to flag as duplicate
Крок 5: Запустіть сервер
Під час виконання кроку 5 «Запустити сервер» спочатку запишіть умови договору: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допоможе зберегти чесність подальших змін у коді. Розглядайте цей етап як договір між вхідними даними та перевіреними результатами. Призначте назви елементам, визначте критерії успіху та не допускайте безповідомного часткового виконання. Робіть контрольні пункти після дорогих кроків. Система відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор намагається знову виконати пізніший етап.
uvicorn main:app --reload --port 8000
Крок 6: Перевірте налаштування
Під час виконання кроку 6 «Перевірка», спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-середовища до спільних. Робіть контрольні пункти після дорогих кроків. Система повторного запуску не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізніший етап.
# Quick sanity check - should return {"status": "ok"}
curl http://localhost:8000/health
curl http://localhost:8000/api/status
Створення конвеєра для імплантації зображень
Під час виконання етапу створення імплантації зображень спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність у подальших змінах коду. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Вимірюйте рівень відтворення інформації на фіксованому наборі запитань перед налаштуванням підказок. Зміни підказок рідко виправляють слабкі алгоритми пошуку. Під час виконання етапу створення імплантації зображень спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність у подальших змінах коду. Віддавайте перевагу малим, тестованим одиницям коду перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій.
Імплантер
Етап вбудовування працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад, один випадок невдачі та примітку щодо скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Розділіть політику часткового оброблення даних від політики їх отримання. Зміна однієї з них не повинна змушувати переписувати іншу при зміні показників якості.
# pipeline/embedder.py
from fastembed import ImageEmbeddingModel, TextEmbeddingModel
from PIL import Image
import numpy as np
from config import CLIP_IMAGE_MODEL, CLIP_TEXT_MODEL
# Load once, reuse for the lifetime of the process
# Models are large (~150MB each) — we never want to reload them per request
_image_model = ImageEmbeddingModel.from_pretrained(CLIP_IMAGE_MODEL)
_text_model = TextEmbeddingModel.from_pretrained(CLIP_TEXT_MODEL)
def embed_image(image_path: str) -> np.ndarray:
"""Convert an image file to a 512-d CLIP embedding."""
image = Image.open(image_path).convert("RGB")
embeddings = list(_image_model.embed([image]))
return np.array(embeddings[0]) # shape: (512,)
def embed_text(query: str) -> np.ndarray:
"""Convert a text string to a 512-d CLIP embedding."""
embeddings = list(_text_model.embed([query]))
return np.array(embeddings[0]) # shape: (512,)
Індексатор
Етап індексації працює найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуальний контроль витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних середовищ. Зберігайте стан графа у випрямленому та типованому форматі. Вкладені блоки приховують інформацію про те, який вузол записав яке поле, та ускладнюють продовження роботи після перерв.
# pipeline/indexer.py
import os
import uuid
from pathlib import Path
from datetime import datetime
from PIL import Image
from pipeline.embedder import embed_image
from store.qdrant_client import get_shard
from tools.tag import generate_tags
from config import BATCH_SIZE
SUPPORTED_FORMATS = {".jpg", ".jpeg", ".png", ".webp", ".bmp", ".tiff"}
def index_folder(folder_path: str) -> dict:
"""
Recursively index all images in a folder into Qdrant Edge.
Returns a summary: total found, indexed, skipped.
"""
folder = Path(folder_path)
shard = get_shard()
image_paths = [
p for p in folder.rglob("*")
if p.suffix.lower() in SUPPORTED_FORMATS
]
total = len(image_paths)
indexed = 0
skipped = 0
batch = []
for i, path in enumerate(image_paths):
try:
vector = embed_image(str(path))
tags = generate_tags(str(path))
img = Image.open(path)
point = {
"id": str(uuid.uuid4()),
"vector": vector.tolist(),
"payload": {
"filename": path.name,
"filepath": str(path.absolute()),
"tags": tags,
"timestamp": int(path.stat().st_mtime),
"width": img.width,
"height": img.height,
}
}
batch.append(point)
indexed += 1
except Exception as e:
print(f"Skipping {path.name}: {e}")
skipped += 1
# Flush every BATCH_SIZE images
if len(batch) >= BATCH_SIZE:
shard.upsert(points=batch)
batch = []
print(f" Progress: {i+1}/{total} images indexed...")
# Flush remaining
if batch:
shard.upsert(points=batch)
return {"total": total, "indexed": indexed, "skipped": skipped}
Індексування зображень у Qdrant Edge
Етап індексування зображень у Qdrant працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний зразок виконання, один випадок збою та примітку щодо скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол записав яке поле, і ускладнюють продовження роботи після перерв. Етап індексування зображень у Qdrant працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний зразок виконання, один випадок збою та примітку щодо скасування змін перед розширенням обсягу роботи. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.
Як тут працює Qdrant Edge
На етапі «Як працює Qdrant Edge» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори мають мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви артефактів, визначте критерії успіху та не допускайте беззвучного часткового завершення. Вимагайте людського схвалення для операцій, які спричиняють витрати грошей чи змінюють дані у продакшені. Підключення під час компіляції не є гарантією повності виконання завдань у бізнес-сенсі.
Налаштування шарду
Для налаштування етапу шарду необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись визначити прихований стан. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні. Встановіть людське схвалення для кроків, які витрачають гроші або змінюють дані в продакшені. Підключення під час компіляції не є гарантією повноти бізнес-функціоналу.
def get_shard() -> EdgeShard:
"""
Return the singleton EdgeShard, creating it on first call.
- If SHARD_DIR does not exist → create a brand-new shard.
- If SHARD_DIR already contains data → reopen it (no config needed).
EdgeShard runs entirely in-process. No binary, no port, no network.
"""
global _shard
if _shard is not None:
return _shard
SHARD_DIR.mkdir(parents=True, exist_ok=True)
# Detect whether this is a fresh shard or an existing one.
# EdgeShard.create() fails if data already exists on disk.
shard_has_data = any(SHARD_DIR.iterdir())
if shard_has_data:
print(f"[qdrant_client] Reopening existing shard at '{SHARD_DIR}'")
_shard = EdgeShard.load(path=SHARD_DIR)
else:
print(f"[qdrant_client] Creating new shard at '{SHARD_DIR}'")
config = EdgeConfig(
vectors={
VECTOR_NAME: EdgeVectorParams(
size=EMBED_DIM,
distance=Distance.Cosine
)
}
)
_shard = EdgeShard.create(path=str(SHARD_DIR), config=config)
print(f"[store] Shard ready — vector: '{VECTOR_NAME}', dim: {EMBED_DIM}")
return _shard
Розділення на створення та завантаження
На етапі створення проти завантаження необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Зберігайте конфігурацію поза кодом додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевірити, не читаючи весь алгоритм. Встановлюйте людське схвалення для кроків, які спричиняють витрати грошей чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повноти бізнес-процесу. На етапі створення проти завантаження необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану структуру процесу.
Шаблон синглтон
Під час роботи над етапом шаблону синглтон спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Розглядайте цей етап як договір між вхідними даними та перевіреними результатами. Дайте назви елементам коду, визначте критерії успіху та не допускайте безповідомного часткового виконання завдань. Робіть перевірки після складних кроків. Система повернення до виконання не повинна знову оплачувати однаковий виклик ШІ, коли оператор намагається виконати наступний етап.
@app.on_event("shutdown")
def on_shutdown():
close_shard()
Схема вантажу
Під час роботи над етапом схеми вантажу спочатку запишіть умови використання: необхідні параметри вхідних даних, сигнал про успішну обробку та наслідки часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із результатами функціональності. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних. Робіть контрольні пункти після дорогих кроків. Система повторного запуску не повинна знову стягувати плату за один і той самий виклик ШІ, коли оператор перезапускає пізніший етап.
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass
class PhotoPayload:
filename:str
path:str
tags: list[str] = field(default_factory=list)
timestamp: Optional[str] = None
width: Optional[int] = None
height: Optional[int] = None
def to_dict(self) -> dict:
return {
"filename": self.filename,
"path": self.path,
"tags": self.tags,
"timestamp": self.timestamp,
"width": self.width,
"height": self.height
}
Записування даних у шард
Під час роботи над етапами написання коду спочатку запишіть умови виконання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність подальших змін у коді. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код.
from qdrant_edge import PointStruct
from store.qdrant_client import get_shard
from schema import PhotoPayload
shard = get_shard()
payload = PhotoPayload(
filename = "beach_sunset.jpg",
path = "/Users/me/Pictures/2024/Goa/beach_sunset.jpg",
tags = ["sunset", "beach", "outdoor"],
timestamp = "2024-05-01T18:42:00",
width = 4032,
height = 3024
)
point = PointStruct(
id = "3f7a2b1c-8e4d-4f9a-b2c1-7d8e9f0a1b2c",
vector = {"image": vector.tolist()}, # named vector matching VECTOR_NAME
payload = payload.to_dict()
)
shard.upsert(points=[point])
Під час роботи над етапами написання коду спочатку запишіть умови виконання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність подальших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну функцію, а не на складну систему обробки даних.
Автоматична позначка фотографій
Етап автоматичної позначки фотографій працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад, один випадок невдачі та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Зберігайте стан графа у простому та типованому вигляді. Вкладені елементи приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
Ідея: класифікація без попереднього навчання
Ідея етапу класифікації zero-shot працює найкраще, коли її розглядають як вимірювану поверхню. Зафіксуйте один ідеальний запис, один випадок невдачі та примітку про скасування перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Видимість витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-версії до спільних середовищ. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.
TAG_VOCABULARY = [
"sunset", "sunrise", "beach", "ocean", "mountain", "forest", "city",
"night", "snow", "rain", "fog", "sunny", "cloudy",
"dog", "cat", "bird", "people", "crowd", "portrait", "selfie",
"food", "coffee", "restaurant", "travel", "architecture",
"car", "road", "nature", "flowers", "trees",
"indoor", "outdoor", "party", "celebration", "sport",
"screenshot", "document", "text", "map",
]
# tools/tag.py
from pipeline.embedder import embed_image, embed_text
from config import TAG_THRESHOLD
import numpy as np
TAG_LABELS = [...] # full list as above
# Pre-compute label embeddings once at module load —
# no point re-embedding the same 50 words on every photo
_label_vectors = {
label: embed_text(label)
for label in TAG_LABELS
}
def generate_tags(image_path: str) -> list[str]:
"""
Run zero-shot classification on an image.
Returns a list of tags whose similarity to the image
exceeds TAG_THRESHOLD (default: 0.20).
"""
image_vector = embed_image(image_path)
tags = []
for label, label_vector in _label_vectors.items():
similarity = np.dot(image_vector, label_vector) # cosine sim on normalised vectors
if similarity >= TAG_THRESHOLD:
tags.append(label)
return tags
Теги у час індексації та під час запиту
Механізм Tags на етапі індексації працює найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Зберігайте стан графа у простій та типованій формі. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв. Механізм Tags на етапі індексації працює найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.
def generate_tags_from_vector(img_vec: np.ndarray, threshold: float = 0.20, max_tags: int = 6) -> list[str]:
"""
Generate tags for an image vector using zero-shot CLIP classification.
Tags with cosine similarity above threshold are included (up to max_tags).
This is a utility function used for generating tags during indexing
or when you already have an image vector.
"""
tag_vecs = _get_tag_vectors()
scores = {
tag: float(np.dot(img_vec, vec)) # both normalized → cosine similarity
for tag, vec in tag_vecs.items()
}
tags = sorted(
[t for t, s in scores.items() if s >= threshold],
key=lambda t: scores[t],
reverse=True,
)[:max_tags]
return tags
Використання тегів як фільтрів
На етапі використання тегів як фільтрів необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як угоду між вхідними даними та перевіреними результатами. Призначте назви елементів, визначте критерії успіху та не допускайте беззвучного часткового завершення. Вимагайте людського схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення під час компіляції не є гарантією повноти бізнес-процесу.
def search_photos(query: str, top_k: int = TOP_K, tags: list[str] = None) -> list[dict]:
#search photo library with a Natural language query
#takes in query, no of results to be displayed, and a list of tags
# returns list of dicts with photo metadata and relevance score
print(f"[search] Received query='{query}' with tags={tags} and top_k={top_k}")
shard = get_shard()
query_vector = embed_text(query)
# Over-fetch when tag filtering is requested to have enough candidates
# after post-filtering by tags
over_fetch_multiplier = 5 if tags else 1
fetch_limit = top_k * over_fetch_multiplier
results = shard.query(
QueryRequest(
query=Query.Nearest(query_vector.tolist(), using=VECTOR_NAME),
limit=fetch_limit,
with_vector=False,
with_payload=True,
)
)
print(f"[search] Found {len(results)} initial hits for query='{query}' with tags={tags}")
hits = []
untagged_hits = [] # Fallback results for images without tags
for point in results:
payload = point.payload or {}
point_tags = payload.get("tags", [])
result_dict = {
"path": payload.get("path"),
"filename": payload.get("filename"),
"tags": point_tags,
"timestamp": payload.get("timestamp"),
"score": round(point.score, 4)
}
# Post-filter by tags if specified
# (EdgeShard doesn't support complex filters, so we filter in Python
# after over-fetching more results than needed)
if tags:
if point_tags and any(t in point_tags for t in tags):
# Has tags and matches the filter
hits.append(result_dict)
elif not point_tags:
# No tags yet (images not auto-tagged), save as fallback
untagged_hits.append(result_dict)
else:
# No tag filter specified, include all results
hits.append(result_dict)
# Stop if we have enough tagged results
if len(hits) >= top_k:
break
# If we don't have enough tagged results, include untagged ones that match the query
if tags and len(hits) < top_k:
hits.extend(untagged_hits[:top_k - len(hits)])
return hits[:top_k]
Створення агента пошуку
На етапі створення агента пошуку необхідно визначити вхідні дані, відповідального за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись визначити прихований стан. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Відображення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні. Встановіть людське схвалення для тих випадків, коли витрачаються гроші чи змінюються дані в продакшені. Підключення під час компіляції не є гарантією повності бізнес-функцій.
curl --location 'http://localhost:8000/search' \
--header 'Content-Type: application/json' \
--data '{"query": "eiffel tower from rooftop","tags":[], "top_k": 1}'
{
"query": "eiffel tower from rooftop",
"results": [
{
"path": "/Users/vatsalasingh/Documents/Datasets/tag_phot/photo-1638051017225-0d9fcca18cf4.jpg",
"filename": "photo-1638051017225-0d9fcca18cf4.jpg",
"tags": [
"cloudy",
"city",
"rain",
"screenshot",
"architecture",
"travel"
],
"timestamp": "2021-12-09T17:27:56",
"score": 0.2864
}
]
}
Граційне оброблення крайніх випадків
Щоб граційно керувати межовими випадками, необхідно перед зміною коду визначити вхідні дані, власника кроку та критерії завершення. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Зберігайте конфігурацію поза кодом додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевірити, не читаючи весь архітектурний план. Встановлюйте людське схвалення для операцій, які спричиняють витрати чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повноти бізнес-функцій. Щоб граційно керувати межовими випадками, необхідно перед зміною коду визначити вхідні дані, власника кроку та критерії завершення. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не
заплутана система трубопроводів.Організація всього за допомогою OpenClaw
Під час роботи на етапі організації спочатку складіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність у подальших змінах коду. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви елементам, визначте критерії успіху та не допускайте безпроблемного часткового виконання. Створюйте контрольні точки після дорогих кроків. Функція відновлення не повинна знову оплачувати один і той самий виклик LLM, коли оператор перепробовує пізнішу ланку.
Як працює OpenClaw
Під час вивчення етапу «Як працює OpenClaw» спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-версії до спільних середовищ. Створюйте контрольні точки після дорогих кроків. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізнішу ланку.
@app.post("/chat")
def chat(req: ChatRequest):
"""
Conversational endpoint. Accepts user message and conversation history,
returns agent's reply after processing with tools.
"""
# Define tool functions that the agent can call
def search_tool(query: str, top_k: int = 10, tag_filter: list = None):
"""Search photos by natural language query"""
return search_photos(query=query, top_k=top_k, tags=tag_filter)
def duplicates_tool(threshold: float = 0.97):
"""Find duplicate or near-duplicate photos"""
return find_duplicates(threshold=threshold)
def tag_tool(image_path: str):
"""Generate and update tags for a specific photo"""
return generate_tags_from_vector(image_path=image_path)
# Create the agent with tools
agent = Agent(
tools=[search_tool, duplicates_tool, tag_tool],
system_prompt="""
You are a personal photo assistant. You help users search, organize,
and understand their local photo library. You have access to tools
for semantic search, duplicate detection, and tagging.
When helping users:
- Use the search tool to find photos by describing their content
- Use duplicates tool to find and clean up duplicate shots
- Use tag tool to inspect or update tags for specific photos
Always be concise and helpful. When returning photo results,
format them clearly with filenames, similarity scores, and tags.
Use emojis sparingly but helpfully.
"""
)
# Run the agent conversation
response = agent.chat(
message=req.message,
history=req.history
)
return {"response": response}
Реальні потоки взаємодії
Під час роботи над етапом реальних потоків взаємодії спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь алгоритм. Робіть контрольні пункти після дорогих кроків. Функція відновлення не повинна знову стягувати плату за той самий виклик LLM, коли оператор перезапускає пізніший етап. Під час роботи над етапом реальних потоків взаємодії спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану систему обробки даних.
Чому важливий шар агентів
Етап шару агентів працює найкраще, коли його розглядають як вимірювану поверхню. Зафіксуйте один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Зберігайте стан графа у простій та типованій формі. Вкладені структури приховують інформацію про те, який вузол заповнив певне поле, що ускладнює продовження роботи після перерв.
Виконання всього локально — та чому це важливо
Робота з виконанням усього локально та на стадії розробки найкраще функціонує, якщо її розглядати як вимірювану поверхню. Запишіть один ідеальний приклад роботи, один випадок збою та примітки щодо скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-версії до спільних середовищ. Тримайте стан графа простим та типованим. Вкладені структури приховують інформацію про те, який вузол записав яке поле, що ускладнює продовження роботи після перерв.
Нічого не залишається на вашому пристрої. Крапка.
The Nothing leaves your device stage працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, де оператори можуть перевіряти їх, не читаючи весь граф. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол записав яке поле, і ускладнюють продовження роботи після перерв. The Nothing leaves your device stage працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.
Що насправді потрібно для його запуску
На етапі «Що насправді потрібно» необхідно визначити вхідні дані, виконавця кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви елементів, визначте критерії успіху та не допускайте мовчазного часткового завершення. Вимагайте людського схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення під час компіляції не є гарантією повності бізнес-процесу.
Що далі — розширення системи
На етапі розширення What s Next необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись визначити прихований стан. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Чітке відображення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні середовища. Встановлюйте людське схвалення для кроків, які витрачають гроші чи змінюють дані в продакшені. Підключення під час компіляції не є гарантією повноти бізнес-функціоналу.
Кластеризація облич
Для етапу кластеризації облич визначте вхідні дані, власника кроку та критерії завершення ще до змін у коді. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Зберігайте конфігурацію поза кодом додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевірити, не читаючи весь код. Встановлюйте людське схвалення для операцій, які спричиняють витрати грошей чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повноти бізнес-функцій. Для етапу кластеризації облич визначте вхідні дані, власника кроку та критерії завершення ще до змін у коді. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану систему обробки даних.
OCR для скріншотів та документів
Під час роботи з OCR для скріншотів та документів спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та наслідки часткової невдачі. Такий перелік допомагає зберігати чесність у подальших змінах коду. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте безповідомного часткового виконання завдань. Робіть перевірки після дорогих кроків. Система повернення роботи не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор намагається виконати наступний етап.
Індексування кадрів відео
Під час виконання етапу індексації відеокадрів спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та наслідки часткової невдачі. Такий перелік допомагає зберігати чесність у подальших змінах коду. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних. Створюйте контрольні точки після дорогих операцій. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізнішу ланку.
Гібридний пошук: вектори + ключові слова + метадані
Під час роботи над етапом гібридного пошукового вектора слід спочатку записати контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Зберігайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Створюйте контрольні точки після дорогих кроків. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізнішу ланку. Під час роботи над етапом гібридного пошукового вектора слід спочатку записати контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану систему обробки даних.
Пошук з урахуванням часу та місця
Етап, який враховує час та місце, працює найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок невдачі та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Розділіть політику розбиття на частини та політику пошуку. Зміна однієї з них не повинна змушувати переписувати іншу при зміні показників якості.
Заключні міркування
Етап «Остаточні міркування» найкраще функціонує, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад роботи, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуальний контроль витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних середовищ. Зберігайте стан графа у простому та типованому вигляді. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.
Посилання та додаткова література
Етап «Додаткова література» функціонує найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол записав яке поле, і ускладнюють продовження роботи після перерв. Етап «Додаткова література» функціонує найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.
Чек-лист для експлуатації
Етап перевірки операційних процедур працює найкраще, якщо його розглядати як вимірювану структуру. Збережіть один ідеальний зразок виконання, один випадок збою та запис про скасування дій перед розширенням обсягу роботи.
Документуйте як успішний, так і відновлювальний сценарії роботи разом. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки.
Зберігайте стан графа у вигляді простих, типованих структур. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
Коли дозволяє бюджет, додайте тест на базову функціональність, який перевіряє критичний шлях у процесі інтеграції за допомогою фікстур, а не реальних платних API.
Віддавайте перевагу невеликим, тестованим одиницям коду перед складними скриптами. Якщо якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.
Зберігайте стан графа у вигляді простих, типованих структур. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
Перш ніж запускати стек у продакшн, заморозьте версії, створіть «золотий» запис для критичного шляху та підтвердьте кроки відкату. У спільних середовищах необхідні обмеження на частоту використання, перевірки прав доступу та чіткий власник для зміни секретів. Віддавайте перевагу надійності перед креативними одноразовими демонстраціями.
Примітка до b7b9768f8acd: не включайте ключі постачальника до репозиторію, встановіть ліміт токенів на сеанс та зберігайте записи поруч із фікстурами для оцінки, щоб подальша заміна моделей залишалася порівнянною.