Python CLI คุย Gemini API ให้โปรด้วย Context Manager และ Resilience

สวัสดีครับ เพื่อนๆ โปรแกรมเมอร์ทุกคน วันนี้ผมจะมาคุยกันเรื่องการสร้าง Python CLI ที่คุยกับ Gemini API แบบโปรๆ กันนะครับ เราจะเน้นไปที่เรื่อง resilience หรือความทนทานของโค้ด และการจัดการโค้ดให้ optimization ด้วย Context Manager นะครับ

เวลาเราเขียนโค้ดที่ต้องเชื่อมต่อกับอะไรบางอย่างบ่อยๆ ไม่ว่าจะเป็น API หรือ Database เรามักจะต้องมานั่งคิดว่าจะเปิด Connection ยังไง แล้วก็ต้องไม่ลืมปิด Connection ให้ถูกจังหวะด้วยใช่ไหมครับ บางทีก็มีเรื่องต้องจัดการเยอะ เช่น การตั้งค่า Key, การจัดการ Connection, หรือแม้กระทั่งการ Retry เมื่อเกิดข้อผิดพลาด แบบนี้นะครับ ถ้าเราจัดการไม่ดี โค้ดของเราก็จะหลุด หรือพังง่ายๆ เลยนะ

ทำไมต้อง Context Manager กับ API?

Context Manager เนี่ยเป็นเครื่องมือใน Python ที่เจ๋งมากๆ เลยครับ มันช่วยให้เราจัดการทรัพยากรพวกนี้ได้แบบอัตโนมัติ ทำให้โค้ดเราสะอาดขึ้น อ่านง่ายขึ้น และมั่นใจได้ว่าทรัพยากรจะถูกจัดสรรและคืนอย่างถูกต้องเสมอครับ ไม่ว่าโค้ดเราจะทำงานได้สำเร็จ หรือจะเกิด Error ขึ้นมา Context Manager ก็จะจัดการให้ทุกอย่างเรียบร้อยครับ ทำให้แอปพลิเคชัน CLI ของเราที่คุยกับ Gemini API มีความ resilience สูงขึ้นอย่างเห็นได้ชัดเลย

แบบธรรมดาๆ ก่อน (ยังไม่โปรเท่าไหร่)

มาดูตัวอย่างแรกกันนะครับ แบบที่ยังไม่ได้ใช้ Context Manager นะครับ เวลาเราคุยกับ Gemini API แบบตรงไปตรงมา เราก็ต้อง Configure API Key แล้วก็สร้าง Model กับ Chat Object ขึ้นมาใช้งานแบบนี้นะครับ ถ้ามีหลายฟังก์ชัน ก็อาจจะต้องเขียนซ้ำๆ หรือจัดการเองเยอะหน่อยนะ

# gemini_cli_basic.py
# ก่อนรันโค้ด อย่าลืมติดตั้ง library ด้วย pip install google-generativeai
# และตั้งค่า Environment Variable GEMINI_API_KEY ด้วย API Key ของคุณนะครับ
# เช่น export GEMINI_API_KEY="your_api_key_here" (สำหรับ Linux/macOS)
# หรือ set GEMINI_API_KEY="your_api_key_here" (สำหรับ Windows Command Prompt)
# หรือ $env:GEMINI_API_KEY="your_api_key_here" (สำหรับ Windows PowerShell)

import google.generativeai as genai
import os
import time

def simple_gemini_chat(prompt: str):
    api_key = os.environ.get("GEMINI_API_KEY")
    if not api_key:
        print("กรุณาตั้งค่า GEMINI_API_KEY ใน Environment Variables ด้วยนะครับ")
        return

    genai.configure(api_key=api_key)
    model = genai.GenerativeModel('gemini-pro')
    try:
        # เราต้องมาสร้าง chat object ใหม่ทุกครั้ง หรือจัดการ state เอง
        chat = model.start_chat(history=[])
        response = chat.send_message(prompt)
        print(f"Gemini บอกว่า: {response.text}")
    except Exception as e:
        print(f"เกิดข้อผิดพลาดตอนคุยกับ Gemini: {e}")
    finally:
        # ถ้ามีอะไรต้อง Clean Up ก็ต้องมาเขียนตรงนี้เองครับ ซึ่งบางทีอาจจะลืมได้นะ
        print("จบการสนทนา (แบบธรรมดา) ครับ")

if __name__ == "__main__":"
    print("--- คุยกับ Gemini แบบธรรมดา ---")
    simple_gemini_chat("แนะนำสถานที่ท่องเที่ยวในประเทศไทยหน่อยครับ")
    time.sleep(2) # รอหน่อยนะครับ
    simple_gemini_chat("เล่าเรื่องสั้นๆ เกี่ยวกับหมาป่าหน่อยครับ")

จากตัวอย่างนี้ จะเห็นว่าเราต้องคอยจัดการ genai.configure และ model.start_chat เองทุกครั้งใช่ไหมครับ ถ้ามีขั้นตอนที่ซับซ้อนกว่านี้ หรือมีทรัพยากรอื่นๆ ที่ต้อง open/close โค้ดเราก็จะเริ่มรกแล้วก็มีโอกาสพลาดได้ง่ายๆ เลยครับ

มาโปรขึ้นด้วย Context Manager กันครับ!

คราวนี้เราจะสร้างคลาสเล็กๆ ที่ทำงานเป็น Context Manager เพื่อห่อหุ้มการจัดการ Gemini API นะครับ แบบนี้โค้ดเราจะ optimization ขึ้นเยอะเลย และ resilience ด้วยครับ ลองดูโค้ดตัวอย่างกันนะ

# gemini_cli_pro.py
# ก่อนรันโค้ด อย่าลืมติดตั้ง library ด้วย pip install google-generativeai
# และตั้งค่า Environment Variable GEMINI_API_KEY ด้วย API Key ของคุณนะครับ

import google.generativeai as genai
import os
import time

class GeminiChatSession:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.model = None
        self.chat = None

    def __enter__(self):
        # นี่คือส่วนที่ Context Manager จะรันตอนเริ่ม 'with' Block นะครับ
        genai.configure(api_key=self.api_key)
        self.model = genai.GenerativeModel('gemini-pro')
        self.chat = self.model.start_chat(history=[])
        print("--- เริ่ม Gemini Chat Session ครับ ---")
        return self.chat # คืน chat object ให้เอาไปใช้งานใน 'with' Block

    def __exit__(self, exc_type, exc_val, exc_tb):
        # ตรงนี้แหละครับที่เราสามารถจัดการ Clean Up, Log Error หรือ Retry ได้
        # ไม่ว่าใน 'with' Block จะเกิด Error หรือไม่ก็ตาม ส่วนนี้จะถูกรันเสมอครับ
        if exc_type:
            print(f"เกิดข้อผิดพลาดใน Session: {exc_val}")
            # อาจจะส่ง Error ไปที่ระบบ Log ของเราเพื่อตรวจสอบได้นะครับ ทำให้ App เรา Resilient ขึ้นนะ
        print("--- จบ Gemini Chat Session ครับ (ไม่ว่าจะเกิดอะไรขึ้น) ---")
        # ไม่มีเมธอด Disconnect ชัดเจนสำหรับ genai library แต่ถ้ามีทรัพยากรอื่น เราก็จัดการได้ตรงนี้เลย

def pro_gemini_chat(prompt: str):
    api_key = os.environ.get("GEMINI_API_KEY")
    if not api_key:
        print("กรุณาตั้งค่า GEMINI_API_KEY ใน Environment Variables ด้วยนะครับ")
        return

    with GeminiChatSession(api_key) as chat_session:
        try:
            response = chat_session.send_message(prompt)
            print(f"Gemini ตอบว่า: {response.text}")
        except Exception as e:
            print(f"ข้อผิดพลาดระหว่างส่งข้อความ: {e}")

if __name__ == "__main__":"
    print("\
--- คุยกับ Gemini แบบโปรด้วย Context Manager ---")
    pro_gemini_chat("เล่าเรื่องสั้นเกี่ยวกับอวกาศให้ฟังหน่อยครับ")
    time.sleep(2)
    pro_gemini_chat("เพลงที่ฮิตที่สุดในปี 2000 มีเพลงอะไรบ้างครับ")

    # ลองดูเวลาเกิด Error ครับ จะเห็นว่า __exit__ ก็ยังทำงานอยู่ดีนะ
    print("\
--- ลองทดสอบเมื่อเกิดข้อผิดพลาด (เช่น API Key ผิด) ---")
    # สมมติว่าตั้งใจทำให้ Key ผิด เพื่อดูว่า Context Manager ทำงานยังไงตอนมี Error
    os.environ["GEMINI_API_KEY"] = "BAD_KEY" 
    pro_gemini_chat("สวัสดีครับ") # ควรจะเห็น Error
    # คืนค่า Key เดิม (สมมติว่า Key ถูกต้องแล้ว) เพื่อการทดสอบต่อไปนะ
    os.environ["GEMINI_API_KEY"] = "YOUR_REAL_API_KEY" # ต้องเปลี่ยนเป็น API Key จริงๆ ของคุณนะ
    print("ถึงแม้มี Error แต่ Context Manager ก็จัดการจบ Session ให้ครับ")

จะเห็นว่าโค้ด pro_gemini_chat ดูสะอาดตาขึ้นเยอะเลยใช่ไหมครับ เพราะว่าการจัดการ genai.configure และ model.start_chat รวมถึงการจัดการตอนจบ Session ย้ายไปอยู่ใน GeminiChatSession หมดแล้วครับ ทำให้เราไม่ต้องมานั่งกังวลเรื่องการ Clean Up ทรัพยากรเองเลยนะ ถ้าเกิด Error ขึ้นมาใน with block เมธอด __exit__ ก็ยังถูกเรียกใช้เสมอครับ แบบนี้แหละครับที่ทำให้แอปพลิเคชันของเรามีความ resilience มากขึ้นอย่างเห็นได้ชัดเลย

สรุปนะครับ

การใช้ Context Manager ไม่ได้แค่ทำให้โค้ดเราดูดีขึ้นนะครับ แต่มันช่วยให้แอปพลิเคชัน CLI ของเราที่คุยกับ Gemini API มีความ resilience สูงขึ้นอย่างเห็นได้ชัด เพราะมันช่วยจัดการ Lifecycle ของทรัพยากรต่างๆ ให้เราอย่างอัตโนมัติ ทำให้เราไม่ต้องกังวลว่าจะลืมปิด หรือทำความสะอาดอะไรครับ โค้ดก็จะ optimization ในแง่ของความอ่านง่ายและบำรุงรักษาง่ายด้วยนะ ลองเอาไปปรับใช้กับโปรเจกต์ของเพื่อนๆ ดูนะครับ!

Read more

HUAWEI Pura 90 Pro Max: เผยทีเซอร์กล้องเพอริสโคป 200MP ซูม 20 เท่า ก่อนเปิดตัว 20 เมษายน

HUAWEI Pura 90 Pro Max: เผยทีเซอร์กล้องเพอริสโคป 200MP ซูม 20 เท่า ก่อนเปิดตัว 20 เมษายน

HUAWEI Pura 90 Pro Max ปล่อยทีเซอร์ฟีเจอร์กล้องเทพ! เตรียมพบกับกล้องเพอริสโคป 200MP ซูม 20 เท่า และ AI Photo Pose ในงานเปิดตัว 20 เมษายนนี้ ห้ามพลาด!

By ทีมงาน devdog
เจาะลึกกลยุทธ์ LiveScore: ถอนทัพ, เติบโต, และปรับตัวในตลาดเดิมพันระดับโลก

เจาะลึกกลยุทธ์ LiveScore: ถอนทัพ, เติบโต, และปรับตัวในตลาดเดิมพันระดับโลก

LiveScore Group ปรับกลยุทธ์ธุรกิจ ถอนทัพจากเนเธอร์แลนด์ สู่การเติบโตใน UK พร้อมรับมือภาษีใหม่ และขยายสู่แอฟริกาใต้ อนาคตธุรกิจ Livescore เป็นอย่างไร?

By ทีมงาน devdog
บทบาทของเครื่องบินขับไล่ F-Series ในสมรภูมิกลางอากาศ: การปิดล้อม, กู้ภัย, และการอัปเกรด

บทบาทของเครื่องบินขับไล่ F-Series ในสมรภูมิกลางอากาศ: การปิดล้อม, กู้ภัย, และการอัปเกรด

เจาะลึกปฏิบัติการปิดล้อมอิหร่าน การช่วยเหลือ F-15E และการอัปเกรด F-35 ของอิสราเอล ท่ามกลางความตึงเครียดในตะวันออกกลาง.

By ทีมงาน devdog
งบประมาณปี 2570: ยุทธศาสตร์ใหม่เพื่อคนไทย รับมือเศรษฐกิจผันผวน

งบประมาณปี 2570: ยุทธศาสตร์ใหม่เพื่อคนไทย รับมือเศรษฐกิจผันผวน

เจาะลึกงบประมาณปี 2570 รัฐบาลมุ่งแก้ปัญหาประชาชน ใช้แนวคิด Zero-Based Budgeting พร้อมไทม์ไลน์และ 9 แผนงานบูรณาการเพื่อขับเคลื่อนเศรษฐกิจอย่างยั่งยืน.

By ทีมงาน devdog