Lập Trình AI với Python & OpenAI API

Hướng dẫn toàn diện từ cơ bản đến nâng cao: Text, JSON & Function Calling

Menu Nội Dung Học

1. Chuẩn bị

Khởi tạo project Python, cài đặt package, lấy và bảo mật API Key.

2. API Cơ bản

Hiểu về Roles (System, User, Assistant), gửi request và tinh chỉnh Parameters.

3. API Nâng cao

Xử lý dữ liệu định dạng JSON Schema (Structured Outputs) và Function Calling.

4. Thực hành & Project

Bài tập vận dụng từng phần và Project cuối khóa tổng hợp kiến thức.

Tài Liệu Tham Khảo

  • OpenAI API Documentation: Nguồn tài liệu chính thức, cung cấp định nghĩa chi tiết về mọi endpoint và parameters (platform.openai.com/docs).
  • Thư viện openai-python: Repository Github chính thức của OpenAI hỗ trợ Python, có rất nhiều ví dụ mẫu và hướng dẫn cập nhật SDK.
  • Tài liệu Pydantic: Cực kỳ quan trọng để định nghĩa Data Models khi làm việc với tính năng Structured Outputs (đảm bảo AI trả về JSON chuẩn xác 100%).
  • Python Official Docs: Tài liệu cơ bản về môi trường ảo (.venv), xử lý chuỗi và cấu trúc dữ liệu trong Python.

Đăng Ký OpenAI API Key

  • Bước 1: Truy cập vào platform.openai.com và đăng nhập/tạo tài khoản.
  • Bước 2: Vào mục Dashboard > API Keys (bên thanh menu trái).
  • Bước 3: Click "Create new secret key". Đặt tên cho key (ví dụ: "Python Project Key").
  • Bước 4: Copy key vừa tạo (bắt đầu bằng sk-proj-...). Lưu ý key chỉ hiện ra một lần duy nhất.
  • Bảo mật: Tuyệt đối không dán trực tiếp key vào code hoặc push lên Github. Chúng ta sẽ lưu nó trong file .env.
OpenAI API developer dashboard technology concept

Tạo Project Python (Step-by-Step)

1. Khởi tạo môi trường ảo (.venv):
Mở Terminal/CMD tại thư mục project và chạy lệnh:

python -m venv .venv
# Kích hoạt (Windows): .venv\Scripts\activate
# Kích hoạt (Mac/Linux): source .venv/bin/activate

2. Cài đặt các Package cần thiết:

pip install openai python-dotenv pydantic

3. Thiết lập biến môi trường (.env):
Tạo file .env ngang hàng với code và thêm:

OPENAI_API_KEY=sk-proj-xxyyzz...

4. Lưu lại thông tin package đã cài đặt:

# Lưu thông tin package vào requirements.txt 
pip freeze > requirements.txt
# Sau này khi deploy hoặc chuyển máy, chỉ cần chạy:
pip install -r requirements.txt

Giải thích chi tiết:

  • Sử dụng .venv giúp thư mục môi trường được ẩn đi, tránh gây rối mắt trong cấu trúc project.
  • openai: SDK chính thức để tương tác với API.
  • python-dotenv: Tự động load API Key từ file .env vào chương trình, giúp code bảo mật hơn.
  • pydantic: Dùng để định nghĩa kiểu dữ liệu JSON Schema ở phần nâng cao.

Hiểu Về Các Roles (Vai Trò)

Khi giao tiếp với AI, hội thoại được cấu trúc dưới dạng một danh sách các "tin nhắn" (messages). Mỗi tin nhắn phải thuộc về một trong 3 vai trò sau:

System/Instructions

Dùng để thiết lập bối cảnh, nhân cách và các quy tắc cốt lõi cho AI. Thường đặt ở đầu danh sách.

VD: "Bạn là giáo viên Toán chuyên nghiệp."

User

Câu hỏi hoặc mệnh lệnh xuất phát từ người dùng cuối (chúng ta). AI sẽ đọc và trả lời những yêu cầu này.

VD: "Giải thích cho tôi định lý Pytago là gì?"

Assistant

Câu trả lời sinh ra từ mô hình AI. Ta có thể tự chèn các tin nhắn này để định hướng AI phản hồi tiếp theo.

VD: "Định lý Pytago phát biểu rằng..."

Gửi & Nhận Response Thông Thường (Text)

Đoạn code bên phải minh họa cách tối giản nhất để kết nối tới OpenAI API và nhận về một câu trả lời dạng văn bản.

  • load_dotenv() tự động tìm file .env và đưa OPENAI_API_KEY vào hệ thống.
  • OpenAI() khởi tạo client. Mặc định nó sẽ tự tìm biến API Key.
  • Hàm create(...) là hàm chính để gọi model.
  • Response trả về là một Object phức tạp. Văn bản tiện dùng nhất nằm ở response.output_text.
import os
from openai import OpenAI
from dotenv import load_dotenv

# Load API Key từ file .env
load_dotenv()

# Khởi tạo OpenAI client
client = OpenAI() 

# Gửi Request
response = client.responses.create(
    model="gpt-5-mini",
    instructions="Bạn là trợ lý.",
    input=[
        {"role": "user", "content": "Xin chào!"}
    ]
)

# In ra phản hồi (Text)
print(response.output_text)

Một Số Options (Tham Số) Cần Thiết

Khi gọi hàm create(), bạn có thể truyền thêm các tham số để kiểm soát đầu ra của AI:

  • Temperature (0.0 - 2.0): Kiểm soát tính sáng tạo. Số thấp (0.1) ra kết quả logic, ổn định. Số cao (0.8+) cho kết quả sáng tạo, tự nhiên hơn.
  • Top_p (0.0 - 1.0): "Nucleus sampling". Lọc các token tiềm năng dựa trên tổng xác suất. Thay vì ngẫu nhiên toàn cục, AI chỉ chọn trong tập từ vựng hữu hạn.
    *Khuyến nghị từ OpenAI: Chỉ nên thay đổi 1 trong 2 tham số (Temperature hoặc Top_p), không đổi cả hai cùng lúc.
  • Max Output Tokens: Giới hạn độ dài output, giúp kiểm soát chi phí API và tránh AI sinh ra văn bản quá dài không cần thiết.
# Gửi request với các tham số tùy chỉnh
response = client.responses.create(
    model="gpt-5.2",
    input="Kể một câu chuyện ngắn.",
    # Tăng tính sáng tạo của câu chuyện
    temperature=0.8,  
    # Giữ mặc định vì đã chỉnh temperature
    top_p=1.0,        
    # Giới hạn sinh ra khoảng ~350 chữ
    max_output_tokens=500    
)

print(response.output_text)

Bài Tập Vận Dụng 1: CLI Chatbot

Yêu cầu: Viết một chương trình Python chạy trên Terminal cho phép người dùng chat liên tục với AI. Chương trình phải có "bộ nhớ" (nhớ được những câu hỏi và trả lời trước đó). Gõ "exit" để thoát.

Cách Giải Bài Tập 1 (Chatbot Có Bộ Nhớ)

Giải thích thuật toán:

  • AI vốn không có "bộ nhớ". Để AI nhớ ngữ cảnh, ta phải gửi lại toàn bộ lịch sử chat trong mỗi request.
  • Tạo một List messages khởi đầu với vai trò system.
  • Sử dụng vòng lặp while True để liên tục nhận input.
  • Mỗi khi User nhập, dùng append() thêm vào messages với role user.
  • Nhận phản hồi từ AI, tiếp tục dùng append() thêm vào với role assistant.
import openai
from dotenv import load_dotenv

load_dotenv()
# Khởi tạo bộ nhớ (lịch sử hội thoại)
messages = []
system_prompt = "Bạn là trợ lý AI trả lời ngắn gọn, dễ hiểu."

while True:
    user_input = input("Bạn: ")
    if user_input.lower() == "exit": 
        print("Tạm biệt!"); break
    
    # Thêm câu hỏi vào lịch sử
    messages.append({"role": "user", "content": user_input})
    
    response = openai.responses.create(
        model="gpt-5-mini", input=messages, instructions=system_prompt
    )
    reply = response.output_text
    print("AI: " + reply)
    
    # Quan trọng: Thêm câu trả lời vào lịch sử
    messages.append({"role": "assistant", "content": reply})

Gửi & Nhận Response Dạng JSON (Cơ Bản)

Trong thực tế, ta thường cần AI trả về dữ liệu có cấu trúc (JSON) thay vì text thuần để dễ dàng xử lý bằng code (ví dụ: lưu vào database).

Cách tiếp cận cơ bản:

  • Dùng text={"format": {"type": "json_object"}} để yêu cầu mô hình trả về JSON hợp lệ.
  • Bắt buộc: Phải ra lệnh rõ trong Prompt yêu cầu AI "trả về định dạng JSON". Nếu không API sẽ báo lỗi.
  • Tuy nhiên, cách này chỉ đảm bảo trả về JSON hợp lệ, không đảm bảo đúng 100% cấu trúc/keys mà bạn cần.
response = client.responses.create(
    model="gpt-5-mini",
    instructions="Bạn là một API. Hãy trả về JSON.",
    # Ép kiểu dữ liệu trả về thành JSON Object
    text={ "format": { "type": "json_object" } },
    input="Cho tôi JSON tên 2 loại trái cây đỏ ."
)

import json
json_str = response.output_text
data = json.loads(json_str)

print(data) 
# KQ: {'fruits': ['táo', 'dâu tây']}

Gửi & Nhận Response Dạng JSON (Nâng Cao)

Tính năng Structured Outputs đảm bảo 100% AI trả về JSON khớp đúng với cấu trúc (Schema) bạn đã định nghĩa trước.

  • Dùng thư viện Pydantic để định nghĩa Model cấu trúc dữ liệu.
  • Sử dụng method client.responses.parse để parse kết quả theo schema.
  • Truyền Model vào tham số text_format.
  • Kết quả trả về không cần json.loads, .output_parsed sẽ tự động build object Python cho bạn.
import openai
from pydantic import BaseModel
from dotenv import load_dotenv

load_dotenv()
# Định nghĩa Schema (Cấu trúc mong muốn)
class UserInfo(BaseModel):
    name: str
    age: int

# Sử dụng .parse thay vì .create
response = openai.responses.parse(
    model="gpt-5-mini",
    input="Tôi tên Nam, 25 tuổi.",
    text_format=UserInfo, # Gắn schema vào
)

# Nhận object trực tiếp
user = response.output_parsed
print(user.name) # Output: Nam
print(user.age)  # Output: 25

Function Calling (Lý Thuyết)

Function Calling là gì?

AI bị giới hạn bởi dữ liệu quá khứ và không thể tự thao tác với thế giới thực. Function Calling (hay Tool Calling) là cung cấp cho AI danh sách các "công cụ" (hàm Python) để nó tự chọn gọi khi cần thiết.


Khi nào cần dùng?

  • Truy xuất dữ liệu thời gian thực: Gọi API thời tiết, giá chứng khoán, tin tức mới nhất.
  • Tương tác với Cơ sở dữ liệu: Lấy thông tin khách hàng từ DB SQL/NoSQL nội bộ.
  • Thực thi hành động: Gửi email, nhắn tin Slack, lưu file.

*Lưu ý: Mô hình KHÔNG tự chạy hàm. Nó chỉ phân tích và trả về "Yêu cầu gọi hàm X với tham số Y". Code Python của bạn mới là nơi thực thi!

API function calling integration concept light theme

Function Calling (Quy Trình Thực Hiện)

Định Nghĩa Tools

Khai báo tools theo JSON Schema với type/name/description/parameters. Nên bật strict: true để mô hình bám schema tốt hơn.

Gửi Request

Gửi input của user cùng mảng tools bằng client.responses.create() để mô hình quyết định có gọi hàm hay không.

AI Phân Tích & Phản Hồi

Duyệt response.output và lấy các item có type="function_call". Trích xuất name, call_id, arguments.

Thực Thi (Local)

Code Python của bạn chạy hàm thực tế bằng tham số đã parse từ arguments. Lưu ý có thể có nhiều function call trong một lượt.

Trả Kết Quả Về Model

Đính kèm kết quả theo dạng type="function_call_output" + call_id, rồi gọi model lần nữa để nhận câu trả lời cuối cùng (hoặc thêm tool calls).

Function Calling (Code Mẫu Chi Tiết)

# 1) Định nghĩa tool theo schema mới (Responses API)
tools = [{
    "type": "function",
    "name": "get_weather",
    "description": "Lấy thời tiết hiện tại theo địa điểm.",
    "strict": True,
    "parameters": {
        "type": "object",
        "properties": {
            "location": {"type": "string"}
        },
        "required": ["location"],
        "additionalProperties": False
    }
}]

# 2) Request đầu tiên (mô hình chọn có gọi tool hay không)
input_messages = [{"role": "user", "content": "Thời tiết Hà Nội hôm nay thế nào?"}]
response = openai.responses.create(
    model="gpt-5-mini", tools=tools, input=input_messages
)
# 3) Xử lý tool calls (có thể 0, 1 hoặc nhiều)
input_messages += response.output

for item in response.output:
    if item.type != "function_call":
        continue

    args = json.loads(item.arguments)
    weather = f"{args['location']}: 30 do C, troi nang"

    input_messages.append({
        "type": "function_call_output",
        "call_id": item.call_id,
        "output": weather
    })

# 4) Gửi kết quả tool để model trả lời tự nhiên
final_response = openai.responses.create(
    model="gpt-5-mini", tools=tools, input=input_messages
)

print(final_response.output_text)

Bài Tập Vận Dụng 2: Data Extraction

Đề bài: Bạn có một văn bản lộn xộn chứa thông tin khách hàng từ CSKH:

"Hôm qua khách Nguyễn Văn A (tuổi 30) gọi điện. Bảo là thích chơi thể thao. Gửi email xác nhận qua nguyenvana@email.com, SDT là 0912345678."

Hãy viết code dùng Pydantic Schema và Structured Outputs để bóc tách thông tin trên thành một Object chuẩn hóa chứa (name, age, email, phone, hobbies) và in kết quả.

Gợi Ý Cách Làm (Bài Tập 2)

  • Bước 1: Import Pydantic
    Import BaseModel từ thư viện Pydantic. Cần import thêm thư viện typing (dùng List/Optional) nếu thuộc tính hobbies lưu nhiều sở thích.
  • Bước 2: Định nghĩa Schema
    Tạo class CustomerInfo(BaseModel). Khai báo kiểu dữ liệu rõ ràng: name: str, age: int, email: str, phone: str, hobbies: list[str].
  • Bước 3: Gửi Request Bằng parse()
    Sử dụng client.responses.parse. Đưa đoạn text CSKH vào phần content của User role. Đừng quên truyền response_format=CustomerInfo.
  • Bước 4: In Kết Quả
    Truy xuất dữ liệu dễ dàng như object Python bình thường: customer = response.output_parsed. Sau đó in ra customer.email.

Bài Tập Vận Dụng 3: AI Thời Tiết (Function Calling)

Đề bài: Tạo một hàm Python cơ bản get_weather(location) giả lập việc trả về nhiệt độ mặc định là 30°C và trời nắng.

Khi người dùng nhập câu hỏi "Thời tiết ở Đà Nẵng thế nào?", ứng dụng của bạn phải sử dụng Function Calling để:
1. AI tự động trích xuất tham số "Đà Nẵng".
2. Ứng dụng chạy hàm giả lập đã tạo.
3. Gửi kết quả ngược lại cho API để AI tổng hợp thành một câu trả lời tự nhiên (VD: "Hiện tại Đà Nẵng đang khoảng 30 độ C và trời nắng nhé!").

Gợi Ý Cách Làm (Bài Tập 3)

  • Bước 1: Khai báo Tools & Gọi API lần 1
    Tạo mảng tools định nghĩa cấu trúc hàm get_weather. Gọi client.responses.create() truyền vào input của user và tham số tools.
  • Bước 2: Xử lý Tool Call & Gọi hàm Local
    Kiểm tra response.output để lấy function call đầu tiên. Trích xuất thuộc tính arguments (dùng json.loads để parse thành Dictionary) để lấy giá trị biến location. Chạy hàm Python get_weather(location) của bạn để lấy dữ liệu dạng chuỗi.
  • Bước 3: Gửi Kết Quả Tool
    Sau khi chạy hàm local, tạo input dạng {"type": "function_call_output", "call_id": ..., "output": ...} để trả kết quả cho mô hình.
  • Bước 4: Gọi API Lần 2
    Tiếp tục gọi client.responses.create() lần thứ hai với previous_response_id=response.id và mảng input chứa function_call_output. Lúc này AI sẽ tổng hợp và trả lời tự nhiên.

Project Cuối Khóa (Tự Chọn 1 Trong 4)

Hãy áp dụng toàn bộ kiến thức về API, Roles, JSON Schema và Function Calling để xây dựng hoàn thiện một trong các dự án thực tế sau đây:

1. Trợ Lý Ảo Đa Năng

Yêu cầu: Xây dựng CLI Chatbot có bộ nhớ và tính cách riêng biệt (VD: Chuyên gia tâm lý, Giáo viên Tiếng Anh).
Gợi ý: Tận dụng System prompt, sử dụng mảng messages để lưu lịch sử hội thoại, tùy chỉnh thông số temperature.

2. Hệ Thống Đọc Hóa Đơn

Yêu cầu: Viết script đọc văn bản ghi chú/hóa đơn tự do và trích xuất thành Data chuẩn (Tên món, Giá, Số lượng).
Gợi ý: Ứng dụng Pydantic định nghĩa BaseModel, sử dụng hàm .parse() để lấy Structured Outputs dưới dạng JSON Object.

3. Live Weather Bot

Yêu cầu: Xây dựng Chatbot có khả năng trả lời chính xác thông tin thời tiết thực tế ở bất kì khu vực nào.
Gợi ý: Áp dụng kỹ thuật Function Calling kết hợp gọi API miễn phí từ bên thứ 3 (như OpenWeatherMap API).

4. Chấm CV Xin Việc Tự Động

Yêu cầu: Đưa nội dung 1 CV vào, yêu cầu AI phân tích ưu/nhược điểm, cho điểm (1-10) và tư vấn vị trí phù hợp.
Gợi ý: Kết hợp Role (System giả lập HR) và JSON Structured Outputs chứa các fields: score, pros, cons, advice.

Q&A

Bạn có câu hỏi nào về các Project hoặc OpenAI API không?

Tài liệu tham khảo thêm: platform.openai.com/docs