fortunius commited on
Commit
b12d8bd
·
verified ·
1 Parent(s): da46927

Upload src/embedder.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. src/embedder.py +18 -71
src/embedder.py CHANGED
@@ -1,92 +1,39 @@
1
  """Embedder for the UI GreenMetric RAG system.
2
 
3
- Manages the embedding model and provides utilities for encoding text
4
- into vectors for ChromaDB storage and query-time retrieval.
5
-
6
- Auto-detects environment:
7
- Local/GitHub → local Qwen3-Embedding via SentenceTransformers
8
- HF Spaces → HF Inference API (GPU) when EMBED_BACKEND=hf_api
9
  """
10
 
11
- import os
12
- import numpy as np
13
  import chromadb
14
 
15
  # ---------------------------------------------------------------------------
16
- # Query instruction
17
- # ---------------------------------------------------------------------------
18
-
19
- _QUERY_INSTRUCTION = (
20
- "Instruct: Given a question about UI GreenMetric university sustainability "
21
- "rankings, retrieve relevant guideline documents and indicator data\nQuery:"
22
- )
23
-
24
  # ---------------------------------------------------------------------------
25
- # Backend detection
26
- # ---------------------------------------------------------------------------
27
-
28
- _BACKEND = os.getenv("EMBED_BACKEND", "local")
29
- _local_model = None
30
-
31
-
32
- def _get_local_model():
33
- global _local_model
34
- if _local_model is None:
35
- from sentence_transformers import SentenceTransformer
36
- _local_model = SentenceTransformer("Qwen/Qwen3-Embedding-0.6B")
37
- print(f"Embedding model: Qwen3-Embedding-0.6B (local)")
38
- print(f"Embedding dimension: {_local_model.get_embedding_dimension()}")
39
- return _local_model
40
-
41
-
42
- def _embed_local(texts: list[str], instruct: bool = False) -> list[list[float]]:
43
- """Embed via local Qwen3 SentenceTransformer."""
44
- model = _get_local_model()
45
- if instruct:
46
- return model.encode(
47
- texts, prompt=_QUERY_INSTRUCTION, show_progress_bar=False, batch_size=4
48
- ).tolist()
49
- return model.encode(
50
- texts, show_progress_bar=False, batch_size=4
51
- ).tolist()
52
 
 
 
53
 
54
- def _embed_hf_api(texts: list[str], instruct: bool = False) -> list[list[float]]:
55
- """Embed via HF Inference API, fall back to local on failure."""
56
- try:
57
- from huggingface_hub import InferenceClient
58
-
59
- client = InferenceClient(
60
- provider="hf-inference",
61
- api_key=os.environ.get("HF_TOKEN"),
62
- model="Qwen/Qwen3-Embedding-0.6B",
63
- )
64
-
65
- if instruct:
66
- texts = [f"{_QUERY_INSTRUCTION} {t}" for t in texts]
67
-
68
- result = client.feature_extraction(texts)
69
- return [r.tolist() if hasattr(r, "tolist") else r for r in result]
70
- except Exception:
71
- return _embed_local(texts, instruct=instruct)
72
 
73
 
74
  # ---------------------------------------------------------------------------
75
- # Public API
76
  # ---------------------------------------------------------------------------
77
 
78
  def embed(texts: list[str], *, show_progress: bool = True) -> list[list[float]]:
79
- """Encode document/chunk text — no instruction prefix needed."""
80
- if _BACKEND == "hf_api":
81
- return _embed_hf_api(texts, instruct=False)
82
- return _embed_local(texts, instruct=False)
83
 
84
 
85
  def embed_query(texts: list[str], *, show_progress: bool = True) -> list[list[float]]:
86
- """Encode search queries with task instruction for better retrieval."""
87
- if _BACKEND == "hf_api":
88
- return _embed_hf_api(texts, instruct=True)
89
- return _embed_local(texts, instruct=True)
90
 
91
 
92
  # ---------------------------------------------------------------------------
@@ -97,7 +44,7 @@ def store(
97
  source_chunks: dict[str, list[dict]],
98
  *,
99
  client_path: str = "./chroma_db",
100
- collection_name: str = "greenmetric_qwen3",
101
  ) -> None:
102
  """Embed every chunk and persist them into a single ChromaDB collection."""
103
  client = chromadb.PersistentClient(path=client_path)
 
1
  """Embedder for the UI GreenMetric RAG system.
2
 
3
+ Manages the BGE-M3 embedding model and provides utilities for encoding
4
+ text into vectors for ChromaDB storage and query-time retrieval.
 
 
 
 
5
  """
6
 
7
+ from sentence_transformers import SentenceTransformer
 
8
  import chromadb
9
 
10
  # ---------------------------------------------------------------------------
11
+ # Model
 
 
 
 
 
 
 
12
  # ---------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ EMBED_MODEL = SentenceTransformer("BAAI/bge-m3")
15
+ EMBED_DIM = EMBED_MODEL.get_embedding_dimension()
16
 
17
+ print(f"Embedding model: BGE-M3")
18
+ print(f"Embedding dimension: {EMBED_DIM}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
 
21
  # ---------------------------------------------------------------------------
22
+ # Embedding
23
  # ---------------------------------------------------------------------------
24
 
25
  def embed(texts: list[str], *, show_progress: bool = True) -> list[list[float]]:
26
+ """Encode document/chunk text."""
27
+ return EMBED_MODEL.encode(
28
+ texts, show_progress_bar=show_progress, batch_size=8
29
+ ).tolist()
30
 
31
 
32
  def embed_query(texts: list[str], *, show_progress: bool = True) -> list[list[float]]:
33
+ """Encode search queries. BGE-M3 doesn't need instruction prefix."""
34
+ return EMBED_MODEL.encode(
35
+ texts, show_progress_bar=show_progress, batch_size=8
36
+ ).tolist()
37
 
38
 
39
  # ---------------------------------------------------------------------------
 
44
  source_chunks: dict[str, list[dict]],
45
  *,
46
  client_path: str = "./chroma_db",
47
+ collection_name: str = "greenmetric_bgem3",
48
  ) -> None:
49
  """Embed every chunk and persist them into a single ChromaDB collection."""
50
  client = chromadb.PersistentClient(path=client_path)