|
|
<!--
|
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
|
{
|
|
|
"original_hash": "46d665af66e51524598af34a42b9b663",
|
|
|
"translation_date": "2025-10-23T20:59:50+00:00",
|
|
|
"source_file": "9-chat-project/README.md",
|
|
|
"language_code": "th"
|
|
|
}
|
|
|
-->
|
|
|
# สร้างผู้ช่วยแชทด้วย AI
|
|
|
|
|
|
จำได้ไหมใน Star Trek ที่ทีมงานพูดคุยกับคอมพิวเตอร์ของยานได้อย่างสบายๆ ถามคำถามซับซ้อนและได้รับคำตอบที่มีความคิดลึกซึ้ง? สิ่งที่ดูเหมือนนิยายวิทยาศาสตร์ในยุค 1960 ตอนนี้กลายเป็นสิ่งที่คุณสามารถสร้างได้ด้วยเทคโนโลยีเว็บที่คุณรู้จักอยู่แล้ว
|
|
|
|
|
|
ในบทเรียนนี้ เราจะสร้างผู้ช่วยแชท AI โดยใช้ HTML, CSS, JavaScript และการเชื่อมต่อกับระบบ backend คุณจะได้เรียนรู้ว่าทักษะที่คุณกำลังเรียนสามารถเชื่อมต่อกับบริการ AI ที่ทรงพลังซึ่งเข้าใจบริบทและสร้างคำตอบที่มีความหมายได้อย่างไร
|
|
|
|
|
|
ลองนึกถึง AI เหมือนการเข้าถึงห้องสมุดขนาดใหญ่ที่ไม่เพียงแค่ค้นหาข้อมูล แต่ยังสามารถสังเคราะห์ข้อมูลให้เป็นคำตอบที่เหมาะสมกับคำถามเฉพาะของคุณได้ แทนที่จะค้นหาผ่านหน้าหลายพันหน้า คุณจะได้รับคำตอบที่ตรงประเด็นและมีบริบท
|
|
|
|
|
|
การเชื่อมต่อเกิดขึ้นผ่านเทคโนโลยีเว็บที่คุ้นเคย HTML สร้างอินเทอร์เฟซแชท CSS จัดการการออกแบบภาพ JavaScript จัดการการโต้ตอบของผู้ใช้ และ API backend เชื่อมต่อทุกอย่างกับบริการ AI มันคล้ายกับการที่ส่วนต่างๆ ของวงออร์เคสตราทำงานร่วมกันเพื่อสร้างซิมโฟนี
|
|
|
|
|
|
เรากำลังสร้างสะพานเชื่อมระหว่างการสื่อสารของมนุษย์กับการประมวลผลของเครื่อง คุณจะได้เรียนรู้ทั้งการนำ AI มาใช้ในเชิงเทคนิคและรูปแบบการออกแบบที่ทำให้การโต้ตอบรู้สึกเป็นธรรมชาติ
|
|
|
|
|
|
เมื่อจบบทเรียนนี้ การเชื่อมต่อ AI จะไม่รู้สึกเหมือนกระบวนการลึกลับอีกต่อไป แต่จะเหมือน API อีกตัวที่คุณสามารถทำงานร่วมได้ คุณจะเข้าใจรูปแบบพื้นฐานที่ขับเคลื่อนแอปพลิเคชันอย่าง ChatGPT และ Claude โดยใช้หลักการพัฒนาเว็บที่คุณได้เรียนรู้มา
|
|
|
|
|
|
นี่คือหน้าตาของโปรเจกต์ที่เสร็จสมบูรณ์:
|
|
|
|
|
|

|
|
|
|
|
|
## ทำความเข้าใจ AI: จากความลึกลับสู่ความเชี่ยวชาญ
|
|
|
|
|
|
ก่อนที่จะลงมือเขียนโค้ด มาทำความเข้าใจสิ่งที่เรากำลังทำกันก่อน หากคุณเคยใช้ API มาก่อน คุณจะรู้รูปแบบพื้นฐาน: ส่งคำขอ รับคำตอบ
|
|
|
|
|
|
API ของ AI มีโครงสร้างคล้ายกัน แต่แทนที่จะดึงข้อมูลที่เก็บไว้ล่วงหน้าจากฐานข้อมูล มันจะสร้างคำตอบใหม่โดยอิงจากรูปแบบที่เรียนรู้จากข้อความจำนวนมหาศาล ลองนึกถึงความแตกต่างระหว่างระบบแคตตาล็อกห้องสมุดกับบรรณารักษ์ที่มีความรู้ซึ่งสามารถสังเคราะห์ข้อมูลจากหลายแหล่งได้
|
|
|
|
|
|
### "Generative AI" คืออะไรจริงๆ?
|
|
|
|
|
|
ลองนึกถึง Rosetta Stone ที่ช่วยให้นักวิชาการเข้าใจอักษรอียิปต์โบราณโดยการค้นหารูปแบบระหว่างภาษาที่รู้จักและไม่รู้จัก โมเดล AI ทำงานในลักษณะเดียวกัน – พวกมันค้นหารูปแบบในข้อความจำนวนมหาศาลเพื่อเข้าใจวิธีการทำงานของภาษา จากนั้นใช้รูปแบบเหล่านั้นเพื่อสร้างคำตอบที่เหมาะสมกับคำถามใหม่
|
|
|
|
|
|
**ขออธิบายด้วยการเปรียบเทียบง่ายๆ:**
|
|
|
- **ฐานข้อมูลแบบดั้งเดิม**: เหมือนการขอสูติบัตรของคุณ – คุณจะได้รับเอกสารเดิมทุกครั้ง
|
|
|
- **เครื่องมือค้นหา**: เหมือนการขอบรรณารักษ์ให้หาหนังสือเกี่ยวกับแมว – พวกเขาจะแสดงสิ่งที่มีอยู่
|
|
|
- **Generative AI**: เหมือนการถามเพื่อนที่มีความรู้เกี่ยวกับแมว – พวกเขาจะบอกสิ่งที่น่าสนใจในคำพูดของตัวเองที่ปรับให้เหมาะกับสิ่งที่คุณอยากรู้
|
|
|
|
|
|
```mermaid
|
|
|
graph LR
|
|
|
A[Your Question] --> B[AI Model]
|
|
|
B --> C[Pattern Recognition]
|
|
|
C --> D[Content Generation]
|
|
|
D --> E[Contextual Response]
|
|
|
|
|
|
F[Training Data<br/>Books, Articles, Web] --> B
|
|
|
```
|
|
|
|
|
|
### วิธีที่โมเดล AI เรียนรู้ (เวอร์ชันง่าย)
|
|
|
|
|
|
โมเดล AI เรียนรู้ผ่านการสัมผัสกับชุดข้อมูลขนาดใหญ่ที่มีข้อความจากหนังสือ บทความ และการสนทนา ในกระบวนการนี้ พวกมันจะระบุรูปแบบใน:
|
|
|
- วิธีการจัดโครงสร้างความคิดในรูปแบบการสื่อสารที่เขียน
|
|
|
- คำที่มักปรากฏร่วมกัน
|
|
|
- วิธีการไหลของการสนทนา
|
|
|
- ความแตกต่างในบริบทระหว่างการสื่อสารแบบทางการและไม่เป็นทางการ
|
|
|
|
|
|
**มันคล้ายกับวิธีที่นักโบราณคดีถอดรหัสภาษาโบราณ**: พวกเขาวิเคราะห์ตัวอย่างนับพันเพื่อทำความเข้าใจไวยากรณ์ คำศัพท์ และบริบททางวัฒนธรรม สุดท้ายก็สามารถตีความข้อความใหม่โดยใช้รูปแบบที่เรียนรู้
|
|
|
|
|
|
### ทำไมต้องใช้ GitHub Models?
|
|
|
|
|
|
เราใช้ GitHub Models ด้วยเหตุผลที่ค่อนข้างปฏิบัติ – มันให้เราเข้าถึง AI ระดับองค์กรโดยไม่ต้องตั้งค่าระบบ AI ของเราเอง (ซึ่งเชื่อเถอะ คุณไม่อยากทำตอนนี้!) ลองนึกถึงการใช้ API สภาพอากาศแทนการพยากรณ์อากาศด้วยตัวเองโดยตั้งสถานีตรวจอากาศทุกที่
|
|
|
|
|
|
มันเป็น "AI-as-a-Service" และส่วนที่ดีที่สุด? เริ่มต้นได้ฟรี คุณสามารถทดลองได้โดยไม่ต้องกังวลว่าจะมีค่าใช้จ่ายสูง
|
|
|
|
|
|
```mermaid
|
|
|
graph LR
|
|
|
A[Frontend Chat UI] --> B[Your Backend API]
|
|
|
B --> C[GitHub Models API]
|
|
|
C --> D[AI Model Processing]
|
|
|
D --> C
|
|
|
C --> B
|
|
|
B --> A
|
|
|
```
|
|
|
|
|
|
เราจะใช้ GitHub Models สำหรับการเชื่อมต่อ backend ซึ่งให้การเข้าถึงความสามารถ AI ระดับมืออาชีพผ่านอินเทอร์เฟซที่เป็นมิตรกับนักพัฒนา [GitHub Models Playground](https://github.com/marketplace/models/azure-openai/gpt-4o-mini/playground) เป็นพื้นที่ทดสอบที่คุณสามารถทดลองใช้โมเดล AI ต่างๆ และเข้าใจความสามารถของมันก่อนที่จะนำไปใช้ในโค้ด
|
|
|
|
|
|

|
|
|
|
|
|
**สิ่งที่ทำให้ Playground มีประโยชน์มาก:**
|
|
|
- **ทดลองใช้** โมเดล AI ต่างๆ เช่น GPT-4o-mini, Claude และอื่นๆ (ฟรีทั้งหมด!)
|
|
|
- **ทดสอบ** ไอเดียและคำสั่งก่อนเขียนโค้ด
|
|
|
- **รับ** โค้ดที่พร้อมใช้งานในภาษาการเขียนโปรแกรมที่คุณชื่นชอบ
|
|
|
- **ปรับแต่ง** การตั้งค่า เช่น ระดับความคิดสร้างสรรค์และความยาวของคำตอบเพื่อดูผลลัพธ์ที่แตกต่างกัน
|
|
|
|
|
|
เมื่อคุณทดลองเล่นไปสักพัก เพียงคลิกที่แท็บ "Code" และเลือกภาษาการเขียนโปรแกรมของคุณเพื่อรับโค้ดการใช้งานที่คุณต้องการ
|
|
|
|
|
|

|
|
|
|
|
|
## การตั้งค่าการเชื่อมต่อ Backend ด้วย Python
|
|
|
|
|
|
ตอนนี้เรามาเริ่มต้นการเชื่อมต่อ AI โดยใช้ Python Python เป็นตัวเลือกที่ยอดเยี่ยมสำหรับแอปพลิเคชัน AI เพราะมีไวยากรณ์ที่เรียบง่ายและไลบรารีที่ทรงพลัง เราจะเริ่มต้นด้วยโค้ดจาก GitHub Models Playground และปรับปรุงให้เป็นฟังก์ชันที่สามารถนำไปใช้ในโปรดักชันได้
|
|
|
|
|
|
### ทำความเข้าใจการใช้งานพื้นฐาน
|
|
|
|
|
|
เมื่อคุณดึงโค้ด Python จาก Playground คุณจะได้โค้ดที่ดูเหมือนแบบนี้ ไม่ต้องกังวลหากดูเหมือนเยอะในตอนแรก – เรามาแยกส่วนและอธิบายทีละส่วน:
|
|
|
|
|
|
```python
|
|
|
"""Run this model in Python
|
|
|
|
|
|
> pip install openai
|
|
|
"""
|
|
|
import os
|
|
|
from openai import OpenAI
|
|
|
|
|
|
# To authenticate with the model you will need to generate a personal access token (PAT) in your GitHub settings.
|
|
|
# Create your PAT token by following instructions here: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
|
|
|
client = OpenAI(
|
|
|
base_url="https://models.github.ai/inference",
|
|
|
api_key=os.environ["GITHUB_TOKEN"],
|
|
|
)
|
|
|
|
|
|
```python
|
|
|
response = client.chat.completions.create(
|
|
|
messages=[
|
|
|
{
|
|
|
"role": "system",
|
|
|
"content": "",
|
|
|
},
|
|
|
{
|
|
|
"role": "user",
|
|
|
"content": "What is the capital of France?",
|
|
|
}
|
|
|
],
|
|
|
model="openai/gpt-4o-mini",
|
|
|
temperature=1,
|
|
|
max_tokens=4096,
|
|
|
top_p=1
|
|
|
)
|
|
|
|
|
|
print(response.choices[0].message.content)
|
|
|
```
|
|
|
|
|
|
**สิ่งที่เกิดขึ้นในโค้ดนี้:**
|
|
|
- **เรา import** เครื่องมือที่เราต้องการ: `os` สำหรับการอ่าน environment variables และ `OpenAI` สำหรับการสื่อสารกับ AI
|
|
|
- **เราเซ็ตอัพ** OpenAI client ให้ชี้ไปที่เซิร์ฟเวอร์ AI ของ GitHub แทนที่จะเป็น OpenAI โดยตรง
|
|
|
- **เรายืนยันตัวตน** โดยใช้ GitHub token พิเศษ (รายละเอียดเพิ่มเติมในภายหลัง!)
|
|
|
- **เราจัดโครงสร้าง** การสนทนาโดยใช้ "roles" ต่างๆ – คิดเหมือนการตั้งฉากสำหรับละคร
|
|
|
- **เราส่ง** คำขอไปยัง AI พร้อมพารามิเตอร์การปรับแต่งบางอย่าง
|
|
|
- **เราดึง** ข้อความตอบกลับจริงจากข้อมูลทั้งหมดที่กลับมา
|
|
|
|
|
|
### ทำความเข้าใจบทบาทข้อความ: กรอบการสนทนา AI
|
|
|
|
|
|
การสนทนา AI ใช้โครงสร้างเฉพาะที่มี "roles" ต่างๆ ซึ่งมีวัตถุประสงค์ที่แตกต่างกัน:
|
|
|
|
|
|
```python
|
|
|
messages=[
|
|
|
{
|
|
|
"role": "system",
|
|
|
"content": "You are a helpful assistant who explains things simply."
|
|
|
},
|
|
|
{
|
|
|
"role": "user",
|
|
|
"content": "What is machine learning?"
|
|
|
}
|
|
|
]
|
|
|
```
|
|
|
|
|
|
**คิดเหมือนการกำกับละคร:**
|
|
|
- **System role**: เหมือนคำแนะนำบนเวทีสำหรับนักแสดง – บอก AI ว่าควรทำตัวอย่างไร มีบุคลิกแบบไหน และตอบสนองอย่างไร
|
|
|
- **User role**: คำถามหรือข้อความจริงจากผู้ใช้แอปพลิเคชัน
|
|
|
- **Assistant role**: คำตอบของ AI (คุณไม่ส่งสิ่งนี้ แต่จะปรากฏในประวัติการสนทนา)
|
|
|
|
|
|
**เปรียบเทียบกับชีวิตจริง**: ลองนึกภาพคุณแนะนำเพื่อนให้รู้จักใครบางคนในงานปาร์ตี้:
|
|
|
- **System message**: "นี่คือเพื่อนของฉัน Sarah เธอเป็นหมอที่อธิบายแนวคิดทางการแพทย์ได้ง่ายๆ"
|
|
|
- **User message**: "คุณช่วยอธิบายวิธีการทำงานของวัคซีนได้ไหม?"
|
|
|
- **Assistant response**: Sarah ตอบในฐานะหมอที่เป็นมิตร ไม่ใช่ในฐานะทนายหรือเชฟ
|
|
|
|
|
|
### ทำความเข้าใจพารามิเตอร์ AI: การปรับแต่งพฤติกรรมการตอบสนอง
|
|
|
|
|
|
พารามิเตอร์ตัวเลขในคำขอ API ของ AI ควบคุมวิธีที่โมเดลสร้างคำตอบ การตั้งค่าเหล่านี้ช่วยให้คุณปรับพฤติกรรมของ AI สำหรับการใช้งานที่แตกต่างกัน:
|
|
|
|
|
|
#### Temperature (0.0 ถึง 2.0): ปุ่มปรับความคิดสร้างสรรค์
|
|
|
|
|
|
**มันทำอะไร**: ควบคุมว่าคำตอบของ AI จะมีความคิดสร้างสรรค์หรือคาดเดาได้มากแค่ไหน
|
|
|
|
|
|
**เปรียบเหมือนระดับการด้นสดของนักดนตรีแจ๊ส:**
|
|
|
- **Temperature = 0.1**: เล่นเมโลดี้เดิมทุกครั้ง (คาดเดาได้สูง)
|
|
|
- **Temperature = 0.7**: เพิ่มการเปลี่ยนแปลงที่น่าสนใจแต่ยังคงเป็นที่รู้จัก (ความคิดสร้างสรรค์สมดุล)
|
|
|
- **Temperature = 1.5**: แจ๊สที่ทดลองเต็มที่พร้อมการเปลี่ยนแปลงที่ไม่คาดคิด (คาดเดาไม่ได้สูง)
|
|
|
|
|
|
```python
|
|
|
# Very predictable responses (good for factual questions)
|
|
|
response = client.chat.completions.create(
|
|
|
messages=[{"role": "user", "content": "What is 2+2?"}],
|
|
|
temperature=0.1 # Will almost always say "4"
|
|
|
)
|
|
|
|
|
|
# Creative responses (good for brainstorming)
|
|
|
response = client.chat.completions.create(
|
|
|
messages=[{"role": "user", "content": "Write a creative story opening"}],
|
|
|
temperature=1.2 # Will generate unique, unexpected stories
|
|
|
)
|
|
|
```
|
|
|
|
|
|
#### Max Tokens (1 ถึง 4096+): ตัวควบคุมความยาวของคำตอบ
|
|
|
|
|
|
**มันทำอะไร**: กำหนดขีดจำกัดความยาวของคำตอบจาก AI
|
|
|
|
|
|
**คิดว่า tokens เป็นคำโดยประมาณ** (ประมาณ 1 token = 0.75 คำในภาษาอังกฤษ):
|
|
|
- **max_tokens=50**: สั้นและกระชับ (เหมือนข้อความ)
|
|
|
- **max_tokens=500**: ย่อหน้าเล็กๆ หรือสองย่อหน้า
|
|
|
- **max_tokens=2000**: คำอธิบายละเอียดพร้อมตัวอย่าง
|
|
|
|
|
|
```python
|
|
|
# Short, concise answers
|
|
|
response = client.chat.completions.create(
|
|
|
messages=[{"role": "user", "content": "Explain JavaScript"}],
|
|
|
max_tokens=100 # Forces a brief explanation
|
|
|
)
|
|
|
|
|
|
# Detailed, comprehensive answers
|
|
|
response = client.chat.completions.create(
|
|
|
messages=[{"role": "user", "content": "Explain JavaScript"}],
|
|
|
max_tokens=1500 # Allows for detailed explanations with examples
|
|
|
)
|
|
|
```
|
|
|
|
|
|
#### Top_p (0.0 ถึง 1.0): พารามิเตอร์ความมุ่งเน้น
|
|
|
|
|
|
**มันทำอะไร**: ควบคุมว่า AI จะมุ่งเน้นไปที่คำตอบที่มีความเป็นไปได้มากที่สุดแค่ไหน
|
|
|
|
|
|
**ลองนึกภาพ AI มีคำศัพท์ขนาดใหญ่ที่จัดอันดับตามความเป็นไปได้ของแต่ละคำ:**
|
|
|
- **top_p=0.1**: พิจารณาเฉพาะคำที่มีความเป็นไปได้สูงสุด 10% (มุ่งเน้นมาก)
|
|
|
- **top_p=0.9**: พิจารณา 90% ของคำที่เป็นไปได้ (มีความคิดสร้างสรรค์มากขึ้น)
|
|
|
- **top_p=1.0**: พิจารณาทุกอย่าง (ความหลากหลายสูงสุด)
|
|
|
|
|
|
**ตัวอย่าง**: หากคุณถามว่า "ท้องฟ้าปกติแล้ว..."
|
|
|
- **Low top_p**: อาจตอบว่า "สีฟ้า" อย่างแน่นอน
|
|
|
- **High top_p**: อาจตอบว่า "สีฟ้า", "มีเมฆ", "กว้างใหญ่", "เปลี่ยนแปลง", "สวยงาม" เป็นต้น
|
|
|
|
|
|
### การรวมทุกอย่างเข้าด้วยกัน: การผสมผสานพารามิเตอร์สำหรับการใช้งานที่แตกต่างกัน
|
|
|
|
|
|
```python
|
|
|
# For factual, consistent answers (like a documentation bot)
|
|
|
factual_params = {
|
|
|
"temperature": 0.2,
|
|
|
"max_tokens": 300,
|
|
|
"top_p": 0.3
|
|
|
}
|
|
|
|
|
|
# For creative writing assistance
|
|
|
creative_params = {
|
|
|
"temperature": 1.1,
|
|
|
"max_tokens": 1000,
|
|
|
"top_p": 0.9
|
|
|
}
|
|
|
|
|
|
# For conversational, helpful responses (balanced)
|
|
|
conversational_params = {
|
|
|
"temperature": 0.7,
|
|
|
"max_tokens": 500,
|
|
|
"top_p": 0.8
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**ทำความเข้าใจว่าทำไมพารามิเตอร์เหล่านี้ถึงสำคัญ**: แอปพลิเคชันต่างๆ ต้องการคำตอบที่แตกต่างกัน บอทบริการลูกค้าควรมีความสม่ำเสมอและเป็นข้อเท็จจริง (temperature ต่ำ) ในขณะที่ผู้ช่วยเขียนเชิงสร้างสรรค์ควรมีจินตนาการและหลากหลาย (temperature สูง) การเข้าใจพารามิเตอร์เหล่านี้ช่วยให้คุณควบคุมบุคลิกและรูปแบบการตอบสนองของ AI ได้
|
|
|
```
|
|
|
|
|
|
**Here's what's happening in this code:**
|
|
|
- **We import** the tools we need: `os` for reading environment variables and `OpenAI` for talking to the AI
|
|
|
- **We set up** the OpenAI client to point to GitHub's AI servers instead of OpenAI directly
|
|
|
- **We authenticate** using a special GitHub token (more on that in a minute!)
|
|
|
- **We structure** our conversation with different "roles" – think of it like setting the scene for a play
|
|
|
- **We send** our request to the AI with some fine-tuning parameters
|
|
|
- **We extract** the actual response text from all the data that comes back
|
|
|
|
|
|
> 🔐 **Security Note**: Never hardcode API keys in your source code! Always use environment variables to store sensitive credentials like your `GITHUB_TOKEN`.
|
|
|
|
|
|
### Creating a Reusable AI Function
|
|
|
|
|
|
Let's refactor this code into a clean, reusable function that we can easily integrate into our web application:
|
|
|
|
|
|
```python
|
|
|
import asyncio
|
|
|
from openai import AsyncOpenAI
|
|
|
|
|
|
# Use AsyncOpenAI for better performance
|
|
|
client = AsyncOpenAI(
|
|
|
base_url="https://models.github.ai/inference",
|
|
|
api_key=os.environ["GITHUB_TOKEN"],
|
|
|
)
|
|
|
|
|
|
async def call_llm_async(prompt: str, system_message: str = "You are a helpful assistant."):
|
|
|
"""
|
|
|
Sends a prompt to the AI model asynchronously and returns the response.
|
|
|
|
|
|
Args:
|
|
|
prompt: The user's question or message
|
|
|
system_message: Instructions that define the AI's behavior and personality
|
|
|
|
|
|
Returns:
|
|
|
str: The AI's response to the prompt
|
|
|
"""
|
|
|
try:
|
|
|
response = await client.chat.completions.create(
|
|
|
messages=[
|
|
|
{
|
|
|
"role": "system",
|
|
|
"content": system_message,
|
|
|
},
|
|
|
{
|
|
|
"role": "user",
|
|
|
"content": prompt,
|
|
|
}
|
|
|
],
|
|
|
model="openai/gpt-4o-mini",
|
|
|
temperature=1,
|
|
|
max_tokens=4096,
|
|
|
top_p=1
|
|
|
)
|
|
|
return response.choices[0].message.content
|
|
|
except Exception as e:
|
|
|
logger.error(f"AI API error: {str(e)}")
|
|
|
return "I'm sorry, I'm having trouble processing your request right now."
|
|
|
|
|
|
# Backward compatibility function for synchronous calls
|
|
|
def call_llm(prompt: str, system_message: str = "You are a helpful assistant."):
|
|
|
"""Synchronous wrapper for async AI calls."""
|
|
|
return asyncio.run(call_llm_async(prompt, system_message))
|
|
|
```
|
|
|
|
|
|
**ทำความเข้าใจฟังก์ชันที่ปรับปรุงนี้:**
|
|
|
- **รับ** พารามิเตอร์สองตัว: ข้อความของผู้ใช้และข้อความระบบที่เป็นตัวเลือก
|
|
|
- **ให้** ข้อความระบบเริ่มต้นสำหรับพฤติกรรมผู้ช่วยทั่วไป
|
|
|
- **ใช้** Python type hints เพื่อการบันทึกโค้ดที่ดีขึ้น
|
|
|
- **คืนค่า** เฉพาะเนื้อหาคำตอบ ทำให้ใช้งานง่ายใน API เว็บของเรา
|
|
|
- **รักษา** พารามิเตอร์โมเดลเดิมเพื่อพฤติกรรม AI ที่สม่ำเสมอ
|
|
|
|
|
|
### ความมหัศจรรย์ของ System Prompts: การตั้งโปรแกรมบุคลิกภาพ AI
|
|
|
|
|
|
หากพารามิเตอร์ควบคุมวิธีที่ AI คิด System Prompts ควบคุมว่า AI คิดว่าตัวเองเป็นใคร นี่เป็นส่วนที่น่าตื่นเต้นที่สุดของการทำงานกับ AI – คุณกำลังให้ AI บุคลิกภาพ ความเชี่ยวชาญ และรูปแบบการสื่อสารที่สมบูรณ์
|
|
|
|
|
|
**ลองนึกถึง System Prompts เหมือนการคัดเลือกนักแสดงสำหรับบทบาทต่างๆ**: แทนที่จะมีผู้ช่วยทั่วไป คุณสามารถสร้างผู้เชี่ยวชาญเฉพาะทางสำหรับสถานการณ์ต่างๆ ต้องการครูที่อดทน? คู่คิดที่สร้างสรรค์? ที่ปรึกษาธุรกิจที่จริงจัง? เพียงแค่เปลี่ยน System Prompt!
|
|
|
|
|
|
#### ทำไม System Prompts ถึงทรงพลัง
|
|
|
|
|
|
นี่คือส่วนที่น่าสนใจ: โมเดล AI ได้รับการฝึกฝนจากการสนทนานับไม่ถ้วนที่ผู้คนรับบทบาทและระดับความเชี่ยวชาญที่แตกต่างกัน เมื่อคุณให้ AI รับบทบาทเฉพาะ มันเหมือนกับการเปิดสวิตช์ที่เปิดใช้งานรูปแบบที่เรียนรู้ทั้งหมด
|
|
|
|
|
|
**มันเหมือนการแสดงแบบ Method Acting สำหรับ AI**: บอกนักแสดงว่า "คุณเป็นศาสตราจารย์ผู้ชาญฉลาด" และดูว่าพวกเขาปรับท่าทาง คำศัพท์ และลักษณะการพูดอย่างไร AI ทำสิ่งที่คล้ายกันอย่างน่าทึ่งด้วยรูปแบบภาษา
|
|
|
|
|
|
#### การสร้าง System Prompts ที่มีประสิทธิภาพ: ศิลปะและวิทยาศาสตร์
|
|
|
|
|
|
**องค์ประกอบของ System Prompt ที่ยอดเยี่ยม:**
|
|
|
1. **บทบาท/ตัวตน**: AI คือใคร?
|
|
|
2. **ความเชี่ยวชาญ**: พวกเขารู้อะไร?
|
|
|
3. **รูปแบบการสื่อสาร**: พวกเขาพูดอย่างไร?
|
|
|
4. **คำแนะนำเฉพาะ**: พวกเขาควรเน้นอะไร?
|
|
|
|
|
|
```python
|
|
|
# ❌ Vague system prompt
|
|
|
"You are helpful."
|
|
|
|
|
|
# ✅ Detailed, effective system prompt
|
|
|
"You are Dr. Sarah Chen, a senior software engineer with 15 years of experience at major tech companies. You explain programming concepts using real-world analogies and always provide practical examples. You're patient with beginners and enthusiastic about helping them understand complex topics."
|
|
|
```
|
|
|
|
|
|
#### ตัวอย่าง System Prompt พร้อมบริบท
|
|
|
|
|
|
มาดูกันว่า System Prompts ต่างๆ สร้างบุคลิกภาพ AI ที่แตกต่างกันอย่างไร:
|
|
|
|
|
|
```python
|
|
|
# Example 1: The Patient Teacher
|
|
|
teacher_prompt = """
|
|
|
You are an experienced programming instructor who has taught thousands of students.
|
|
|
You break down complex concepts into simple steps, use analogies from everyday life,
|
|
|
and always check if the student understands before moving on. You're encouraging
|
|
|
and never make students feel bad for not knowing something.
|
|
|
"""
|
|
|
|
|
|
# Example 2: The Creative Collaborator
|
|
|
creative_prompt = """
|
|
|
You are a creative writing partner who loves brainstorming wild ideas. You're
|
|
|
enthusiastic, imaginative, and always build on the user's ideas rather than
|
|
|
replacing them. You ask thought-provoking questions to spark creativity and
|
|
|
offer unexpected perspectives that make stories more interesting.
|
|
|
"""
|
|
|
|
|
|
# Example 3: The Strategic Business Advisor
|
|
|
business_prompt = """
|
|
|
You are a strategic business consultant with an MBA and 20 years of experience
|
|
|
helping startups scale. You think in frameworks, provide structured advice,
|
|
|
and always consider both short-term tactics and long-term strategy. You ask
|
|
|
probing questions to understand the full business context before giving advice.
|
|
|
"""
|
|
|
```
|
|
|
|
|
|
#### การเห็น System Prompts ในการใช้งาน
|
|
|
|
|
|
มาทดสอบคำถามเดียวกันด้วย System Prompts ที่แตกต่างกันเพื่อดูความแตกต่างที่ชัดเจน:
|
|
|
|
|
|
**คำถาม**: "ฉันควรจัดการการยืนยันตัวตนของผู้ใช้ในแอปเว็บของฉันอย่างไร?"
|
|
|
|
|
|
```python
|
|
|
# With teacher prompt:
|
|
|
teacher_response = call_llm(
|
|
|
"How do I handle user authentication in my web app?",
|
|
|
teacher_prompt
|
|
|
)
|
|
|
# Typical response: "Great question! Let's break authentication down into simple steps.
|
|
|
# Think of it like a nightclub bouncer checking IDs..."
|
|
|
|
|
|
# With business prompt:
|
|
|
business_response = call_llm(
|
|
|
"How do I handle user authentication in my web app?",
|
|
|
business_prompt
|
|
|
)
|
|
|
# Typical response: "From a strategic perspective, authentication is crucial for user
|
|
|
# trust and regulatory compliance. Let me outline a framework considering security,
|
|
|
# user experience, and scalability..."
|
|
|
```
|
|
|
|
|
|
#### เทคนิคขั้นสูงของ System Prompt
|
|
|
|
|
|
**1. การตั้งค่าบริบท**: ให้ข้อมูลพื้นฐานแก่ AI
|
|
|
```python
|
|
|
system_prompt = """
|
|
|
You are helping a junior developer who just started their first job at a startup.
|
|
|
They know basic HTML/CSS/JavaScript but are new to backend development and databases.
|
|
|
Be encouraging and explain things step-by-step without being condescending.
|
|
|
"""
|
|
|
```
|
|
|
|
|
|
**2. การจัดรูปแบบผลลัพธ์**: บอก AI ว่าควรจัดโครงสร้างคำตอบอย่างไร
|
|
|
```python
|
|
|
system_prompt = """
|
|
|
You are a technical mentor. Always structure your responses as:
|
|
|
1. Quick Answer (1-2 sentences)
|
|
|
2. Detailed Explanation
|
|
|
3. Code Example
|
|
|
4. Common Pitfalls to Avoid
|
|
|
5. Next Steps for Learning
|
|
|
"""
|
|
|
```
|
|
|
|
|
|
**3. การตั้งข้อจำกัด**: กำหนดสิ่งที่ AI ไม่ควรทำ
|
|
|
```python
|
|
|
system_prompt = """
|
|
|
You are a coding tutor focused on teaching best practices. Never write complete
|
|
|
solutions for the user - instead, guide them with hints and questions so they
|
|
|
learn by doing. Always explain the 'why' behind coding decisions.
|
|
|
"""
|
|
|
```
|
|
|
|
|
|
#### ทำไมสิ่งนี้ถึงสำคัญสำหรับผู้ช่วยแชทของคุณ
|
|
|
|
|
|
การเข้าใจ System Prompts ช่วยให้คุณมีพลังในการสร้างผู้ช่วย AI เฉพาะทาง:
|
|
|
- **บอทบริการลูก
|
|
|
**นี่คือเหตุผลที่ FastAPI เหมาะสมกับสิ่งที่เรากำลังสร้าง:**
|
|
|
- **Async โดยค่าเริ่มต้น**: สามารถจัดการคำขอ AI หลายคำขอพร้อมกันโดยไม่ติดขัด
|
|
|
- **เอกสารอัตโนมัติ**: แค่ไปที่ `/docs` ก็จะได้หน้าเอกสาร API ที่สวยงามและโต้ตอบได้ฟรี
|
|
|
- **การตรวจสอบความถูกต้องในตัว**: จับข้อผิดพลาดก่อนที่จะเกิดปัญหา
|
|
|
- **เร็วสุดๆ**: เป็นหนึ่งในเฟรมเวิร์ค Python ที่เร็วที่สุด
|
|
|
- **Python สมัยใหม่**: ใช้ฟีเจอร์ล่าสุดและดีที่สุดของ Python
|
|
|
|
|
|
**และนี่คือเหตุผลที่เราต้องการ Backend:**
|
|
|
|
|
|
**ความปลอดภัย**: คีย์ API ของ AI ของคุณเหมือนรหัสผ่าน – ถ้าคุณใส่มันใน JavaScript ฝั่ง Frontend ใครก็ตามที่ดูโค้ดของเว็บไซต์คุณสามารถขโมยมันไปใช้เครดิต AI ของคุณได้ Backend จะช่วยเก็บข้อมูลสำคัญให้ปลอดภัย
|
|
|
|
|
|
**การจำกัดอัตราและการควบคุม**: Backend ช่วยให้คุณควบคุมความถี่ที่ผู้ใช้สามารถส่งคำขอได้, เพิ่มการยืนยันตัวตนผู้ใช้ และเพิ่มการบันทึกเพื่อติดตามการใช้งาน
|
|
|
|
|
|
**การประมวลผลข้อมูล**: คุณอาจต้องการบันทึกการสนทนา, กรองเนื้อหาที่ไม่เหมาะสม หรือรวมบริการ AI หลายตัวเข้าด้วยกัน Backend คือที่ที่ตรรกะเหล่านี้อยู่
|
|
|
|
|
|
**สถาปัตยกรรมคล้ายกับโมเดล Client-Server:**
|
|
|
- **Frontend**: ชั้นอินเทอร์เฟซผู้ใช้สำหรับการโต้ตอบ
|
|
|
- **Backend API**: ชั้นการประมวลผลคำขอและการกำหนดเส้นทาง
|
|
|
- **AI Service**: การคำนวณภายนอกและการสร้างการตอบกลับ
|
|
|
- **Environment Variables**: การจัดเก็บการตั้งค่าและข้อมูลรับรองอย่างปลอดภัย
|
|
|
|
|
|
### ทำความเข้าใจการไหลของคำขอและการตอบกลับ
|
|
|
|
|
|
มาดูกันว่าเกิดอะไรขึ้นเมื่อผู้ใช้ส่งข้อความ:
|
|
|
|
|
|
```mermaid
|
|
|
sequenceDiagram
|
|
|
participant User as 👤 User
|
|
|
participant Frontend as 🌐 Frontend
|
|
|
participant API as 🔧 FastAPI Server
|
|
|
participant AI as 🤖 AI Service
|
|
|
|
|
|
User->>Frontend: Types "Hello AI!"
|
|
|
Frontend->>API: POST /hello {"message": "Hello AI!"}
|
|
|
Note over API: Validates request<br/>Adds system prompt
|
|
|
API->>AI: Sends formatted request
|
|
|
AI->>API: Returns AI response
|
|
|
Note over API: Processes response<br/>Logs conversation
|
|
|
API->>Frontend: {"response": "Hello! How can I help?"}
|
|
|
Frontend->>User: Displays AI message
|
|
|
```
|
|
|
|
|
|
**ทำความเข้าใจแต่ละขั้นตอน:**
|
|
|
1. **การโต้ตอบของผู้ใช้**: ผู้ใช้พิมพ์ข้อความในอินเทอร์เฟซแชท
|
|
|
2. **การประมวลผล Frontend**: JavaScript จับข้อมูลที่ป้อนและจัดรูปแบบเป็น JSON
|
|
|
3. **การตรวจสอบ API**: FastAPI ตรวจสอบคำขอโดยอัตโนมัติด้วยโมเดล Pydantic
|
|
|
4. **การรวม AI**: Backend เพิ่มบริบท (System Prompt) และเรียกใช้บริการ AI
|
|
|
5. **การจัดการการตอบกลับ**: API รับการตอบกลับจาก AI และสามารถปรับเปลี่ยนได้หากจำเป็น
|
|
|
6. **การแสดงผล Frontend**: JavaScript แสดงการตอบกลับในอินเทอร์เฟซแชท
|
|
|
|
|
|
### ทำความเข้าใจสถาปัตยกรรม API
|
|
|
|
|
|
```mermaid
|
|
|
sequenceDiagram
|
|
|
participant Frontend
|
|
|
participant FastAPI
|
|
|
participant AI Function
|
|
|
participant GitHub Models
|
|
|
|
|
|
Frontend->>FastAPI: POST /hello {"message": "Hello AI!"}
|
|
|
FastAPI->>AI Function: call_llm(message, system_prompt)
|
|
|
AI Function->>GitHub Models: API request
|
|
|
GitHub Models->>AI Function: AI response
|
|
|
AI Function->>FastAPI: response text
|
|
|
FastAPI->>Frontend: {"response": "Hello! How can I help?"}
|
|
|
```
|
|
|
|
|
|
### การสร้างแอปพลิเคชัน FastAPI
|
|
|
|
|
|
มาสร้าง API ของเราทีละขั้นตอน สร้างไฟล์ชื่อ `api.py` ด้วยโค้ด FastAPI ดังนี้:
|
|
|
|
|
|
```python
|
|
|
# api.py
|
|
|
from fastapi import FastAPI, HTTPException
|
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
from pydantic import BaseModel
|
|
|
from llm import call_llm
|
|
|
import logging
|
|
|
|
|
|
# Configure logging
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# Create FastAPI application
|
|
|
app = FastAPI(
|
|
|
title="AI Chat API",
|
|
|
description="A high-performance API for AI-powered chat applications",
|
|
|
version="1.0.0"
|
|
|
)
|
|
|
|
|
|
# Configure CORS
|
|
|
app.add_middleware(
|
|
|
CORSMiddleware,
|
|
|
allow_origins=["*"], # Configure appropriately for production
|
|
|
allow_credentials=True,
|
|
|
allow_methods=["*"],
|
|
|
allow_headers=["*"],
|
|
|
)
|
|
|
|
|
|
# Pydantic models for request/response validation
|
|
|
class ChatMessage(BaseModel):
|
|
|
message: str
|
|
|
|
|
|
class ChatResponse(BaseModel):
|
|
|
response: str
|
|
|
|
|
|
@app.get("/")
|
|
|
async def root():
|
|
|
"""Root endpoint providing API information."""
|
|
|
return {
|
|
|
"message": "Welcome to the AI Chat API",
|
|
|
"docs": "/docs",
|
|
|
"health": "/health"
|
|
|
}
|
|
|
|
|
|
@app.get("/health")
|
|
|
async def health_check():
|
|
|
"""Health check endpoint."""
|
|
|
return {"status": "healthy", "service": "ai-chat-api"}
|
|
|
|
|
|
@app.post("/hello", response_model=ChatResponse)
|
|
|
async def chat_endpoint(chat_message: ChatMessage):
|
|
|
"""Main chat endpoint that processes messages and returns AI responses."""
|
|
|
try:
|
|
|
# Extract and validate message
|
|
|
message = chat_message.message.strip()
|
|
|
if not message:
|
|
|
raise HTTPException(status_code=400, detail="Message cannot be empty")
|
|
|
|
|
|
logger.info(f"Processing message: {message[:50]}...")
|
|
|
|
|
|
# Call AI service (note: call_llm should be made async for better performance)
|
|
|
ai_response = await call_llm_async(message, "You are a helpful and friendly assistant.")
|
|
|
|
|
|
logger.info("AI response generated successfully")
|
|
|
return ChatResponse(response=ai_response)
|
|
|
|
|
|
except HTTPException:
|
|
|
raise
|
|
|
except Exception as e:
|
|
|
logger.error(f"Error processing chat message: {str(e)}")
|
|
|
raise HTTPException(status_code=500, detail="Internal server error")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
import uvicorn
|
|
|
uvicorn.run(app, host="0.0.0.0", port=5000, reload=True)
|
|
|
```
|
|
|
|
|
|
**ทำความเข้าใจการใช้งาน FastAPI:**
|
|
|
- **นำเข้า** FastAPI เพื่อฟังก์ชันเฟรมเวิร์คเว็บสมัยใหม่และ Pydantic เพื่อการตรวจสอบข้อมูล
|
|
|
- **สร้าง**เอกสาร API อัตโนมัติ (สามารถเข้าถึงได้ที่ `/docs` เมื่อเซิร์ฟเวอร์ทำงาน)
|
|
|
- **เปิดใช้งาน** CORS middleware เพื่ออนุญาตคำขอจาก Frontend ที่มาจากต้นทางต่างกัน
|
|
|
- **กำหนด**โมเดล Pydantic เพื่อการตรวจสอบคำขอ/การตอบกลับอัตโนมัติและการสร้างเอกสาร
|
|
|
- **ใช้** Endpoints แบบ Async เพื่อประสิทธิภาพที่ดีกว่ากับคำขอพร้อมกัน
|
|
|
- **ดำเนินการ**รหัสสถานะ HTTP และการจัดการข้อผิดพลาดอย่างเหมาะสมด้วย HTTPException
|
|
|
- **รวม**การบันทึกที่มีโครงสร้างเพื่อการตรวจสอบและแก้ไขข้อผิดพลาด
|
|
|
- **ให้บริการ** Endpoint ตรวจสอบสถานะเพื่อการติดตามสถานะของบริการ
|
|
|
|
|
|
**ข้อดีหลักของ FastAPI เมื่อเทียบกับเฟรมเวิร์คแบบดั้งเดิม:**
|
|
|
- **การตรวจสอบอัตโนมัติ**: โมเดล Pydantic ช่วยให้มั่นใจในความสมบูรณ์ของข้อมูลก่อนการประมวลผล
|
|
|
- **เอกสารแบบโต้ตอบ**: ไปที่ `/docs` เพื่อดูเอกสาร API ที่สร้างอัตโนมัติและสามารถทดสอบได้
|
|
|
- **ความปลอดภัยของประเภทข้อมูล**: Python type hints ช่วยป้องกันข้อผิดพลาดในระหว่างการทำงานและปรับปรุงคุณภาพของโค้ด
|
|
|
- **รองรับ Async**: จัดการคำขอ AI หลายคำขอพร้อมกันโดยไม่ติดขัด
|
|
|
- **ประสิทธิภาพ**: การประมวลผลคำขอที่เร็วขึ้นอย่างมากสำหรับแอปพลิเคชันแบบเรียลไทม์
|
|
|
|
|
|
### ทำความเข้าใจ CORS: ยามรักษาความปลอดภัยของเว็บ
|
|
|
|
|
|
CORS (Cross-Origin Resource Sharing) เปรียบเสมือนยามรักษาความปลอดภัยที่อาคารที่ตรวจสอบว่าผู้เยี่ยมชมได้รับอนุญาตให้เข้าไปหรือไม่ มาทำความเข้าใจว่าทำไมสิ่งนี้ถึงสำคัญและส่งผลต่อแอปพลิเคชันของคุณอย่างไร
|
|
|
|
|
|
#### CORS คืออะไรและทำไมถึงมีอยู่?
|
|
|
|
|
|
**ปัญหา**: ลองจินตนาการว่าหากเว็บไซต์ใดๆ สามารถส่งคำขอไปยังเว็บไซต์ธนาคารของคุณแทนคุณโดยไม่ได้รับอนุญาต นั่นจะเป็นฝันร้ายด้านความปลอดภัย! เบราว์เซอร์ป้องกันสิ่งนี้โดยค่าเริ่มต้นผ่าน "นโยบายต้นทางเดียวกัน"
|
|
|
|
|
|
**นโยบายต้นทางเดียวกัน**: เบราว์เซอร์อนุญาตให้หน้าเว็บส่งคำขอไปยังโดเมน, พอร์ต และโปรโตคอลเดียวกันที่โหลดมาเท่านั้น
|
|
|
|
|
|
**เปรียบเทียบกับโลกจริง**: เหมือนกับการรักษาความปลอดภัยของอาคารอพาร์ตเมนต์ – โดยปกติแล้วเฉพาะผู้อยู่อาศัย (ต้นทางเดียวกัน) เท่านั้นที่สามารถเข้าถึงอาคารได้ หากคุณต้องการให้เพื่อน (ต้นทางต่างกัน) มาเยี่ยม คุณต้องบอกยามว่าอนุญาต
|
|
|
|
|
|
#### CORS ในสภาพแวดล้อมการพัฒนา
|
|
|
|
|
|
ในระหว่างการพัฒนา Frontend และ Backend ของคุณทำงานบนพอร์ตต่างกัน:
|
|
|
- Frontend: `http://localhost:3000` (หรือ file:// หากเปิด HTML โดยตรง)
|
|
|
- Backend: `http://localhost:5000`
|
|
|
|
|
|
สิ่งเหล่านี้ถือว่าเป็น "ต้นทางต่างกัน" แม้ว่าจะอยู่บนคอมพิวเตอร์เครื่องเดียวกัน!
|
|
|
|
|
|
```python
|
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
|
|
app = FastAPI(__name__)
|
|
|
CORS(app) # This tells browsers: "It's okay for other origins to make requests to this API"
|
|
|
```
|
|
|
|
|
|
**สิ่งที่การตั้งค่า CORS ทำในทางปฏิบัติ:**
|
|
|
- **เพิ่ม** HTTP headers พิเศษในคำตอบของ API ที่บอกเบราว์เซอร์ว่า "คำขอข้ามต้นทางนี้ได้รับอนุญาต"
|
|
|
- **จัดการ**คำขอ "preflight" (เบราว์เซอร์บางครั้งตรวจสอบสิทธิ์ก่อนส่งคำขอจริง)
|
|
|
- **ป้องกัน**ข้อผิดพลาด "ถูกบล็อกโดยนโยบาย CORS" ในคอนโซลเบราว์เซอร์ของคุณ
|
|
|
|
|
|
#### ความปลอดภัยของ CORS: การพัฒนา vs การใช้งานจริง
|
|
|
|
|
|
```python
|
|
|
# 🚨 Development: Allows ALL origins (convenient but insecure)
|
|
|
CORS(app)
|
|
|
|
|
|
# ✅ Production: Only allow your specific frontend domain
|
|
|
CORS(app, origins=["https://yourdomain.com", "https://www.yourdomain.com"])
|
|
|
|
|
|
# 🔒 Advanced: Different origins for different environments
|
|
|
if app.debug: # Development mode
|
|
|
CORS(app, origins=["http://localhost:3000", "http://127.0.0.1:3000"])
|
|
|
else: # Production mode
|
|
|
CORS(app, origins=["https://yourdomain.com"])
|
|
|
```
|
|
|
|
|
|
**ทำไมสิ่งนี้ถึงสำคัญ**: ในการพัฒนา `CORS(app)` เหมือนกับการปล่อยประตูหน้าบ้านของคุณไว้โดยไม่ล็อค – สะดวกแต่ไม่ปลอดภัย ในการใช้งานจริง คุณต้องระบุอย่างชัดเจนว่าเว็บไซต์ใดสามารถพูดคุยกับ API ของคุณได้
|
|
|
|
|
|
#### สถานการณ์ CORS ทั่วไปและวิธีแก้ไข
|
|
|
|
|
|
| สถานการณ์ | ปัญหา | วิธีแก้ไข |
|
|
|
|------------|-------|-----------|
|
|
|
| **การพัฒนาในเครื่อง** | Frontend ไม่สามารถเข้าถึง Backend | เพิ่ม CORSMiddleware ใน FastAPI |
|
|
|
| **GitHub Pages + Heroku** | Frontend ที่เผยแพร่ไม่สามารถเข้าถึง API | เพิ่ม URL GitHub Pages ของคุณในต้นทาง CORS |
|
|
|
| **โดเมนที่กำหนดเอง** | ข้อผิดพลาด CORS ในการใช้งานจริง | อัปเดตต้นทาง CORS ให้ตรงกับโดเมนของคุณ |
|
|
|
| **แอปมือถือ** | แอปไม่สามารถเข้าถึงเว็บ API | เพิ่มโดเมนของแอปของคุณหรือใช้ `*` อย่างระมัดระวัง |
|
|
|
|
|
|
**เคล็ดลับ**: คุณสามารถตรวจสอบ headers ของ CORS ในเครื่องมือสำหรับนักพัฒนาของเบราว์เซอร์ในแท็บ Network มองหา headers เช่น `Access-Control-Allow-Origin` ในคำตอบ
|
|
|
|
|
|
### การจัดการข้อผิดพลาดและการตรวจสอบความถูกต้อง
|
|
|
|
|
|
สังเกตว่า API ของเรารวมการจัดการข้อผิดพลาดที่เหมาะสม:
|
|
|
|
|
|
```python
|
|
|
# Validate that we received a message
|
|
|
if not message:
|
|
|
return jsonify({"error": "Message field is required"}), 400
|
|
|
```
|
|
|
|
|
|
**หลักการตรวจสอบความถูกต้องที่สำคัญ:**
|
|
|
- **ตรวจสอบ**ฟิลด์ที่จำเป็นก่อนการประมวลผลคำขอ
|
|
|
- **ส่งคืน**ข้อความข้อผิดพลาดที่มีความหมายในรูปแบบ JSON
|
|
|
- **ใช้**รหัสสถานะ HTTP ที่เหมาะสม (400 สำหรับคำขอที่ไม่ถูกต้อง)
|
|
|
- **ให้**ข้อเสนอแนะที่ชัดเจนเพื่อช่วยนักพัฒนา Frontend แก้ไขปัญหา
|
|
|
|
|
|
## การตั้งค่าและการรัน Backend ของคุณ
|
|
|
|
|
|
ตอนนี้เรามีการรวม AI และเซิร์ฟเวอร์ FastAPI พร้อมแล้ว มารันทุกอย่างกัน การตั้งค่ารวมถึงการติดตั้งไลบรารี Python, การกำหนดค่า Environment Variables และการเริ่มเซิร์ฟเวอร์พัฒนา
|
|
|
|
|
|
### การตั้งค่าสภาพแวดล้อม Python
|
|
|
|
|
|
มาสร้างสภาพแวดล้อมการพัฒนา Python ของคุณ Virtual environments เปรียบเสมือนวิธีการแยกส่วนของโครงการ Manhattan – แต่ละโครงการจะมีพื้นที่แยกของตัวเองพร้อมเครื่องมือและไลบรารีเฉพาะ ป้องกันความขัดแย้งระหว่างโครงการต่างๆ
|
|
|
|
|
|
```bash
|
|
|
# Navigate to your backend directory
|
|
|
cd backend
|
|
|
|
|
|
# Create a virtual environment (like creating a clean room for your project)
|
|
|
python -m venv venv
|
|
|
|
|
|
# Activate it (Linux/Mac)
|
|
|
source ./venv/bin/activate
|
|
|
|
|
|
# On Windows, use:
|
|
|
# venv\Scripts\activate
|
|
|
|
|
|
# Install the good stuff
|
|
|
pip install openai fastapi uvicorn python-dotenv
|
|
|
```
|
|
|
|
|
|
**สิ่งที่เราทำไป:**
|
|
|
- **สร้าง**พื้นที่ Python ของเราเองที่เราสามารถติดตั้งแพ็กเกจโดยไม่ส่งผลกระทบต่อสิ่งอื่น
|
|
|
- **เปิดใช้งาน**เพื่อให้เทอร์มินัลของเรารู้ว่าจะใช้สภาพแวดล้อมนี้โดยเฉพาะ
|
|
|
- **ติดตั้ง**สิ่งจำเป็น: OpenAI สำหรับ AI, FastAPI สำหรับเว็บ API, Uvicorn เพื่อรันมัน และ python-dotenv เพื่อจัดการความลับอย่างปลอดภัย
|
|
|
|
|
|
**อธิบายไลบรารีที่สำคัญ:**
|
|
|
- **FastAPI**: เฟรมเวิร์คเว็บสมัยใหม่และรวดเร็วพร้อมเอกสาร API อัตโนมัติ
|
|
|
- **Uvicorn**: เซิร์ฟเวอร์ ASGI ที่เร็วมากที่รันแอปพลิเคชัน FastAPI
|
|
|
- **OpenAI**: ไลบรารีอย่างเป็นทางการสำหรับ GitHub Models และการรวม API ของ OpenAI
|
|
|
- **python-dotenv**: การโหลด Environment Variables อย่างปลอดภัยจากไฟล์ .env
|
|
|
|
|
|
### การกำหนดค่า Environment: เก็บความลับให้ปลอดภัย
|
|
|
|
|
|
ก่อนที่เราจะเริ่ม API ของเรา เราต้องพูดถึงบทเรียนสำคัญที่สุดในเว็บพัฒนา: วิธีเก็บความลับให้ปลอดภัยจริงๆ Environment Variables เปรียบเสมือนตู้เซฟที่ปลอดภัยที่แอปพลิเคชันของคุณเท่านั้นที่สามารถเข้าถึงได้
|
|
|
|
|
|
#### Environment Variables คืออะไร?
|
|
|
|
|
|
**คิดว่า Environment Variables เหมือนตู้เซฟนิรภัย** – คุณใส่ของมีค่าไว้ในนั้น และมีเพียงคุณ (และแอปของคุณ) ที่มีกุญแจเพื่อเปิดมัน แทนที่จะเขียนข้อมูลสำคัญลงในโค้ดโดยตรง (ที่ใครๆ ก็สามารถเห็นได้) คุณเก็บมันไว้อย่างปลอดภัยใน Environment
|
|
|
|
|
|
**นี่คือความแตกต่าง:**
|
|
|
- **วิธีที่ผิด**: เขียนรหัสผ่านบนกระดาษโน้ตแล้วแปะไว้ที่หน้าจอ
|
|
|
- **วิธีที่ถูกต้อง**: เก็บรหัสผ่านไว้ในตัวจัดการรหัสผ่านที่ปลอดภัยที่มีเพียงคุณเท่านั้นที่เข้าถึงได้
|
|
|
|
|
|
#### ทำไม Environment Variables ถึงสำคัญ
|
|
|
|
|
|
```python
|
|
|
# 🚨 NEVER DO THIS - API key visible to everyone
|
|
|
client = OpenAI(
|
|
|
api_key="ghp_1234567890abcdef...", # Anyone can steal this!
|
|
|
base_url="https://models.github.ai/inference"
|
|
|
)
|
|
|
|
|
|
# ✅ DO THIS - API key stored securely
|
|
|
client = OpenAI(
|
|
|
api_key=os.environ["GITHUB_TOKEN"], # Only your app can access this
|
|
|
base_url="https://models.github.ai/inference"
|
|
|
)
|
|
|
```
|
|
|
|
|
|
**สิ่งที่เกิดขึ้นเมื่อคุณเขียนความลับลงในโค้ด:**
|
|
|
1. **การเปิดเผยในระบบควบคุมเวอร์ชัน**: ใครก็ตามที่เข้าถึง Git repository ของคุณจะเห็นคีย์ API ของคุณ
|
|
|
2. **Repository สาธารณะ**: หากคุณอัปโหลดไปยัง GitHub คีย์ของคุณจะมองเห็นได้ทั่วอินเทอร์เน็ต
|
|
|
3. **การแชร์ทีม**: นักพัฒนาคนอื่นที่ทำงานในโครงการของคุณจะเข้าถึงคีย์ API ส่วนตัวของคุณ
|
|
|
4. **การละเมิดความปลอดภัย**: หากมีคนขโมยคีย์ API ของคุณ พวกเขาสามารถใช้เครดิต AI ของคุณได้
|
|
|
|
|
|
#### การตั้งค่าไฟล์ Environment
|
|
|
|
|
|
สร้างไฟล์ `.env` ในไดเรกทอรี Backend ของคุณ ไฟล์นี้จะเก็บความลับของคุณไว้ในเครื่อง:
|
|
|
|
|
|
```bash
|
|
|
# .env file - This should NEVER be committed to Git
|
|
|
GITHUB_TOKEN=your_github_personal_access_token_here
|
|
|
FASTAPI_DEBUG=True
|
|
|
ENVIRONMENT=development
|
|
|
```
|
|
|
|
|
|
**ทำความเข้าใจไฟล์ .env:**
|
|
|
- **หนึ่งความลับต่อบรรทัด**ในรูปแบบ `KEY=value`
|
|
|
- **ไม่มีช่องว่าง**รอบเครื่องหมายเท่ากับ
|
|
|
- **ไม่ต้องใช้เครื่องหมายคำพูด**รอบค่า (โดยปกติ)
|
|
|
- **ความคิดเห็น**เริ่มต้นด้วย `#`
|
|
|
|
|
|
#### การสร้าง GitHub Personal Access Token ของคุณ
|
|
|
|
|
|
Token GitHub ของคุณเปรียบเสมือนรหัสผ่านพิเศษที่ให้แอปพลิเคชันของคุณสิทธิ์ในการใช้บริการ AI ของ GitHub:
|
|
|
|
|
|
**ขั้นตอนการสร้าง Token:**
|
|
|
1. **ไปที่ GitHub Settings** → Developer settings → Personal access tokens → Tokens (classic)
|
|
|
2. **คลิก "Generate new token (classic)"**
|
|
|
3. **ตั้งค่าการหมดอายุ** (30 วันสำหรับการทดสอบ, นานกว่านั้นสำหรับการใช้งานจริง)
|
|
|
4. **เลือก scopes**: เลือก "repo" และสิทธิ์อื่นๆ ที่คุณต้องการ
|
|
|
5. **สร้าง Token** และคัดลอกทันที (คุณจะไม่สามารถดูมันอีก!)
|
|
|
6. **วางลงในไฟล์ .env ของคุณ**
|
|
|
|
|
|
```bash
|
|
|
# Example of what your token looks like (this is fake!)
|
|
|
GITHUB_TOKEN=ghp_1A2B3C4D5E6F7G8H9I0J1K2L3M4N5O6P7Q8R
|
|
|
```
|
|
|
|
|
|
#### การโหลด Environment Variables ใน Python
|
|
|
|
|
|
```python
|
|
|
import os
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
|
# Load environment variables from .env file
|
|
|
load_dotenv()
|
|
|
|
|
|
# Now you can access them securely
|
|
|
api_key = os.environ.get("GITHUB_TOKEN")
|
|
|
if not api_key:
|
|
|
raise ValueError("GITHUB_TOKEN not found in environment variables!")
|
|
|
|
|
|
client = OpenAI(
|
|
|
api_key=api_key,
|
|
|
base_url="https://models.github.ai/inference"
|
|
|
)
|
|
|
```
|
|
|
|
|
|
**สิ่งที่โค้ดนี้ทำ:**
|
|
|
- **โหลด**ไฟล์ .env ของคุณและทำให้ตัวแปรพร้อมใช้งานใน Python
|
|
|
- **ตรวจสอบ**ว่ามี Token ที่จำเป็นอยู่หรือไม่ (การจัดการข้อผิดพลาดที่ดี!)
|
|
|
- **แจ้งข้อผิดพลาด**ที่ชัดเจนหากไม่มี Token
|
|
|
- **ใช้** Token อย่างปลอดภัยโดยไม่เปิดเผยในโค้ด
|
|
|
|
|
|
#### ความปลอดภัยของ Git: ไฟล์ .gitignore
|
|
|
|
|
|
ไฟล์ `.gitignore` ของคุณบอก Git ว่าไฟล์ใดไม่ควรติดตามหรืออัปโหลด:
|
|
|
|
|
|
```bash
|
|
|
# .gitignore - Add these lines
|
|
|
.env
|
|
|
*.env
|
|
|
.env.local
|
|
|
.env.production
|
|
|
__pycache__/
|
|
|
venv/
|
|
|
.vscode/
|
|
|
```
|
|
|
|
|
|
**ทำไมสิ่งนี้ถึงสำคัญ**: เมื่อคุณเพิ่ม `.env` ลงใน `.gitignore` Git จะไม่สนใจไฟล์ Environment ของคุณ ป้องกันไม่ให้คุณอัปโหลดความลับไปยัง GitHub โดยไม่ตั้งใจ
|
|
|
|
|
|
#### สภาพแวดล้อมที่แตกต่าง ความลับที่แตกต่าง
|
|
|
|
|
|
แอปพลิเคชันระดับมืออาชีพใช้คีย์ API ที่แตกต่างกันสำหรับสภาพแวดล้อมที่แตกต่างกัน:
|
|
|
|
|
|
```bash
|
|
|
# .env.development
|
|
|
GITHUB_TOKEN=your_development_token
|
|
|
DEBUG=True
|
|
|
|
|
|
# .env.production
|
|
|
GITHUB_TOKEN=your_production_token
|
|
|
DEBUG=False
|
|
|
```
|
|
|
|
|
|
**ทำไมสิ่งนี้ถึงสำคัญ**: คุณไม่ต้องการให้การทดลองในระหว่างการพัฒนาส่งผลกระทบต่อโควต้า AI ในการใช้งานจริง และคุณต้องการระดับความปลอดภัยที่แตกต่างกันสำหรับสภาพแวดล้อมที่แตกต่างกัน
|
|
|
|
|
|
### การเริ่มเซิร์ฟเวอร์พัฒนา: ทำให้ FastAPI ของคุณมีชีวิต
|
|
|
|
|
|
ตอนนี้ถึงเวลาที่น่าตื่นเต้น – การเริ่มเซิร์ฟเวอร์พัฒนา FastAPI ของคุณและดูการรวม AI ของคุณมีชีวิต! FastAPI ใช้ Uvicorn ซึ่งเป็นเซิร์ฟเวอร์ ASGI ที่เร็วมากที่ออกแบบมาโดยเฉพาะสำหรับแอปพลิเคชัน Python แบบ Async
|
|
|
|
|
|
#### ทำความเข้าใจกระบวนการเริ่มต้นเซิร์ฟเวอร์ FastAPI
|
|
|
|
|
|
```bash
|
|
|
# Method 1: Direct Python execution (includes auto-reload)
|
|
|
python api.py
|
|
|
|
|
|
# Method 2: Using Uvicorn directly (more control)
|
|
|
uvicorn api:app --host 0.0.0.0 --port 5000 --reload
|
|
|
```
|
|
|
|
|
|
เมื่อคุณรันคำสั่งนี้ นี่คือสิ่งที่เกิดขึ้นเบื้องหลัง:
|
|
|
|
|
|
**1. Python โหลดแอปพลิเคชัน FastAPI ของคุณ**:
|
|
|
- นำเข้าไลบรารีที่จำเป็นทั้งหมด (FastAPI, Pydantic, OpenAI ฯลฯ)
|
|
|
- โหลด Environment Variables จากไฟล์ `.env` ของคุณ
|
|
|
- สร้างอินสแตนซ์แอปพลิเคชัน FastAPI พร้อมเอกสารอัตโนมัติ
|
|
|
|
|
|
**2. Uvicorn กำหนดค่าเซิร์ฟเวอร์ ASGI**:
|
|
|
- ผูกกับพอร์ต 5000 พร้อมความสามารถในการจัดการคำขอแบบ Async
|
|
|
- ตั้งค่าการกำหนดเส้นทางคำขอพร้อมการตรวจสอบอัตโนมัติ
|
|
|
- เปิดใช้งานการโหลดใหม่อัตโนมัติสำหรับ
|
|
|
#### การแก้ไขปัญหาที่พบบ่อยเมื่อเริ่มต้นใช้งาน
|
|
|
|
|
|
| ข้อความแสดงข้อผิดพลาด | หมายความว่า | วิธีแก้ไข |
|
|
|
|------------------------|-------------|-----------|
|
|
|
| `ModuleNotFoundError: No module named 'fastapi'` | FastAPI ยังไม่ได้ติดตั้ง | รันคำสั่ง `pip install fastapi uvicorn` ใน virtual environment ของคุณ |
|
|
|
| `ModuleNotFoundError: No module named 'uvicorn'` | ASGI server ยังไม่ได้ติดตั้ง | รันคำสั่ง `pip install uvicorn` ใน virtual environment ของคุณ |
|
|
|
| `KeyError: 'GITHUB_TOKEN'` | ไม่พบตัวแปร environment | ตรวจสอบไฟล์ `.env` และคำสั่ง `load_dotenv()` |
|
|
|
| `Address already in use` | พอร์ต 5000 ถูกใช้งานอยู่ | ปิดโปรเซสอื่นที่ใช้พอร์ต 5000 หรือเปลี่ยนพอร์ต |
|
|
|
| `ValidationError` | ข้อมูลที่ส่งมาไม่ตรงกับโมเดล Pydantic | ตรวจสอบรูปแบบคำขอให้ตรงกับ schema ที่คาดหวัง |
|
|
|
| `HTTPException 422` | ไม่สามารถประมวลผลข้อมูลได้ | การตรวจสอบคำขอล้มเหลว ตรวจสอบ `/docs` เพื่อดูรูปแบบที่ถูกต้อง |
|
|
|
| `OpenAI API error` | การยืนยันตัวตนบริการ AI ล้มเหลว | ตรวจสอบว่า GitHub token ของคุณถูกต้องและมีสิทธิ์ที่เหมาะสม |
|
|
|
|
|
|
#### แนวทางปฏิบัติที่ดีที่สุดในการพัฒนา
|
|
|
|
|
|
**Hot Reloading**: FastAPI กับ Uvicorn มีฟีเจอร์การรีโหลดอัตโนมัติเมื่อคุณบันทึกการเปลี่ยนแปลงในไฟล์ Python ซึ่งช่วยให้คุณสามารถแก้ไขโค้ดและทดสอบได้ทันทีโดยไม่ต้องรีสตาร์ทด้วยตัวเอง
|
|
|
|
|
|
**การบันทึกข้อมูลสำหรับการพัฒนา**: เพิ่มการบันทึกข้อมูลเพื่อเข้าใจว่าเกิดอะไรขึ้น:
|
|
|
|
|
|
**ทำไมการบันทึกข้อมูลถึงช่วยได้**: ในระหว่างการพัฒนา คุณสามารถดูได้ว่ามีคำขออะไรเข้ามา AI ตอบกลับอะไร และข้อผิดพลาดเกิดขึ้นที่ไหน ซึ่งช่วยให้การแก้ไขปัญหาเร็วขึ้นมาก
|
|
|
|
|
|
### การตั้งค่ากับ GitHub Codespaces: การพัฒนาในคลาวด์ที่ง่ายขึ้น
|
|
|
|
|
|
GitHub Codespaces เปรียบเสมือนการมีคอมพิวเตอร์พัฒนาที่ทรงพลังในคลาวด์ที่คุณสามารถเข้าถึงได้จากเบราว์เซอร์ใดก็ได้ หากคุณทำงานใน Codespaces มีขั้นตอนเพิ่มเติมบางอย่างเพื่อทำให้ backend ของคุณสามารถเข้าถึง frontend ได้
|
|
|
|
|
|
#### การทำความเข้าใจเครือข่ายของ Codespaces
|
|
|
|
|
|
ในสภาพแวดล้อมการพัฒนาแบบโลคอล ทุกอย่างจะรันบนคอมพิวเตอร์เดียวกัน:
|
|
|
- Backend: `http://localhost:5000`
|
|
|
- Frontend: `http://localhost:3000` (หรือ file://)
|
|
|
|
|
|
ใน Codespaces สภาพแวดล้อมการพัฒนาของคุณจะรันบนเซิร์ฟเวอร์ของ GitHub ดังนั้น "localhost" จะมีความหมายที่แตกต่างออกไป GitHub จะสร้าง URL สาธารณะสำหรับบริการของคุณโดยอัตโนมัติ แต่คุณต้องตั้งค่าพวกมันให้ถูกต้อง
|
|
|
|
|
|
#### ขั้นตอนการตั้งค่า Codespaces
|
|
|
|
|
|
**1. เริ่มเซิร์ฟเวอร์ backend ของคุณ**:
|
|
|
คุณจะเห็นข้อความเริ่มต้นของ FastAPI/Uvicorn ที่คุ้นเคย แต่สังเกตว่ามันกำลังรันอยู่ในสภาพแวดล้อมของ Codespace
|
|
|
|
|
|
**2. ตั้งค่าการมองเห็นพอร์ต**:
|
|
|
- มองหาแท็บ "Ports" ในแผงด้านล่างของ VS Code
|
|
|
- หา port 5000 ในรายการ
|
|
|
- คลิกขวาที่ port 5000
|
|
|
- เลือก "Port Visibility" → "Public"
|
|
|
|
|
|
**ทำไมต้องตั้งค่าเป็นสาธารณะ?** โดยปกติพอร์ตใน Codespace จะเป็นแบบส่วนตัว (เข้าถึงได้เฉพาะคุณ) การตั้งค่าให้เป็นสาธารณะจะช่วยให้ frontend (ที่รันในเบราว์เซอร์) สามารถสื่อสารกับ backend ได้
|
|
|
|
|
|
**3. รับ URL สาธารณะของคุณ**:
|
|
|
หลังจากตั้งค่าพอร์ตเป็นสาธารณะ คุณจะเห็น URL เช่น:
|
|
|
|
|
|
**4. อัปเดตการตั้งค่า frontend ของคุณ**:
|
|
|
|
|
|
#### การทำความเข้าใจ URL ของ Codespace
|
|
|
|
|
|
URL ของ Codespace มีรูปแบบที่คาดเดาได้:
|
|
|
|
|
|
**การแยกส่วนนี้**:
|
|
|
- `codespace-name`: ตัวระบุเฉพาะสำหรับ Codespace ของคุณ (มักจะรวมชื่อผู้ใช้ของคุณ)
|
|
|
- `port`: หมายเลขพอร์ตที่บริการของคุณกำลังรันอยู่ (5000 สำหรับแอป FastAPI ของเรา)
|
|
|
- `app.github.dev`: โดเมนของ GitHub สำหรับแอปพลิเคชันใน Codespace
|
|
|
|
|
|
#### การทดสอบการตั้งค่า Codespace ของคุณ
|
|
|
|
|
|
**1. ทดสอบ backend โดยตรง**:
|
|
|
เปิด URL สาธารณะของคุณในแท็บเบราว์เซอร์ใหม่ คุณควรเห็น:
|
|
|
|
|
|
**2. ทดสอบด้วยเครื่องมือพัฒนาเบราว์เซอร์**:
|
|
|
|
|
|
#### Codespaces vs การพัฒนาแบบโลคอล
|
|
|
|
|
|
| ด้าน | การพัฒนาแบบโลคอล | GitHub Codespaces |
|
|
|
|------|------------------|------------------|
|
|
|
| **เวลาในการตั้งค่า** | นานกว่า (ติดตั้ง Python, dependencies) | ทันที (สภาพแวดล้อมที่ตั้งค่าไว้ล่วงหน้า) |
|
|
|
| **การเข้าถึง URL** | `http://localhost:5000` | `https://xyz-5000.app.github.dev` |
|
|
|
| **การตั้งค่าพอร์ต** | อัตโนมัติ | ตั้งค่าด้วยตนเอง (ทำให้พอร์ตเป็นสาธารณะ) |
|
|
|
| **การเก็บรักษาไฟล์** | เครื่องโลคอล | Repository ของ GitHub |
|
|
|
| **การทำงานร่วมกัน** | แชร์สภาพแวดล้อมได้ยาก | แชร์ลิงก์ Codespace ได้ง่าย |
|
|
|
| **การพึ่งพาอินเทอร์เน็ต** | เฉพาะการเรียก API AI | จำเป็นสำหรับทุกอย่าง |
|
|
|
|
|
|
#### เคล็ดลับการพัฒนาใน Codespace
|
|
|
|
|
|
**ตัวแปร Environment ใน Codespaces**:
|
|
|
ไฟล์ `.env` ของคุณทำงานในลักษณะเดียวกันใน Codespaces แต่คุณสามารถตั้งค่าตัวแปร environment ได้โดยตรงใน Codespace
|
|
|
|
|
|
**การจัดการพอร์ต**:
|
|
|
- Codespaces ตรวจจับโดยอัตโนมัติเมื่อแอปพลิเคชันของคุณเริ่มฟังพอร์ต
|
|
|
- คุณสามารถส่งต่อพอร์ตหลายพอร์ตพร้อมกัน (มีประโยชน์หากคุณเพิ่มฐานข้อมูลในภายหลัง)
|
|
|
- พอร์ตจะยังคงเข้าถึงได้ตราบใดที่ Codespace ของคุณยังรันอยู่
|
|
|
|
|
|
**กระบวนการทำงานในการพัฒนา**:
|
|
|
1. แก้ไขโค้ดใน VS Code
|
|
|
2. FastAPI รีโหลดอัตโนมัติ (ด้วยโหมด reload ของ Uvicorn)
|
|
|
3. ทดสอบการเปลี่ยนแปลงทันทีผ่าน URL สาธารณะ
|
|
|
4. Commit และ push เมื่อพร้อม
|
|
|
|
|
|
💡 **เคล็ดลับ**: บันทึก URL backend ของ Codespace ของคุณในระหว่างการพัฒนา เนื่องจากชื่อ Codespace มีความเสถียร URL จะไม่เปลี่ยนแปลงตราบใดที่คุณใช้ Codespace เดิม
|
|
|
|
|
|
## การสร้างอินเทอร์เฟซแชทของ Frontend: จุดเชื่อมต่อระหว่างมนุษย์และ AI
|
|
|
|
|
|
ตอนนี้เราจะสร้างส่วนติดต่อผู้ใช้ – ส่วนที่กำหนดว่าผู้คนจะโต้ตอบกับผู้ช่วย AI ของคุณอย่างไร เช่นเดียวกับการออกแบบอินเทอร์เฟซของ iPhone รุ่นแรก เรามุ่งเน้นที่การทำให้เทคโนโลยีที่ซับซ้อนรู้สึกใช้งานง่ายและเป็นธรรมชาติ
|
|
|
|
|
|
### การทำความเข้าใจสถาปัตยกรรม Frontend สมัยใหม่
|
|
|
|
|
|
อินเทอร์เฟซแชทของเราจะเป็นสิ่งที่เรียกว่า "Single Page Application" หรือ SPA แทนที่จะใช้วิธีการแบบเก่าที่ทุกครั้งที่คลิกจะโหลดหน้าใหม่ แอปของเราจะอัปเดตอย่างราบรื่นและทันที:
|
|
|
|
|
|
**เว็บไซต์แบบเก่า**: เหมือนการอ่านหนังสือ – คุณพลิกไปยังหน้าที่ใหม่ทั้งหมด
|
|
|
**แอปแชทของเรา**: เหมือนการใช้โทรศัพท์ – ทุกอย่างไหลลื่นและอัปเดตอย่างราบรื่น
|
|
|
|
|
|
### สามเสาหลักของการพัฒนา Frontend
|
|
|
|
|
|
แอปพลิเคชัน frontend ทุกตัว – ตั้งแต่เว็บไซต์ง่ายๆ ไปจนถึงแอปพลิเคชันที่ซับซ้อนอย่าง Discord หรือ Slack – ถูกสร้างขึ้นบนสามเทคโนโลยีหลัก คิดว่ามันเป็นพื้นฐานของทุกสิ่งที่คุณเห็นและโต้ตอบบนเว็บ:
|
|
|
|
|
|
**HTML (โครงสร้าง)**: นี่คือพื้นฐานของคุณ
|
|
|
- กำหนดว่าองค์ประกอบใดมีอยู่ (ปุ่ม, ช่องข้อความ, คอนเทนเนอร์)
|
|
|
- ให้ความหมายกับเนื้อหา (นี่คือหัวข้อ, นี่คือฟอร์ม ฯลฯ)
|
|
|
- สร้างโครงสร้างพื้นฐานที่ทุกอย่างอื่นสร้างขึ้น
|
|
|
|
|
|
**CSS (การนำเสนอ)**: นี่คือผู้ออกแบบภายในของคุณ
|
|
|
- ทำให้ทุกอย่างดูสวยงาม (สี, ฟอนต์, การจัดวาง)
|
|
|
- จัดการขนาดหน้าจอที่แตกต่างกัน (โทรศัพท์ vs แล็ปท็อป vs แท็บเล็ต)
|
|
|
- สร้างแอนิเมชันที่ราบรื่นและการตอบสนองทางภาพ
|
|
|
|
|
|
**JavaScript (พฤติกรรม)**: นี่คือสมองของคุณ
|
|
|
- ตอบสนองต่อสิ่งที่ผู้ใช้ทำ (คลิก, พิมพ์, เลื่อน)
|
|
|
- สื่อสารกับ backend และอัปเดตหน้า
|
|
|
- ทำให้ทุกอย่างมีการโต้ตอบและไดนามิก
|
|
|
|
|
|
**คิดว่าเหมือนการออกแบบสถาปัตยกรรม**:
|
|
|
- **HTML**: พิมพ์เขียวโครงสร้าง (กำหนดพื้นที่และความสัมพันธ์)
|
|
|
- **CSS**: การออกแบบสุนทรียภาพและสิ่งแวดล้อม (สไตล์ภาพและประสบการณ์ผู้ใช้)
|
|
|
- **JavaScript**: ระบบกลไก (ฟังก์ชันและการโต้ตอบ)
|
|
|
|
|
|
### ทำไมสถาปัตยกรรม JavaScript สมัยใหม่ถึงสำคัญ
|
|
|
|
|
|
แอปแชทของเราจะใช้รูปแบบ JavaScript สมัยใหม่ที่คุณจะพบในแอปพลิเคชันระดับมืออาชีพ การทำความเข้าใจแนวคิดเหล่านี้จะช่วยให้คุณเติบโตในฐานะนักพัฒนา:
|
|
|
|
|
|
**Class-Based Architecture**: เราจะจัดระเบียบโค้ดของเราเป็นคลาส ซึ่งเหมือนกับการสร้างพิมพ์เขียวสำหรับออบเจ็กต์
|
|
|
**Async/Await**: วิธีการสมัยใหม่ในการจัดการกับการดำเนินการที่ใช้เวลา (เช่น การเรียก API)
|
|
|
**Event-Driven Programming**: แอปของเราตอบสนองต่อการกระทำของผู้ใช้ (คลิก, กดปุ่ม) แทนที่จะรันในลูป
|
|
|
**DOM Manipulation**: อัปเดตเนื้อหาเว็บเพจแบบไดนามิกตามการโต้ตอบของผู้ใช้และการตอบกลับของ API
|
|
|
|
|
|
### การตั้งค่าโครงสร้างโปรเจกต์
|
|
|
|
|
|
สร้างไดเรกทอรี frontend ด้วยโครงสร้างที่จัดระเบียบดังนี้:
|
|
|
|
|
|
**การทำความเข้าใจสถาปัตยกรรม**:
|
|
|
- **แยก** ความกังวลระหว่างโครงสร้าง (HTML), พฤติกรรม (JavaScript), และการนำเสนอ (CSS)
|
|
|
- **รักษา** โครงสร้างไฟล์ที่เรียบง่ายและง่ายต่อการนำทางและแก้ไข
|
|
|
- **ปฏิบัติตาม** แนวทางปฏิบัติที่ดีที่สุดในการพัฒนาเว็บสำหรับการจัดระเบียบและการบำรุงรักษา
|
|
|
|
|
|
### การสร้างโครงสร้าง HTML: โครงสร้างเชิงความหมายเพื่อการเข้าถึง
|
|
|
|
|
|
เริ่มต้นด้วยโครงสร้าง HTML การพัฒนาเว็บสมัยใหม่เน้น "HTML เชิงความหมาย" – การใช้องค์ประกอบ HTML ที่อธิบายวัตถุประสงค์ของพวกมันอย่างชัดเจน ไม่ใช่แค่ลักษณะของพวกมัน ซึ่งทำให้แอปพลิเคชันของคุณสามารถเข้าถึงได้สำหรับเครื่องอ่านหน้าจอ, เครื่องมือค้นหา, และเครื่องมืออื่นๆ
|
|
|
|
|
|
**ทำไม HTML เชิงความหมายถึงสำคัญ**: ลองจินตนาการว่าคุณกำลังอธิบายแอปแชทของคุณให้ใครบางคนฟังทางโทรศัพท์ คุณจะพูดว่า "มีส่วนหัวที่มีชื่อเรื่อง, พื้นที่หลักที่มีการสนทนา, และฟอร์มที่ด้านล่างสำหรับการพิมพ์ข้อความ" HTML เชิงความหมายใช้องค์ประกอบที่ตรงกับคำอธิบายธรรมชาตินี้
|
|
|
|
|
|
สร้าง `index.html` ด้วยโครงสร้างที่คิดมาอย่างดีดังนี้:
|
|
|
|
|
|
**การทำความเข้าใจแต่ละองค์ประกอบ HTML และวัตถุประสงค์ของมัน**:
|
|
|
|
|
|
#### โครงสร้างเอกสาร
|
|
|
- **`<!DOCTYPE html>`**: บอกเบราว์เซอร์ว่านี่คือ HTML5 สมัยใหม่
|
|
|
- **`<html lang="en">`**: ระบุภาษาของหน้าเว็บสำหรับเครื่องอ่านหน้าจอและเครื่องมือแปลภาษา
|
|
|
- **`<meta charset="UTF-8">`**: รับรองการเข้ารหัสตัวอักษรที่เหมาะสมสำหรับข้อความระหว่างประเทศ
|
|
|
- **`<meta name="viewport"...>`**: ทำให้หน้าเว็บตอบสนองต่อมือถือโดยควบคุมการซูมและการปรับขนาด
|
|
|
|
|
|
#### องค์ประกอบเชิงความหมาย
|
|
|
- **`<header>`**: ระบุส่วนบนอย่างชัดเจนพร้อมชื่อเรื่องและคำอธิบาย
|
|
|
- **`<main>`**: กำหนดพื้นที่เนื้อหาหลัก (ที่การสนทนาเกิดขึ้น)
|
|
|
- **`<form>`**: ถูกต้องตามหลักการสำหรับการป้อนข้อมูลของผู้ใช้ ช่วยให้การนำทางด้วยแป้นพิมพ์เป็นไปอย่างเหมาะสม
|
|
|
|
|
|
#### คุณสมบัติการเข้าถึง
|
|
|
- **`role="log"`**: บอกเครื่องอ่านหน้าจอว่าส่วนนี้มีบันทึกข้อความตามลำดับเวลา
|
|
|
- **`aria-live="polite"`**: ประกาศข้อความใหม่ให้เครื่องอ่านหน้าจอโดยไม่ขัดจังหวะ
|
|
|
- **`aria-label`**: ให้คำอธิบายที่ชัดเจนสำหรับการควบคุมฟอร์ม
|
|
|
- **`required`**: เบราว์เซอร์ตรวจสอบว่าผู้ใช้ป้อนข้อความก่อนส่ง
|
|
|
|
|
|
#### การรวม CSS และ JavaScript
|
|
|
- **`class` attributes**: ให้จุดเชื่อมโยงสำหรับการจัดสไตล์ CSS (เช่น `chat-container`, `input-group`)
|
|
|
- **`id` attributes**: อนุญาตให้ JavaScript ค้นหาและจัดการองค์ประกอบเฉพาะ
|
|
|
- **ตำแหน่ง Script**: ไฟล์ JavaScript โหลดที่ท้ายสุดเพื่อให้ HTML โหลดก่อน
|
|
|
|
|
|
**ทำไมโครงสร้างนี้ถึงทำงานได้ดี**:
|
|
|
- **ลำดับที่มีเหตุผล**: ส่วนหัว → เนื้อหาหลัก → ฟอร์มป้อนข้อมูลตรงกับลำดับการอ่านตามธรรมชาติ
|
|
|
- **เข้าถึงด้วยแป้นพิมพ์**: ผู้ใช้สามารถกด Tab ผ่านองค์ประกอบที่โต้ตอบได้ทั้งหมด
|
|
|
- **เป็นมิตรกับเครื่องอ่านหน้าจอ**: จุดสังเกตและคำอธิบายที่ชัดเจนสำหรับผู้ใช้ที่มีปัญหาด้านการมองเห็น
|
|
|
- **ตอบสนองต่อมือถือ**: แท็ก meta viewport ช่วยให้การออกแบบตอบสนอง
|
|
|
- **การปรับปรุงแบบก้าวหน้า**: ทำงานได้แม้ว่า CSS หรือ JavaScript จะล้มเหลวในการโหลด
|
|
|
|
|
|
### การเพิ่ม JavaScript แบบโต้ตอบ: ตรรกะของแอปพลิเคชันเว็บสมัยใหม่
|
|
|
|
|
|
ตอนนี้เรามาสร้าง JavaScript ที่ทำให้อินเทอร์เฟซแชทของเรามีชีวิตชีวา เราจะใช้รูปแบบ JavaScript สมัยใหม่ที่คุณจะพบในการพัฒนาเว็บระดับมืออาชีพ รวมถึงคลาส ES6, async/await, และการเขียนโปรแกรมแบบขับเคลื่อนด้วยเหตุการณ์
|
|
|
|
|
|
#### การทำความเข้าใจสถาปัตยกรรม JavaScript สมัยใหม่
|
|
|
|
|
|
แทนที่จะเขียนโค้ดแบบ procedural (ชุดฟังก์ชันที่รันตามลำดับ) เราจะสร้าง **สถาปัตยกรรมแบบคลาส** คิดว่าคลาสเป็นพิมพ์เขียวสำหรับการสร้างออบเจ็กต์ – เหมือนกับพิมพ์เขียวของสถาปนิกที่สามารถใช้สร้างบ้านหลายหลัง
|
|
|
|
|
|
**ทำไมต้องใช้คลาสสำหรับแอปพลิเคชันเว็บ?**
|
|
|
- **การจัดระเบียบ**: ฟังก์ชันที่เกี่ยวข้องทั้งหมดถูกรวมเข้าด้วยกัน
|
|
|
- **การนำกลับมาใช้ใหม่**: คุณสามารถสร้างอินสแตนซ์แชทหลายตัวในหน้าเดียวกัน
|
|
|
- **การบำรุงรักษา**: ง่ายต่อการดีบักและแก้ไขฟีเจอร์เฉพาะ
|
|
|
- **มาตรฐานระดับมืออาชีพ**: รูปแบบนี้ถูกใช้ในเฟรมเวิร์กอย่าง React, Vue, และ Angular
|
|
|
|
|
|
สร้าง `app.js` ด้วย JavaScript ที่มีโครงสร้างดีและทันสมัย:
|
|
|
|
|
|
#### การทำความเข้าใจแต่ละแนวคิดของ JavaScript
|
|
|
|
|
|
**โครงสร้างคลาส ES6**:
|
|
|
|
|
|
**รูปแบบ Async/Await**:
|
|
|
|
|
|
**การเขียนโปรแกรมแบบขับเคลื่อนด้วยเหตุการณ์**:
|
|
|
แทนที่จะตรวจสอบอย่างต่อเนื่องว่ามีอะไรเกิดขึ้น เรา "
|
|
|
สถาปัตยกรรมนี้สามารถปรับขยายได้ – คุณสามารถเพิ่มฟีเจอร์ต่างๆ เช่น การแก้ไขข้อความ การอัปโหลดไฟล์ หรือการสนทนาแบบหลายเธรดได้อย่างง่ายดายโดยไม่ต้องเขียนโครงสร้างหลักใหม่
|
|
|
|
|
|
### การออกแบบอินเทอร์เฟซแชทของคุณ
|
|
|
|
|
|
ตอนนี้เรามาสร้างอินเทอร์เฟซแชทที่ทันสมัยและดูน่าสนใจด้วย CSS การออกแบบที่ดีช่วยให้แอปพลิเคชันของคุณดูเป็นมืออาชีพและปรับปรุงประสบการณ์การใช้งานโดยรวม เราจะใช้ฟีเจอร์ CSS สมัยใหม่ เช่น Flexbox, CSS Grid และคุณสมบัติแบบกำหนดเองเพื่อการออกแบบที่ตอบสนองและเข้าถึงได้ง่าย
|
|
|
|
|
|
สร้างไฟล์ `styles.css` พร้อมสไตล์ที่ครอบคลุมดังนี้:
|
|
|
|
|
|
```css
|
|
|
/* styles.css - Modern chat interface styling */
|
|
|
|
|
|
:root {
|
|
|
--primary-color: #2563eb;
|
|
|
--secondary-color: #f1f5f9;
|
|
|
--user-color: #3b82f6;
|
|
|
--assistant-color: #6b7280;
|
|
|
--error-color: #ef4444;
|
|
|
--text-primary: #1e293b;
|
|
|
--text-secondary: #64748b;
|
|
|
--border-radius: 12px;
|
|
|
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
|
}
|
|
|
|
|
|
* {
|
|
|
margin: 0;
|
|
|
padding: 0;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
body {
|
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
min-height: 100vh;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
padding: 20px;
|
|
|
}
|
|
|
|
|
|
.chat-container {
|
|
|
width: 100%;
|
|
|
max-width: 800px;
|
|
|
height: 600px;
|
|
|
background: white;
|
|
|
border-radius: var(--border-radius);
|
|
|
box-shadow: var(--shadow);
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.chat-header {
|
|
|
background: var(--primary-color);
|
|
|
color: white;
|
|
|
padding: 20px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.chat-header h1 {
|
|
|
font-size: 1.5rem;
|
|
|
margin-bottom: 5px;
|
|
|
}
|
|
|
|
|
|
.chat-header p {
|
|
|
opacity: 0.9;
|
|
|
font-size: 0.9rem;
|
|
|
}
|
|
|
|
|
|
.chat-messages {
|
|
|
flex: 1;
|
|
|
padding: 20px;
|
|
|
overflow-y: auto;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 15px;
|
|
|
background: var(--secondary-color);
|
|
|
}
|
|
|
|
|
|
.message {
|
|
|
display: flex;
|
|
|
max-width: 80%;
|
|
|
animation: slideIn 0.3s ease-out;
|
|
|
}
|
|
|
|
|
|
.message.user {
|
|
|
align-self: flex-end;
|
|
|
}
|
|
|
|
|
|
.message.user .message-content {
|
|
|
background: var(--user-color);
|
|
|
color: white;
|
|
|
border-radius: var(--border-radius) var(--border-radius) 4px var(--border-radius);
|
|
|
}
|
|
|
|
|
|
.message.assistant {
|
|
|
align-self: flex-start;
|
|
|
}
|
|
|
|
|
|
.message.assistant .message-content {
|
|
|
background: white;
|
|
|
color: var(--text-primary);
|
|
|
border-radius: var(--border-radius) var(--border-radius) var(--border-radius) 4px;
|
|
|
border: 1px solid #e2e8f0;
|
|
|
}
|
|
|
|
|
|
.message.error .message-content {
|
|
|
background: var(--error-color);
|
|
|
color: white;
|
|
|
border-radius: var(--border-radius);
|
|
|
}
|
|
|
|
|
|
.message-content {
|
|
|
padding: 12px 16px;
|
|
|
box-shadow: var(--shadow);
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
.message-text {
|
|
|
display: block;
|
|
|
line-height: 1.5;
|
|
|
word-wrap: break-word;
|
|
|
}
|
|
|
|
|
|
.message-time {
|
|
|
display: block;
|
|
|
font-size: 0.75rem;
|
|
|
opacity: 0.7;
|
|
|
margin-top: 5px;
|
|
|
}
|
|
|
|
|
|
.chat-form {
|
|
|
padding: 20px;
|
|
|
border-top: 1px solid #e2e8f0;
|
|
|
background: white;
|
|
|
}
|
|
|
|
|
|
.input-group {
|
|
|
display: flex;
|
|
|
gap: 10px;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
#messageInput {
|
|
|
flex: 1;
|
|
|
padding: 12px 16px;
|
|
|
border: 2px solid #e2e8f0;
|
|
|
border-radius: var(--border-radius);
|
|
|
font-size: 1rem;
|
|
|
outline: none;
|
|
|
transition: border-color 0.2s ease;
|
|
|
}
|
|
|
|
|
|
#messageInput:focus {
|
|
|
border-color: var(--primary-color);
|
|
|
}
|
|
|
|
|
|
#messageInput:disabled {
|
|
|
background: #f8fafc;
|
|
|
opacity: 0.6;
|
|
|
cursor: not-allowed;
|
|
|
}
|
|
|
|
|
|
#sendBtn {
|
|
|
padding: 12px 24px;
|
|
|
background: var(--primary-color);
|
|
|
color: white;
|
|
|
border: none;
|
|
|
border-radius: var(--border-radius);
|
|
|
font-size: 1rem;
|
|
|
font-weight: 600;
|
|
|
cursor: pointer;
|
|
|
transition: background-color 0.2s ease;
|
|
|
min-width: 80px;
|
|
|
}
|
|
|
|
|
|
#sendBtn:hover:not(:disabled) {
|
|
|
background: #1d4ed8;
|
|
|
}
|
|
|
|
|
|
#sendBtn:disabled {
|
|
|
background: #94a3b8;
|
|
|
cursor: not-allowed;
|
|
|
}
|
|
|
|
|
|
@keyframes slideIn {
|
|
|
from {
|
|
|
opacity: 0;
|
|
|
transform: translateY(10px);
|
|
|
}
|
|
|
to {
|
|
|
opacity: 1;
|
|
|
transform: translateY(0);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Responsive design for mobile devices */
|
|
|
@media (max-width: 768px) {
|
|
|
body {
|
|
|
padding: 10px;
|
|
|
}
|
|
|
|
|
|
.chat-container {
|
|
|
height: calc(100vh - 20px);
|
|
|
border-radius: 8px;
|
|
|
}
|
|
|
|
|
|
.message {
|
|
|
max-width: 90%;
|
|
|
}
|
|
|
|
|
|
.input-group {
|
|
|
flex-direction: column;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
#messageInput {
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
#sendBtn {
|
|
|
width: 100%;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Accessibility improvements */
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
|
.message {
|
|
|
animation: none;
|
|
|
}
|
|
|
|
|
|
* {
|
|
|
transition: none !important;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Dark mode support */
|
|
|
@media (prefers-color-scheme: dark) {
|
|
|
.chat-container {
|
|
|
background: #1e293b;
|
|
|
color: #f1f5f9;
|
|
|
}
|
|
|
|
|
|
.chat-messages {
|
|
|
background: #0f172a;
|
|
|
}
|
|
|
|
|
|
.message.assistant .message-content {
|
|
|
background: #334155;
|
|
|
color: #f1f5f9;
|
|
|
border-color: #475569;
|
|
|
}
|
|
|
|
|
|
.chat-form {
|
|
|
background: #1e293b;
|
|
|
border-color: #475569;
|
|
|
}
|
|
|
|
|
|
#messageInput {
|
|
|
background: #334155;
|
|
|
color: #f1f5f9;
|
|
|
border-color: #475569;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**ทำความเข้าใจโครงสร้าง CSS:**
|
|
|
- **ใช้** คุณสมบัติแบบกำหนดเองของ CSS (ตัวแปร) เพื่อการออกแบบธีมที่สม่ำเสมอและการบำรุงรักษาที่ง่าย
|
|
|
- **ใช้** การจัดวางแบบ Flexbox เพื่อการออกแบบที่ตอบสนองและการจัดตำแหน่งที่เหมาะสม
|
|
|
- **รวม** การเคลื่อนไหวที่ราบรื่นสำหรับการปรากฏของข้อความโดยไม่ทำให้รบกวน
|
|
|
- **ให้** ความแตกต่างทางภาพระหว่างข้อความของผู้ใช้ การตอบกลับของ AI และสถานะข้อผิดพลาด
|
|
|
- **รองรับ** การออกแบบที่ตอบสนองซึ่งใช้งานได้ทั้งบนเดสก์ท็อปและอุปกรณ์มือถือ
|
|
|
- **คำนึงถึง** การเข้าถึงด้วยการลดการเคลื่อนไหวและอัตราส่วนความคมชัดที่เหมาะสม
|
|
|
- **รองรับ** โหมดกลางคืนตามการตั้งค่าระบบของผู้ใช้
|
|
|
|
|
|
### การตั้งค่า URL ของ Backend
|
|
|
|
|
|
ขั้นตอนสุดท้ายคือการอัปเดต `BASE_URL` ใน JavaScript ของคุณให้ตรงกับเซิร์ฟเวอร์ backend:
|
|
|
|
|
|
```javascript
|
|
|
// For local development
|
|
|
this.BASE_URL = "http://localhost:5000";
|
|
|
|
|
|
// For GitHub Codespaces (replace with your actual URL)
|
|
|
this.BASE_URL = "https://your-codespace-name-5000.app.github.dev";
|
|
|
```
|
|
|
|
|
|
**การกำหนด URL ของ backend:**
|
|
|
- **การพัฒนาในเครื่อง**: ใช้ `http://localhost:5000` หากคุณรันทั้ง frontend และ backend ในเครื่อง
|
|
|
- **Codespaces**: ค้นหา URL ของ backend ในแท็บ Ports หลังจากทำให้พอร์ต 5000 เป็นสาธารณะ
|
|
|
- **การใช้งานจริง**: แทนที่ด้วยโดเมนจริงของคุณเมื่อปรับใช้กับบริการโฮสติ้ง
|
|
|
|
|
|
> 💡 **เคล็ดลับการทดสอบ**: คุณสามารถทดสอบ backend ของคุณโดยไปที่ URL หลักในเบราว์เซอร์ คุณควรเห็นข้อความต้อนรับจากเซิร์ฟเวอร์ FastAPI ของคุณ
|
|
|
|
|
|
## การทดสอบและการปรับใช้
|
|
|
|
|
|
ตอนนี้คุณได้สร้างทั้งส่วน frontend และ backend แล้ว มาทดสอบว่าแอปพลิเคชันทำงานร่วมกันได้ดีและสำรวจตัวเลือกการปรับใช้เพื่อแบ่งปันผู้ช่วยแชทของคุณกับผู้อื่น
|
|
|
|
|
|
### ขั้นตอนการทดสอบในเครื่อง
|
|
|
|
|
|
ทำตามขั้นตอนเหล่านี้เพื่อทดสอบแอปพลิเคชันของคุณ:
|
|
|
|
|
|
```mermaid
|
|
|
graph TD
|
|
|
A[Start Backend Server] --> B[Configure Environment Variables]
|
|
|
B --> C[Test API Endpoints]
|
|
|
C --> D[Open Frontend in Browser]
|
|
|
D --> E[Test Chat Functionality]
|
|
|
E --> F[Debug Any Issues]
|
|
|
```
|
|
|
|
|
|
**กระบวนการทดสอบทีละขั้นตอน:**
|
|
|
|
|
|
1. **เริ่มเซิร์ฟเวอร์ backend ของคุณ**:
|
|
|
```bash
|
|
|
cd backend
|
|
|
source venv/bin/activate # or venv\Scripts\activate on Windows
|
|
|
python api.py
|
|
|
```
|
|
|
|
|
|
2. **ตรวจสอบว่า API ทำงาน**:
|
|
|
- เปิด `http://localhost:5000` ในเบราว์เซอร์ของคุณ
|
|
|
- คุณควรเห็นข้อความต้อนรับจากเซิร์ฟเวอร์ FastAPI ของคุณ
|
|
|
|
|
|
3. **เปิด frontend ของคุณ**:
|
|
|
- ไปที่ไดเรกทอรี frontend ของคุณ
|
|
|
- เปิด `index.html` ในเว็บเบราว์เซอร์ของคุณ
|
|
|
- หรือใช้ส่วนขยาย Live Server ของ VS Code เพื่อประสบการณ์การพัฒนาที่ดีกว่า
|
|
|
|
|
|
4. **ทดสอบฟังก์ชันการแชท**:
|
|
|
- พิมพ์ข้อความในช่องป้อนข้อมูล
|
|
|
- คลิก "ส่ง" หรือกด Enter
|
|
|
- ตรวจสอบว่า AI ตอบกลับอย่างเหมาะสม
|
|
|
- ตรวจสอบคอนโซลเบราว์เซอร์สำหรับข้อผิดพลาด JavaScript
|
|
|
|
|
|
### การแก้ไขปัญหาทั่วไป
|
|
|
|
|
|
| ปัญหา | อาการ | วิธีแก้ไข |
|
|
|
|-------|--------|-----------|
|
|
|
| **CORS Error** | Frontend ไม่สามารถเข้าถึง backend ได้ | ตรวจสอบว่า FastAPI CORSMiddleware ถูกตั้งค่าอย่างถูกต้อง |
|
|
|
| **API Key Error** | การตอบกลับ 401 Unauthorized | ตรวจสอบตัวแปรสภาพแวดล้อม `GITHUB_TOKEN` ของคุณ |
|
|
|
| **Connection Refused** | ข้อผิดพลาดเครือข่ายใน frontend | ตรวจสอบ URL ของ backend และเซิร์ฟเวอร์ Flask ว่ากำลังทำงานอยู่ |
|
|
|
| **No AI Response** | การตอบกลับว่างเปล่าหรือข้อผิดพลาด | ตรวจสอบบันทึก backend สำหรับปัญหาโควต้า API หรือการตรวจสอบสิทธิ์ |
|
|
|
|
|
|
**ขั้นตอนการแก้ไขปัญหาทั่วไป:**
|
|
|
- **ตรวจสอบ** คอนโซลเครื่องมือสำหรับนักพัฒนาในเบราว์เซอร์สำหรับข้อผิดพลาด JavaScript
|
|
|
- **ตรวจสอบ** แท็บเครือข่ายแสดงคำขอ API และการตอบกลับที่สำเร็จ
|
|
|
- **ตรวจสอบ** เอาต์พุตเทอร์มินัล backend สำหรับข้อผิดพลาด Python หรือปัญหา API
|
|
|
- **ยืนยัน** ตัวแปรสภาพแวดล้อมถูกโหลดและเข้าถึงได้อย่างถูกต้อง
|
|
|
|
|
|
## การท้าทาย GitHub Copilot Agent 🚀
|
|
|
|
|
|
ใช้โหมด Agent เพื่อทำการท้าทายต่อไปนี้:
|
|
|
|
|
|
**คำอธิบาย:** ปรับปรุงผู้ช่วยแชทโดยเพิ่มประวัติการสนทนาและการเก็บข้อความ การท้าทายนี้จะช่วยให้คุณเข้าใจวิธีการจัดการสถานะในแอปพลิเคชันแชทและการจัดเก็บข้อมูลเพื่อประสบการณ์ผู้ใช้ที่ดีขึ้น
|
|
|
|
|
|
**คำสั่ง:** ปรับเปลี่ยนแอปพลิเคชันแชทเพื่อรวมประวัติการสนทนาที่คงอยู่ระหว่างเซสชัน เพิ่มฟังก์ชันการบันทึกข้อความแชทลงใน local storage แสดงประวัติการสนทนาเมื่อหน้าโหลด และเพิ่มปุ่ม "Clear History" รวมถึงการแสดงสถานะการพิมพ์และการประทับเวลาเพื่อให้ประสบการณ์แชทดูสมจริงยิ่งขึ้น
|
|
|
|
|
|
เรียนรู้เพิ่มเติมเกี่ยวกับ [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) ที่นี่
|
|
|
|
|
|
## งาน: สร้างผู้ช่วย AI ส่วนตัวของคุณ
|
|
|
|
|
|
ตอนนี้คุณจะสร้างการใช้งานผู้ช่วย AI ของคุณเอง แทนที่จะทำซ้ำโค้ดในบทเรียน นี่เป็นโอกาสในการนำแนวคิดไปใช้ในขณะที่สร้างสิ่งที่สะท้อนถึงความสนใจและกรณีการใช้งานของคุณเอง
|
|
|
|
|
|
### ข้อกำหนดของโปรเจกต์
|
|
|
|
|
|
มาจัดตั้งโปรเจกต์ของคุณด้วยโครงสร้างที่สะอาดและเป็นระเบียบ:
|
|
|
|
|
|
```text
|
|
|
my-ai-assistant/
|
|
|
├── backend/
|
|
|
│ ├── api.py # Your FastAPI server
|
|
|
│ ├── llm.py # AI integration functions
|
|
|
│ ├── .env # Your secrets (keep this safe!)
|
|
|
│ └── requirements.txt # Python dependencies
|
|
|
├── frontend/
|
|
|
│ ├── index.html # Your chat interface
|
|
|
│ ├── app.js # The JavaScript magic
|
|
|
│ └── styles.css # Make it look amazing
|
|
|
└── README.md # Tell the world about your creation
|
|
|
```
|
|
|
|
|
|
### งานการพัฒนาแกนหลัก
|
|
|
|
|
|
**การพัฒนา Backend:**
|
|
|
- **ปรับ**โค้ด FastAPI ของเราให้เป็นของคุณเอง
|
|
|
- **สร้าง**บุคลิก AI ที่ไม่เหมือนใคร – อาจเป็นผู้ช่วยทำอาหารที่มีประโยชน์ คู่หูการเขียนเชิงสร้างสรรค์ หรือเพื่อนช่วยเรียน?
|
|
|
- **เพิ่ม**การจัดการข้อผิดพลาดที่มั่นคงเพื่อให้แอปของคุณไม่ล่มเมื่อเกิดปัญหา
|
|
|
- **เขียน**เอกสารที่ชัดเจนสำหรับใครก็ตามที่ต้องการเข้าใจว่า API ของคุณทำงานอย่างไร
|
|
|
|
|
|
**การพัฒนา Frontend:**
|
|
|
- **สร้าง**อินเทอร์เฟซแชทที่รู้สึกใช้งานง่ายและน่าต้อนรับ
|
|
|
- **เขียน** JavaScript ที่สะอาดและทันสมัยที่คุณภูมิใจที่จะแสดงให้ผู้พัฒนาอื่นๆ ดู
|
|
|
- **ออกแบบ**การตกแต่งที่สะท้อนบุคลิกของ AI ของคุณ – สนุกและมีสีสัน? สะอาดและเรียบง่าย? ขึ้นอยู่กับคุณทั้งหมด!
|
|
|
- **ตรวจสอบ**ให้แน่ใจว่ามันทำงานได้ดีทั้งบนโทรศัพท์และคอมพิวเตอร์
|
|
|
|
|
|
**ข้อกำหนดการปรับแต่งส่วนตัว:**
|
|
|
- **เลือก**ชื่อและบุคลิกที่ไม่เหมือนใครสำหรับผู้ช่วย AI ของคุณ – อาจเป็นสิ่งที่สะท้อนถึงความสนใจของคุณหรือปัญหาที่คุณต้องการแก้ไข
|
|
|
- **ปรับแต่ง**การออกแบบภาพให้ตรงกับบรรยากาศของผู้ช่วยของคุณ
|
|
|
- **เขียน**ข้อความต้อนรับที่น่าสนใจซึ่งทำให้ผู้คนอยากเริ่มแชท
|
|
|
- **ทดสอบ**ผู้ช่วยของคุณด้วยคำถามประเภทต่างๆ เพื่อดูว่ามันตอบสนองอย่างไร
|
|
|
|
|
|
### แนวคิดการปรับปรุง (ตัวเลือก)
|
|
|
|
|
|
ต้องการยกระดับโปรเจกต์ของคุณไปอีกขั้นหรือไม่? นี่คือแนวคิดสนุกๆ ที่คุณสามารถสำรวจได้:
|
|
|
|
|
|
| ฟีเจอร์ | คำอธิบาย | ทักษะที่คุณจะฝึกฝน |
|
|
|
|---------|-----------|---------------------|
|
|
|
| **ประวัติข้อความ** | จำการสนทนาแม้หลังจากรีเฟรชหน้า | การทำงานกับ localStorage, การจัดการ JSON |
|
|
|
| **สถานะการพิมพ์** | แสดง "AI กำลังพิมพ์..." ขณะรอการตอบกลับ | การเคลื่อนไหว CSS, การเขียนโปรแกรมแบบ async |
|
|
|
| **การประทับเวลา** | แสดงเวลาที่ส่งข้อความแต่ละข้อความ | การจัดรูปแบบวันที่/เวลา, การออกแบบ UX |
|
|
|
| **ส่งออกแชท** | ให้ผู้ใช้ดาวน์โหลดการสนทนาของพวกเขา | การจัดการไฟล์, การส่งออกข้อมูล |
|
|
|
| **การเปลี่ยนธีม** | สลับโหมดแสง/กลางคืน | ตัวแปร CSS, การตั้งค่าผู้ใช้ |
|
|
|
| **การป้อนด้วยเสียง** | เพิ่มฟังก์ชันการพูดเป็นข้อความ | Web APIs, การเข้าถึง |
|
|
|
|
|
|
### การทดสอบและเอกสาร
|
|
|
|
|
|
**การประกันคุณภาพ:**
|
|
|
- **ทดสอบ**แอปพลิเคชันของคุณด้วยประเภทอินพุตและกรณีขอบต่างๆ
|
|
|
- **ตรวจสอบ**การออกแบบที่ตอบสนองทำงานบนขนาดหน้าจอที่แตกต่างกัน
|
|
|
- **ตรวจสอบ**การเข้าถึงด้วยการนำทางด้วยแป้นพิมพ์และโปรแกรมอ่านหน้าจอ
|
|
|
- **ตรวจสอบ** HTML และ CSS สำหรับการปฏิบัติตามมาตรฐาน
|
|
|
|
|
|
**ข้อกำหนดเอกสาร:**
|
|
|
- **เขียน** README.md อธิบายโปรเจกต์ของคุณและวิธีการรัน
|
|
|
- **รวม**ภาพหน้าจอของอินเทอร์เฟซแชทของคุณในขณะทำงาน
|
|
|
- **เอกสาร**ฟีเจอร์หรือการปรับแต่งที่ไม่เหมือนใครที่คุณเพิ่ม
|
|
|
- **ให้**คำแนะนำการตั้งค่าที่ชัดเจนสำหรับนักพัฒนาคนอื่นๆ
|
|
|
|
|
|
### แนวทางการส่งงาน
|
|
|
|
|
|
**สิ่งที่ต้องส่ง:**
|
|
|
1. โฟลเดอร์โปรเจกต์ที่สมบูรณ์พร้อมโค้ดต้นฉบับทั้งหมด
|
|
|
2. README.md พร้อมคำอธิบายโปรเจกต์และคำแนะนำการตั้งค่า
|
|
|
3. ภาพหน้าจอที่แสดงผู้ช่วยแชทของคุณในขณะทำงาน
|
|
|
4. การสะท้อนสั้นๆ เกี่ยวกับสิ่งที่คุณเรียนรู้และความท้าทายที่คุณเผชิญ
|
|
|
|
|
|
**เกณฑ์การประเมิน:**
|
|
|
- **ฟังก์ชันการทำงาน**: ผู้ช่วยแชททำงานตามที่คาดไว้หรือไม่?
|
|
|
- **คุณภาพของโค้ด**: โค้ดมีการจัดระเบียบดี มีคำอธิบาย และดูแลรักษาได้หรือไม่?
|
|
|
- **การออกแบบ**: อินเทอร์เฟซดูน่าสนใจและใช้งานง่ายหรือไม่?
|
|
|
- **ความคิดสร้างสรรค์**: การใช้งานของคุณมีเอกลักษณ์และปรับแต่งได้มากแค่ไหน?
|
|
|
- **เอกสาร**: คำแนะนำการตั้งค่าชัดเจนและสมบูรณ์หรือไม่?
|
|
|
|
|
|
> 💡 **เคล็ดลับความสำเร็จ**: เริ่มต้นด้วยข้อกำหนดพื้นฐานก่อน จากนั้นเพิ่มการปรับปรุงเมื่อทุกอย่างทำงานได้ดี มุ่งเน้นไปที่การสร้างประสบการณ์หลักที่สมบูรณ์แบบก่อนเพิ่มฟีเจอร์ขั้นสูง
|
|
|
|
|
|
## วิธีแก้ไข
|
|
|
|
|
|
[Solution](./solution/README.md)
|
|
|
|
|
|
## การท้าทายเพิ่มเติม
|
|
|
|
|
|
พร้อมที่จะยกระดับผู้ช่วย AI ของคุณไปอีกขั้นหรือไม่? ลองทำการท้าทายขั้นสูงเหล่านี้ที่จะช่วยให้คุณเข้าใจการรวม AI และการพัฒนาเว็บในระดับลึกยิ่งขึ้น
|
|
|
|
|
|
### การปรับแต่งบุคลิกภาพ
|
|
|
|
|
|
ความมหัศจรรย์ที่แท้จริงเกิดขึ้นเมื่อคุณให้ผู้ช่วย AI ของคุณมีบุคลิกที่ไม่เหมือนใคร ทดลองกับคำสั่งระบบต่างๆ เพื่อสร้างผู้ช่วยเฉพาะทาง:
|
|
|
|
|
|
**ตัวอย่างผู้ช่วยมืออาชีพ:**
|
|
|
```python
|
|
|
call_llm(message, "You are a professional business consultant with 20 years of experience. Provide structured, actionable advice with specific steps and considerations.")
|
|
|
```
|
|
|
|
|
|
**ตัวอย่างผู้ช่วยเขียนเชิงสร้างสรรค์:**
|
|
|
```python
|
|
|
call_llm(message, "You are an enthusiastic creative writing coach. Help users develop their storytelling skills with imaginative prompts and constructive feedback.")
|
|
|
```
|
|
|
|
|
|
**ตัวอย่างที่ปรึกษาด้านเทคนิค:**
|
|
|
```python
|
|
|
call_llm(message, "You are a patient senior developer who explains complex programming concepts using simple analogies and practical examples.")
|
|
|
```
|
|
|
|
|
|
### การปรับปรุง Frontend
|
|
|
|
|
|
เปลี่ยนอินเทอร์เฟซแชทของคุณด้วยการปรับปรุงภาพและฟังก์ชันเหล่านี้:
|
|
|
|
|
|
**ฟีเจอร์ CSS ขั้นสูง:**
|
|
|
- **เพิ่ม**การเคลื่อนไหวและการเปลี่ยนข้อความที่ราบรื่น
|
|
|
- **เพิ่ม**การออกแบบฟองแชทแบบกำหนดเองด้วยรูปร่างและการไล่สี CSS
|
|
|
- **สร้าง**แอนิเมชันสถานะการพิมพ์สำหรับเมื่อ AI กำลัง "คิด"
|
|
|
- **ออกแบบ**ปฏิกิริยาอิโมจิหรือระบบการให้คะแนนข้อความ
|
|
|
|
|
|
**การปรับปรุง JavaScript:**
|
|
|
- **เพิ่ม**ทางลัดแป้นพิมพ์ (Ctrl+Enter เพื่อส่ง, Escape เพื่อเคลียร์อินพุต)
|
|
|
- **เพิ่ม**ฟังก์ชันการค้นหาและกรองข้อความ
|
|
|
- **สร้าง**ฟีเจอร์ส่งออกการสนทนา (ดาวน์โหลดเป็นข้อความหรือ JSON)
|
|
|
- **เพิ่ม**การบันทึกอัตโนมัติลงใน localStorage เพื่อป้องกันการสูญเสียข้อความ
|
|
|
|
|
|
### การรวม AI ขั้นสูง
|
|
|
|
|
|
**บุคลิกภาพ AI หลายตัว:**
|
|
|
- **สร้าง**เมนูแบบเลื่อนลงเพื่อสลับระหว่างบุคลิกภาพ AI ต่างๆ
|
|
|
- **บันทึก**บุคลิกภาพที่ผู้ใช้ชื่นชอบใน localStorage
|
|
|
- **เพิ่ม**การสลับบริบทที่รักษาการไหลของการสนทนา
|
|
|
|
|
|
**ฟีเจอร์การตอบกลับอัจฉริยะ:**
|
|
|
- **เพิ่ม**การรับรู้บริบทการสนทนา (AI จำข้อความก่อนหน้า)
|
|
|
- **เพิ่ม**คำแนะนำอัจฉริยะตามหัวข้อการสนทนา
|
|
|
- **สร้าง**ปุ่มตอบกลับด่วนสำหรับคำถามทั่วไป
|
|
|
|
|
|
> 🎯 **เป้าหมายการเรียนรู้**: การท้าทายเพิ่มเติมเหล่านี้ช่วยให้คุณเข้าใจรูปแบบการพัฒนาเว็บขั้นสูงและเทคนิคการรวม AI ที่ใช้ในแอปพลิเคชันระดับการผลิต
|
|
|
|
|
|
## สรุปและขั้นตอนถัดไป
|
|
|
|
|
|
ขอแสดงความยินดี! คุณได้สร้างผู้ช่วยแชทที่ขับเคลื่อนด้วย AI จากศูนย์สำเร็จแล้ว โปรเจกต์นี้ได้ให้คุณมีประสบการณ์จริงกับเทคโนโลยีการพัฒนาเว็บสมัยใหม่และการรวม AI – ทักษะที่มีคุณค่าเพิ่มขึ้นในโลกเทคโนโลยีปัจจุบัน
|
|
|
|
|
|
### สิ่งที่คุณได้ทำสำเร็จ
|
|
|
|
|
|
ตลอดบทเรียนนี้ คุณได้เชี่ยวชาญเทคโนโลยีและแนวคิดสำคัญหลายประการ:
|
|
|
|
|
|
**การพัฒนา Backend:**
|
|
|
- **รวม**กับ GitHub Models API เพื่อฟังก์ชัน AI
|
|
|
- **สร้าง** API แบบ RESTful โดยใช้ Flask พร้อมการจัดการข้อผิดพลาดที่เหมาะสม
|
|
|
- **เพิ่ม**การตรวจสอบสิทธิ์ที่ปลอดภัยโดยใช้ตัวแปรสภาพแวดล้อม
|
|
|
- **ตั้งค่า** CORS สำหรับคำขอข้ามต้นกำเนิดระหว่าง frontend และ backend
|
|
|
|
|
|
**การพัฒนา Frontend:**
|
|
|
- **สร้าง**อินเทอร์เฟซแชทที่ตอบสนองโดยใช้ HTML เชิงความหมาย
|
|
|
- **เขียน** JavaScript สมัยใหม่ด้วย async/await และสถาปัตยกรรมแบบคลาส
|
|
|
- **ออกแบบ**อินเทอร์เฟซผู้ใช้ที่น่าสนใจด้วย CSS Grid, Flexbox และการเคลื่อนไหว
|
|
|
- **เพิ่ม**ฟีเจอร์การเข้าถึงและหลักการออกแบบที่ตอบสนอง
|
|
|
|
|
|
**การรวมแบบ Full-Stack:**
|
|
|
- **เชื่อมต่อ** frontend และ backend ผ่านคำขอ API HTTP
|
|
|
- **จัดการ**การโต้ตอบของผู้ใช้แบบเรียลไทม์และการไหลของข้อมูลแบบอะซิงโครนัส
|
|
|
- **เพิ่ม**การจัดการข้อผิดพลาดและความคิดเห็นของผู้ใช้ทั่วทั้งแอปพลิเคชัน
|
|
|
- **ทดสอบ**เวิร์กโฟลว์แอปพลิเคชันทั้งหมดตั้งแต่การป้อนข้อมูลของผู้ใช้ไปจนถึงการ
|
|
|
- **การส่งต่อพอร์ต** สำหรับการทดสอบแอปพลิเคชันของคุณ
|
|
|
|
|
|
**สิ่งที่ Codespaces มอบให้:**
|
|
|
- **ขจัดปัญหา** การตั้งค่าและการกำหนดค่าของสภาพแวดล้อมในเครื่อง
|
|
|
- **มอบ** สภาพแวดล้อมการพัฒนาที่สม่ำเสมอในอุปกรณ์ต่าง ๆ
|
|
|
- **รวม** เครื่องมือและส่วนขยายที่ตั้งค่าไว้ล่วงหน้าสำหรับการพัฒนาเว็บ
|
|
|
- **เสนอ** การผสานรวมที่ราบรื่นกับ GitHub สำหรับการควบคุมเวอร์ชันและการทำงานร่วมกัน
|
|
|
|
|
|
> 🚀 **เคล็ดลับมือโปร**: Codespaces เหมาะอย่างยิ่งสำหรับการเรียนรู้และสร้างต้นแบบแอปพลิเคชัน AI เนื่องจากจัดการการตั้งค่าสภาพแวดล้อมที่ซับซ้อนทั้งหมดโดยอัตโนมัติ ทำให้คุณสามารถมุ่งเน้นไปที่การสร้างและการเรียนรู้แทนที่จะต้องแก้ไขปัญหาการตั้งค่า
|
|
|
|
|
|
---
|
|
|
|
|
|
**ข้อจำกัดความรับผิดชอบ**:
|
|
|
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้ |