Spaces:
Runtime error
Runtime error
File size: 4,697 Bytes
d11e1fe bec7021 dbd9820 ec7f6a1 037a839 200fee8 ec7f6a1 d11e1fe ec7f6a1 7f617c9 ec7f6a1 7f617c9 ec7f6a1 073d270 7f617c9 ec7f6a1 7f617c9 ec7f6a1 d11e1fe 2583cf2 d11e1fe ec7f6a1 8e038e1 2c6bd00 8e038e1 ec7f6a1 e8bb95c 2c6bd00 ec7f6a1 037a839 ec7f6a1 037a839 2c6bd00 d11e1fe 8e038e1 97d2e91 359c625 97d2e91 359c625 97d2e91 359c625 037a839 359c625 2c6bd00 359c625 2c6bd00 359c625 2c6bd00 359c625 bec7021 8e038e1 bec7021 ec7f6a1 5ac0022 bec7021 5ac0022 d11e1fe d00f6f0 d5e5243 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
# ✅ Modules de LlamaIndex
from llama_index.core.settings import Settings
from llama_index.core import Document
from llama_index.llms.llama_cpp import LlamaCPP
from llama_index.core.node_parser import SemanticSplitterNodeParser
# ✅ Pour l'embedding LOCAL via transformers
from transformers import AutoTokenizer, AutoModel
import torch
import torch.nn.functional as F
import os
app = FastAPI()
# ✅ Configuration locale du cache HF pour Hugging Face
# ✅ Définir un chemin autorisé pour le cache (à l'intérieur du container Hugging Face)
CACHE_DIR = "/app/cache"
os.environ["HF_HOME"] = CACHE_DIR
os.environ["TRANSFORMERS_CACHE"] = CACHE_DIR
os.environ["HF_MODULES_CACHE"] = CACHE_DIR
os.environ["HF_HUB_CACHE"] = CACHE_DIR
# ✅ Configuration du modèle d’embedding local (ex: BGE / Nomic / GTE etc.)
MODEL_NAME = "BAAI/bge-small-en-v1.5"
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, cache_dir=CACHE_DIR)
model = AutoModel.from_pretrained(MODEL_NAME, cache_dir=CACHE_DIR)
def get_embedding(text: str):
with torch.no_grad():
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
outputs = model(**inputs)
embeddings = outputs.last_hidden_state[:, 0]
return F.normalize(embeddings, p=2, dim=1).squeeze().tolist()
# ✅ Données entrantes du POST
class ChunkRequest(BaseModel):
text: str
source_id: Optional[str] = None
titre: Optional[str] = None
source: Optional[str] = None
type: Optional[str] = None
@app.post("/chunk")
async def chunk_text(data: ChunkRequest):
try:
# ✅ Vérification du texte reçu
print(f"✅ Texte reçu ({len(data.text)} caractères) : {data.text[:200]}...")
print("✅ ✔️ Reçu – On passe à la configuration du modèle LLM...")
# ✅ Chargement du modèle LLM depuis Hugging Face en ligne (pas de .gguf local)
llm = LlamaCPP(
print("✅ ✔️ Modèle LLM chargé sans erreur on continue...")
model_url="https://huggingface.co/leafspark/Mistral-7B-Instruct-v0.2-Q4_K_M-GGUF/resolve/main/mistral-7b-instruct-v0.2.Q4_K_M.gguf",
temperature=0.1,
max_new_tokens=512,
context_window=2048,
generate_kwargs={"top_p": 0.95},
model_kwargs={"n_gpu_layers": 1},
)
# ✅ Intégration manuelle de l'embedding local dans Settings
class SimpleEmbedding:
def get_text_embedding(self, text: str):
return get_embedding(text)
try:
Settings.llm = llm
Settings.embed_model = SimpleEmbedding()
print("✅ ✔️ Settings configurés avec LLM et embedding")
except Exception as e:
print(f"❌ Erreur dans la configuration des Settings : {e}")
return {"error": str(e)}
import sys
print("✅ LLM et embedding configurés - prêt pour le split")
print("✅ Début du split sémantique...", flush=True)
parser = SemanticSplitterNodeParser.from_defaults()
fallback_splitter = Settings.node_parser # fallback = splitter par défaut
doc = Document(text=data.text)
try:
nodes = parser.get_nodes_from_documents([doc])
print(f"✅ Nombre de chunks générés : {len(nodes)}")
print(f"🧩 Exemple chunk : {nodes[0].text[:100]}...")
except Exception as e:
import traceback
traceback.print_exc()
print(f"❌ Erreur lors du split sémantique : {e}")
nodes = fallback_splitter.get_nodes_from_documents([doc])
print(f"⚠️ Split fallback utilisé - chunks générés : {len(nodes)}")
# ✅ Découpage sémantique intelligent
# parser = SemanticSplitterNodeParser.from_defaults()
# nodes = parser.get_nodes_from_documents([Document(text=data.text)])
# ✅ Vérification du nombre de chunks générés
print(f"✅ Nombre de chunks générés : {len(nodes)}")
return {
"chunks": [node.text for node in nodes],
"metadatas": [node.metadata for node in nodes],
"source_id": data.source_id,
"titre": data.titre,
"source": data.source,
"type": data.type,
"error": None # ← essentiel pour que n8n voie "rien à signaler"
}
except Exception as e:
return {"error": str(e)}
if __name__ == "__main__":
import uvicorn
uvicorn.run("app:app", host="0.0.0.0", port=7860)
|