final markdown
This commit is contained in:
@@ -10,7 +10,6 @@ import kz.konturai.parser.model.ReportHistory;
|
||||
import kz.konturai.parser.repository.ReportHistoryRepository;
|
||||
import kz.konturai.parser.service.ReportGenerationService;
|
||||
import kz.konturai.parser.service.DeepResearchService;
|
||||
import kz.konturai.parser.service.ResearchPdfService;
|
||||
import kz.konturai.parser.service.ReportSynthesisService;
|
||||
import kz.konturai.parser.service.MinIOService;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -38,20 +37,17 @@ public class ReportController {
|
||||
private final ReportHistoryRepository reportHistoryRepository;
|
||||
private final MinIOService minIOService;
|
||||
private final DeepResearchService deepResearchService;
|
||||
private final ResearchPdfService researchPdfService;
|
||||
private final ReportSynthesisService reportSynthesisService;
|
||||
|
||||
public ReportController(ReportGenerationService reportGenerationService,
|
||||
ReportHistoryRepository reportHistoryRepository,
|
||||
MinIOService minIOService,
|
||||
DeepResearchService deepResearchService,
|
||||
ResearchPdfService researchPdfService,
|
||||
ReportSynthesisService reportSynthesisService) {
|
||||
this.reportGenerationService = reportGenerationService;
|
||||
this.reportHistoryRepository = reportHistoryRepository;
|
||||
this.minIOService = minIOService;
|
||||
this.deepResearchService = deepResearchService;
|
||||
this.researchPdfService = researchPdfService;
|
||||
this.reportSynthesisService = reportSynthesisService;
|
||||
}
|
||||
|
||||
@@ -79,7 +75,7 @@ public class ReportController {
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<ApiResponse<ReportGenerationResponse>> generateResearchReport(
|
||||
public ResponseEntity<byte[]> generateResearchReport(
|
||||
@Validated @RequestBody ResearchReportRequest request) {
|
||||
// Валидация входных данных
|
||||
if (request.getQuery() == null || request.getQuery().trim().isEmpty()) {
|
||||
@@ -94,61 +90,52 @@ public class ReportController {
|
||||
request.getBreadth(),
|
||||
request.getReportType());
|
||||
|
||||
// Генерация уникального ID задачи
|
||||
String taskId = UUID.randomUUID().toString();
|
||||
|
||||
// Предполагаемое время завершения
|
||||
LocalDateTime estimatedCompletion = LocalDateTime.now().plusMinutes(8);
|
||||
|
||||
// Запускаем асинхронный процесс: deep-research -> synthesis via Ollama -> PDF
|
||||
// -> сохранение
|
||||
deepResearchService.generateReportAsync(deepRequest)
|
||||
// Синхронно выполняем: deep-research -> synthesis via Ollama -> Markdown
|
||||
DeepResearchResponse researchResponse = deepResearchService.generateReportAsync(deepRequest)
|
||||
.publishOn(Schedulers.boundedElastic())
|
||||
.flatMap(researchResponse -> {
|
||||
if (researchResponse == null
|
||||
|| researchResponse.getLearnings() == null
|
||||
|| researchResponse.getLearnings().isEmpty()) {
|
||||
return reactor.core.publisher.Mono.error(
|
||||
new RuntimeException(
|
||||
"Empty research response content"));
|
||||
}
|
||||
return reportSynthesisService
|
||||
.synthesizeReport(request.getQuery(),
|
||||
researchResponse.getLearnings(),
|
||||
request.getLang())
|
||||
.map(synthesizedMarkdown -> new Object[] { researchResponse,
|
||||
synthesizedMarkdown });
|
||||
})
|
||||
.map(tuple -> {
|
||||
DeepResearchResponse researchResponse = (DeepResearchResponse) tuple[0];
|
||||
String synthesizedMarkdown = (String) tuple[1];
|
||||
byte[] pdfBytes = researchPdfService.generatePdfReport(request.getQuery(),
|
||||
synthesizedMarkdown, researchResponse.getVisitedUrls());
|
||||
String filename = "research_report_" + System.currentTimeMillis() + ".pdf";
|
||||
saveResearchReportToHistory(request, filename, pdfBytes, researchResponse);
|
||||
return true;
|
||||
})
|
||||
.doOnError(e -> {
|
||||
System.err.println("Error generating research report async: " + e.getMessage());
|
||||
})
|
||||
.subscribe(
|
||||
ok -> {
|
||||
},
|
||||
err -> {
|
||||
// Avoid onErrorDropped by consuming error here
|
||||
System.err.println("Async pipeline error: " + err.getMessage());
|
||||
});
|
||||
.block();
|
||||
if (researchResponse == null || researchResponse.getLearnings() == null
|
||||
|| researchResponse.getLearnings().isEmpty()) {
|
||||
return ResponseEntity.internalServerError().build();
|
||||
}
|
||||
|
||||
ReportGenerationResponse response = new ReportGenerationResponse(
|
||||
taskId,
|
||||
"Исследование запущено в фоновом режиме. Ожидаемое время завершения: "
|
||||
+ estimatedCompletion
|
||||
.format(java.time.format.DateTimeFormatter.ofPattern(
|
||||
"HH:mm")),
|
||||
estimatedCompletion,
|
||||
"PROCESSING");
|
||||
String synthesizedMarkdown = reportSynthesisService
|
||||
.synthesizeReport(request.getQuery(), researchResponse.getLearnings(),
|
||||
request.getLang())
|
||||
.publishOn(Schedulers.boundedElastic())
|
||||
.block();
|
||||
if (synthesizedMarkdown == null) {
|
||||
return ResponseEntity.internalServerError().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success("Исследовательский отчёт поставлен в очередь", response));
|
||||
String finalMarkdown = buildMarkdownWithSources(synthesizedMarkdown, researchResponse.getVisitedUrls());
|
||||
byte[] bytes = finalMarkdown.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
||||
|
||||
String filename = "research_report.md";
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"" + filename + "\"")
|
||||
.contentType(MediaType.parseMediaType("text/markdown; charset=UTF-8"))
|
||||
.body(bytes);
|
||||
}
|
||||
|
||||
private String buildMarkdownWithSources(String synthesizedMarkdown, java.util.List<String> visitedUrls) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(synthesizedMarkdown == null ? "" : synthesizedMarkdown.trim());
|
||||
sb.append("\n\n---\n\n");
|
||||
sb.append("## Источники\n\n");
|
||||
if (visitedUrls == null || visitedUrls.isEmpty()) {
|
||||
sb.append("(источники не предоставлены)\n");
|
||||
return sb.toString();
|
||||
}
|
||||
for (int i = 0; i < visitedUrls.size(); i++) {
|
||||
String url = visitedUrls.get(i);
|
||||
if (url == null || url.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
sb.append((i + 1)).append(". ").append(url.trim()).append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void saveResearchReportToHistory(ResearchReportRequest request, String filename,
|
||||
|
||||
Reference in New Issue
Block a user