votanthanh32004 commited on
Commit
4964210
·
1 Parent(s): ece0cc5
Files changed (2) hide show
  1. app.py +106 -22
  2. requirements.txt +2 -0
app.py CHANGED
@@ -1,43 +1,127 @@
1
  import uvicorn
2
  from fastapi import FastAPI, Body
3
  from sentence_transformers import SentenceTransformer
 
 
4
 
5
- # ==========================================
6
- # PHẦN 1: KHỞI TẠO AI ENGINE
7
- # ==========================================
8
- print("⏳ Đang tải Model AI (All-MiniLM-L6-v2)...")
9
  # Tải model 1 lần duy nhất khi Server khởi động
10
  model = SentenceTransformer('all-MiniLM-L6-v2')
11
  print("✅ Model đã sẵn sàng!")
12
 
 
 
 
 
 
 
 
13
  app = FastAPI()
14
 
15
  @app.get("/")
16
- def home():
17
- return {"status": "AI Server is RUNNING on Hugging Face", "model": "all-MiniLM-L6-v2"}
 
 
 
 
 
18
 
19
  @app.post("/vectorize")
20
- def vectorize_products(payload: dict = Body(...)):
21
- """
22
- API nhận vào JSON: { "products": ["Tên SP 1", "Tên SP 2"] }
23
- Trả về: { "vectors": [[0.1, ...], [0.2, ...]] }
24
- """
25
- products_text = payload.get("products", [])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- # Kiểm tra đầu vào
28
- if not products_text:
29
- return {"vectors": []}
30
 
31
- print(f"⚡ Đang xử {len(products_text)} sản phẩm...")
 
 
 
 
 
32
 
33
- # Tính toán Vector
34
- vectors = model.encode(products_text).tolist()
 
 
 
 
 
 
35
 
36
- return {"vectors": vectors}
 
37
 
38
- # ==========================================
39
- # PHẦN 2: KHỞI ĐỘNG SERVER
40
- # ==========================================
41
  if __name__ == "__main__":
42
  # Hugging Face yêu cầu bắt buộc chạy ở port 7860
43
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
  import uvicorn
2
  from fastapi import FastAPI, Body
3
  from sentence_transformers import SentenceTransformer
4
+ from sklearn.metrics.pairwise import cosine_similarity
5
+ import numpy as np
6
 
 
 
 
 
7
  # Tải model 1 lần duy nhất khi Server khởi động
8
  model = SentenceTransformer('all-MiniLM-L6-v2')
9
  print("✅ Model đã sẵn sàng!")
10
 
11
+ product_db = {
12
+ "ids": [],
13
+ "vectors": None,
14
+ "cached_result": {}
15
+ }
16
+
17
+ #App
18
  app = FastAPI()
19
 
20
  @app.get("/")
21
+ async def home():
22
+ return {"status": "AI Server is RUNNING", "model": "all-MiniLM-L6-v2"}
23
+
24
+ @app.get("/status")
25
+ async def status():
26
+ count = len(product_db["ids"])
27
+ return {"count": count}
28
 
29
  @app.post("/vectorize")
30
+ async def vectorize_products(payload: dict = Body(...)):
31
+ products = payload.get("products", [])
32
+ k_item = payload.get("k_item",5)
33
+ if not products:
34
+ return {"error": "Danh sách sản phẩm trống"}
35
+ product_names = [x['name'] for x in products]
36
+ product_ids = [x['id'] for x in products]
37
+ # Tính ra vector
38
+ vectors = model.encode(product_names)
39
+ product_db["vectors"] = vectors # lưu lại
40
+
41
+ product_db["ids"] = product_ids
42
+
43
+ sim_matrix = cosine_similarity(vectors)
44
+ res = {}
45
+ # Duyệt qua từng dòng của ma trận
46
+ for i in range(len(product_ids)):
47
+ current_id = product_ids[i]
48
+ scores = sim_matrix[i]
49
+
50
+ # Sắp xếp index giảm dần
51
+ sorted_indices = np.argsort(scores)[::-1]
52
+
53
+ # Lấy top k (bỏ qua index 0 là chính nó)
54
+ top_indices = sorted_indices[1 : k_item + 1]
55
+
56
+ # Map từ Index -> ID thật
57
+ similar_ids = [product_ids[idx] for idx in top_indices]
58
+
59
+ # Lưu vào dict kết quả (Key phải là string)
60
+ res[str(current_id)] = [int(x) for x in similar_ids]
61
+ product_db['cached_result'] = res
62
+ # Trả về đúng cấu trúc AiResponse bên Java
63
+ return {"result": res}
64
+
65
+ @app.get("/refresh_cache")
66
+ async def refresh_cache():
67
+ return {"result": product_db.get("cached_result", {})}
68
+
69
+ @app.post("/add_product")
70
+ async def add_product(payload: dict = Body(...)):
71
+ # 1. Lấy dữ liệu đầu vào
72
+ new_id = payload.get("id")
73
+ new_name = payload.get("name")
74
+
75
+ if new_id is None or not new_name:
76
+ return {"error": "Dữ liệu không hợp lệ"}
77
+
78
+ print(f"⚡ Đang thêm sản phẩm mới: ID {new_id} - {new_name}")
79
+
80
+ # 2. Vector hóa CHỈ 1 SẢN PHẨM MỚI (Cực nhanh)
81
+ # Kết quả là 1 vector (Shape: 1 x 768)
82
+ new_vector = model.encode([new_name])
83
+
84
+ # 3. Lấy kho dữ liệu cũ từ RAM
85
+ existing_vectors = product_db["vectors"]
86
+ existing_ids = product_db["ids"]
87
+ cached_result = product_db["cached_result"]
88
+
89
+ # Trường hợp chưa Init dữ liệu thì coi như init mới
90
+ if existing_vectors is None or len(existing_ids) == 0:
91
+ return {"result": {}}
92
+
93
+ # 4. TÍNH TOÁN TƯƠNG ĐỒNG (Điểm mấu chốt của tốc độ)
94
+ # So sánh vector mới với toàn bộ vector cũ
95
+ # cosine_similarity(new, old) -> Trả về mảng điểm số
96
+ sim_scores = cosine_similarity(new_vector, existing_vectors)[0]
97
+
98
+ # 5. Tìm Top K cho sản phẩm mới
99
+ k_item = 5
100
+ # Sắp xếp giảm dần và lấy top k
101
+ top_indices = np.argsort(sim_scores)[::-1][:k_item]
102
 
103
+ # Map từ index sang ID thật
104
+ similar_ids = [int(existing_ids[idx]) for idx in top_indices]
 
105
 
106
+ # 6. CẬP NHẬT DATABASE TRONG RAM (Để lần sau thêm tiếp còn dùng)
107
+ # Thêm ID mới vào danh sách
108
+ product_db["ids"].append(new_id)
109
+
110
+ # Nối vector mới vào ma trận cũ (Append vào dòng cuối)
111
+ product_db["vectors"] = np.vstack([existing_vectors, new_vector])
112
 
113
+ # Cập nhật Cache kết quả
114
+ result_map = {str(new_id): similar_ids}
115
+
116
+ # (Optional) Update ngược: Nếu sản phẩm cũ thấy sản phẩm mới này giống nó
117
+ # Đoạn này làm phức tạp hơn, tạm thời ta chỉ quan tâm chiều xuôi: New -> Old
118
+ cached_result.update(result_map)
119
+
120
+ print(f"✅ Đã thêm xong ID {new_id}. Tìm thấy {len(similar_ids)} sản phẩm tương tự.")
121
 
122
+ # Trả về kết quả để Java update cache
123
+ return {"result": result_map}
124
 
 
 
 
125
  if __name__ == "__main__":
126
  # Hugging Face yêu cầu bắt buộc chạy ở port 7860
127
  uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt CHANGED
@@ -1,4 +1,6 @@
1
  fastapi
2
  uvicorn[standard]
3
  sentence-transformers
 
 
4
  torch --index-url https://download.pytorch.org/whl/cpu
 
1
  fastapi
2
  uvicorn[standard]
3
  sentence-transformers
4
+ scikit-learn
5
+ numpy
6
  torch --index-url https://download.pytorch.org/whl/cpu