Как я подружил ZennoPoster с локальным ИИ — и он сам начал чинить мои скрипты

SAT

Client
Регистрация
24.12.2024
Сообщения
56
Благодарностей
116
Баллы
33
140543

Привет всем!

Хочу поделиться кейсом — как подключил локальный ИИ

к ZennoPoster через файловый сигнал.

Сразу важный момент про ограничение: проект ZennoPoster
зашифрован, C#-код внутри тоже. Поэтому AI Code Sherlock
не видит скрипты напрямую из проекта.

Workflow такой:
1. Ты открываешь нужный C#-блок в ZennoPoster
2. Копируешь код в текстовый файл или прямо в поле чата
3. Копируешь лог ошибки из ZP
4. AI Code Sherlock анализирует и выдаёт патч
5. Ты применяешь патч обратно в ZP вручную

Либо через File Signal автоматически — ZP сам пишет
запрос в файл, Sherlock отвечает патчем, ZP его читает.

Звучит как лишний шаг — но на практике это быстрее
чем копировать код в ChatGPT и обратно вручную.
Плюс история всех патчей сохраняется, бэкапы
создаются автоматически.

Буду рад фидбеку от тех кто работает с ZP регулярно —
что ещё можно автоматизировать в этом workflow?

Я автоматизирую всё что движется уже несколько лет. ZennoPoster — мой основной инструмент. Шаблоны, парсеры, регистраторы, постеры — всё через него.

И у меня была одна боль, которая не давала покоя.

Боль, которую знает каждый зенно-разработчик

Ты пишешь шаблон. Долго. Потом запускаешь — и он падает. Смотришь в лог:

[ERROR] NullReferenceException at ProcessResponse() line 847

[ERROR] Index was outside the bounds of the array
[ERROR] Object reference not set to an instance of an object

Окей. Открываешь C#-код, ищешь строку 847, пытаешься понять что там происходит. Думаешь 20 минут. Фиксишь. Запускаешь снова. Падает на строке 1203.
Я прогонял через ChatGPT, через Claude. Копировал ошибку, копировал код, ждал ответа, копировал ответ обратно. Потом снова. Потом снова.
Это работало — но это был ад ручного труда.
Я подумал: а что если ИИ будет делать это сам? Читать лог, находить проблему, писать фикс, применять его — без моего участия?
Так начался проект AI Code Sherlock.


140587

Что такое AI Code Sherlock

Если коротко: это бесплатный десктопный IDE-ассистент с открытым исходным кодом, который:

  • Читает логи ошибок
  • Находит первопричину (не симптом, а именно причину)
  • Генерирует точечный патч — только те строки которые нужно изменить
  • Применяет его с бэкапом
  • Может делать это автономно в цикле

Ключевое слово — точечный. Большинство ИИ-инструментов переписывают весь файл целиком. Это катастрофа для рабочего шаблона на 2000 строк. AI Code Sherlock меняет только конкретный блок:

[SEARCH_BLOCK]

result = response.SelectToken("data[0].value");
[REPLACE_BLOCK]
if (response == null || !response.HasValues)
return null;
result = response.SelectToken("data[0].value");

[END_PATCH]

Нашёл точное вхождение → проверил что оно одно → сделал бэкап → заменил. Если что-то пошло не так — один клик и откат.


Самая интересная часть: интеграция с ZennoPoster через File Signal

Вот где начинается магия.

AI Code Sherlock имеет встроенный механизм File Signal — это IPC (межпроцессное взаимодействие) через обычные текстовые файлы на диске.

Схема работает так:

[ZennoPoster шаблон]

↓ пишет запрос в файл
signals/request/req_001.txt

[AI Code Sherlock мониторит папку]
↓ читает запрос, отправляет ИИ
ИИ обрабатывает...
↓ пишет ответ
signals/response/req_001.txt

[ZennoPoster читает ответ]

Никаких API-серверов. Никаких портов. Никаких сетевых настроек. Просто папки на диске.



Как настроить в ZennoPoster

В шаблоне ZennoPoster добавляешь 3 блока C# код с таким содержимым:


Сниппет 1 — Читаем запрос из папки:
string requestFolder  = @"C:\AI Code Sherlock\signals\request";
string responseFolder = @"C:\AI Code Sherlock\signals\response";

System.IO.Directory.CreateDirectory(requestFolder);
System.IO.Directory.CreateDirectory(responseFolder);

project.Variables["signal_request_id"].Value = "";
project.Variables["signal_prompt"].Value     = "";

int waited = 0;
string reqFile = "";

while (waited < 120000)
{
    string[] files = System.IO.Directory.GetFiles(requestFolder, "*.txt");
    if (files.Length > 0)
    {
        reqFile = files[0];
        break;
    }
    System.Threading.Thread.Sleep(500);
    waited += 500;
}

if (string.IsNullOrEmpty(reqFile))
{
    project.SendInfoToLog("Signal: таймаут — нет запроса за 120с", true);
    throw new Exception("no_request");
}

System.Threading.Thread.Sleep(150);

string requestId = System.IO.Path.GetFileNameWithoutExtension(reqFile);
string prompt    = System.IO.File.ReadAllText(reqFile, System.Text.Encoding.UTF8).Trim();

System.IO.File.Delete(reqFile);

project.Variables["signal_request_id"].Value = requestId;
project.Variables["signal_prompt"].Value     = prompt;

project.SendInfoToLog("Signal: получен [" + requestId + "] (" + prompt.Length + " симв.)", true);
Сниппет 2 — Отправляем запрос к ИИ (HTTP):
string prompt = project.Variables["signal_prompt"].Value;

if (string.IsNullOrEmpty(prompt))
{
    project.SendInfoToLog("Signal: промпт пустой", true);
    throw new Exception("empty_prompt");
}

string apiUrl = "http://localhost:11434/v1/chat/completions";
// Для OpenAI: "https://api.openai.com/v1/chat/completions"
string apiKey = "";
// Для OpenAI: "sk-..."
string model  = "gemini-3-flash-preview";
// Или: "gpt-4o", "llama3.2" и т.д.

// Экранируем промпт вручную (без Newtonsoft)
string escapedPrompt = prompt
    .Replace("\\", "\\\\")
    .Replace("\"", "\\\"")
    .Replace("\r\n", "\\n")
    .Replace("\n", "\\n")
    .Replace("\r", "\\n")
    .Replace("\t", "\\t");

string jsonBody = "{\"model\":\"" + model + "\",\"messages\":[{\"role\":\"user\",\"content\":\"" + escapedPrompt + "\"}],\"temperature\":0.2,\"max_tokens\":4096}";

var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(apiUrl);
request.Method      = "POST";
request.ContentType = "application/json";
request.Timeout     = 120000;

if (!string.IsNullOrEmpty(apiKey))
    request.Headers.Add("Authorization", "Bearer " + apiKey);

byte[] bodyBytes = System.Text.Encoding.UTF8.GetBytes(jsonBody);
request.ContentLength = bodyBytes.Length;

using (var stream = request.GetRequestStream())
    stream.Write(bodyBytes, 0, bodyBytes.Length);

string rawJson = "";
try
{
    using (var resp = (System.Net.HttpWebResponse)request.GetResponse())
    using (var reader = new System.IO.StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8))
        rawJson = reader.ReadToEnd();
}
catch (System.Net.WebException ex)
{
    using (var reader = new System.IO.StreamReader(ex.Response.GetResponseStream(), System.Text.Encoding.UTF8))
        rawJson = reader.ReadToEnd();
    project.SendInfoToLog("Signal: ошибка API — " + rawJson, true);
    throw new Exception("api_error");
}

// Парсим без Newtonsoft — ищем "content":"..."
var match = System.Text.RegularExpressions.Regex.Match(
    rawJson,
    "\"content\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"",
    System.Text.RegularExpressions.RegexOptions.Singleline
);

string answer = match.Success ? match.Groups[1].Value : rawJson;

// Обратное экранирование
answer = answer
    .Replace("\\n", "\n")
    .Replace("\\r", "\r")
    .Replace("\\t", "\t")
    .Replace("\\\"", "\"")
    .Replace("\\\\", "\\");

project.Variables["signal_ai_response"].Value = answer.Trim();
project.SendInfoToLog("Signal: ИИ ответил (" + answer.Length + " симв.)", true);
Сниппет 2 — Отправляем запрос к ИИ (local Ollama):
string prompt = project.Variables["signal_prompt"].Value;

if (string.IsNullOrEmpty(prompt))
{
    project.SendInfoToLog("Signal: промпт пустой", true);
    throw new Exception("empty_prompt");
}

// ── Настройки Ollama ────────────────────────────────────────
string ollamaUrl = "http://localhost:11434/api/generate";
string model     = "llama3"; // ← замени на свою модель
// Список моделей: ollama list

// Экранируем промпт
string escapedPrompt = prompt
    .Replace("\\", "\\\\")
    .Replace("\"", "\\\"")
    .Replace("\r\n", "\\n")
    .Replace("\n", "\\n")
    .Replace("\r", "\\n")
    .Replace("\t", "\\t");

// Ollama /api/generate — stream:false чтобы получить один JSON
string jsonBody = "{\"model\":\"" + model + "\",\"prompt\":\"" + escapedPrompt + "\",\"stream\":false,\"options\":{\"temperature\":0.2,\"num_predict\":4096}}";

var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(ollamaUrl);
request.Method      = "POST";
request.ContentType = "application/json";
request.Timeout     = 300000; // 5 минут — локальные модели медленнее

byte[] bodyBytes = System.Text.Encoding.UTF8.GetBytes(jsonBody);
request.ContentLength = bodyBytes.Length;

using (var stream = request.GetRequestStream())
    stream.Write(bodyBytes, 0, bodyBytes.Length);

string rawJson = "";
try
{
    using (var resp = (System.Net.HttpWebResponse)request.GetResponse())
    using (var reader = new System.IO.StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8))
        rawJson = reader.ReadToEnd();
}
catch (System.Net.WebException ex)
{
    string errBody = "";
    try
    {
        using (var reader = new System.IO.StreamReader(ex.Response.GetResponseStream(), System.Text.Encoding.UTF8))
            errBody = reader.ReadToEnd();
    }
    catch {}
    project.SendInfoToLog("Signal: ошибка Ollama — " + ex.Message + " | " + errBody, true);
    throw new Exception("ollama_error");
}

// Ollama возвращает: {"model":"...","response":"текст ответа","done":true,...}
// Парсим поле "response"
var match = System.Text.RegularExpressions.Regex.Match(
    rawJson,
    "\"response\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"",
    System.Text.RegularExpressions.RegexOptions.Singleline
);

string answer = match.Success ? match.Groups[1].Value : rawJson;

// Обратное экранирование
answer = answer
    .Replace("\\n", "\n")
    .Replace("\\r", "\r")
    .Replace("\\t", "\t")
    .Replace("\\\"", "\"")
    .Replace("\\\\", "\\");

project.Variables["signal_ai_response"].Value = answer.Trim();
project.SendInfoToLog("Signal: Ollama ответил (" + answer.Length + " симв.)", true);
Сниппет 3 — Записываем ответ в папку response:
string responseFolder = @"C:\AI Code Sherlock\signals\response";
System.IO.Directory.CreateDirectory(responseFolder);

string requestId  = project.Variables["signal_request_id"].Value;
string aiResponse = project.Variables["signal_ai_response"].Value;

if (string.IsNullOrEmpty(requestId))
{
    project.SendInfoToLog("Signal: нет request_id", true);
    throw new Exception("no_request_id");
}

if (string.IsNullOrEmpty(aiResponse))
{
    project.SendInfoToLog("Signal: ответ пустой", true);
    throw new Exception("empty_response");
}

string resFile = System.IO.Path.Combine(responseFolder, requestId + ".txt");
System.IO.File.WriteAllText(resFile, aiResponse, System.Text.Encoding.UTF8);

project.SendInfoToLog("Signal: записан → " + requestId + ".txt", true);

// Сброс для следующего цикла
project.Variables["signal_request_id"].Value  = "";
project.Variables["signal_prompt"].Value      = "";
project.Variables["signal_ai_response"].Value = "";

И всё. ZennoPoster отправил запрос — AI Code Sherlock ответил.

Для динамической компиляции и удобной отладки используйте этот C#-загрузчик. Он позволяет на лету подтягивать и выполнять вашу основную логику, предварительно сохраненную в .cs файл.
СНИППЕТ ПОД АВТОМАТИЧЕСКИЙ ДЕБАГИНГ ИЛИ AUTO-PIPELINE:
// ── ЗАГРУЗЧИК — вставляй в каждый из 3 кубиков, меняя только methodName ──
string csFile    = @"C:\AI Code Sherlock\zp_scripts\signal_handler.cs";
string methodName = "ReadRequest"; // ← меняй: ReadRequest / QueryOllama / WriteResponse

// Читаем исходник
string sourceCode = System.IO.File.ReadAllText(csFile, System.Text.Encoding.UTF8);

// Компилируем
var provider = new Microsoft.CSharp.CSharpCodeProvider();
var compParams = new System.CodeDom.Compiler.CompilerParameters();
compParams.GenerateInMemory   = true;
compParams.ReferencedAssemblies.Add("System.dll");
compParams.ReferencedAssemblies.Add("System.Net.dll");
compParams.ReferencedAssemblies.Add("System.Core.dll");
// Путь к ZennoPoster DLL — обычно здесь:
compParams.ReferencedAssemblies.Add(@"C:\Program Files\ZennoLab\RU\ZennoPoster Pro V7\7.8.15.0\Progs\ZennoLab.InterfacesLibrary.dll");

var result = provider.CompileAssemblyFromSource(compParams, sourceCode);

if (result.Errors.HasErrors)
{
    string errors = "";
    foreach (System.CodeDom.Compiler.CompilerError e in result.Errors)
        errors += "Строка " + e.Line + ": " + e.ErrorText + "\n";
    System.IO.File.AppendAllText(
        @"C:\AI Code Sherlock\zp_scripts\signal_handler.log",
        "[" + DateTime.Now + "] COMPILE ERROR:\n" + errors,
        System.Text.Encoding.UTF8
    );
    throw new Exception("compile_error: " + errors);
}

// Запускаем нужный метод
var assembly = result.CompiledAssembly;
var type     = assembly.GetType("SignalHandler");
var method   = type.GetMethod(methodName);
method.Invoke(null, new object[] { project });

signal_handler.cs:
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using ZennoLab.InterfacesLibrary.ProjectModel;

public class SignalHandler
{
    // Путь к лог-файлу
    private static string logFile = @"C:\AI Code Sherlock\zp_scripts\signal_handler.log";

    // ── Запись в лог ───────────────────────────────────────
    public static void Log(string message)
    {
        string line = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + message;
        try { File.AppendAllText(logFile, line + "\r\n", Encoding.UTF8); }
        catch { }
    }

    // ── Сниппет 1: Читаем входящий запрос ─────────────────
    public static void ReadRequest(IZennoPosterProjectModel project)
    {
        string requestFolder  = @"C:\AI Code Sherlock\signals\request";
        string responseFolder = @"C:\AI Code Sherlock\signals\response";

        Directory.CreateDirectory(requestFolder);
        Directory.CreateDirectory(responseFolder);

        project.Variables["signal_request_id"].Value = "";
        project.Variables["signal_prompt"].Value     = "";

        Log("ReadRequest: ожидаем запрос...");

        int waited = 0;
        string reqFile = "";

        while (waited < 120000)
        {
            string[] files = Directory.GetFiles(requestFolder, "*.txt");
            if (files.Length > 0) { reqFile = files[0]; break; }
            Thread.Sleep(500);
            waited += 500;
        }

        if (string.IsNullOrEmpty(reqFile))
        {
            Log("ReadRequest: таймаут 120с — запросов нет");
            throw new Exception("no_request");
        }

        Thread.Sleep(150);

        string requestId = Path.GetFileNameWithoutExtension(reqFile);
        string prompt    = File.ReadAllText(reqFile, Encoding.UTF8).Trim();
        File.Delete(reqFile);

        project.Variables["signal_request_id"].Value = requestId;
        project.Variables["signal_prompt"].Value     = prompt;

        Log("ReadRequest: получен [" + requestId + "] (" + prompt.Length + " симв.)");
        project.SendInfoToLog("Signal: получен [" + requestId + "]", true);
    }

    // ── Сниппет 2: Запрос к Ollama ─────────────────────────
    public static void QueryOllama(IZennoPosterProjectModel project)
    {
        string prompt = project.Variables["signal_prompt"].Value;

        if (string.IsNullOrEmpty(prompt))
        {
            Log("QueryOllama: промпт пустой");
            throw new Exception("empty_prompt");
        }

        string ollamaUrl = "http://localhost:11434/api/generate";
        string model     = "llama3"; // ← меняй модель здесь

        Log("QueryOllama: отправляем запрос к модели " + model);

        string escapedPrompt = prompt
            .Replace("\\", "\\\\").Replace("\"", "\\\"")
            .Replace("\r\n", "\\n").Replace("\n", "\\n")
            .Replace("\r", "\\n").Replace("\t", "\\t");

        string jsonBody = "{\"model\":\"" + model + "\",\"prompt\":\"" + escapedPrompt
            + "\",\"stream\":false,\"options\":{\"temperature\":0.2,\"num_predict\":4096}}";

        var request = (HttpWebRequest)WebRequest.Create(ollamaUrl);
        request.Method      = "POST";
        request.ContentType = "application/json";
        request.Timeout     = 300000;

        byte[] bodyBytes = Encoding.UTF8.GetBytes(jsonBody);
        request.ContentLength = bodyBytes.Length;
        using (var s = request.GetRequestStream()) s.Write(bodyBytes, 0, bodyBytes.Length);

        string rawJson = "";
        try
        {
            using (var resp = (HttpWebResponse)request.GetResponse())
            using (var reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8))
                rawJson = reader.ReadToEnd();
        }
        catch (WebException ex)
        {
            string err = "";
            try { using (var r = new StreamReader(ex.Response.GetResponseStream(), Encoding.UTF8)) err = r.ReadToEnd(); } catch {}
            Log("QueryOllama: ошибка — " + ex.Message + " | " + err);
            project.SendInfoToLog("Signal: ошибка Ollama — " + ex.Message, true);
            throw new Exception("ollama_error");
        }

        var match = Regex.Match(rawJson,
            "\"response\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"",
            RegexOptions.Singleline);

        string answer = match.Success ? match.Groups[1].Value : rawJson;
        answer = answer.Replace("\\n","\n").Replace("\\r","\r")
                       .Replace("\\t","\t").Replace("\\\"","\"").Replace("\\\\","\\");

        project.Variables["signal_ai_response"].Value = answer.Trim();

        Log("QueryOllama: ответ получен (" + answer.Length + " симв.)");
        project.SendInfoToLog("Signal: Ollama ответил (" + answer.Length + " симв.)", true);
    }

    // ── Сниппет 3: Записываем ответ в response ─────────────
    public static void WriteResponse(IZennoPosterProjectModel project)
    {
        string responseFolder = @"C:\AI Code Sherlock\signals\response";
        Directory.CreateDirectory(responseFolder);

        string requestId  = project.Variables["signal_request_id"].Value;
        string aiResponse = project.Variables["signal_ai_response"].Value;

        if (string.IsNullOrEmpty(requestId))
        {
            Log("WriteResponse: нет request_id");
            throw new Exception("no_request_id");
        }

        string resFile = Path.Combine(responseFolder, requestId + ".txt");
        File.WriteAllText(resFile, aiResponse, Encoding.UTF8);

        Log("WriteResponse: записан → " + requestId + ".txt");
        project.SendInfoToLog("Signal: ответ записан → " + requestId + ".txt", true);

        project.Variables["signal_request_id"].Value  = "";
        project.Variables["signal_prompt"].Value      = "";
        project.Variables["signal_ai_response"].Value = "";
    }
}
Реальный кейс: автономная отладка парсера

Расскажу конкретный пример из своей практики.
У меня был парсер маркетплейса. Работал нормально месяц, потом сайт обновил структуру и всё сломалось. Лог был такой:


[10:23:41][ERR] XPathException: Expression must evaluate to a node-set

at ParseProductCard() line 312
[10:23:41][ERR] Attribute 'data-price' not found on element
at ExtractPrice() line 445

[10:23:41][ERR] Null reference in BuildProductObject() line 521

Три ошибки. Три разных места. Раньше я бы потратил час на отладку.

Вместо этого я открыл AI Code Sherlock, включил Режим Шерлока, вставил лог — и нажал отправить.

Через 15 секунд:

АНАЛИЗ ШЕРЛОКА:

Первопричина: сайт изменил структуру карточки товара —
атрибут data-price перенесён в дочерний span.
Все три ошибки — следствие одного изменения.

Уверенность: ВЫСОКАЯ (94%) — XPath-ошибка однозначно
указывает на изменение структуры DOM.

ПАТЧ:
[SEARCH_BLOCK]

var price = node.SelectSingleNode("@data-price")?.Value;
[REPLACE_BLOCK]
var price = node.SelectSingleNode(".//span[@class='price']/@data-price")
?.Value
?? node.SelectSingleNode("@data-price")?.Value;

[END_PATCH]

Применил. Парсер заработал. Всё время — 3 минуты.


Auto-Improve Pipeline: ИИ итерирует сам

Это самая мощная фича для тех кто пишет алгоритмы обработки данных.
Настраиваешь:

  • Цель: "скрипт должен обрабатывать 1000 записей без ошибок и с точностью > 95%"
  • Скрипт: твой Python/C# скрипт для теста
  • Стратегия: одна из восьми (Safe Ratchet, Balanced, Explorer...)
  • Итераций: до 20
Нажимаешь Run — и идёшь пить кофе.

Pipeline сам:

  1. Запускает скрипт
  2. Читает лог
  3. Генерирует патч
  4. Проверяет синтаксис
  5. Применяет (с бэкапом)
  6. Запускает снова
  7. Проверяет метрики
  8. Повторяет
В моём случае за 7 итераций точность парсера поднялась с 67% до 91%.

[PIPELINE] Итерация 1/20 стратегия=BALANCED

[RUN] test_parser.py → exit 0 (8.2s) точность=0.67
[ПАТЧ] ✓ применён · бэкап создан
[RUN] test_parser.py → exit 0 (8.1s) точность=0.74 ↑+0.07

[PIPELINE] Итерация 4/20
[RUN] точность=0.88 ↑+0.14 от старта
...

[PIPELINE] Итерация 7/20
[RUN] точность=0.91 ↑ ЦЕЛЬ ДОСТИГНУТА

[PIPELINE] ✅ GOAL_ACHIEVED · остановка


8 стратегий ИИ для разных задач
Это не просто настройка — это реально разные подходы к решению проблем:


СтратегияКогда использовать
ConservativeИсправить только ошибки, не трогать рабочее
⚖ BalancedИсправить + умеренные улучшения (по умолчанию)
AggressiveРефакторинг, максимум изменений
Safe RatchetПрименять только если метрики улучшились
ExplorerКаждая итерация — принципиально новый подход
HypothesisСформировать гипотезу → проверить → сделать вывод
EnsembleГенерирует 3 варианта патча, выбирает лучший
ExploitУсиливать то что уже работает

Для ZennoPoster-разработки я чаще всего использую Conservative (чинить только сломанное) и Safe Ratchet (только если точность улучшилась).



Работает офлайн — твой код никуда не уходит

Это важно для тех кто работает с коммерческими шаблонами.
AI Code Sherlock работает полностью локально с Ollama:


Bash:
ollama serve

ollama pull deepseek-coder-v2  # лучшая модель для кода
Никаких API-ключей. Никакой отправки кода на чужие серверы. Всё на твоей машине.

Если хочешь мощнее — подключаешь облачные модели: GPT-4o, Gemini 3.0 Flash, Groq (llama3.3-70b бесплатно), Mistral Codestral.




Консенсус-движок: опрашиваем несколько моделей

Для критичных задач можно включить Consensus Engine — это когда несколько моделей отвечают одновременно, а система выбирает лучший ответ:

  • Vote: патч принимается если ≥N моделей согласны
  • Best-of-N: выбирается ответ с наибольшим числом корректных патчей
  • Merge: берём уникальные патчи от всех моделей
  • Judge: одна модель читает ответы остальных и выбирает лучший
Для отладки сложных шаблонов это реально помогает — разные модели видят разные аспекты проблемы.



Карта ошибок: память проекта

Каждая ошибка сохраняется с подтверждённым решением. Когда та же ошибка появляется снова — ИИ видит контекст:

## КАРТА ОШИБОК — ранее решённые проблемы:


Ошибка: NullReferenceException в ParseProductCard()
Причина: отсутствие проверки на null перед обращением к дочерним узлам
Решение: добавить null-guard перед каждым SelectSingleNode()

⚠ ЗАПРЕЩЁННЫЕ ПОДХОДЫ:
- НЕ оборачивать в try/catch без исправления причины — уже пробовали, не помогло

- Вместо этого: проверять наличие узла перед обращением

Меньше повторяющихся ошибок. Меньше кругов отладки.



Честно про статус проекта

Я должен сказать прямо: AI Code Sherlock — ранняя разработка.

Что это значит на практике:

  • Основной функционал работает стабильно — патчи, Pipeline, File Signal, версионирование
  • Интерфейс функциональный, не идеальный — где-то не хватает polish
  • Тестировалось в основном на Python и C# — другие языки работают, но меньше проверены
  • File Signal с ZennoPoster работает, но потребует от тебя немного настройки под свою конкретную конфигурацию
Что уже точно работает хорошо:
  • Парсинг патчей из ответов ИИ
  • Применение с бэкапом и версионированием
  • Pipeline с метриками и auto-rollback
  • Режим Шерлока для анализа ошибок
  • File Signal IPC
  • Работа с Ollama офлайн

Это не продукт корпорации с командой из 50 человек. Это реальный инструмент который я сделал для себя, и который решает реальные задачи прямо сейчас.


Попробовать

GitHub (исходный код, всё бесплатно):

https://github.com/signupss/ai-code-sherlock

Сайт с описанием всех фич:

https://codesherlock.dev

Установка:


Bash:
git clone https://github.com/signupss/ai-code-sherlock.git

cd ai-code-sherlock

pip install -r requirements.txt

python main.py
Нужен Python 3.11+. Зависимостей минимум — PyQt6, aiohttp, aiofiles.

Если захочешь попробовать File Signal с ZennoPoster

Напиши в комментариях — покажу полный пример шаблона ZennoPoster с интеграцией, включая:


  • Чтение лога ошибки из переменной проекта
  • Отправку в AI Code Sherlock
  • Получение патча обратно
  • Автоматическое применение

Буду рад фидбеку — особенно от тех кто работает с ZennoPoster регулярно. Что ещё должен уметь инструмент чтобы реально помогать в этом workflow?



Проект в активной разработке. Звезда на GitHub очень помогает — это сигнал что инструмент нужен людям.


⭐
https://github.com/signupss/ai-code-sherlock
 

Вложения

  • 21 КБ Просмотры: 3
Последнее редактирование:
  • Спасибо
Реакции: brun0 и deskuznetsov

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)