ollamaUrl ??= config('services.ollama.url'); $this->embedModel ??= config('services.ollama.embedding_model'); } /** * Erstellt ein Embedding via Ollama und persistiert die Memory. */ public function remember(string $content, array $metadata = []): Memory { $embedding = $this->embed($content); return Memory::create([ 'content' => $content, 'metadata' => $metadata, 'embedding' => $embedding ? new Vector($embedding) : null, ]); } /** * @return array */ public function recall(string $query, int $limit = 5): array { $embedding = $this->embed($query); if ($embedding === null) { return Memory::latest()->limit($limit)->get()->all(); } return Memory::query() ->nearestNeighbors('embedding', new Vector($embedding), Distance::Cosine) ->limit($limit) ->get() ->all(); } /** * Erzeugt ein Embedding über die Ollama /api/embeddings Schnittstelle. * * @return array|null */ public function embed(string $text): ?array { try { $response = Http::timeout(30) ->post(rtrim($this->ollamaUrl, '/').'/api/embeddings', [ 'model' => $this->embedModel, 'prompt' => $text, ]); if (! $response->successful()) { Log::warning('Embedding-Request fehlgeschlagen', ['status' => $response->status()]); return null; } return $response->json('embedding'); } catch (\Throwable $e) { Log::error('Embedding-Fehler', ['exception' => $e->getMessage()]); return null; } } public function summarizeRecent(int $limit = 10): string { $memories = Memory::latest()->limit($limit)->get(); return $memories ->map(fn (Memory $m) => '- '.str($m->content)->limit(160)) ->implode("\n"); } }