Files
marketing-parser/Техническое Задание на реализацию AI-агента для синтеза отчётов с использованием Ollama.md
T
2025-10-05 16:40:36 +05:00

8.3 KiB
Raw Blame History

Проект: Доработка модуля генерации отчётов в существующем Java/Spring Boot бэкенде.

  1. Общее описание Целью является создание "Агента-синтезатора" внутри бэкенда. Этот агент будет использовать существующий сервис OllamaAnalyticsService для взаимодействия с локально развёрнутой языковой моделью Ollama. Задача агента — принять "сырые" тезисы (learnings) от сервиса deep-research и с помощью Ollama сгенерировать из них связный, структурированный и стилистически выверенный текстовый отчёт в формате Markdown.

  2. Требования к реализации 2.1. Создание нового сервиса: ReportSynthesisService

Необходимо создать новый Spring-сервис (@Service).

Этот сервис будет зависеть от уже существующего OllamaAnalyticsService и должен инжектировать его (@Autowired).

Сервис должен иметь один публичный метод:

Java

public Mono synthesizeReport(String originalQuery, List learnings, String lang) Вход:

originalQuery: Исходная тема исследования.

learnings: Список "сырых" тезисов от deep-research.

lang: Целевой язык отчёта.

Выход: Mono, содержащий готовый отчёт в формате Markdown.

2.2. Логика работы ReportSynthesisService

Метод synthesizeReport получает на вход данные.

Он объединяет список learnings в единый блок текста, где каждый тезис начинается с новой строки (например, с помощью String.join("\n- ", learnings)).

Он формирует промпт (инструкцию) для модели Ollama (см. п. 2.3).

Ключевой шаг: Он вызывает метод generateWithInstruction из вашего существующего OllamaAnalyticsService:

Java

// Преобразуем асинхронный вызов в Mono Mono synthesizedReportMono = Mono.fromCallable(() -> ollamaAnalyticsService.generateWithInstruction(aggregatedLearnings, prompt) ); Метод возвращает synthesizedReportMono.

2.3. Разработка промпта для Ollama

Промпт — это сердце качественного результата. Он должен быть чётким и структурированным. Этот промпт будет реализован как форматированная строка внутри ReportSynthesisService.

Пример промпта для Ollama (модели типа Llama3, Gemma):

Ты — профессиональный AI-аналитик. Твоя задача — написать подробный и структурированный отчёт на основе предоставленных данных. Не добавляй никаких предисловий или комментариев от себя, просто верни готовый отчёт.

Тема исследования:

${originalQuery}

Собранные данные (тезисы):

  • ${learnings_as_string}

Твоя задача:

  1. Язык: Напиши отчёт полностью на ${lang} языке.
  2. Структура: Отчёт должен иметь чёткую структуру: введение, основная часть с несколькими разделами и подразделами, и заключение.
  3. Форматирование: Используй Markdown. Для главных заголовков разделов используй ##, для подзаголовков — ###. Для списков используй -.
  4. Стиль: Преврати разрозненные тезисы в единую, связную и хорошо написанную статью. Не просто перечисляй факты, а анализируй и обобщай их.
  5. Ограничение: Используй только ту информацию, которая дана в собранных данных. Не придумывай ничего от себя.

Начинай отчёт с главного заголовка. 2.4. Интеграция в существующий асинхронный процесс

Необходимо модифицировать ваш существующий метод в контроллере, который запускает весь процесс. Вместо вызова OpenAI, теперь будет вызываться ваш новый ReportSynthesisService.

Примерная схема интеграции (на основе вашего кода):

Java

// ... // Инжектируем новый сервис @Autowired private ReportSynthesisService reportSynthesisService;

// ... в вашем методе generateResearchReport deepResearchService.generateReportAsync(deepRequest) .publishOn(Schedulers.boundedElastic()) .flatMap(researchResponse -> { // Используем flatMap для асинхронной цепочки if (researchResponse == null || researchResponse.getLearnings() == null || researchResponse.getLearnings().isEmpty()) { return Mono.error(new RuntimeException("Empty research response content")); } // НОВЫЙ ШАГ: Вызываем наш сервис синтеза с Ollama return reportSynthesisService.synthesizeReport( request.getQuery(), researchResponse.getLearnings(), request.getLang() ).map(synthesizedText -> new SynthesizedReport(researchResponse, synthesizedText)); // Объединяем результаты }) .map(synthesizedReport -> { // Здесь мы используем synthesizedText для генерации PDF // Этот код остаётся почти без изменений byte[] pdfBytes = researchPdfService.generatePdfReport( request.getQuery(), synthesizedReport.getOriginalResponse(), synthesizedReport.getSynthesizedMarkdown() // Передаем новый красивый текст от Ollama ); String filename = "researchreport" + System.currentTimeMillis() + ".pdf"; saveResearchReportToHistory(request, filename, pdfBytes, synthesizedReport.getOriginalResponse()); return true; }) .doOnError(e -> { System.err.println("Error in full research chain: " + e.getMessage()); }) .subscribe(); // ... Вам также понадобится немного изменить researchPdfService.generatePdfReport, чтобы он принимал новый синтезированный Markdown-текст в качестве основного контента.

  1. Конфигурация Вся конфигурация для Ollama уже есть в вашем OllamaAnalyticsService. Новых настроек добавлять не нужно.

Важная рекомендация: Убедитесь, что в вашем application.properties (или yml) для ollama.model указана достаточно мощная модель, способная следовать сложным инструкциям. Модель gemma3:1b слишком слабая для такой задачи. Рекомендуется использовать:

llama3:8b-instruct (хороший баланс)

gemma:7b-it

mistral или mixtral

Пример:

Properties

ollama.host=http://185.35.223.45:11434 ollama.model=llama3:8b-instruct ollama.timeoutMs=180000 # Увеличьте таймаут до 3 минут, т.к. генерация отчёта - долгая задача 4. Ожидаемый результат После реализации бэкенд будет использовать ваш собственный, локально развёрнутый Ollama для создания высококачественных, структурированных PDF-отчётов, полностью контролируя весь процесс и не завися от внешних платных API для синтеза текста.