Commit 8fccd372 authored by Vũ Hoàng Anh's avatar Vũ Hoàng Anh

chore: ignore hehe, test, and scripts folders

parent 6e5f501c
......@@ -39,6 +39,11 @@ backend/*.pyc
# Preference folder (development/temporary)
preference/
# Development/Test folders
backend/hehe/
backend/test/
backend/scripts/
# OS
.DS_Store
Thumbs.db
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Method,Name,Error,Occurrences
POST,/api/agent/chat [MAIN],CatchResponseError('Status: 404'),80
POST,/api/agent/chat [MAIN],CatchResponseError('Status: 0'),7
POST,/test/db-search [DB_ONLY],HTTPError('404 Client Error: Not Found for url: /test/db-search [DB_ONLY]'),231
Type,Name,Request Count,Failure Count,Median Response Time,Average Response Time,Min Response Time,Max Response Time,Average Content Size,Requests/s,Failures/s,50%,66%,75%,80%,90%,95%,98%,99%,99.9%,99.99%,100%
POST,/api/agent/chat [MAIN],87,87,1200.0,1715.7884011494702,1.9360000733286142,6251.831999979913,20.229885057471265,3.7430531309093538,3.7430531309093538,1200,1500,2600,2600,4300,6000,6200,6300,6300,6300,6300
GET,/health,6,0,760.0,1024.0447499866907,86.62169997114688,2807.93920008,17220.0,0.25814159523512786,0.0,770,770,1500,1500,2800,2800,2800,2800,2800,2800,2800
POST,/test/db-search [DB_ONLY],231,231,800.0,1095.216632898276,2.817099913954735,7268.948999932036,22.0,9.938451416552422,9.938451416552422,800,1200,1300,1500,2600,3100,5100,5800,7300,7300,7300
,Aggregated,324,318,890.0,1260.533646911808,1.9360000733286142,7268.948999932036,340.0061728395062,13.939646142696905,13.681504547461776,890,1300,1500,2100,2600,4200,6000,6200,7300,7300,7300
Timestamp,User Count,Type,Name,Requests/s,Failures/s,50%,66%,75%,80%,90%,95%,98%,99%,99.9%,99.99%,100%,Total Request Count,Total Failure Count,Total Median Response Time,Total Average Response Time,Total Min Response Time,Total Max Response Time,Total Average Content Size
1767665177,0,,Aggregated,0.000000,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,0,0,0,0.0,0,0,0
1767665178,10,,Aggregated,0.000000,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,0,0,0,0.0,0,0,0
1767665179,20,,Aggregated,0.000000,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,0,0,0,0.0,0,0,0
1767665180,30,,Aggregated,0.000000,0.000000,2600,2600,2600,2600,2600,2800,2800,2800,2800,2800,2800,12,11,2600.0,2172.7166083583143,13.209500000812113,2807.93920008,1455.1666666666667
1767665181,40,,Aggregated,0.000000,0.000000,2600,2600,2600,2800,3000,3100,3200,3200,3200,3200,3200,23,22,2600.0,2127.1039913256614,13.209500000812113,3222.1904000034556,769.7391304347826
1767665182,50,,Aggregated,3.333333,3.000000,2600,2600,2600,2600,2900,3100,3400,3400,3400,3400,3400,41,40,2600.0,1878.9734097606524,13.209500000812113,3379.774900036864,441.4634146341463
1767665183,50,,Aggregated,4.000000,3.750000,2600,2600,2600,2600,2900,3100,3200,3400,3400,3400,3400,51,50,2600.0,1680.0740803934304,13.209500000812113,3379.774900036864,359.2156862745098
1767665185,50,,Aggregated,6.000000,5.800000,2400,2600,2600,2600,3100,3500,4100,4200,4200,4200,4200,68,67,1100.0,1646.725695587092,13.209500000812113,4216.733000008389,274.9117647058824
1767665186,50,,Aggregated,7.285714,7.142857,1400,2600,2600,2600,3400,4200,5200,5600,5600,5600,5600,80,79,1400.0,1743.8070987467654,13.209500000812113,5642.961099976674,236.975
1767665187,50,,Aggregated,8.500000,8.375000,1200,2600,2600,2600,3500,5000,5200,5600,6100,6100,6100,106,105,1200.0,1724.8162594327334,13.209500000812113,6071.023600059561,184.24528301886792
1767665188,50,,Aggregated,8.777778,8.666667,1100,2400,2600,2600,5000,6000,6300,7200,7300,7300,7300,137,136,1100.0,1771.4287751791046,13.209500000812113,7268.948999932036,147.53284671532847
1767665190,50,,Aggregated,13.000000,12.900000,850,1200,2600,2600,3600,5600,6200,7200,7300,7300,7300,169,166,850.0,1466.0903857917574,2.817099913954735,7268.948999932036,327.2899408284024
1767665191,50,,Aggregated,13.900000,13.800000,830,1200,2400,2600,3200,5200,6200,7200,7300,7300,7300,191,188,830.0,1378.066231930599,2.817099913954735,7268.948999932036,292.1256544502618
1767665192,50,,Aggregated,13.900000,13.800000,870,1200,1500,2600,3100,5200,6100,6300,7300,7300,7300,203,200,870.0,1357.2945172349082,2.817099913954735,7268.948999932036,275.83251231527095
1767665193,50,,Aggregated,16.600000,16.400000,950,1200,1500,2600,3000,5200,6100,6300,7300,7300,7300,217,214,950.0,1361.8354663539308,2.817099913954735,7268.948999932036,259.4562211981567
1767665194,50,,Aggregated,17.300000,17.100000,1100,1400,2100,2500,2900,5000,6100,6300,7300,7300,7300,249,246,1100.0,1419.1991526060308,2.817099913954735,7268.948999932036,228.93975903614458
1767665196,50,,Aggregated,16.600000,16.400000,1100,1400,1900,2500,2900,5000,6100,6300,7300,7300,7300,258,252,1000.0,1382.0461077478446,1.9360000733286142,7268.948999932036,421.69767441860466
1767665197,50,,Aggregated,18.600000,18.100000,950,1300,1600,2400,2600,4200,6100,6300,7300,7300,7300,283,277,950.0,1327.5479494664792,1.9360000733286142,7268.948999932036,386.3886925795053
1767665199,50,,Aggregated,17.600000,17.100000,840,1200,1500,2300,2600,4100,6000,6200,7300,7300,7300,308,302,830.0,1242.4250762961055,1.9360000733286142,7268.948999932036,356.7402597402597
1767665200,50,,Aggregated,16.000000,15.500000,890,1300,1500,2100,2600,4200,6000,6200,7300,7300,7300,324,318,890.0,1260.533646911808,1.9360000733286142,7268.948999932036,340.0061728395062
import random
from locust import HttpUser, between, task
# Danh sách từ khóa để random
PRODUCTS = [
"áo phông",
"áo khoác",
"áo len",
"áo polo",
"áo sơ mi",
"quần jean",
"quần âu",
"quần short",
"váy liền",
"chân váy",
]
COLORS = ["", "màu đen", "màu trắng", "màu đỏ", "màu xanh", "màu vàng", "màu be"]
GENDERS = ["", "nam", "nữ", "bé trai", "bé gái"]
class FashionUser(HttpUser):
# Thời gian nghỉ giữa các lần request (mô phỏng người thật: 1-3s)
wait_time = between(1, 3)
# --- DB TESTS (ĐÃ TEST XONG, TẠM TẮT) ---
# @task(3)
# def search_random_product(self):
# """
# Giả lập user tìm kiếm sản phẩm bất kỳ.
# Ghép random: [Sản phẩm] + [Giới tính] + [Màu]
# Ví dụ: "áo phông nam màu đen"
# """
# # Random query builder
# p = random.choice(PRODUCTS)
# g = random.choice(GENDERS)
# c = random.choice(COLORS)
# query = f"{p} {g} {c}".strip()
# # Loại bỏ khoảng trắng thừa
# query = " ".join(query.split())
# self.client.post("/test/db-search", json={"query": query, "limit": 10}, name="/test/db-search (Dynamic)")
# @task(1)
# def search_hot_items(self):
# """
# Giả lập các món Hot trend nhiều người tìm giống nhau (Cache test)
# """
# hot_item = "áo giữ nhiệt"
# self.client.post("/test/db-search", json={"query": hot_item, "limit": 10}, name="/test/db-search (Hero Item)")
# @task(3)
# def fast_ping_check(self):
# """
# Kiểm tra tốc độ thuần túy của việc lấy Connection + SELECT 1.
# Nếu cái này < 100ms mà Search > 3000ms --> Do câu Query nặng.
# Nếu cái này cũng > 3000ms --> Do Pool bị nghẽn (Server quá tải).
# """
# self.client.post("/test/db-ping", json={}, name="/test/db-ping (Isolate Latency)")
# --- LOGIC GRAPH TEST (BẬT) ---
@task(1)
def check_graph_overhead(self):
"""
Test Logic Flow (Mock LLM + MemorySaver).
⚠️ Chạy với 300-500 users thôi, không nên quá 1000.
"""
query = random.choice(["hello", "tìm áo", "giá bao nhiêu", "có màu gì"])
self.client.post("/test/graph-mock-chat", json={"query": query}, name="/test/graph Logic (Mock LLM)")
"""
🎯 Production-like Performance Testing with Locust
Test thực tế các endpoint QUAN TRỌNG của chatbot để tìm bottleneck.
CÁCH CHẠY:
1. Start API server:
cd backend
python run.py
2. Run Locust với file này:
locust -f locust/locustfile_production.py --host=http://localhost:8000
3. Mở browser: http://localhost:8089
- Number of users: 50 (tăng dần để test scalability)
- Spawn rate: 10 users/second
- Host: http://localhost:8000
📊 METRICS CẦN QUAN TÂM:
- Response Time (P50, P95, P99): Thời gian phản hồi
- RPS (Requests per second): Throughput
- Failure Rate: Tỷ lệ lỗi
"""
import random
import time
from locust import HttpUser, between, events, task
# ============================================================
# TEST DATA - Mô phỏng real user queries
# ============================================================
CHAT_QUERIES = [
# Simple product search (nhanh)
"tìm áo phông nam",
"quần jean nữ",
"váy liền",
# Complex search với filters (chậm hơn)
"áo khoác nam màu đen giá dưới 500k",
"quần short nữ mùa hè",
# Knowledge queries (test RAG knowledge base)
"Canifa có cửa hàng ở Hà Nội không?",
"chính sách đổi trả",
"bảng size áo nam",
# Conversational (test LLM reasoning)
"xin chào",
"cảm ơn bạn",
]
VISUAL_SEARCH_IMAGES = [
"https://canifa.com/img/500/750/resize/6/t/6ts24w007-sk010-m-1-u.webp",
"https://canifa.com/img/500/750/resize/6/a/6aw24w006-sb492-thumb-2.webp",
]
# ============================================================
# CUSTOM METRICS - Track specific bottlenecks
# ============================================================
chat_response_times = []
db_query_times = []
llm_call_times = []
@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
"""Print summary khi test xong."""
print("\n" + "=" * 60)
print("📊 PERFORMANCE TEST SUMMARY")
print("=" * 60)
if chat_response_times:
avg_chat = sum(chat_response_times) / len(chat_response_times)
print(f"💬 Chat Response Time (avg): {avg_chat:.2f}ms")
print(f" P50: {sorted(chat_response_times)[len(chat_response_times) // 2]:.2f}ms")
print(f" P95: {sorted(chat_response_times)[int(len(chat_response_times) * 0.95)]:.2f}ms")
print("\n🎯 RECOMMENDED ACTIONS:")
print("1. Check response times > 2000ms")
print("2. Identify which endpoint has highest latency")
print("3. Use profiling tools (below) for deep dive")
print("=" * 60 + "\n")
# ============================================================
# USER BEHAVIORS
# ============================================================
class ChatbotUser(HttpUser):
"""Mô phỏng user sử dụng chatbot."""
wait_time = between(2, 5) # User thường đợi 2-5s giữa các câu hỏi
def on_start(self):
"""Initialize user - giống như user mở chat lần đầu."""
self.user_id = f"user_{random.randint(1000, 9999)}"
self.thread_id = f"thread_{int(time.time() * 1000)}_{random.randint(0, 999)}"
@task(10)
def chat_message(self):
"""
Task quan trọng nhất - test FULL chatbot flow.
Weight: 10 (chiếm 10/12 = 83% traffic)
"""
query = random.choice(CHAT_QUERIES)
start_time = time.time()
with self.client.post(
"/api/agent/chat",
json={"message": query, "user_id": self.user_id, "thread_id": self.thread_id},
catch_response=True,
name="/api/agent/chat [MAIN]",
) as response:
duration = (time.time() - start_time) * 1000 # ms
chat_response_times.append(duration)
if response.status_code == 200:
response.success()
else:
response.failure(f"Status: {response.status_code}")
@task(1)
def health_check(self):
"""
Health check endpoint.
Weight: 1 (8% traffic)
"""
self.client.get("/", name="/health")
@task(1)
def visual_search(self):
"""
Test visual search nếu có.
Weight: 1 (8% traffic)
"""
img_url = random.choice(VISUAL_SEARCH_IMAGES)
self.client.post(
"/api/recommend/image",
json={"image_url": img_url},
name="/api/recommend/image [VISUAL]",
catch_response=True,
)
class DatabaseStressUser(HttpUser):
"""
Riêng để test ONLY database bottleneck.
Chạy riêng test này để isolate DB performance.
"""
wait_time = between(8, 20) # Mô phỏng người dùng thật: đợi 8-20s giữa các lần search
@task
def db_direct_query(self):
"""Test trực tiếp StarRocks query speed."""
self.client.post(
"/test/db-search",
json={"query": random.choice(["áo phông", "quần jean", "váy"]), "limit": 10},
name="/test/db-search [DB_ONLY]",
)
# ============================================================
# SHAPE CONFIGURATION - Simulate real traffic pattern
# ============================================================
class WebsiteUserShape:
"""
Mô phỏng traffic pattern thực tế:
- Sáng sớm: ít user
- Trưa + tối: peak hours
- Đêm khuya: vắng
CHỈ DÙNG KHI MUỐN TEST THEO PATTERN, KHÔNG DÙNG CHO TEST NHANH.
"""
pass # Implement nếu cần
if __name__ == "__main__":
print("🚀 Starting Locust Performance Test...")
print("📖 Read the docstring for instructions!")
{
"mcpServers": {
"dbeaver": {
"command": "dbeaver-mcp-server",
"env": {
"DBEAVER_DEBUG": "false",
"DBEAVER_TIMEOUT": "30000"
}
},
"sequential-thinking": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sequential-thinking"
],
"env": {}
},
"docs-langchain": {
"serverUrl": "https://docs.langchain.com/mcp"
},
"playwright": {
"command": "npx",
"args": [
"@playwright/mcp@latest"
]
},
"locust-canifa": {
"command": "python",
"args": [
"d:\\cnf\\chatbot_canifa\\backend\\locust\\locust_mcp_server.py"
],
"env": {
"LOCUST_HOST": "http://localhost:8000",
"LOCUST_USERS": "50",
"LOCUST_SPAWN_RATE": "10",
"LOCUST_RUN_TIME": "30s"
}
}
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# Chạy từ thư mục d:\cnf\chatbot_canifa\backend\hehe
# 1. Khởi động Server (4 Workers)
python api_server_perf.py
# 2. Chạy Locust Test (500 Users)
locust -f locustfile_production.py --host=http://localhost:8000 --headless -u 500 -r 20 --run-time 1m --html report.html
# 3. Lệnh "trảm" process nếu bị treo
Stop-Process -Name python -Force
\ No newline at end of file
# ============================================================
# 🚀 AUTO PERFORMANCE TEST RUNNER
# ============================================================
# Script tự động:
# 1. Start Mock Server (port 8000)
# 2. Đợi server ready
# 3. Run Locust performance test
# 4. Cleanup
# ============================================================
Write-Host "=" -NoNewline -ForegroundColor Cyan
Write-Host "=" * 59 -ForegroundColor Cyan
Write-Host "🚀 CANIFA CHATBOT - PERFORMANCE TEST AUTOMATION" -ForegroundColor Green
Write-Host "=" -NoNewline -ForegroundColor Cyan
Write-Host "=" * 59 -ForegroundColor Cyan
# Activate venv
Write-Host "`n📦 Activating virtual environment..." -ForegroundColor Yellow
& ..\..\.venv\Scripts\Activate.ps1
# Start Mock Server in background
Write-Host "🎭 Starting Mock Server (Port 8000)..." -ForegroundColor Yellow
$serverJob = Start-Job -ScriptBlock {
Set-Location "D:\cnf\chatbot_canifa\backend"
& .venv\Scripts\Activate.ps1
python locust/api_server_perf.py
}
Write-Host "⏳ Waiting for server to be ready..." -ForegroundColor Yellow
Start-Sleep -Seconds 5
# Check if server is running
try {
$response = Invoke-WebRequest -Uri "http://localhost:8000/" -UseBasicParsing -TimeoutSec 3
Write-Host "✅ Mock Server is ready!" -ForegroundColor Green
} catch {
Write-Host "❌ Mock Server failed to start!" -ForegroundColor Red
Stop-Job $serverJob
Remove-Job $serverJob
exit 1
}
# Run Locust Test
Write-Host "`n🦗 Running Locust Performance Test..." -ForegroundColor Yellow
Write-Host " - Users: 50" -ForegroundColor Cyan
Write-Host " - Spawn Rate: 10/s" -ForegroundColor Cyan
Write-Host " - Duration: 30s" -ForegroundColor Cyan
Write-Host ""
locust -f locust/locustfile_production.py `
--headless `
--host http://localhost:8000 `
-u 50 `
-r 10 `
--run-time 30s `
--html locust/locust_report.html `
--csv locust/locust_stats
# Cleanup
Write-Host "`n🧹 Stopping Mock Server..." -ForegroundColor Yellow
Stop-Job $serverJob
Remove-Job $serverJob
Write-Host "`n" -NoNewline
Write-Host "=" -NoNewline -ForegroundColor Cyan
Write-Host "=" * 59 -ForegroundColor Cyan
Write-Host "✅ PERFORMANCE TEST COMPLETE!" -ForegroundColor Green
Write-Host "=" -NoNewline -ForegroundColor Cyan
Write-Host "=" * 59 -ForegroundColor Cyan
Write-Host "`n📊 View Results:" -ForegroundColor Yellow
Write-Host " - HTML Report: locust/locust_report.html" -ForegroundColor Cyan
Write-Host " - CSV Stats: locust/locust_stats_*.csv" -ForegroundColor Cyan
Write-Host ""
import requests
import json
import sys
url = "http://localhost:5000/api/agent/stream/chat"
headers = {"Content-Type": "application/json"}
data = {
"query": "Xin chào từ Python script",
"user_id": "python_test_user"
}
print(f"Sending POST to {url}...")
try:
with requests.post(url, json=data, headers=headers, stream=True) as r:
print(f"Status Code: {r.status_code}")
if r.status_code != 200:
print(f"Error: {r.text}")
sys.exit(1)
print("Response Stream:")
for line in r.iter_lines():
if line:
decoded_line = line.decode('utf-8')
print(decoded_line)
except Exception as e:
print(f"Exception: {e}")
import sys
import time
import random
# 1. Giả lập class ConversationManager y hệt như trong code thật
class MockConversationManager:
def __init__(self):
# Giả vờ kết nối DB tốn thời gian
print(" [DB] 🐢 Connecting to Database... (Init)")
self.connection_id = random.randint(1000, 9999)
print(f" [DB] ✅ Connected! ID kết nối: {self.connection_id}")
def query(self):
return f"Result from conn {self.connection_id}"
# 2. Biến toàn cục lưu instance (Singleton pattern)
_instance = None
def get_conversation_manager():
global _instance
if _instance is None:
print(" [System] ⚠️ Chưa có instance, đang tạo mới...")
_instance = MockConversationManager()
else:
print(" [System] ♻️ Đã có instance, dùng lại hàng cũ.")
return _instance
# 3. Giả lập các Request từ User gọi vào Server
print("-" * 50)
print("DEMO: GIẢ LẬP SERVER NHẬN REQUEST LIÊN TỤC")
print("-" * 50)
# Request 1 (User A)
print("\n👉 REQUEST 1: User A vào Chat")
manager1 = get_conversation_manager()
print(f"User A dùng Manager ID: {id(manager1)} (Conn ID: {manager1.connection_id})")
# Request 2 (User B)
print("\n👉 REQUEST 2: User B vào Chat")
manager2 = get_conversation_manager()
print(f"User B dùng Manager ID: {id(manager2)} (Conn ID: {manager2.connection_id})")
# Request 3 (User C)
print("\n👉 REQUEST 3: User C vào Chat")
manager3 = get_conversation_manager()
print(f"User C dùng Manager ID: {id(manager3)} (Conn ID: {manager3.connection_id})")
print("\n" + "-" * 50)
print("KẾT QUẢ KIỂM TRA:")
if manager1 is manager2 is manager3:
print("✅ THÀNH CÔNG: Cả 3 request đều dùng chung 1 object duy nhất!")
print(" => Không bị tạo lại kết nối DB thừa thãi.")
else:
print("❌ THẤT BẠI: Các object khác nhau.")
"""
Test Script: Kiểm tra Vector Index - SIÊU GỌN
Chỉ đo thời gian từ lúc có full query đến khi nhận kết quả
"""
import sys
import os
import asyncio
import time
# Add parent dir to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from common.embedding_service import create_embedding_async
from common.starrocks_connection import StarRocksConnection
async def main():
print("="*60)
print("🔍 TEST VECTOR INDEX - PERFORMANCE CHECK")
print("="*60)
# 1. Chuẩn bị dữ liệu (Embedding)
test_query = "áo sơ mi"
print(f" Creating embedding for: '{test_query}'...")
query_vector = await create_embedding_async(test_query)
# 2. Tạo full query string (COPY Y HỆT câu bro bảo "ngon" nhưng thêm Hint chuẩn)
v_str = "[" + ",".join(str(v) for v in query_vector) + "]"
sql = f"""
SELECT /*+ SET_VAR(ann_params='{{"ef_search":64}}') */
internal_ref_code,
approx_cosine_similarity(vector, {v_str}) as score
FROM shared_source.magento_product_dimension_with_text_embedding__tmp
ORDER BY score DESC
LIMIT 50
"""
# 3. Kết nối DB
db = StarRocksConnection()
conn = db.connect()
conn.ping(reconnect=True)
try:
with conn.cursor() as cursor:
# --- KIỂM TRA PLAN ---
print("🔬 Đang kiểm tra Query Plan (XEM FULL)...")
cursor.execute(f"EXPLAIN {sql}")
plan = cursor.fetchall()
is_vector_on = False
for row in plan:
line = str(row)
print(f" > {line}") # In full để mình soi
if "VECTORINDEX: ON" in line:
is_vector_on = True
print(f"\n📊 Vector Index Status: {'ON ✅' if is_vector_on else 'OFF ❌'}")
# Baseline: Độ trễ mạng
t_base_0 = time.perf_counter()
cursor.execute("SELECT 1")
cursor.fetchone()
baseline_ms = (time.perf_counter() - t_base_0) * 1000
print(f"📡 Network Baseline: {baseline_ms:.2f} ms")
print(f"\n🚀 ĐANG GỬI TRUY VẤN (10 vòng lặp)...")
durations = []
for i in range(1, 11):
start_time = time.perf_counter()
cursor.execute(sql)
rows = cursor.fetchall()
duration_ms = (time.perf_counter() - start_time) * 1000
durations.append(duration_ms)
status_icon = "⚡" if duration_ms < 80 else "🐢"
print(f"🔄 Lần {i:02d}: {duration_ms:7.2f} ms {status_icon}")
print("-" * 30)
print(f"📈 AVG: {sum(durations)/10:.2f}ms | MIN: {min(durations):.2f}ms | MAX: {max(durations):.2f}ms")
print("-" * 30 + "\n")
except Exception as e:
print(f"\n❌ Lỗi: {e}\n")
finally:
pass
print("="*60 + "\n")
if __name__ == "__main__":
asyncio.run(main())
"""
Test Script: Kiểm tra Vector Index - SIÊU GỌN
Chỉ đo thời gian từ lúc có full query đến khi nhận kết quả
"""
import sys
import os
import asyncio
import time
# Add parent dir to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from common.embedding_service import create_embedding_async
from common.starrocks_connection import StarRocksConnection
async def main():
print("="*60)
print("🔍 TEST VECTOR INDEX - PERFORMANCE CHECK")
print("="*60)
# 1. Chuẩn bị dữ liệu (Embedding)
test_query = "áo sơ mi"
print(f" Creating embedding for: '{test_query}'...")
query_vector = await create_embedding_async(test_query)
# 2. Tạo full query string (COPY Y HỆT câu bro bảo "ngon" nhưng thêm Hint chuẩn)
v_str = "[" + ",".join(str(v) for v in query_vector) + "]"
sql = f"""
SELECT /*+ SET_VAR(ann_params='{{"ef_search":64}}') */
internal_ref_code,
approx_cosine_similarity(vector, {v_str}) as score
FROM shared_source.magento_product_dimension_with_text_embedding__tmp
ORDER BY score DESC
LIMIT 50
"""
# 3. Kết nối DB
db = StarRocksConnection()
conn = db.connect()
conn.ping(reconnect=True)
try:
with conn.cursor() as cursor:
# --- KIỂM TRA PLAN ---
print("🔬 Đang kiểm tra Query Plan (XEM FULL)...")
cursor.execute(f"EXPLAIN {sql}")
plan = cursor.fetchall()
is_vector_on = False
for row in plan:
line = str(row)
print(f" > {line}") # In full để mình soi
if "VECTORINDEX: ON" in line:
is_vector_on = True
print(f"\n📊 Vector Index Status: {'ON ✅' if is_vector_on else 'OFF ❌'}")
# Baseline: Độ trễ mạng
t_base_0 = time.perf_counter()
cursor.execute("SELECT 1")
cursor.fetchone()
baseline_ms = (time.perf_counter() - t_base_0) * 1000
print(f"📡 Network Baseline: {baseline_ms:.2f} ms")
print(f"\n🚀 ĐANG GỬI TRUY VẤN (10 vòng lặp)...")
durations = []
for i in range(1, 11):
start_time = time.perf_counter()
cursor.execute(sql)
rows = cursor.fetchall()
duration_ms = (time.perf_counter() - start_time) * 1000
durations.append(duration_ms)
status_icon = "⚡" if duration_ms < 80 else "🐢"
print(f"🔄 Lần {i:02d}: {duration_ms:7.2f} ms {status_icon}")
print("-" * 30)
print(f"📈 AVG: {sum(durations)/10:.2f}ms | MIN: {min(durations):.2f}ms | MAX: {max(durations):.2f}ms")
print("-" * 30 + "\n")
except Exception as e:
print(f"\n❌ Lỗi: {e}\n")
finally:
pass
print("="*60 + "\n")
if __name__ == "__main__":
asyncio.run(main())
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment