- Added tone instruction retrieval to SupportReplyService. - Improved user feedback when no relevant article is found. - Included article URL and tone instruction in LLM prompt. - Updated response format to include source information. - Enhanced article management UI with search functionality and editing capabilities. - Introduced a new API endpoint for nearest articles based on vector search. - Added confidence badge component to display article confidence levels. - Implemented tests for article searching, editing, and nearest article API. - Removed obsolete .htaccess file.
54 lines
2.1 KiB
PHP
54 lines
2.1 KiB
PHP
<?php
|
|
|
|
namespace App\Repositories;
|
|
|
|
use App\DTOs\ArticleCandidateDTO;
|
|
use App\Models\Article;
|
|
use App\Models\ArticleChunk;
|
|
use App\Repositories\Contracts\ArticleRepositoryInterface;
|
|
|
|
class ArticleRepository implements ArticleRepositoryInterface
|
|
{
|
|
public function findSimilarByEmbedding(array $embedding, int $limit = 5, array $embeddingContext = [], array $filters = []): array
|
|
{
|
|
$vector = '['.implode(',', array_map(static fn ($value) => (float) $value, $embedding)).']';
|
|
|
|
$chunkDistances = ArticleChunk::query()
|
|
->selectRaw('article_id, MIN(embedding <=> ?::vector) as distance', [$vector])
|
|
->whereNotNull('embedding')
|
|
->when((bool) ($filters['published_only'] ?? false), function ($query) {
|
|
$query->whereHas('article', function ($articleQuery) {
|
|
$articleQuery
|
|
->where('status', 'published')
|
|
->where('is_ai_draft', false);
|
|
});
|
|
})
|
|
->when($embeddingContext !== [], function ($query) use ($embeddingContext) {
|
|
$query
|
|
->where('embedding_provider_instance_id', $embeddingContext['provider_instance_id'] ?? null)
|
|
->where('embedding_model', $embeddingContext['embedding_model'] ?? null);
|
|
})
|
|
->groupBy('article_id')
|
|
->orderByRaw('MIN(embedding <=> ?::vector)', [$vector])
|
|
->limit($limit)
|
|
->get();
|
|
|
|
if ($chunkDistances->isEmpty()) {
|
|
return [];
|
|
}
|
|
|
|
$distanceByArticleId = $chunkDistances->pluck('distance', 'article_id');
|
|
$articleIds = $chunkDistances->pluck('article_id')->all();
|
|
|
|
$articles = Article::query()
|
|
->whereIn('id', $articleIds)
|
|
->get()
|
|
->sortBy(fn (Article $a) => (float) ($distanceByArticleId[$a->id] ?? 1))
|
|
->values();
|
|
|
|
return $articles
|
|
->map(fn (Article $article) => ArticleCandidateDTO::fromArticle($article, (float) ($distanceByArticleId[$article->id] ?? 1)))
|
|
->all();
|
|
}
|
|
}
|