Практические советы: как я превратил свою фотогалерею в автономного ИИ-агента
Пошаговая инструкция по использованию практических советов: как я превратил свою фотогалерею в автономного ИИ-агента: контракты, проверки и готовые блоки кода для команд, использующих эту модель.
В этом руководстве пошагово описывается путь от сырья до функционирующей системы для проекта «Как я превратил свою галерею фотографий в автономного ИИ-агента — Полное руководство». Основной акцент сделан на практических шагах, четких проверках и коде, который можно просто добавить в репозиторий без необходимости догадываться о его назначении. На этапе обзора необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Рекомендуется использовать небольшие, тестируемые единицы вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций.
Введение
На этапе введения сначала запишите условия контракта: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Укажите названия элементов, определите критерии успеха и не допускайте молчаливого частичного выполнения задачи. Выполняйте контрольные точки после дорогостоящих операций. Система возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий этап.
Почему традиционный поиск фотографий не справляется со своей задачей
При работе над этапом «Почему традиционный поиск фотографий?» сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой список помогает избегать ошибок при последующих изменениях кода. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости заранее предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Выполняйте контрольные точки после дорогостоящих операций. Система возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий шаг.
Подход с использованием альбомов неэффективен в реальных условиях
При работе над этапом «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 сначала запишите спецификацию: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет избежать ошибок при последующих изменениях кода. Рядом с функциональными результатами записывайте временные показатели и стоимость токенов или запросов. Отслеживание затрат с самого начала предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Создавайте контрольные точки после дорогостоящих операций. Функция возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий узел.
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)
Собираем всё вместе
На этапе объединения всех компонентов сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы с настройками, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Создавайте контрольные точки после дорогостоящих операций. Система возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, если оператор попытается выполнить следующий шаг заново. На этапе объединения всех компонентов сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Предпочитайте небольшие, тестируемые модули большим скриптам. При сбое какого-либо шага причина неудачи должна указывать на конкретную ответственность, а не на запутанную структуру обработки данных.
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 «Запуск» сначала запишите условия соглашения: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как соглашение между входными данными и проверенными выходными результатами. Укажите названия элементов, определите критерии успешности и не допускайте молчаливого частичного выполнения задачи. Создавайте контрольные точки после дорогостоящих операций. При возобновлении работы система не должна снова взимать плату за один и тот же вызов большой языковой модели, если оператор пытается выполнить следующий этап.
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])
При работе над этапами разработки сначала запишите условия работы системы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Лучше использовать небольшие, тестируемые модули вместо обширных скриптов. При сбое какого-либо шага причина неудачи должна указывать на конкретную ответственность, а не на запутанную структуру обработки данных.
Автоматическая маркировка фотографий
Этап автоматической маркировки фотографий работает наилучшим образом, если рассматривать его как измеримую структуру. Соберите один пример успешного выполнения, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не допускайте молчаливого частичного выполнения задачи. Сохраняйте структуру графа простой и типизированной. Вложенные элементы скрывают информацию о том, какой узел заполнил тот или иной поле, что приводит к нарушению возобновления работы после перерывов.
Идея: классификация без обучения
Идея этапа классификации без обучения на примерах работает наилучшим образом, когда он рассматривается как измеримая поверхность. Соберите один идеальный пример обработки, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Записывайте временные показатели, а также стоимость обработки токенов или запросов рядом с функциональными результатами. Отображение стоимости на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Сохраняйте структуру графа простой и типизированной; вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и могут нарушить возобновление работы после прерываний.
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
При работе над этапом оркестрации сначала запишите контракт: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Укажите названия элементов, определите критерии успеха и не допускайте безусловного частичного завершения работы. Создавайте контрольные точки после дорогостоящих операций. Механизм возобновления работы не должен повторно запрашивать один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий узел.
Как работает OpenClaw
При работе над этапом «Как работает OpenClaw» сначала запишите условия использования: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой список поможет избежать ошибок при последующих изменениях кода. Рядом с функциональными результатами записывайте время выполнения и стоимость токенов или запросов. Отслеживание затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Выполняйте контрольные точки после дорогостоящих операций. Функция возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, если оператор пытается выполнить последующий шаг.
@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}
Реальные потоки взаимодействия
На этапе разработки реальных потоков взаимодействия сначала необходимо зафиксировать условия работы: требуемые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы с настройками, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Вносите контрольные точки после дорогостоящих операций. Система возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий шаг. На этапе разработки реальных потоков взаимодействия сначала необходимо зафиксировать условия работы: требуемые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Лучше использовать небольшие, тестируемые модули вместо обширных скриптов. При сбое какого-либо шага причина неудачи должна указывать на конкретную ответственность, а не на запутанную структуру обработки данных.
Почему важен слой агентов
Этап слоя агентов работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия создаваемым элементам, определите критерии успешного выполнения и не соглашайтесь на молчаливое частичное завершение работы. Сохраняйте структуру графа простой и типизированной. Вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, что приводит к нарушению возобновления работы после перерывов.
Работа со всем локально — и почему это важно
Режим работы «Всё на локальном устройстве» и этапы разработки работают наилучшим образом, когда их рассматривают как измеримые элементы. Сначала зафиксируйте один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию, прежде чем расширять объём работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счёты при переходе от демо-среды к общедоступным средам. Сохраняйте структуру графа простой и типизированной; вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и могут нарушить возобновление работы после прерываний.
Ничего не покидает ваше устройство. Пunkt.
Система Nothing leaves your device работает наилучшим образом, когда рассматривается как измеримая поверхность. Сохраняйте один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работы. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Сохраняйте состояние структуры простым и типизированным. Вложенные объекты скрывают информацию о том, какой узел записал какое поле, и мешают возобновлению работы после прерываний. Система Nothing leaves your device работает наилучшим образом, когда рассматривается как измеримая поверхность. Сохраняйте один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работы. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг сбивается, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций.
Что на самом деле требуется для её работы
На этапе определения того, что на самом деле требуется, необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия результатам работы, определите критерии успеха и не допускайте молчаливого частичного завершения задачи. Внедряйте утверждение человека для операций, связанных с тратой денег или изменением производственных данных. Подключение компонентов во время компиляции не гарантирует полноты реализации бизнес-логики.
Что дальше — расширение системы
На этапе расширения What’s Next необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения и стоимость токенов или запросов. Отображение затрат на раннем этапе предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды. Для операций, связанных с тратой денег или изменением производственных данных, требуется утверждение человека. Подключение на этапе компиляции не гарантирует полноты решения с точки зрения бизнес-процессов.
Кластеризация лиц
На этапе кластеризации лиц необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища конфиденциальных данных и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Для операций, связанных с тратой денег или изменением производственных данных, необходимо предусмотреть утверждение человеком. Простое подключение компонентов во время компиляции не гарантирует полноты реализации бизнес-логики. На этапе кластеризации лиц необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Лучше использовать небольшие, тестируемые модули вместо обширных скриптов. При сбое шага он должен указывать на конкретную причину, а не на сложную структуру обработки данных.
OCR для скриншотов и документов
При работе над OCR для скриншотов и документов сначала запишите условия соглашения: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист поможет избежать ошибок при последующих изменениях кода. Рассматривайте этот этап как соглашение между входными данными и проверенными результатами. Укажите названия элементов, определите критерии успешности и не допускайте молчаливого частичного выполнения задачи. Вводите контрольные точки после дорогостоящих операций. Система возобновления работы не должна повторно взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий этап.
Индексация кадров видео
При работе над этапом индексации видеокадров сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает избегать ошибок при последующих изменениях кода. Рядом с функциональными результатами записывайте временные показатели и стоимость токенов или запросов. Отображение затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Выполняйте контрольные точки после дорогостоящих операций. Функция возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, если оператор попытается выполнить последующий шаг.
Гибридный поиск: векторы + ключевые слова + метаданные
При работе с этапом гибридного поиска на основе векторов ключевых слов сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Создавайте контрольные точки после дорогостоящих операций. Функция возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий шаг. При работе с этапом гибридного поиска на основе векторов ключевых слов сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Предпочитайте небольшие, тестируемые единицы кода большим скриптам. При сбое какого-либо шага причина неудачи должна указывать на конкретную ответственность, а не на запутанную структуру обработки данных.
Поиск с учётом времени и местоположения
Этот этап работает наилучшим образом, если рассматривать его как измеримую поверхность. Соберите один идеальный пример результатов, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задачи. Разделяйте политику разбиения данных на части и политику поиска. Изменение одной из них не должно принуждать к переписыванию другой при изменении показателей качества.
Заключительные мысли
Этап «Заключительные мысли» работает наилучшим образом, если рассматривать его как измеримую поверхность. Зафиксируйте один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на раннем этапе предотвращает неожиданные счёты при переходе от демо-среды к общедоступным средам. Сохраняйте структуру графа простой и типизированной; вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и могут нарушить возобновление работы после прерываний.
Ссылки и дополнительная литература
Этап «Справки и дополнительная литература» работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работы. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Сохраняйте состояние структуры простым и типизированным. Вложенные данные маскируют информацию о том, какой узел заполнил тот или иной поле, и приводят к нарушению продолжения работы после перерывов. Этап «Справки и дополнительная литература» работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работы. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-либо шаг срабатывает некорректно, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций.
Чек-лист для эксплуатации
Этап составления чек-листа операций работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример выполнения, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ.
Задокументируйте одновременно успешный и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки.
Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
Каждый раз, когда это позволяют бюджетные ограничения, добавляйте тест на базовую работоспособность, который проверяет критически важные этапы в рамках CI с использованием фикстчеров, а не реальных платных API.
Предпочитайте небольшие, тестируемые единицы кода большим скриптам. При сбое какого-либо шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций.
Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
Перед тем как запускать стек в продакшен, заморозьте версии, сделайте «золотой» отчет для критического пути и уточните шаги возврата к предыдущей версии. В совместных средах необходимы ограничения по частоте запросов, проверки принадлежности пользователя и четко определенный ответственный за обновление секретов. Лучше выбирать надежность, чем креативные одноразовые демонстрации.
Примечание для b7b9768f8acd: не храните ключи поставщика в репозитории, установите лимит токенов на сессию и сохраняйте отчеты рядом с фикстурами для оценки, чтобы последующие замены моделей оставались сопоставимыми.