fix: responder a partir dos livros com embeddings em português
Usa o modelo multilingual, ignora trechos curtos e o template do Llama 3.2 para a resposta sair em uma frase completa. O chat deixa a API livre durante a geração, o upload indexa o PDF e os agendamentos não são gravados duas vezes.
This commit is contained in:
1 parent
7af7ba530d
commit
8eeb6b89f4
11 files changed
+185
-90
No files matched your search
@@ -22,12 +22,15 @@ class PDFProcessor:
|
||||
|
||||
# Convert to dictionaries with metadata
|
||||
chunk_data = []
|
||||
for i, doc in enumerate(chunks):
|
||||
for doc in chunks:
|
||||
content = " ".join(doc.page_content.split())
|
||||
if len(content) < 80:
|
||||
continue
|
||||
chunk_data.append({
|
||||
"content": doc.page_content,
|
||||
"content": content,
|
||||
"metadata": {
|
||||
**metadata,
|
||||
"chunk_id": i,
|
||||
"chunk_id": len(chunk_data),
|
||||
"source": file_path,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,9 +2,10 @@ from qdrant_client import QdrantClient
|
||||
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue
|
||||
import numpy as np
|
||||
from typing import List, Dict, Optional
|
||||
import os
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import uuid
|
||||
|
||||
class QdrantService:
|
||||
def __init__(self, url: str, collection_name: str = "espiritismo_books"):
|
||||
@@ -46,24 +47,22 @@ class QdrantService:
|
||||
|
||||
def add_chunks(self, chunks: List[Dict]):
|
||||
"""Add chunks to the collection."""
|
||||
points = []
|
||||
|
||||
for i, chunk in enumerate(chunks):
|
||||
point = PointStruct(
|
||||
id=chunk.get("id") or i,
|
||||
points = [
|
||||
PointStruct(
|
||||
id=str(chunk.get("id") or uuid.uuid4()),
|
||||
vector=chunk["embedding"],
|
||||
payload={
|
||||
"content": chunk["content"],
|
||||
"metadata": chunk["metadata"],
|
||||
}
|
||||
},
|
||||
)
|
||||
points.append(point)
|
||||
for chunk in chunks
|
||||
]
|
||||
|
||||
for start in range(0, len(points), 128):
|
||||
batch = points[start:start + 128]
|
||||
self.client.upsert(collection_name=self.collection_name, points=batch)
|
||||
if points:
|
||||
self.client.upsert(
|
||||
collection_name=self.collection_name,
|
||||
points=points,
|
||||
)
|
||||
print(f"Added {len(points)} chunks to Qdrant")
|
||||
|
||||
def search(self, query_embedding, top_k: int = 3) -> List[Dict]:
|
||||
@@ -87,17 +86,22 @@ class QdrantService:
|
||||
|
||||
def get_books(self) -> List[str]:
|
||||
"""Get list of books in the collection."""
|
||||
points = self.client.scroll(
|
||||
collection_name=self.collection_name,
|
||||
limit=10000,
|
||||
)[0]
|
||||
|
||||
books = set()
|
||||
for point in points:
|
||||
metadata = point.payload["metadata"]
|
||||
books.add(metadata.get("title", "Unknown"))
|
||||
offset = None
|
||||
while True:
|
||||
points, offset = self.client.scroll(
|
||||
collection_name=self.collection_name,
|
||||
limit=256,
|
||||
offset=offset,
|
||||
with_vectors=False,
|
||||
)
|
||||
for point in points:
|
||||
metadata = (point.payload or {}).get("metadata") or {}
|
||||
books.add(metadata.get("title", "Unknown"))
|
||||
if offset is None:
|
||||
break
|
||||
|
||||
return sorted(list(books))
|
||||
return sorted(books)
|
||||
|
||||
def get_collection_info(self) -> Dict:
|
||||
"""Get information about the collection."""
|
||||
@@ -138,21 +142,19 @@ class RAGService:
|
||||
"""Generate a response based on the query and context."""
|
||||
context_text = "\n\n".join(context)
|
||||
|
||||
system_prompt = f"""Você é um assistente especializado em espiritismo. Use as informações abaixo para responder à pergunta do usuário.
|
||||
system_prompt = f"""Você responde perguntas sobre espiritismo usando apenas o contexto.
|
||||
Escreva uma ou duas frases completas, em português. Não repita a pergunta nem as instruções.
|
||||
Se o contexto não bastar, responda apenas: Não encontrei essa informação nos livros indexados.
|
||||
|
||||
Informações:
|
||||
{context_text}
|
||||
|
||||
Instruções:
|
||||
- Responda de forma clara e concisa
|
||||
- Use o contexto fornecido
|
||||
- Quando citar passagens, mencione o livro e capítulo (se disponível)
|
||||
- Se não souber a resposta, diga que não encontrou na base de dados"""
|
||||
|
||||
prompt = f"{system_prompt}\n\nPergunta: {query}\nResposta:"
|
||||
response = self._get_llm().generate(prompt, max_tokens=500)
|
||||
|
||||
return response
|
||||
Contexto:
|
||||
{context_text}"""
|
||||
template = (
|
||||
"<|start_header_id|>user<|end_header_id|>\n\n"
|
||||
"{0}<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n"
|
||||
)
|
||||
with self._get_llm().chat_session(system_prompt=system_prompt, prompt_template=template):
|
||||
response = self.llm.generate(query, max_tokens=160, temp=0.1)
|
||||
return response.strip()
|
||||
|
||||
def query(self, query: str, top_k: int = 3) -> Dict:
|
||||
"""Query the RAG system."""
|
||||
|
||||
Reference in new issue
Block a user