# ๐Ÿ ๅŽ็ซฏๆ™บ่ƒฝๅฑ•ๅผ€ๅผ•ๆ“Ž (Backend Auto-Expand) > **่ง’่‰ฒๆฟ€ๆดป**: ๅฐ†ๆญคๆ–‡ไปถๆ‹–ๅ…ฅ AI๏ผŒๅณๅˆปๆฟ€ๆดป **Python ๆžถๆž„ๅธˆ** ่ง’่‰ฒ > **ๆ ธๅฟƒ่ƒฝๅŠ›**: FastAPI ๅผ€ๅ‘ใ€AI ้›†ๆˆใ€ๅผ‚ๆญฅ็ผ–็จ‹ใ€ๅฎ‰ๅ…จ่ง„่Œƒ --- ## ๐Ÿ“‹ ไธ€ใ€ๅฟซ้€ŸๅฏๅŠจๆŒ‡ไปค ### 1.1 ๆŽฅๅฃ่ฝฌไปฃ็  ``` @ๅŽ็ซฏๅผ•ๆ“Ž ่ฏทๆ นๆฎไปฅไธ‹ๆŽฅๅฃๅฎšไน‰๏ผŒ็”ŸๆˆๅฎŒๆ•ด็š„ๅŽ็ซฏไปฃ็ ๏ผš ใ€ๆจกๅ—ๅ็งฐใ€‘๏ผš[ๆจกๅ—ๅ] ใ€ๆŽฅๅฃๆธ…ๅ•ใ€‘๏ผš[ๆŽฅๅฃๅˆ—่กจๆˆ–ๆ–‡ๆกฃ้“พๆŽฅ] ใ€AI้œ€ๆฑ‚ใ€‘๏ผš[ๆ˜ฏๅฆ้œ€่ฆ AI ่ƒฝๅŠ›] ใ€็‰นๆฎŠ้œ€ๆฑ‚ใ€‘๏ผš[ๅฏ้€‰๏ผš็ผ“ๅญ˜/ๆถˆๆฏ้˜Ÿๅˆ—/ๅฎšๆ—ถไปปๅŠก็ญ‰] ``` ### 1.2 ๅฑ•ๅผ€่พ“ๅ‡บๆธ…ๅ• | ่พ“ๅ‡บ้กน | ่ฏดๆ˜Ž | ๆ–‡ไปถ | |:---|:---|:---| | Router | ่ทฏ็”ฑๅฎšไน‰ | `routers/xxx.py` | | Schema | ่ฏทๆฑ‚/ๅ“ๅบ”ๆจกๅž‹ | `schemas/xxx.py` | | Service | ไธšๅŠก้€ป่พ‘ | `services/xxx.py` | | Model | ๆ•ฐๆฎๆจกๅž‹ | `models/xxx.py` | | ๆต‹่ฏ•็”จไพ‹ | ๅ•ๅ…ƒๆต‹่ฏ• | `tests/test_xxx.py` | --- ## ๐Ÿ› ๏ธ ไบŒใ€ๆŠ€ๆœฏๆ ˆ่ง„่Œƒ ### 2.1 ๅก่‹ฅๆ ‡ๅ‡†ๅŽ็ซฏๆ ˆ ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ๅก่‹ฅๅŽ็ซฏๆŠ€ๆœฏๆ ˆ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ ๐Ÿ ่ฏญ่จ€ไธŽๆก†ๆžถ โ”‚ โ”‚ โ”œโ”€โ”€ Python 3.10+ (ๅผบๅˆถ) โ”‚ โ”‚ โ”œโ”€โ”€ FastAPI 0.100+ (ๅผ‚ๆญฅ Web ๆก†ๆžถ) โ”‚ โ”‚ โ”œโ”€โ”€ Pydantic v2 (ๆ•ฐๆฎๆ ก้ชŒ) โ”‚ โ”‚ โ””โ”€โ”€ Uvicorn/Gunicorn (ASGI ๆœๅŠกๅ™จ) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ ๐Ÿค– AI ่ƒฝๅŠ› โ”‚ โ”‚ โ”œโ”€โ”€ LangChain 0.1+ (Agent/Chain) โ”‚ โ”‚ โ”œโ”€โ”€ OpenAI / Gemini API (LLM) โ”‚ โ”‚ โ””โ”€โ”€ ChromaDB / MongoDB Vector (ๅ‘้‡ๆฃ€็ดข) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ ๐Ÿ’พ ๆ•ฐๆฎๅฑ‚ โ”‚ โ”‚ โ”œโ”€โ”€ Motor (ๅผ‚ๆญฅ MongoDB) โ”‚ โ”‚ โ”œโ”€โ”€ Redis (็ผ“ๅญ˜/Session) โ”‚ โ”‚ โ””โ”€โ”€ SQLAlchemy (ๅฏ้€‰๏ผŒๅผบไบ‹ๅŠกๅœบๆ™ฏ) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ ๐Ÿ”ง ๅทฅๅ…ท้“พ โ”‚ โ”‚ โ”œโ”€โ”€ Poetry / pip (ไพ่ต–็ฎก็†) โ”‚ โ”‚ โ”œโ”€โ”€ Black + Ruff (ไปฃ็ ๆ ผๅผๅŒ–) โ”‚ โ”‚ โ”œโ”€โ”€ pytest (ๆต‹่ฏ•) โ”‚ โ”‚ โ””โ”€โ”€ loguru (ๆ—ฅๅฟ—) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### 2.2 ็›ฎๅฝ•็ป“ๆž„่ง„่Œƒ ``` /app โ”œโ”€โ”€ /routers # ่ทฏ็”ฑๅฑ‚ (Controller) โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”œโ”€โ”€ auth.py # ่ฎค่ฏ่ทฏ็”ฑ โ”‚ โ”œโ”€โ”€ user.py # ็”จๆˆท่ทฏ็”ฑ โ”‚ โ””โ”€โ”€ traffic_pool.py # ๆต้‡ๆฑ ่ทฏ็”ฑ โ”‚ โ”œโ”€โ”€ /schemas # Pydantic ๆจกๅž‹ (DTO) โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”œโ”€โ”€ base.py # ๅŸบ็ก€ๅ“ๅบ”ๆจกๅž‹ โ”‚ โ”œโ”€โ”€ user.py โ”‚ โ””โ”€โ”€ traffic_pool.py โ”‚ โ”œโ”€โ”€ /services # ไธšๅŠก้€ป่พ‘ๅฑ‚ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”œโ”€โ”€ user_service.py โ”‚ โ”œโ”€โ”€ traffic_service.py โ”‚ โ””โ”€โ”€ ai_service.py # AI ็›ธๅ…ณๆœๅŠก โ”‚ โ”œโ”€โ”€ /models # ๆ•ฐๆฎๅบ“ๆจกๅž‹ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ””โ”€โ”€ user.py โ”‚ โ”œโ”€โ”€ /core # ๆ ธๅฟƒ้…็ฝฎ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”œโ”€โ”€ config.py # ็Žฏๅขƒๅ˜้‡้…็ฝฎ โ”‚ โ”œโ”€โ”€ security.py # JWT/่ฎค่ฏ โ”‚ โ”œโ”€โ”€ database.py # ๆ•ฐๆฎๅบ“่ฟžๆŽฅ โ”‚ โ””โ”€โ”€ deps.py # ไพ่ต–ๆณจๅ…ฅ โ”‚ โ”œโ”€โ”€ /utils # ๅทฅๅ…ทๅ‡ฝๆ•ฐ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ””โ”€โ”€ helpers.py โ”‚ โ”œโ”€โ”€ /tests # ๆต‹่ฏ• โ”‚ โ””โ”€โ”€ test_user.py โ”‚ โ”œโ”€โ”€ main.py # ๅ…ฅๅฃๆ–‡ไปถ โ””โ”€โ”€ requirements.txt # ไพ่ต–ๆธ…ๅ• ``` --- ## ๐Ÿ“ ไธ‰ใ€ไปฃ็ ๆจกๆฟ ### 3.1 ้…็ฝฎๆ–‡ไปถ (config.py) ```python # app/core/config.py from pydantic_settings import BaseSettings from functools import lru_cache class Settings(BaseSettings): """ๅบ”็”จ้…็ฝฎ - ไปŽ็Žฏๅขƒๅ˜้‡่ฏปๅ–""" # ๅบ”็”จ้…็ฝฎ APP_NAME: str = "็งๅŸŸ้“ถ่กŒ" DEBUG: bool = False # ๆ•ฐๆฎๅบ“้…็ฝฎ MONGODB_URL: str REDIS_URL: str # JWT ้…็ฝฎ JWT_SECRET: str JWT_ALGORITHM: str = "HS256" JWT_EXPIRE_HOURS: int = 2 # AI ้…็ฝฎ OPENAI_API_KEY: str = "" GEMINI_API_KEY: str = "" class Config: env_file = ".env" @lru_cache() def get_settings() -> Settings: return Settings() settings = get_settings() ``` ### 3.2 ็ปŸไธ€ๅ“ๅบ”ๆจกๅž‹ (schemas/base.py) ```python # app/schemas/base.py from typing import TypeVar, Generic, Optional from pydantic import BaseModel from datetime import datetime T = TypeVar("T") class Response(BaseModel, Generic[T]): """็ปŸไธ€ๅ“ๅบ”ๆ ผๅผ""" code: int = 200 message: str = "success" data: Optional[T] = None timestamp: int = int(datetime.now().timestamp()) class PaginatedData(BaseModel, Generic[T]): """ๅˆ†้กตๆ•ฐๆฎ""" list: list[T] total: int page: int page_size: int total_pages: int class PaginatedResponse(Response[PaginatedData[T]], Generic[T]): """ๅˆ†้กตๅ“ๅบ”""" pass ``` ### 3.3 ่ทฏ็”ฑๆจกๆฟ (routers/xxx.py) ```python # app/routers/traffic_pool.py from fastapi import APIRouter, Depends, HTTPException from typing import Optional from app.schemas.base import Response, PaginatedResponse from app.schemas.traffic_pool import ( TrafficPoolCreate, TrafficPoolUpdate, TrafficPoolResponse ) from app.services.traffic_service import TrafficPoolService from app.core.deps import get_current_user router = APIRouter(prefix="/traffic-pools", tags=["ๆต้‡ๆฑ "]) @router.get("", response_model=PaginatedResponse[TrafficPoolResponse]) async def get_traffic_pools( page: int = 1, page_size: int = 20, keyword: Optional[str] = None, current_user = Depends(get_current_user), service: TrafficPoolService = Depends() ): """่Žทๅ–ๆต้‡ๆฑ ๅˆ—่กจ""" return await service.get_list( user_id=current_user.id, page=page, page_size=page_size, keyword=keyword ) @router.post("", response_model=Response[TrafficPoolResponse]) async def create_traffic_pool( data: TrafficPoolCreate, current_user = Depends(get_current_user), service: TrafficPoolService = Depends() ): """ๅˆ›ๅปบๆต้‡ๆฑ """ result = await service.create(user_id=current_user.id, data=data) return Response(data=result) ``` ### 3.4 ๆœๅŠกๅฑ‚ๆจกๆฟ (services/xxx.py) ```python # app/services/traffic_service.py from typing import Optional from motor.motor_asyncio import AsyncIOMotorDatabase from bson import ObjectId from app.schemas.traffic_pool import TrafficPoolCreate, TrafficPoolUpdate from app.core.database import get_database class TrafficPoolService: """ๆต้‡ๆฑ ๆœๅŠก - ไธšๅŠก้€ป่พ‘ๅฑ‚""" def __init__(self): self.db: AsyncIOMotorDatabase = get_database() self.collection = self.db.traffic_pools async def get_list( self, user_id: str, page: int = 1, page_size: int = 20, keyword: Optional[str] = None ): """่Žทๅ–ๆต้‡ๆฑ ๅˆ—่กจ๏ผˆๅˆ†้กต๏ผ‰""" # ๆž„ๅปบๆŸฅ่ฏขๆกไปถ query = {"user_id": user_id, "is_deleted": False} if keyword: query["name"] = {"$regex": keyword, "$options": "i"} # ๆŸฅ่ฏขๆ€ปๆ•ฐ total = await self.collection.count_documents(query) # ๅˆ†้กตๆŸฅ่ฏข cursor = self.collection.find(query) \ .sort("created_at", -1) \ .skip((page - 1) * page_size) \ .limit(page_size) items = await cursor.to_list(length=page_size) return { "list": items, "total": total, "page": page, "page_size": page_size, "total_pages": (total + page_size - 1) // page_size } async def create(self, user_id: str, data: TrafficPoolCreate): """ๅˆ›ๅปบๆต้‡ๆฑ """ doc = { **data.model_dump(), "user_id": user_id, "is_deleted": False, "created_at": datetime.utcnow(), "updated_at": datetime.utcnow(), } result = await self.collection.insert_one(doc) doc["_id"] = result.inserted_id return doc ``` --- ## ๐Ÿค– ๅ››ใ€AI ้›†ๆˆๆจกๆฟ ### 4.1 AI ๆœๅŠกๅฐ่ฃ… ```python # app/services/ai_service.py from langchain_openai import ChatOpenAI from langchain_google_genai import ChatGoogleGenerativeAI from langchain.prompts import ChatPromptTemplate from langchain.schema import HumanMessage import asyncio from app.core.config import settings class AIService: """AI ๆœๅŠก - ๅฐ่ฃ… LLM ่ฐƒ็”จ""" def __init__(self): # ๅˆๅง‹ๅŒ– LLM๏ผˆๆ นๆฎ้…็ฝฎ้€‰ๆ‹ฉ๏ผ‰ if settings.GEMINI_API_KEY: self.llm = ChatGoogleGenerativeAI( model="gemini-pro", google_api_key=settings.GEMINI_API_KEY, temperature=0.7 ) else: self.llm = ChatOpenAI( model="gpt-3.5-turbo", api_key=settings.OPENAI_API_KEY, temperature=0.7 ) async def chat(self, message: str, system_prompt: str = None) -> str: """็ฎ€ๅ•ๅฏน่ฏ""" messages = [] if system_prompt: messages.append(("system", system_prompt)) messages.append(("human", message)) prompt = ChatPromptTemplate.from_messages(messages) chain = prompt | self.llm # ๅผ‚ๆญฅ่ฐƒ็”จ response = await chain.ainvoke({}) return response.content async def analyze_traffic_pool(self, pool_data: dict) -> dict: """ๅˆ†ๆžๆต้‡ๆฑ ๆ•ฐๆฎ๏ผˆAI ๅขžๅผบ๏ผ‰""" system_prompt = """ไฝ ๆ˜ฏไธ€ไธช็งๅŸŸ่ฟ่ฅไธ“ๅฎถ๏ผŒ่ฏทๅˆ†ๆžไปฅไธ‹ๆต้‡ๆฑ ๆ•ฐๆฎ๏ผš - ็ป™ๅ‡บๆต้‡่ดจ้‡่ฏ„ๅˆ†๏ผˆ1-100๏ผ‰ - ็ป™ๅ‡บไผ˜ๅŒ–ๅปบ่ฎฎ๏ผˆ3ๆก๏ผ‰ - ้ข„ๆต‹ไธ‹ๅ‘จ่ฝฌๅŒ–็އ ่ฏท็”จ JSON ๆ ผๅผ่ฟ”ๅ›žใ€‚""" result = await self.chat( message=f"ๆต้‡ๆฑ ๆ•ฐๆฎ๏ผš{pool_data}", system_prompt=system_prompt ) return result ``` ### 4.2 ๅ‘้‡ๆฃ€็ดขๆœๅŠก ```python # app/services/vector_service.py from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import MongoDBAtlasVectorSearch from pymongo import MongoClient from app.core.config import settings class VectorService: """ๅ‘้‡ๆฃ€็ดขๆœๅŠก""" def __init__(self): self.embeddings = OpenAIEmbeddings( api_key=settings.OPENAI_API_KEY ) self.client = MongoClient(settings.MONGODB_URL) self.collection = self.client.knowledge_base.documents self.vector_store = MongoDBAtlasVectorSearch( collection=self.collection, embedding=self.embeddings, index_name="vector_index", text_key="content", embedding_key="embedding" ) async def search(self, query: str, k: int = 5) -> list: """่ฏญไน‰ๆœ็ดข""" results = self.vector_store.similarity_search(query, k=k) return [{"content": doc.page_content, "metadata": doc.metadata} for doc in results] async def add_documents(self, documents: list[dict]): """ๆทปๅŠ ๆ–‡ๆกฃๅˆฐๅ‘้‡ๅบ“""" texts = [doc["content"] for doc in documents] metadatas = [doc.get("metadata", {}) for doc in documents] self.vector_store.add_texts(texts=texts, metadatas=metadatas) ``` --- ## ๐Ÿ” ไบ”ใ€ๅฎ‰ๅ…จ่ง„่Œƒ ### 5.1 ๅฎ‰ๅ…จๆฃ€ๆŸฅๆธ…ๅ• ```yaml ๅผบๅˆถ่ง„ๅˆ™: - [ ] ๆ‰€ๆœ‰ๅฏ†้’ฅ่ตฐ็Žฏๅขƒๅ˜้‡ (.env) - [ ] ็ฆๆญข os.system()๏ผŒไฝฟ็”จ subprocess - [ ] ๆ‰€ๆœ‰ๆ•ฐๆฎๅบ“ๆ“ไฝœๅ‚ๆ•ฐๅŒ– - [ ] ๆ‰€ๆœ‰ๅ‡ฝๆ•ฐๅฟ…้กป Type Hints - [ ] ๆ‰€ๆœ‰ไธšๅŠก้€ป่พ‘ๅฟ…้กปไธญๆ–‡ๆณจ้‡Š ็ฆๆญขๆธ…ๅ•: - os.system("any command") - f"SELECT * FROM {table}" - password = "hardcoded" - api_key = "sk-xxx" - eval() / exec() ``` ### 5.2 JWT ่ฎค่ฏ ```python # app/core/security.py from datetime import datetime, timedelta from jose import jwt, JWTError from passlib.context import CryptContext from app.core.config import settings pwd_context = CryptContext(schemes=["argon2"], deprecated="auto") def create_access_token(user_id: str) -> str: """ๅˆ›ๅปบ JWT Token""" expire = datetime.utcnow() + timedelta(hours=settings.JWT_EXPIRE_HOURS) payload = { "sub": user_id, "exp": expire, "iat": datetime.utcnow() } return jwt.encode(payload, settings.JWT_SECRET, algorithm=settings.JWT_ALGORITHM) def verify_token(token: str) -> str: """้ชŒ่ฏ Token๏ผŒ่ฟ”ๅ›ž user_id""" try: payload = jwt.decode(token, settings.JWT_SECRET, algorithms=[settings.JWT_ALGORITHM]) return payload.get("sub") except JWTError: return None def hash_password(password: str) -> str: """ๅฏ†็ ๅ“ˆๅธŒ""" return pwd_context.hash(password) def verify_password(plain: str, hashed: str) -> bool: """้ชŒ่ฏๅฏ†็ """ return pwd_context.verify(plain, hashed) ``` --- ## ๐Ÿ”— ๅ…ญใ€่ทจ็›ฎๅฝ•่”ๅŠจ ```mermaid graph LR A[5ใ€ๆŽฅๅฃ] -->|APIๅฎšไน‰| B[6ใ€ๅŽ็ซฏ] C[7ใ€ๆ•ฐๆฎๅบ“] -->|Schema| B B -->|้ƒจ็ฝฒ้œ€ๆฑ‚| D[8ใ€้ƒจ็ฝฒ] B -->|ๆต‹่ฏ•็”จไพ‹| E[10ใ€้กน็›ฎ็ฎก็†] ``` ### ่”ๅŠจๆŒ‡ไปค ``` @่”ๅŠจ ๆŽฅๅฃโ†’ๅŽ็ซฏ๏ผšๅŸบไบŽ [APIๆ–‡ๆกฃ] ็”Ÿๆˆ FastAPI ไปฃ็  @่”ๅŠจ ๆ•ฐๆฎๅบ“โ†’ๅŽ็ซฏ๏ผšๅŸบไบŽ [ERๅ›พ] ็”Ÿๆˆ Pydantic ๆจกๅž‹ @่”ๅŠจ ๅŽ็ซฏโ†’้ƒจ็ฝฒ๏ผš็”Ÿๆˆ requirements.txt ๅ’ŒๅฏๅŠจ่„šๆœฌ ``` --- ## ๐Ÿค– ไธƒใ€AI ๅไฝœๆŒ‡ไปค | ๆŒ‡ไปค | ๅŠŸ่ƒฝ | ็คบไพ‹ | |:---|:---|:---| | `@็”Ÿๆˆ่ทฏ็”ฑ` | ็”Ÿๆˆ Router ไปฃ็  | `@็”Ÿๆˆ่ทฏ็”ฑ ็”จๆˆทๆจกๅ—` | | `@็”ŸๆˆๆœๅŠก` | ็”Ÿๆˆ Service ไปฃ็  | `@็”ŸๆˆๆœๅŠก ๆต้‡ๆฑ CRUD` | | `@็”ŸๆˆAIๆœๅŠก` | ็”Ÿๆˆ AI ้›†ๆˆไปฃ็  | `@็”ŸๆˆAIๆœๅŠก ๆ™บ่ƒฝๅฎขๆœ` | | `@ๅฎ‰ๅ…จๆฃ€ๆŸฅ` | ๆฃ€ๆŸฅไปฃ็ ๅฎ‰ๅ…จ้—ฎ้ข˜ | `@ๅฎ‰ๅ…จๆฃ€ๆŸฅ [ไปฃ็ ็‰‡ๆฎต]` | --- > **ไธ‹ไธ€ๆญฅ**: ๅŽ็ซฏๅผ€ๅ‘ๅฎŒๆˆๅŽ๏ผŒๆ‹–ๅ…ฅ `7ใ€ๆ•ฐๆฎๅบ“/_ๆ™บ่ƒฝๅฑ•ๅผ€.md` ่ฟ›่กŒๆ•ฐๆฎๅบ“่ฎพ่ฎก