DeepSeek Harness: Плагинный подход к AI-инфраструктуре
DeepSeek Harness превращает компонент AI-пайплайна в плагин, позволяя гибко собирать решения для разработки, тестирования и развертывания моделей.
Архитектура плагинов в DeepSeek Harness
Основные концепции плагинной системы
DeepSeek Harness использует декларативный подход: каждый плагин — это автономный компонент, который подключается к общим точкам расширения ядра. Ядро предоставляет набор хуков (например, on_model_load, on_validate, on_deploy), а плагин объявляет, какие из них он хочет обработать. Такая архитектура обеспечивает предсказуемость конфигурации и упрощает тестирование отдельных функций.
Основные элементы плагинной системы:
| Элемент | Назначение |
|---|---|
| Манифест | YAML-файл (plugin.yaml), в котором указаны имя, версия, зависимости и объявленные хуки. |
| Интерфейс плагина | Трейт DshPlugin, содержащий методы initialize, execute и shutdown. Реализация требует лишь тех методов, которые нужны для объявленных хуков. |
| Точка расширения | Регистратор (ExtensionRegistry), который сканирует директорию plugins/ и загружает все корректные манифесты. |
| Система конфигурации | Общий конфиг (config.toml) может содержать секции plugin.<name>, позволяя переопределать параметры без перекомпиляции. |
yaml# plugins/my‑validator/plugin.yaml
name: my-validator
version: 0.4.2
description: Проверяет входные данные на соответствие правилу «не более трёх параметров»
hooks:
- on_validate
author: Алексей Кузнецов
rust// plugins/my‑validator/src/lib.rs
use dsh_core::DshPlugin;
pub struct MyValidatorPlugin;
impl DshPlugin for MyValidatorPlugin {
fn initialize(&mut self, ctx: &dsh_core::PluginContext) -> anyhow::Result<()> {
// Сохраняем контекст для использования в execute
ctx.logger
.info("MyValidatorPlugin инициализирован")
}
fn execute(&self, data: &[u8], ctx: &dsh_core::PluginContext) -> anyhow::Result<Vec<u8>> {
// Пример валидации: подсчитываем количество запятых
let count = data.iter().filter(|&&b| b == b',').count();
if count > 3 {
ctx.logger
.error(&format!("Превышено максимальное количество параметров: {}", count));
// Возвращаем пустой результат — ядро воспринимает это как ошибку валидации
Ok(Vec::new())
} else {
// Пропускаем данные дальше
Ok(data.to_vec())
}
}
fn shutdown(&mut self, ctx: &dsh_core::PluginContext) -> anyhow::Result<()> {
ctx.logger.info("MyValidatorPlugin завершает работу")
}
}
С практической точки зрения, такой подход позволяет заменять или дополнять компоненты без перезапуска всего AI-пайплайна. Если вам нужно новое правило валидации, достаточно поместить новый плагин в каталог, обновить манифест и перезагрузить сервис — ядро автоматически вызовет объявленный хук.
Как плагины взаимодействуют с ядром
Загрузка плагина происходит в три этапа:
- Сканирование и парсинг –
ExtensionRegistryрекурсивно ищет файлыplugin.yaml. Парсер проверяет обязательные поля (name,hooks) и загружает зависимости из локального кэша crates.io или внутреннего репо. - Компоновка и инициализация – используя
cargo build --lib, система компилирует плагин как динамическую библиотеку (.so). После успешной компиляции вызываетсяinitialize, где плагин получает доступ к общему логгеру, метрикам и конфигурации. - Регистрация хуков – ядро вызывает метод
register_hookдля каждого объявленного хука, передавая ссылку на экземпляр плагина. На этом этапе плагин может влиять на поток данных: изменять входные данные, добавлять метаданные или прерывать выполнение.
rust// core/src/registry.rs
pub struct ExtensionRegistry {
plugins: Mutex<Vec<Box<dyn DshPlugin>>>,
}
impl ExtensionRegistry {
pub fn load(&self, path: &Path) -> anyhow::Result<()> {
for entry in path.read_dir()? {
let entry = entry?;
if entry.path().join("plugin.yaml").exists() {
let plugin = self.compile_and_load(entry.path())?;
self.plugins
.lock()
.unwrap()
.push(plugin);
}
}
Ok(())
}
fn compile_and_load(&self, plugin_dir: PathBuf) -> anyhow::Result<Box<dyn DshPlugin>> {
// Вызываем `cargo build` внутри plugin_dir
let output = Command::new("cargo")
.args(["build", "--release"])
.current_dir(&plugin_dir)
.output()?;
if !output.status.success() {
return Err(anyhow::anyhow!("Компиляция плагина не удалась"));
}
// Загружаем динамическую библиотеку
let lib_path = plugin_dir.join("target/release/libplugin.so");
let lib = libloading::Library::new(lib_path)?;
// Используем dlopen для создания экземпляра через фабричный символ
let create: libloading::Symbol<fn() -> Box<dyn DshPlugin>> =
unsafe { lib.get(b"create_plugin")? };
let plugin = create();
Ok(plugin)
}
}
Во время работы ядра каждый хук вызывает зарегистрированные обработчики в порядке, определённом в конфигурации. Например, при загрузке модели выполняется цепочка:
on_load → [plugin_a::execute] → [plugin_b::execute] → on_model_ready
Плагины могут общаться между собой через общий event-bus (EventBus<T>), что полезно для кросс-плагинной аналитики. Конфигурация обмена событиями определяется в общем config.toml:
toml[bus]
enabled = true
buffer_size = 1024
[bus.filters]
plugin_a = ["metric::latency"]
plugin_b = ["metric::throughput"]
Если мы посмотрим на реальный пример, плагин dsh-plugin‑metrics собирает статистику выполнения каждого хука и отправляет её в Prometheus. Другой плагин, dsh-plugin‑alert, подписывается на те же события и инициирует оповещение, когда значение превышает порог.
С технической точки зрения, такая модульность позволяет тестировать плагин изолированно: вы можете запустить единичный тест, эмулирующий ядро и передающий фиктивные данные, не затрагивая остальную систему. Это также упрощает отладку — каждый плагин имеет собственный логгер с привязкой к имени, что помогает быстро идентифицировать источник проблемы.
С практической точки зрения, знание этих механизмов означает, что вы можете безопасно расширять AI-пайплайн, не беспокоясь о неожиданных побочных эффектах. Добавление нового шага — это всего лишь создание плагина, объявление хука и перезагрузка сервиса. Такой подход сохраняет предсказуемость всей системы и в то же время даёт свободу экспериментировать.
Связанные материалы этого же сайта:
- Использование DESIGN.md из awesome-design-md для генерации UI через AI-агентов
- Graphify-Labs: Превращение кода в запросную графовую БД
- Оптимизация производительности системы ECC для AI-агентов
- Ponytail: как сделать ИИ-агента ленивым сеньором-разработ...
- Создание музейного экспоната с помощью агента на Rust
Разработка пользовательских плагинов
Структура плагина и необходимые зависимости
DeepSeek Harness использует плагинную архитектуру, которая позволяет расширять AI-пайплайн через стандартный интерфейс. Базовая структура плагина включает:
textdsh-plugins/ ├── core/ │ ├── base.py # Базовый класс плагина │ ├── registry.py # Регистратор плагинов │ └── hooks.py # Хуки выполнения ├── examples/ │ └── llm_plugin.py # Пример плагина для LLM ├── my_plugin/ │ ├── __init__.py │ ├── config.yaml # Конфигурация плагина │ ├── hooks.py # Переопределённые хуки │ └── dependencies/ # Дополнительные зависимости └── setup.py
Основные зависимости:
cordis— фреймворк для управления зависимостями и версиями плагиновai-agents— библиотека для работы с языковыми моделями и агентамиdsh-core— базовый движок DeepSeek Harness
yaml# my_plugin/config.yaml
name: "my_plugin"
version: "1.0.0"
description: "Пример плагина для обработки LLM-запросов"
dependencies:
- cordis>=2.0.0
- ai-agents>=0.5.0
- dsh-core>=1.2.0
Пример создания простого плагина для LLM
Ниже приведён минимальный плагин, который добавляет обработку пользовательских промптов через LLM:
python# my_plugin/__init__.py
from dsh_plugins.core.base import BasePlugin
from dsh_plugins.core.registry import plugin_registry
from ai_agents.llm import LLMClient
@plugin_registry.register
class LLMPlugin(BasePlugin):
"""Плагин для интеграции LLM в пайплайн"""
def __init__(self, config):
super().__init__(config)
self.llm = LLMClient(model=config.get("model", "gpt-4"))
def process(self, data, context=None):
"""Обработка данных через LLM"""
prompt = self._build_prompt(data)
response = self.llm.generate(prompt)
return self._extract_result(response)
def _build_prompt(self, data):
"""Формирование промпта на основе входных данных"""
return f"Проанализируй следующий запрос: {data}"
def _extract_result(self, response):
"""Извлечение релевантного результата из ответа LLM"""
# Простая реализация — возвращаем весь ответ
return {"result": response.text}
Настройка плагина в Harness:
python# examples/llm_plugin.py
from dsh_plugins.my_plugin import LLMPlugin
config = {
"model": "gpt-4",
"temperature": 0.7,
"max_tokens": 1024
}
plugin = LLMPlugin(config)
# Интеграция в пайплайн
from dsh_plugins.core.hooks import HookManager
hook_manager = HookManager()
hook_manager.register("pre_process", plugin.process)
Типичные проблемы и решения:
| Проблема | Решение |
|---|---|
ImportError: cannot import 'cordis' | Убедитесь, что cordis установлен: pip install cordis>=2.0.0 |
LLMPlugin not found в реестре | Проверьте, что плагин зарегистрирован через @plugin_registry.register |
Память заканчивается при больших запросах | Используйте потоковую обработку через LLMClient.stream() |
Полезные ссылки:
- Использование DESIGN.md из awesome-design-md для генерации UI через AI-агентов
- Graphify-Labs: Превращение кода в запросную графовую БД
- Оптимизация производительности системы ECC для AI-агентов
- Ponytail: как сделать ИИ-агента ленивым сеньором-разработ...
- Создание музейного экспоната с помощью агента на Rust
Интеграция с существующими инструментами
Интеграция с существующими инструментами
Подключение плагинов к CI/CD пайплайнам
DeepSeek Harness поставляется с плагином для GitHub Actions, который позволяет запускать проверку моделей прямо в пайплайне. Добавьте шаг в .github/workflows/ci.yml:
yaml- name: DeepSeek Harness CI
uses: deepseek-ai/harness-plugin@v1
with:
task: test
model: deepseek-coder-6b
data-path: ./tests/dataset
Плагин также поддерживает GitLab CI. Добавьте задание в .gitlab-ci.yml:
yamldeepseek_test:
image: python:3.11
before_script:
- pip install deepseek-harness
script:
- harness run --plugin ci --model deepseek-coder-6b --data ./tests/dataset
Для Jenkins используйте плагин через pipeline-строку:
groovypipeline { agent any stages { stage('AI Validation') { steps { deepseekHarness( task: 'test', model: 'deepseek-coder-6b', dataPath: './tests/dataset' ) } } } }
Если вам нужен кастомный CI, плагин предоставляет REST API. Пример вызова через curl:
bashcurl -X POST https://ci.example.com/api/harness/run \
-H "Content-Type: application/json" \
-d '{
"plugin": "ci",
"model": "deepseek-coder-6b",
"data_path": "./tests/dataset"
}'
Использование DESIGN.md из awesome-design-md для генерации UI через AI-агентов
Использование плагинов в локальной AI-лаборатории
Локальная AI-лаборатория обычно строится на базе Docker Compose. Добавьте сервис для Harness в docker-compose.yml:
yamlversion: '3.8'
services:
harness:
image: deepseekai/harness:latest
volumes:
- ./models:/models
- ./configs:/configs
environment:
- HARNESS_PLUGIN=lab
- MODEL_PATH=/models/deepseek-coder-6b
ports:
- "8080:8080"
После запуска контейнера вы можете запускать модели через плагин:
bash# Инициализируем плагин в лаборатории
harness init --plugin lab --config ./configs/lab.yaml
# Запускаем тестирование модели
harness run --plugin lab --model deepseek-coder-6b --dataset ./tests/dataset
Для мониторинга работы плагина используйте встроенный экспортер Prometheus. Добавьте в prometheus.yml:
yamlscrape_configs:
- job_name: 'harness'
static_configs:
- targets: ['harness:8080']
metrics_path: '/metrics'
Плагин также поддерживает интеграцию с Loki для логирования. Пример конфигурации:
yamlloki:
address: http://loki:3100
labels:
job: harness-lab
Теперь вы можете просматривать логи через Grafana:
bash# Пример запроса в Grafana
{
"expr": "{job=\"harness-lab\"} |~ \".*error.*\"",
"time_range": "1h"
}
Graphify-Labs: Превращение кода в запросную графовою БД
Оптимизация производительности системы ECC для AI-агентов
Ponytail: как сделать ИИ-агента ленивым сеньором-разработ...
Создание музейного экспоната с помощью агента на Rust
FAQ
Как начать работу с плагинами DeepSeek Harness?
Для начала работы с плагинами DeepSeek Harness вам нужно всего лишь добавить их в конфигурационный файл пайплайна. Сам процесс похож на подключение дополнительного модуля к существующему серверу — ничего сложного.
yaml# pipeline.yaml
plugins:
- name: deepseek-validator
version: v1.2.0
config:
model: "deepseek-coder:6b"
validation_rules: ["type-check", "security-scan"]
- name: deepseek-tester
version: v0.9.3
config:
test_framework: "pytest"
coverage_threshold: 80
После добавления плагинов запустите пайплайн как обычно — он автоматически обнаружит новые компоненты и включит их в процесс. Самое главное, что вам не нужно переписывать весь AI-пайплайн, чтобы попробовать что-то новое.
Использование DESIGN.md из awesome-design-md для генерации UI через AI-агентов
Какие языки программирования поддерживаются для плагинов?
DeepSeek Harness написан на Rust, но плагины можно создавать на многих языках благодаря встроенному интерпретатору. Вот что я обычно использую в реальных проектах:
Rust — для высокопроизводительных плагинов, которые нужны быстрые и предсказуемые временные характеристики:
rust// examples/validator.rs
use deepseek_harness::Plugin;
pub struct TypeValidator;
#[async_trait]
impl Plugin for TypeValidator {
async fn validate(&self, input: &str) -> Result<(), Error> {
if !input.contains('{') || !input.contains('}') {
return Err(Error::ValidationFailed("Missing brackets".into()));
}
Ok(())
}
}
Python — для скриптовых задач и быстрой прототипизации:
python# examples/tester.py
from deepseek_harness import Plugin
class CoveragePlugin(Plugin):
def __init__(self, threshold=80):
self.threshold = threshold
async def execute(self, data):
coverage = calculate_coverage(data)
if coverage < self.threshold:
raise Exception(f"Coverage {coverage}% below threshold {self.threshold}%")
return {"status": "ok", "coverage": coverage}
Go — когда нужна производительность, но вы предпочитаете синтаксис, близкий к Go:
go// examples/analyzer.go
package main
import (
"context"
"github.com/deepseek-harness/plugin-sdk"
)
type SecurityAnalyzer struct {
plugin.Sdk
}
func (a *SecurityAnalyzer) Run(ctx context.Context, input string) (string, error) {
result, err := analyzeSecurity(input)
if err != nil {
return "", err
}
return result, nil
}
Graphify-Labs: Превращение кода в запросную графовую БД
Можно ли использовать плагины в продакшене?
Да, плагины DeepSeek Harness полностью пригодны для продакшена. На самом деле, именно так я и использую их в крупной продуктовой компании, где поддерживаю инфраструктуру на Kubernetes.
Для продакшена вам нужно настроить несколько ключевых моментов:
- Система мониторинга — плагины должны быть видны в Prometheus:
yaml# monitoring.yaml
metrics:
- name: deepseek_plugin_execution_time
help: "Time taken by DeepSeek plugins to execute"
type: histogram
buckets: [0.1, 0.5, 1.0, 2.0, 5.0]
- name: deepseek_plugin_errors_total
help: "Total number of plugin errors"
type: counter
labels: ["plugin_name", "error_type"]
- Алерты — чтобы знать, когда что-то идёт не так:
yaml# alertmanager.yaml
groups:
- name: deepseek_plugins
rules:
- alert: DeepSeekPluginError
expr: deepseek_plugin_errors_total > 0 for 5m
labels:
severity: warning
annotations:
summary: "DeepSeek plugin {{labels.plugin_name}} has errors"
description: "Plugin {{labels.plugin_name}} has been failing for more than 5 minutes"
- Резервное копирование — плагины не должны быть единственным пунктом в конвейере:
bash# backup.sh
#!/bin/bash
# Создаем резервную копию конфигурации плагинов
cp -r /etc/deepseek/plugins/ /backup/plugins_$(date +%Y%m%d_%H%M%S)/
# Проверяем работоспособность основных плагинов
for plugin in validator tester analyzer; do
if ! systemctl is-active --quiet deepseek-${plugin}; then
echo "WARNING: deepseek-${plugin} is not running"
fi
done
Оптимизация производительности системы ECC для AI-агентов
Где найти примеры плагинов?
В официальном репозитории DeepSeek Harness есть несколько полезных примеров плагинов, которые я часто использую в качестве отправной точки:
Базовый шаблон плагина — хороший старт для любого нового плагина:
bash# Пример: basic-plugin
git clone https://github.com/deepseek-ai/harness-plugins.git
cd basic-plugin
Пример валидатора — проверка входных данных на соответствие правилам:
rust// examples/validator/src/lib.rs
use deepseek_harness::prelude::*;
#[derive(Debug)]
pub struct SchemaValidator;
#[async_trait]
impl Plugin for SchemaValidator {
async fn validate(&self, data: &str) -> Result<(), PluginError> {
let parsed: serde_json::Value = serde_json::from_str(data)
.map_err(|e| PluginError::Validation(e.to_string()))?;
// Простая проверка наличия обязательных полей
if !parsed.get("model").is_some() || !parsed.get("prompt").is_some() {
return Err(PluginError::Validation("Missing required fields".into()));
}
Ok(())
}
}
Пример тестера — автоматизированное тестирование с использованием pytest:
python# examples/tester/test_plugin.py
import pytest
from deepseek_harness.plugins import BasePlugin
class TestDeepSeekPlugin:
@pytest.mark.asyncio
async def test_validation(self, plugin_instance):
result = await plugin_instance.validate('{"model": "test", "prompt": "hello"}')
assert result.is_ok()
@pytest.mark.asyncio
async def test_invalid_input(self, plugin_instance):
result = await plugin_instance.validate('invalid json')
assert result.is_err()
Пример мониторинга — сбор метрик для плагинов:
go// examples/monitoring/collector.go
package main
import (
"context"
"time"
"github.com/deepseek-harness/plugin-sdk"
"github.com/prometheus/client_golang/prometheus"
)
type MetricsCollector struct {
*plugin.BasePlugin
executionTime *prometheus.HistogramVec
}
func (m *MetricsCollector) Run(ctx context.Context) error {
// Собираем метрики
go m.collectMetrics(ctx)
return nil
}
func (m *MetricsCollector) collectMetrics(ctx context.Context) {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
// Логика сбора метрик
m.reportMetrics()
case <-ctx.Done():
return
}
}
}
Ponytail: как сделать ИИ-агента ленивым сеньором-разработ...
Как обеспечить безопасность плагинов?
Безопасность плагинов — это системный вопрос, а не разовая настройка. Вот подход, который я применяю в продакшене:
1. Изолированные среды выполнения
bash# Создаем изолированные среды для каждого плагина
mkdir -p /opt/deepseek/plugins
cd /opt/deepseek/plugins
# Пример для Python-плагина
python3 -m venv validator-env
source validator-env/bin/activate
pip install deepseek-harness==1.2.0
2. Контроль версий и подписи
bash# Подписываем каждый плагин перед развертыванием
openssl dgst -sha256 plugin-validator.py > plugin-validator.py.sha256
# Проверяем подпись перед выполнением
if ! openssl dgst -sha256 -verify public_key.pem plugin-validator.py.sha256; then
echo "ERROR: Plugin signature verification failed"
exit 1
fi
3. Ограничения ресурсов
yaml# docker-compose.yml для безопасного выполнения плагинов
version: '3.8'
services:
validator:
build: ./plugins/validator
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.1'
memory: 128M
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
4. Мониторинг подозрительной активности
bash# Пример скрипта мониторинга
#!/bin/bash
# security-monitor.sh
LOG_FILE="/var/log/deepseek-plugins.log"
THRESHOLD_TIME=30 # секунд
# Проверяем, не занимает ли плагин слишком много времени
check_plugin_time() {
local plugin_name=$1
local start_time=$(grep "Starting $plugin_name" $LOG_FILE | tail -1 | cut -d'[' -f2 | cut -d']' -f1)
if [ -n "$start_time" ]; then
local current_time=$(date +%s.%N)
local elapsed=$(echo "$current_time - $start_time" | bc)
if (( $(echo "$elapsed > $THRESHOLD_TIME" | bc -l) )); then
echo "ALERT: Plugin $plugin_name took ${elapsed}s (threshold: ${THRESHOLD_TIME}s)"
# Отправляем уведомление
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"DeepSeek plugin $plugin_name is slow: ${elapsed}s\"}" \
$SLACK_WEBHOOK_URL
fi
fi
}
# Проверяем все плагины
for plugin in validator tester analyzer; do
check_plugin_time $plugin
done
5. Регулярные аудиты
bash# Ежедневная проверка безопасности
#!/bin/bash
# daily-security-check.sh
# Проверяем обновления плагинов
for plugin_dir in /opt/deepseek/plugins/*/; do
plugin_name=$(basename $plugin_dir)
echo "Checking $plugin_name for updates..."
# Здесь должна быть ваша логика проверки обновлений
# Например, сравнение хеш-сумм, проверка подписей и т.д.
done
# Проверяем наличие незарегистрированных плагинов
find /opt/deepseek/plugins -type f -name "*.py" -o -name "*.rs" -o -name "*.go" | \
while read file; do
if ! grep -q "plugin.json" $file; then
echo "WARNING: $file doesn't have plugin.json metadata"
fi
done