telegram-pms-bot / nlu_processor.py
nssuwan186's picture
Fix: Correct Dockerfile and NLU processor
10d681d
import os
import json
import time
import random
import google.generativeai as genai
from google.api_core import exceptions
# ตัวแปรสำหรับเก็บโมเดล Gemini
model = None
# ตั้งค่า API Key และโมเดล
try:
# อ่าน API Key จาก Environment Secret
GEMINI_API_KEY = os.environ.get('GEMINI_API_KEY')
if not GEMINI_API_KEY:
# ข้อความภาษาไทยที่แก้ไขแล้ว
raise ValueError("ไม่พบ GEMINI_API_KEY ใน Environment Secret")
genai.configure(api_key=GEMINI_API_KEY)
# ใช้ gemini-1.5-flash เพื่อความรวดเร็วในการประมวลผล NLU
model = genai.GenerativeModel('gemini-1.5-flash')
except Exception as e:
# ข้อความภาษาไทยที่แก้ไขแล้ว
print(f"เกิดข้อผิดพลาดร้ายแรงตอนตั้งค่า Gemini: {e}")
model = None
def generate_with_retry(model, prompt, max_retries=5):
"""เรียกใช้ Gemini API พร้อมกลไกการลองซ้ำ (retry) และ Exponential Backoff"""
if not model:
# ข้อความภาษาไทยที่แก้ไขแล้ว
return {"intent": "error", "message": "Gemini model ไม่ได้ถูกตั้งค่าอย่างถูกต้อง"}
attempt = 0
wait_time = 1
# กำหนดโครงสร้าง JSON และ System Instruction สำหรับ NLU
config = {
"generation_config": {
"response_mime_type": "application/json",
},
"safety_settings": [
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
]
}
system_instruction = """คุณคือ Natural Language Understanding (NLU) Processor ที่เก่งภาษาไทย
หน้าที่ของคุณคือแปลงข้อความของผู้ใช้ให้เป็น JSON ที่มี intent และ entities เท่านั้น
- intent: คือเจตนาหลักของผู้ใช้
- entities: คือข้อมูลสำคัญที่สกัดได้จากข้อความ
ห้ามเพิ่มข้อความอธิบายอื่นใดนอกเหนือจาก JSON object ที่ร้องขอ
ตัวอย่าง:
- ข้อความ: \"อยากจองห้องพักสำหรับ 2 คน วันที่ 25 ธันวา\"
- ผลลัพธ์ JSON: {\"intent\": \"create_booking\", \"entities\": {\"guests\": 2, \"date\": \"25-12\"}}
- ข้อความ: \"ขอดูข้อมูลผู้เช่าห้อง A101\"
- ผลลัพธ์ JSON: {\"intent\": \"get_renter\", \"entities\": {\"room_number\": \"A101\"}}
"""
while attempt < max_retries:
try:
response = model.generate_content(
[system_instruction, prompt],
generation_config=config["generation_config"],
safety_settings=config["safety_settings"]
)
return response
except exceptions.ResourceExhausted as e:
# ข้อความภาษาไทยที่แก้ไขแล้ว
print(f"Too Many Requests, กำลังลองใหม่ใน {wait_time} วินาที...")
time.sleep(wait_time + random.uniform(0, 1))
wait_time *= 2
attempt += 1
except Exception as e:
# ข้อความภาษาไทยที่แก้ไขแล้ว
print(f"เกิดข้อผิดพลาดที่ไม่คาดคิดขณะเรียก Gemini: {e}")
return None
print("ไม่สามารถรับการตอบกลับได้หลังจากการพยายามหลายครั้ง")
return None
def process_user_message(user_message):
"""ประมวลผลข้อความของผู้ใช้เพื่อแยก Intent และ Entities"""
# ใช้ Prompt ที่เรียบง่ายเนื่องจาก System Instruction กำหนดรูปแบบเอาไว้แล้ว
prompt = f"ข้อความของผู้ใช้: '{user_message}'"
response = generate_with_retry(model, prompt)
if response and response.text:
try:
# โมเดลถูกบังคับให้ตอบกลับเป็น JSON ด้วย response_mime_type
return json.loads(response.text)
except json.JSONDecodeError:
# ข้อความภาษาไทยที่แก้ไขแล้ว
return {"intent": "error", "message": f"ผลลัพธ์ไม่ใช่ JSON ที่ถูกต้อง: {response.text}"}
else:
# ข้อความภาษาไทยที่แก้ไขแล้ว
return {"intent": "error", "message": "ไม่ได้รับการตอบกลับจาก Gemini หรือข้อความว่างเปล่า"}
# ตัวอย่างการใช้งาน (สำหรับทดสอบ)
if __name__ == '__main__':
# รันโค้ดนี้เมื่อไฟล์ถูกเรียกใช้โดยตรง
print("--- ทดสอบ NLU Processor ---")
test_message_1 = "ฉันอยากจองตั๋วรถไฟไปหัวหินวันที่ 25 ธันวาคม"
print(f"\nข้อความที่ 1: {test_message_1}")
result_1 = process_user_message(test_message_1)
# ใช้ ensure_ascii=False เพื่อแสดงผลภาษาไทยใน JSON
print(json.dumps(result_1, indent=4, ensure_ascii=False))
test_message_2 = "สวัสดีครับ"
print(f"\nข้อความที่ 2: {test_message_2}")
result_2 = process_user_message(test_message_2)
print(json.dumps(result_2, indent=4, ensure_ascii=False))