Human-Library-Endpunkte
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package com.homme.demo.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@@ -14,7 +13,6 @@ import com.homme.demo.dto.ChatRequest;
|
||||
import com.homme.demo.service.RagService;
|
||||
|
||||
|
||||
@CrossOrigin(origins = "${homme.cors.allowed-origins}")
|
||||
@RestController
|
||||
@RequestMapping("/chat")
|
||||
public class ChatController {
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.homme.demo.controller;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.homme.demo.service.WordPressIngestService;
|
||||
|
||||
@@ -25,4 +29,5 @@ public class IngestController {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,25 +2,36 @@ package com.homme.demo.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import com.homme.demo.dto.ApiResponse;
|
||||
import com.homme.demo.dto.ContributionRequest;
|
||||
import com.homme.demo.dto.FileProcessedDto;
|
||||
import com.homme.demo.dto.UploadWordFileResponseDto;
|
||||
import com.homme.demo.entity.Contribution;
|
||||
import com.homme.demo.input.ContentInput;
|
||||
import com.homme.demo.repository.ContributionRepository;
|
||||
import com.homme.demo.service.AzureSpeechService;
|
||||
import com.homme.demo.service.KnowledgeIngestService;
|
||||
import com.homme.demo.service.WordExportService;
|
||||
@@ -30,46 +41,154 @@ import com.homme.demo.service.WordExportService;
|
||||
@RequestMapping("/knowledge-base")
|
||||
public class KnowledgeIngestController {
|
||||
|
||||
private static final Set<String> ALLOWED_DOC_EXT = Set.of("docx", "doc", "pdf", "txt");
|
||||
private static final Set<String> ALLOWED_AUDIO_EXT = Set.of("webm", "ogg", "mp3", "wav", "m4a", "mp4");
|
||||
|
||||
|
||||
@Autowired
|
||||
private WordExportService wordExportService;
|
||||
|
||||
@Autowired
|
||||
private KnowledgeIngestService knowledgeIngestService;
|
||||
|
||||
@Autowired
|
||||
private AzureSpeechService azureSpeechService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AzureSpeechService azureSpeechService;
|
||||
|
||||
@Autowired
|
||||
private ContributionRepository contributionRepository;
|
||||
|
||||
@Value("${homme.admin.token}")
|
||||
private String adminToken;
|
||||
|
||||
|
||||
@GetMapping("/build")
|
||||
public List<ApiResponse<FileProcessedDto>> buildKnowledgeBase() throws Exception {
|
||||
return knowledgeIngestService.buildKnowledgeBase();
|
||||
}
|
||||
|
||||
@PostMapping("/transcription")
|
||||
public String transcribe(@RequestParam("file") MultipartFile file) throws IOException{
|
||||
|
||||
|
||||
|
||||
byte[] audioBytes = file.getBytes();
|
||||
String fileName = file.getOriginalFilename();
|
||||
return azureSpeechService.transcribe(audioBytes, fileName);
|
||||
|
||||
|
||||
@PostMapping("/transcription")
|
||||
public ResponseEntity<Map<String, String>> transcribe(@RequestParam("audio") MultipartFile audio) throws IOException {
|
||||
|
||||
String ext = getExtension(audio.getOriginalFilename());
|
||||
if (!ALLOWED_AUDIO_EXT.contains(ext)) {
|
||||
return new ResponseEntity<>(Map.of("error", "Nicht unterstütztes Audioformat."), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
String text = azureSpeechService.transcribe(audio.getBytes(), audio.getOriginalFilename());
|
||||
return ResponseEntity.ok(Map.of("text", text));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@PostMapping("/extract")
|
||||
public ResponseEntity<Map<String, String>> extract(@RequestParam("file") MultipartFile file) throws Exception {
|
||||
|
||||
String ext = getExtension(file.getOriginalFilename());
|
||||
if (!ALLOWED_DOC_EXT.contains(ext)) {
|
||||
return new ResponseEntity<>(Map.of("error", "Nur DOCX, DOC, PDF oder TXT erlaubt."), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
String text = knowledgeIngestService.extractText(file.getBytes(), file.getOriginalFilename());
|
||||
return ResponseEntity.ok(Map.of("text", text));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/contributions", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<Map<String, Object>> saveContribution(@RequestBody ContributionRequest request) {
|
||||
|
||||
if (request.getConsent() == null || !request.getConsent()) {
|
||||
return new ResponseEntity<>(Map.of("error", "Einwilligung ist erforderlich."), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (request.getName() == null || request.getName().isBlank()) {
|
||||
return new ResponseEntity<>(Map.of("error", "Name ist erforderlich."), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (request.getText() == null || request.getText().isBlank()) {
|
||||
return new ResponseEntity<>(Map.of("error", "Text darf nicht leer sein."), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
Contribution contribution = Contribution.builder()
|
||||
.source(request.getSource())
|
||||
.name(request.getName().trim())
|
||||
.gender(request.getGender())
|
||||
.city((request.getCity() == null || request.getCity().isBlank()) ? "Dortmund" : request.getCity().trim())
|
||||
.text(request.getText())
|
||||
.consent(true)
|
||||
.status("PENDING")
|
||||
.createdAt(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
Contribution saved = contributionRepository.save(contribution);
|
||||
|
||||
return new ResponseEntity<>(Map.of("id", saved.getId(), "status", saved.getStatus()), HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/contributions/pending")
|
||||
public List<Contribution> pendingContributions(@RequestHeader("X-Admin-Token") String token) {
|
||||
checkAdminToken(token);
|
||||
return contributionRepository.findByStatus("PENDING");
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/contributions/{id}/approve")
|
||||
public ResponseEntity<ApiResponse<FileProcessedDto>> approveContribution(@PathVariable Long id,
|
||||
@RequestHeader("X-Admin-Token") String token) {
|
||||
|
||||
checkAdminToken(token);
|
||||
try {
|
||||
Contribution contribution = contributionRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("Beitrag nicht gefunden."));
|
||||
|
||||
byte[] docx = wordExportService.createInterviewDocx(contribution.getText());
|
||||
|
||||
String fileName = "%s_%s_%s.docx".formatted(
|
||||
LocalDate.now(),
|
||||
contribution.getName().replace(" ", "_"),
|
||||
contribution.getCity());
|
||||
|
||||
UploadWordFileResponseDto upload = knowledgeIngestService.uploadWordFile(fileName, docx);
|
||||
if (!upload.isSuccess()) {
|
||||
return new ResponseEntity<>(ApiResponse.error("Upload fehlgeschlagen: " + upload.getMessage()),
|
||||
HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
ApiResponse<FileProcessedDto> processed = knowledgeIngestService.processOneFile(upload.getLink());
|
||||
|
||||
contribution.setStatus("APPROVED");
|
||||
contributionRepository.save(contribution);
|
||||
|
||||
return new ResponseEntity<>(processed, HttpStatus.OK);
|
||||
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>(ApiResponse.error("Fehler: " + e.getMessage()),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkAdminToken(String token) {
|
||||
if (adminToken == null || adminToken.isBlank() || !adminToken.equals(token)) {
|
||||
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Ungültiger Admin-Token");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getExtension(String fileName) {
|
||||
if (fileName == null || !fileName.contains(".")) return "";
|
||||
return fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/save-new-interview", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public ResponseEntity<ApiResponse<FileProcessedDto>> saveNewInterview(@ModelAttribute ContentInput contentInput ) {
|
||||
|
||||
|
||||
System.out.println("rrrr ");
|
||||
try {
|
||||
String rawText;
|
||||
|
||||
|
||||
|
||||
if (contentInput.getFile() != null && !contentInput.getFile().isEmpty()) {
|
||||
rawText = wordExportService.leseDatei(contentInput.getFile());
|
||||
|
||||
|
||||
|
||||
} else if (contentInput.getText() != null && !contentInput.getText().isBlank()) {
|
||||
rawText = contentInput.getText();
|
||||
|
||||
@@ -81,28 +200,28 @@ public class KnowledgeIngestController {
|
||||
return new ResponseEntity<>(ApiResponse.error("Kein lesbarer Inhalt gefunden."), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
|
||||
String title = (contentInput.getTitle() == null || contentInput.getTitle().isBlank())
|
||||
? "Anonymous" : contentInput.getTitle();
|
||||
|
||||
|
||||
String city = (contentInput.getCity() == null|| contentInput.getCity().isBlank())
|
||||
? "Dortmund" : contentInput.getCity();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
byte[] docx = wordExportService.createInterviewDocx(rawText);
|
||||
|
||||
|
||||
String fileName = "%s_%s_%s.docx".formatted(LocalDate.now(),title.trim().replace(" ", "_"),city);
|
||||
|
||||
|
||||
UploadWordFileResponseDto upload = knowledgeIngestService.uploadWordFile(fileName, docx);
|
||||
|
||||
|
||||
if(!upload.isSuccess()) {
|
||||
|
||||
|
||||
return new ResponseEntity<>(ApiResponse.error("Upload fehlgeschlagen: " +upload.getMessage()), HttpStatus.BAD_REQUEST);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
ApiResponse<FileProcessedDto> processed = knowledgeIngestService.processOneFile(upload.getLink());
|
||||
return new ResponseEntity<>(processed, HttpStatus.CREATED);
|
||||
|
||||
@@ -112,7 +231,3 @@ public class KnowledgeIngestController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user