JasonFinley0821 commited on
Commit
a4137be
·
1 Parent(s): a9e6507

feat : upgrade embedding

Browse files
Files changed (6) hide show
  1. .env.example +6 -1
  2. app.py +1 -11
  3. db/chroma_init.py +0 -35
  4. db/postgres_init.py +57 -0
  5. rag.py +5 -2
  6. requirements.txt +2 -2
.env.example CHANGED
@@ -1 +1,6 @@
1
- GOOGLE_API_KEY=your_google_ai_api_key
 
 
 
 
 
 
1
+ GOOGLE_API_KEY=your_google_ai_api_key
2
+ DB_HOST=your_db_host
3
+ DB_PORT=your_db_port
4
+ DB_DATABASE=your_db_database
5
+ DB_USER=your_db_user
6
+ DB_PASSWORD=your_db_password
app.py CHANGED
@@ -5,24 +5,14 @@ from fastapi import FastAPI, HTTPException
5
  from pydantic import BaseModel
6
  from dotenv import load_dotenv
7
  from rag import build_rag_chain
8
- from db.chroma_init import load_recipes_to_chroma
9
 
10
  load_dotenv()
11
  app = FastAPI(
12
  title="Recipe RAG API (Gemini 2.0)",
13
- description="使用 FastAPI + LangChain + Chroma + HuggingFace Embeddings 的服務",
14
  version="1.0.0"
15
  )
16
 
17
- # 啟動時若 Chroma 尚未建立,嘗試載入 sample data(可按需註解)
18
- CHROMA_DIR = "./chroma_db"
19
- if not os.path.exists(CHROMA_DIR) or not os.listdir(CHROMA_DIR):
20
- try:
21
- print("load : chroma init")
22
- load_recipes_to_chroma()
23
- except Exception as e:
24
- print("Warning: chroma init failed:", e)
25
-
26
  # 建立 RAG chain(可共用)
27
  RAG_CHAIN = build_rag_chain(k=4)
28
 
 
5
  from pydantic import BaseModel
6
  from dotenv import load_dotenv
7
  from rag import build_rag_chain
 
8
 
9
  load_dotenv()
10
  app = FastAPI(
11
  title="Recipe RAG API (Gemini 2.0)",
12
+ description="使用 FastAPI + LangChain + postgres + PGVector + HuggingFace Embeddings 的服務",
13
  version="1.0.0"
14
  )
15
 
 
 
 
 
 
 
 
 
 
16
  # 建立 RAG chain(可共用)
17
  RAG_CHAIN = build_rag_chain(k=4)
18
 
db/chroma_init.py DELETED
@@ -1,35 +0,0 @@
1
- # db/chroma_init.py
2
- from langchain_chroma import Chroma
3
- from langchain_huggingface import HuggingFaceEmbeddings
4
-
5
- CHROMA_DIR = "./chroma_db"
6
- MODEL_NAME="sentence-transformers/all-MiniLM-L6-v2"
7
-
8
- def load_recipes_to_chroma(texts):
9
-
10
- # 使用 HuggingFace Embeddings(推薦)
11
- embeddings = HuggingFaceEmbeddings(
12
- model_name=MODEL_NAME
13
- )
14
-
15
- # 建立 Chroma DB
16
- db = Chroma.from_texts(
17
- texts=texts,
18
- embedding=embeddings,
19
- persist_directory=CHROMA_DIR
20
- )
21
-
22
- db.persist()
23
- return db
24
-
25
- # --- 建立 Chroma DB ---
26
- def get_vectordb():
27
- embeddings = HuggingFaceEmbeddings(
28
- model_name=MODEL_NAME
29
- )
30
-
31
- db = Chroma(
32
- persist_directory=CHROMA_DIR,
33
- embedding_function=embeddings
34
- )
35
- return db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db/postgres_init.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import psycopg2
2
+ from langchain_huggingface import HuggingFaceEmbeddings
3
+ # 💡 將 Chroma 替換為 PostgreSQL 的向量儲存類
4
+ # 這裡我們使用 LangChain 提供的 PostgresVectorStore
5
+ from langchain_community.vectorstores.pgvector import PGVector
6
+ import os
7
+ from dotenv import load_dotenv
8
+
9
+ load_dotenv()
10
+
11
+ # ⚠️ 請替換為您的實際配置
12
+ # 假設您的資料庫中已經創建了 'recipes_vectors' 表格
13
+ # --- 1. 資料庫連線設定 ---
14
+ # --- 資料庫連線設定 ---
15
+ DB_HOST=os.getenv("DB_HOST", "localhost")
16
+ DB_PORT=os.getenv("DB_PORT")
17
+ DB_DATABASE=os.getenv("DB_DATABASE")
18
+ DB_USER=os.getenv("DB_USER")
19
+ DB_PASSWORD=os.getenv("DB_PASSWORD")
20
+
21
+ DB_CONFIG = {
22
+ "host": DB_HOST, # 如果找不到,提供預設值
23
+ "database": DB_DATABASE,
24
+ "user": DB_USER,
25
+ "password": DB_PASSWORD,
26
+ "port": DB_PORT
27
+ }
28
+
29
+ TABLE_NAME = "recipes"
30
+ VECTOR_DIM = 384 # 確保這個維度和您的 'embedding' 欄位定義一致
31
+ # 🚨 選擇一個多語言模型。例如:BGE-M3 (維度 1024) 或 paraphrase-multilingual-mpnet-base-v2 (維度 768)
32
+ MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
33
+
34
+ # 這是 PGVector 實例使用的連接字串格式
35
+ CONNECTION_STRING = PGVector.connection_string_from_db_params(
36
+ driver="psycopg2",
37
+ **DB_CONFIG
38
+ )
39
+
40
+ # --- 將此函數定義為 get_vectordb ---
41
+ def get_vectordb():
42
+ """
43
+ 獲取已存在的 PostgreSQL 向量儲存實例 (PGVector)。
44
+ 此函數取代了原先獲取 Chroma 實例的功能。
45
+ """
46
+ embeddings = HuggingFaceEmbeddings(
47
+ model_name=MODEL_NAME
48
+ )
49
+
50
+ # 使用您的 PostgreSQL 連接字串和集合名稱
51
+ db = PGVector(
52
+ connection_string=CONNECTION_STRING,
53
+ embedding_function=embeddings,
54
+ collection_name=TABLE_NAME, # 您的 recipe table 名稱
55
+ use_jsonb=True
56
+ )
57
+ return db
rag.py CHANGED
@@ -10,7 +10,7 @@ from langchain_core.prompts import SystemMessagePromptTemplate, HumanMessageProm
10
  from langchain_core.prompts import PromptTemplate # 確保導入這個,用於 HumanMessage 的子模板
11
  from langchain_core.prompts import ChatPromptTemplate
12
  from models.model_wrapper import get_llm
13
- from db.chroma_init import get_vectordb
14
  from langchain_core.exceptions import OutputParserException
15
 
16
  # --- 🎯 食譜 Pydantic 結構定義 ---
@@ -87,12 +87,15 @@ def build_rag_chain(k=4):
87
  structured_llm = llm.with_structured_output(RecipeList)
88
 
89
  def get_context_and_query(query: str):
90
- docs = retriever.invoke(query)
 
91
  context = "\n".join([d.page_content for d in docs])
92
  return {"context": context, "query": query, "docs": docs}
93
 
94
  # 調整 rag 函式以返回更清晰的結果
95
  def rag(query: str):
 
 
96
 
97
  # ----------------------------------------------------
98
  # 1. 執行檢索 (RunnableLambda 讓我們在 LCEL 外執行並拿到中間結果)
 
10
  from langchain_core.prompts import PromptTemplate # 確保導入這個,用於 HumanMessage 的子模板
11
  from langchain_core.prompts import ChatPromptTemplate
12
  from models.model_wrapper import get_llm
13
+ from db.postgres_init import get_vectordb
14
  from langchain_core.exceptions import OutputParserException
15
 
16
  # --- 🎯 食譜 Pydantic 結構定義 ---
 
87
  structured_llm = llm.with_structured_output(RecipeList)
88
 
89
  def get_context_and_query(query: str):
90
+ # 這裡的 retriever.invoke() 現在會對 PostgreSQL 執行向量相似性搜索
91
+ docs = retriever.invoke(query)
92
  context = "\n".join([d.page_content for d in docs])
93
  return {"context": context, "query": query, "docs": docs}
94
 
95
  # 調整 rag 函式以返回更清晰的結果
96
  def rag(query: str):
97
+
98
+ docs = []
99
 
100
  # ----------------------------------------------------
101
  # 1. 執行檢索 (RunnableLambda 讓我們在 LCEL 外執行並拿到中間結果)
requirements.txt CHANGED
@@ -5,9 +5,9 @@ langchain-core
5
  langchain-community
6
  langchain-google-genai
7
  langchain-huggingface
8
- langchain-chroma
9
- chromadb
10
  sentence-transformers
11
  huggingface-hub
12
  python-dotenv
13
  pydantic
 
 
 
5
  langchain-community
6
  langchain-google-genai
7
  langchain-huggingface
 
 
8
  sentence-transformers
9
  huggingface-hub
10
  python-dotenv
11
  pydantic
12
+ psycopg2-binary
13
+ pgvector