/
akadnikov
/
CMIS_agent_Java
Обзор
Документация
Войти
/
akadnikov
/
CMIS_agent_Java
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/main/java/com/example/cmisagent/QueryAnalyzerService.java
267 строк
11 KB
akadnikov
Initial commit
25 фев 2026, 23:17
Верифицирован
25 фев 2026, 23:17
882add4
Код
Авторство
О чём код?
package com.example.cmisagent; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * Сервис для анализа запросов пользователя * Помогает агенту выбрать правильный инструмент */ @Slf4j @Service public class QueryAnalyzerService { // Паттерны для определения типа запроса private static final Map<String, List<Pattern>> QUERY_PATTERNS = new HashMap<>(); static { // Структурированный поиск QUERY_PATTERNS.put("structured_search", Arrays.asList( Pattern.compile("\\bнайди\\b.*(все|документы|файлы)", Pattern.CASE_INSENSITIVE), Pattern.compile("\\bпокажи\\b.*(список|документы)", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(договор|счет|акт|протокол|отчет)\\b", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(за|от|по)\\b.*(дат[ауе]|год|месяц|период)", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(автор|создал|изменил)\\b", Pattern.CASE_INSENSITIVE) )); // Семантический поиск QUERY_PATTERNS.put("semantic_search", Arrays.asList( Pattern.compile("\\b(документ|файл).*(о|об|про)\\b", Pattern.CASE_INSENSITIVE), Pattern.compile("\\bчто.*(говорится|написано|сказано)\\b", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(условия|правила|требования|обязательства)\\b", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(похожие|аналогичные|схожие)\\b", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(содержит|упоминает|описывает)\\b", Pattern.CASE_INSENSITIVE) )); // Запрос метаданных QUERY_PATTERNS.put("metadata_query", Arrays.asList( Pattern.compile("\\b(информация|данные|свойства|метаданные)\\b.*(о документе|файле)", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(кто|когда|где)\\b.*(создал|изменил|загрузил)", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(версия|размер|тип|формат)\\b", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(права|доступ|разрешения)\\b", Pattern.CASE_INSENSITIVE) )); // Получение содержимого QUERY_PATTERNS.put("content_retrieval", Arrays.asList( Pattern.compile("\\b(покажи|открой|прочитай)\\b.*(содержимое|текст|содержание)", Pattern.CASE_INSENSITIVE), Pattern.compile("\\bчто написано\\b", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(резюме|краткое содержание|суть)\\b", Pattern.CASE_INSENSITIVE), Pattern.compile("\\b(анализ|анализируй)\\b.*(документ|текст)", Pattern.CASE_INSENSITIVE) )); } /** * Анализ запроса пользователя */ public QueryAnalysis analyze(String query) { log.info("Analyzing query: {}", query); // Подсчет совпадений для каждого типа Map<String, Integer> scores = new HashMap<>(); for (Map.Entry<String, List<Pattern>> entry : QUERY_PATTERNS.entrySet()) { String queryType = entry.getKey(); List<Pattern> patterns = entry.getValue(); int score = 0; for (Pattern pattern : patterns) { if (pattern.matcher(query).find()) { score++; } } scores.put(queryType, score); } // Определение наиболее вероятного типа String queryType; double confidence; if (scores.values().stream().allMatch(s -> s == 0)) { queryType = "structured_search"; // по умолчанию confidence = 0.5; } else { queryType = scores.entrySet().stream() .max(Map.Entry.comparingByValue()) .map(Map.Entry::getKey) .orElse("structured_search"); int totalPatterns = QUERY_PATTERNS.values().stream() .mapToInt(List::size) .sum(); confidence = (double) scores.get(queryType) / totalPatterns; } // Маппинг типов на инструменты Map<String, String> toolMapping = Map.of( "structured_search", "searchDocuments", "semantic_search", "semanticSearch", "metadata_query", "getDocumentMetadata", "content_retrieval", "retrieveDocumentContent" ); String recommendedTool = toolMapping.get(queryType); // Извлечение сущностей Map<String, Object> entities = extractEntities(query); log.info("Analysis result: type={}, confidence={}, tool={}", queryType, confidence, recommendedTool); return QueryAnalysis.builder() .queryType(queryType) .confidence(confidence) .recommendedTool(recommendedTool) .extractedEntities(entities) .build(); } /** * Извлечение сущностей из запроса */ private Map<String, Object> extractEntities(String query) { Map<String, Object> entities = new HashMap<>(); // Извлечение дат List<String> dates = extractDates(query); if (!dates.isEmpty()) { entities.put("dates", dates); } // Извлечение типов документов List<String> docTypes = extractDocumentTypes(query); if (!docTypes.isEmpty()) { entities.put("documentTypes", docTypes); } // Извлечение организаций List<String> organizations = extractOrganizations(query); if (!organizations.isEmpty()) { entities.put("organizations", organizations); } return entities; } /** * Извлечение дат из текста */ private List<String> extractDates(String query) { List<String> dates = new ArrayList<>(); // Год Pattern yearPattern = Pattern.compile("\\b(\\d{4})\\s*год"); Matcher yearMatcher = yearPattern.matcher(query); while (yearMatcher.find()) { dates.add(yearMatcher.group(1)); } // Месяцы Pattern monthPattern = Pattern.compile( "\\b(январ[ья]|феврал[ья]|март[а]?|апрел[ья]|ма[йя]|июн[ья]|июл[ья]|август[а]?|сентябр[ья]|октябр[ья]|ноябр[ья]|декабр[ья])", Pattern.CASE_INSENSITIVE ); Matcher monthMatcher = monthPattern.matcher(query); while (monthMatcher.find()) { dates.add(monthMatcher.group(1)); } // Даты в формате DD.MM.YYYY Pattern datePattern = Pattern.compile("\\b(\\d{1,2}\\.\\d{1,2}\\.\\d{4})"); Matcher dateMatcher = datePattern.matcher(query); while (dateMatcher.find()) { dates.add(dateMatcher.group(1)); } return dates; } /** * Извлечение типов документов */ private List<String> extractDocumentTypes(String query) { List<String> docTypes = Arrays.asList( "договор", "контракт", "счет", "акт", "протокол", "отчет", "накладная", "счет-фактура" ); return docTypes.stream() .filter(type -> query.toLowerCase().contains(type)) .collect(Collectors.toList()); } /** * Извлечение названий организаций */ private List<String> extractOrganizations(String query) { List<String> organizations = new ArrayList<>(); // Паттерн для ООО, АО, ЗАО и т.д. Pattern orgPattern = Pattern.compile( "(ООО|ОАО|ЗАО|ИП|АО)\\s+[\"']([^\"']+)[\"']" ); Matcher matcher = orgPattern.matcher(query); while (matcher.find()) { String orgType = matcher.group(1); String orgName = matcher.group(2); organizations.add(orgType + " " + orgName); } return organizations; } /** * Определение сложности запроса */ public boolean isComplexQuery(String query) { // Сложные запросы содержат несколько действий List<Pattern> complexPatterns = Arrays.asList( Pattern.compile("найди.*и.*покажи", Pattern.CASE_INSENSITIVE), Pattern.compile("найди.*и.*создай", Pattern.CASE_INSENSITIVE), Pattern.compile("сравни", Pattern.CASE_INSENSITIVE), Pattern.compile("все документы.*от.*и от", Pattern.CASE_INSENSITIVE) ); return complexPatterns.stream() .anyMatch(pattern -> pattern.matcher(query).find()); } /** * Генерация подсказок для пользователя */ public List<String> generateSuggestions(QueryAnalysis analysis) { List<String> suggestions = new ArrayList<>(); String queryType = analysis.getQueryType(); Map<String, Object> entities = analysis.getExtractedEntities(); switch (queryType) { case "structured_search": if (!entities.containsKey("dates")) { suggestions.add("Укажите период поиска для более точных результатов"); } if (!entities.containsKey("documentTypes")) { suggestions.add("Укажите тип документа (договор, счет, акт и т.д.)"); } break; case "semantic_search": suggestions.add("Для более точного поиска опишите подробнее, что вы ищете"); break; case "metadata_query": suggestions.add("Для получения метаданных нужен ID или точное имя документа"); break; case "content_retrieval": suggestions.add("После получения содержимого вы можете попросить создать резюме"); break; } return suggestions; } }