File size: 8,396 Bytes
325b400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import os, sys
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.abspath(os.path.join(current_dir, '..', '..'))
sys.path.append(project_root)
from support import get_key
api_key = get_key.get_random_api_key()
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))





def is_insert_related_to_product_category_variant(user_question: str) -> bool:
    import google.generativeai as genai
    import time
    from retrying import retry


    # Lấy key và cấu hình
    api_key = get_key.get_random_api_key()
    genai.configure(api_key=api_key)
    
    generation_config = {
        "temperature": 0.3,
        "top_p": 0.9,
        "top_k": 20,
        "max_output_tokens": 1024,
        "response_mime_type": "text/plain",
    }

    model = genai.GenerativeModel(
        model_name="gemini-2.0-flash-thinking-exp-01-21",
        generation_config=generation_config,
    )

    # Prompt hệ thống
    system_prompt = f"""

Bạn là một bộ phân loại ý định (intent classifier).



Nhiệm vụ của bạn là kiểm tra xem **câu hỏi của người dùng có liên quan đến việc thêm mới (INSERT) các thực thể sau đây không**:

1. Thêm danh mục (category), cập nhật(chỉnh sửa) danh mục (update category)

2. Thêm sản phẩm (product), Cập nhật(chỉnh sửa) sản phẩm (update product)

3. Thêm biến thể sản phẩm (product variants), Cập nhật(chỉnh sửa) biến thể sản phẩm (update product variants)



---



### Câu hỏi người dùng:

{user_question}



---



### ✅ Kết quả mong muốn:

- Nếu câu hỏi có yêu cầu thêm danh mục, sản phẩm, hoặc biến thể sản phẩm → Trả về: `True`

- Nếu không liên quan đến hành động thêm → Trả về: `False`

- Tuyệt đối **không giải thích thêm**, chỉ trả về đúng `True` hoặc `False`

"""

    @retry(stop_max_attempt_number=3, wait_fixed=1000)  # 3 lần, cách nhau 1s
    def try_classify():
        chat_session = model.start_chat(history=[{"role": "user", "parts": [system_prompt]}])
        response = chat_session.send_message("Trả lời True hoặc False.")

        # Check nội dung phản hồi
        if response.candidates and response.candidates[0].parts:
            result = response.text.strip().lower()
            if result.startswith("true"):
                return True
            elif result.startswith("false"):
                return False
        raise ValueError("Không có phản hồi hợp lệ từ Gemini")

    try:
        return try_classify()
    except Exception as e:
        print(f"❌ Lỗi sau 3 lần thử: {e}")
        return False



def filter_syntax_sql(input, schema_sql, query):
    import google.generativeai as genai
    api_key = get_key.get_random_api_key()
    genai.configure(api_key=api_key)
    generation_config = {
        "temperature": 0.5,
        "top_p": 0.95,
        "top_k": 40,
        "max_output_tokens": 8192,
        "response_mime_type": "text/plain",
    }

    model = genai.GenerativeModel(
        model_name="gemini-2.5-flash-lite-preview-06-17",
        generation_config=generation_config,
    )

    chat_session = model.start_chat(
        history=[
            {
                "role": "user",
                "parts": [
                    f"""

Bạn là một chuyên gia SQL. Nhiệm vụ của bạn là **kiểm tra xem câu lệnh SQL dưới đây có hợp lệ và đáp ứng đúng yêu cầu hay không**, dựa trên:



1. ✅ Câu hỏi truy vấn từ người dùng

2. ✅ Cấu trúc schema được cung cấp



---



### 🧩 Câu hỏi từ người dùng:

{query}



---



### 🧾 Câu lệnh SQL cần kiểm tra:

{input}



---



### 🧱 Schema hệ thống (phải tuân thủ theo, không được phép bỏ qua):

{schema_sql}



---



### 📌 Yêu cầu kiểm tra bắt buộc:



1. **Câu SQL phải phù hợp với yêu cầu người dùng**.

   - SQL trả về phải thể hiện đúng mục đích của câu hỏi (ví dụ thêm, sửa, truy vấn thông tin nào đó).

2. **Câu SQL phải đúng cú pháp MySQL**. Không có lỗi cú pháp, sai từ khóa, hay sai định dạng.

3. **SQL phải tuân thủ đúng schema**:

   - Tên bảng, tên cột phải đúng như mô tả trong schema.

   - Không truy vấn vào bảng không tồn tại.

4. **Đảm bảo tính đầy đủ nghiệp vụ**:

   - Nếu INSERT vào `product`, thì **bắt buộc phải có** INSERT vào `product_translation`.

   - Nếu INSERT vào `category`, thì **bắt buộc phải có** INSERT vào `category_translation`.

5. **Phòng chống dữ liệu trùng lặp**:

   - Trước khi thêm `product`, phải kiểm tra `pro_name` đã tồn tại hay chưa.

   - Trước khi thêm `category`, phải kiểm tra `cate_name` đã tồn tại hay chưa.

6. **Không được sử dụng các khối IF...THEN...ELSE** trong SQL — hãy dùng logic SQL đơn giản, rõ ràng.

7. Nếu câu SQL **trống**, hoặc không rõ ràng, hoặc có vấn đề cú pháp/logic, hãy trả về `False`.

8. Cú pháp Insert cho Product phải kèm theo danh mục hàng hóa mà họ muốn thêm vào. Không được thêm sản phẩm mà không có danh mục hàng hóa.

9. Khi Insert Product Variants thì phải kèm theo Product ID mà họ muốn thêm vào. Không được thêm biến thể sản phẩm mà không có ID sản phẩm. Check kĩ càng liệu rằng việc thêm product_variants có hợp lệ hay không. Có kèm theo size của biến thể đó hay không. Cú pháp khi tạo cũng cần check xem liệu là biến thể cho sản phẩm đó với siz eddos có tồn tại hay không.

10. Khi cập nhật Category thì phải kiểm tra xem liệu là tên mà họ muốn thay đổi có tồn tại hay không.ArithmeticError

11. Khi cập nhật Product Variants phải kiểm tra xem liệu biến thể cập nhật có giống cũ hay không, hay tạo một biến thể khác ngoài ra phải check xem số lượng có lớn hơn 0 hay không. 



---



### 🎯 Kết quả mong đợi:

- Trả về **duy nhất** một từ: `True` nếu câu SQL hợp lệ và đúng như các yêu cầu trên.

- Trả về `False` nếu **bất kỳ yêu cầu nào ở trên không đạt**.



**Không** được trả lời thêm bất kỳ thông tin nào khác ngoài `True` hoặc `False`.

## 🎓 Few-shot Examples:



### ✅ Ví dụ 1:

**Câu hỏi**: Thêm sản phẩm "Trà xanh" vào danh mục "Trà truyền thống". Trả về True



**SQL**:

```sql

SELECT @category_id := `cate_id` FROM `category` WHERE `cate_name` = 'Trà truyền thống' AND `is_deleted` = 0;

SELECT @existing_product_id := `pro_id` FROM `product` WHERE `pro_name` = 'Trà xanh' AND `is_deleted` = 0;

INSERT INTO `product` (`pro_name`, `description`, `category_id`, `date_created`, `date_updated`, `is_deleted`, `list_pro_img`)

SELECT 'Trà xanh', 'Trà xanh thơm mát', @category_id, NOW(), NOW(), 0, '' WHERE @existing_product_id IS NULL;

INSERT INTO `product_translation` (`pro_id`, `pro_name`, `description`, `language_code`, `date_created`, `date_updated`, `is_deleted`)

VALUES (LAST_INSERT_ID(), 'Green Tea', 'Cool green tea', 'EN', NOW(), NOW(), 0);



### ✅ Ví dụ 2:

**Câu hỏi**: Thêm sản phẩm Trà sữa dâu vào danh mục Trà sữa.



SQL:

SELECT `cate_id` FROM `category` WHERE `cate_name` = 'Trà sữa' AND `is_deleted` = 0;

Kết quả mong muốn: False

⛔ Lý do: Chỉ kiểm tra danh mục, chưa thực hiện thêm sản phẩm hoặc translation.





**Vui lòng chỉ trả về kết quả là True hoặc False, không thêm bất kỳ thông tin nào khác.**



"""
                ],
            }
        ]
    )

    response = chat_session.send_message("Câu SQL trên hợp lệ hay không?. **Vui lòng chỉ trả về kết quả là True hoặc False, không thêm bất kỳ thông tin nào khác.**")
    result = response.text.strip().lower()

    if result.startswith("true"):
        return True
    elif result.startswith("false"):
        return False
    else:
        return False