Skip to content

Commit dbd0880

Browse files
author
Alexander Cherednikov
committed
Delete comments
1 parent def0dea commit dbd0880

6 files changed

Lines changed: 7 additions & 175 deletions

File tree

src/Command/ProductsSearchCommand.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,9 @@ private function searchProducts(string $query): array
7575
{
7676
$embedding = ($this->embedder)($query, pooling: 'mean', normalize: true);
7777

78-
// Handle different embedding result types
7978
if (is_array($embedding)) {
8079
$vector = $embedding[0];
8180
} else {
82-
// For Tensor objects, convert to array and take first element
8381
$vector = $embedding instanceof \Codewithkyrian\Transformers\Tensor\Tensor ? $embedding[0] : [];
8482
}
8583

src/Command/ProductsVectorizeCommand.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,9 @@ private function processBatch(array $batch): void
150150
'description' => $product['description'],
151151
];
152152

153-
// Handle different embedding result types
154153
if (is_array($embedding)) {
155154
$vector = $embedding[0];
156155
} else {
157-
// For Tensor objects, convert to array and take first element
158156
$vector = $embedding instanceof \Codewithkyrian\Transformers\Tensor\Tensor ? $embedding[0] : [];
159157
}
160158

src/Command/RAGDemoCommand.php

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,8 @@ public function __construct(
2828
protected function configure(): void
2929
{
3030
$this
31-
->setDescription('Демонстрация улучшенной RAG архитектуры с четким разделением этапов')
3231
->addOption('query', null, InputOption::VALUE_REQUIRED, 'Поисковый запрос для демонстрации')
33-
->addOption('interactive', 'i', InputOption::VALUE_NONE, 'Интерактивный режим чата')
34-
->setHelp(<<<HELP
35-
Эта команда демонстрирует улучшенную RAG (Retrieval-Augmented Generation) архитектуру
36-
с четким разделением на 3 этапа согласно рекомендации куратора:
37-
38-
1. 🧠 Query Processing - анализ и векторизация запроса
39-
2. 🔍 Retrieval - поиск релевантных документов в Qdrant
40-
3. ✨ Generation - строго ограниченная генерация ответа только на основе найденных товаров
41-
42-
Примеры использования:
43-
php bin/console rag:demo --query "процессор AMD для игр"
44-
php bin/console rag:demo --interactive
45-
HELP);
32+
->addOption('interactive', 'i', InputOption::VALUE_NONE, 'Интерактивный режим чата');
4633
}
4734

4835
protected function execute(InputInterface $input, OutputInterface $output): int
@@ -103,7 +90,7 @@ private function runInteractiveMode(SymfonyStyle $io): int
10390
}
10491

10592
try {
106-
$sessionId = 'interactive_'.time(); // Уникальный ID для интерактивной сессии
93+
$sessionId = 'interactive_'.time();
10794
$result = $this->ragService->searchWithContext($query, $sessionId);
10895
$this->displayCompactResult($result, $io);
10996
} catch (\Exception $e) {
@@ -161,7 +148,6 @@ private function displayCompactResult(RAGSearchResult $result, SymfonyStyle $io)
161148
private function showUsageExamples(SymfonyStyle $io): void
162149
{
163150
$io->section('Примеры использования');
164-
165151
$examples = [
166152
'Разовый поиск' => 'php bin/console rag:demo --query "процессор AMD для игр"',
167153
'Интерактивный чат' => 'php bin/console rag:demo --interactive',

src/Service/ImprovedRAGService.php

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@
2020
use Qdrant\Qdrant;
2121
use Symfony\Component\HttpClient\Psr18Client;
2222

23-
/**
24-
* Правильная реализация RAG-сервиса с тремя четкими этапами:
25-
* 1. Query Processing - обработка и оптимизация запроса
26-
* 2. Retrieval - поиск релевантных документов
27-
* 3. Generation - генерация ответа на основе найденных документов
28-
*/
2923
class ImprovedRAGService implements RAGServiceInterface
3024
{
3125
private const COLLECTION_NAME = 'products';
@@ -41,47 +35,30 @@ public function __construct(
4135
) {
4236
}
4337

44-
/**
45-
* Главный метод RAG pipeline.
46-
*/
4738
public function search(string $userQuery): RAGSearchResult
4839
{
4940
return $this->searchWithContext($userQuery, 'default_session');
5041
}
5142

52-
/**
53-
* RAG поиск с учетом контекста сессии.
54-
*/
5543
public function searchWithContext(string $userQuery, string $sessionId): RAGSearchResult
5644
{
5745
$this->ensureInitialized();
5846

59-
// Получаем контекст предыдущих запросов
6047
$context = $this->contextService->getSearchContext($sessionId);
61-
62-
// Этап 1: Query Processing с контекстом
6348
$optimizedQuery = $this->processQuery($userQuery, $context);
64-
65-
// Попытаемся определить категорию для фильтрации
6649
$categoryFilter = $context ?: $this->contextService->inferCategoryFromQuery($userQuery);
67-
68-
// Этап 2: Retrieval с возможной фильтрацией
6950
$documents = $this->retrieveDocuments($optimizedQuery, $categoryFilter);
7051

71-
// Если с фильтром ничего не найдено, попробуем без фильтра
7252
if (empty($documents) && $categoryFilter) {
7353
$documents = $this->retrieveDocuments($optimizedQuery, null);
7454
}
7555

76-
// Сохраняем контекст для следующих запросов
7756
if (!empty($documents)) {
7857
$category = $this->contextService->extractCategoryFromResults($documents);
7958
if ($category) {
8059
$this->contextService->setSearchContext($sessionId, $category, $userQuery);
8160
}
8261
}
83-
84-
// Этап 3: Generation
8562
$aiResponse = $this->generateResponse($documents, $userQuery);
8663

8764
return new RAGSearchResult(
@@ -92,53 +69,41 @@ public function searchWithContext(string $userQuery, string $sessionId): RAGSear
9269
);
9370
}
9471

95-
/**
96-
* ЭТАП 1: Query Processing
97-
* Анализирует запрос через LLM с учетом контекста и создает оптимизированный поисковый термин.
98-
*/
9972
private function processQuery(string $userQuery, ?string $context = null): string
10073
{
10174
try {
10275
return $this->llamaService->analyzeSearchQuery($userQuery, $context);
10376
} catch (\Exception $e) {
104-
// Fallback: если LLM недоступен, используем исходный запрос
10577
return $userQuery;
10678
}
10779
}
10880

10981
/**
110-
* ЭТАП 2: Retrieval
111-
* Выполняет векторный поиск в Qdrant с возможной фильтрацией по категории.
112-
*
11382
* @return array<int, array<string, mixed>>
11483
*/
11584
private function retrieveDocuments(string $optimizedQuery, ?string $categoryFilter = null): array
11685
{
117-
// Векторизуем оптимизированный запрос
11886
if (null === $this->embedder) {
11987
throw RAGException::serviceUnavailable('Embedder not initialized');
12088
}
12189

12290
$embedding = ($this->embedder)($optimizedQuery, pooling: 'mean', normalize: true);
12391
$queryVector = is_array($embedding) ? $embedding[0] : ($embedding instanceof \Codewithkyrian\Transformers\Tensor\Tensor ? $embedding[0] : []);
12492

125-
// Создаем поисковый запрос для Qdrant
12693
$searchVector = new VectorStruct($queryVector, 'default');
12794
$searchRequest = new SearchRequest($searchVector);
12895
$searchRequest
12996
->setLimit(self::DEFAULT_LIMIT)
13097
->setWithPayload(true)
13198
->setScoreThreshold(self::DEFAULT_THRESHOLD);
13299

133-
// Добавляем фильтр по категории, если указана
134100
if ($categoryFilter) {
135101
$filter = new Filter();
136102
$condition = new MatchString('category', $categoryFilter);
137103
$filter->addMust($condition);
138104
$searchRequest->setFilter($filter);
139105
}
140106

141-
// Выполняем поиск
142107
try {
143108
$response = $this->qdrantClient
144109
?->collections(self::COLLECTION_NAME)
@@ -152,9 +117,6 @@ private function retrieveDocuments(string $optimizedQuery, ?string $categoryFilt
152117
}
153118

154119
/**
155-
* ЭТАП 3: Generation
156-
* Генерирует персонализированный ответ на основе найденных документов.
157-
*
158120
* @param array<int, array<string, mixed>> $documents
159121
*/
160122
private function generateResponse(array $documents, string $originalQuery): string
@@ -164,47 +126,37 @@ private function generateResponse(array $documents, string $originalQuery): stri
164126
}
165127

166128
try {
167-
// Используем constrained generation для точного ответа
168129
return $this->llamaService->generateConstrainedResponse($documents, $originalQuery);
169130
} catch (\Exception $e) {
170-
// Fallback: базовый ответ без LLM
171131
$count = count($documents);
172132
$topProduct = $documents[0]['payload']['name'] ?? 'товар';
173133

174134
return "Найдено $count товар(ов). Рекомендуем: $topProduct";
175135
}
176136
}
177137

178-
/**
179-
* Инициализация всех необходимых сервисов.
180-
*/
181138
private function ensureInitialized(): void
182139
{
183140
if (null !== $this->qdrantClient && null !== $this->embedder) {
184141
return;
185142
}
186143

187-
// Настройка окружения для избежания конфликтов OpenMP
188144
if (!getenv('KMP_DUPLICATE_LIB_OK')) {
189145
putenv('KMP_DUPLICATE_LIB_OK=TRUE');
190146
}
191147

192-
// Инициализация Qdrant клиента
193148
if (null === $this->qdrantClient) {
194149
$config = new Config('http://localhost', 6333);
195150
$transport = new Transport(new Psr18Client(), $config);
196151
$this->qdrantClient = new Qdrant($transport);
197152
}
198153

199-
// Инициализация embedder модели
200154
if (null === $this->embedder) {
201155
$this->embedder = pipeline(Task::Embeddings, 'onnx-community/Qwen3-Embedding-0.6B-ONNX');
202156
}
203157
}
204158

205159
/**
206-
* Проверка готовности всех компонентов RAG системы.
207-
*
208160
* @return array<string, mixed>
209161
*/
210162
public function healthCheck(): array
@@ -217,35 +169,27 @@ public function healthCheck(): array
217169
];
218170

219171
try {
220-
// Проверка LlamaService
221172
$health['llama_service'] = $this->llamaService->isAvailable();
222173
} catch (\Exception) {
223174
$health['llama_service'] = false;
224175
}
225176

226177
try {
227-
// Инициализируем если нужно
228178
$this->ensureInitialized();
229179

230-
// Проверка Qdrant
231180
$this->qdrantClient?->collections(self::COLLECTION_NAME)->info();
232181
$health['qdrant'] = true;
233182

234-
// Проверка embedder (если инициализирован без ошибок, то работает)
235183
$health['embedder'] = null !== $this->embedder;
236184
} catch (\Exception) {
237-
// Qdrant или embedder недоступны
238185
}
239186

240-
// Общая готовность - можем работать даже без LLM, но нужны Qdrant + embedder
241187
$health['overall'] = $health['qdrant'] && $health['embedder'];
242188

243189
return $health;
244190
}
245191

246192
/**
247-
* Получить статистику коллекции.
248-
*
249193
* @return array<string, mixed>
250194
*/
251195
public function getCollectionStats(): array

0 commit comments

Comments
 (0)