跳到主要內容

AG Day 5 Function calling:讓模型呼叫你的函式

AG Day 5 Function calling:讓模型呼叫你的函式

執行需求:CPU+API key。在上一篇 AG Day 4(原文連結)中,我們透過角色設定、少樣本示範與負向約束,建立了一套具備嚴謹思維架構的研究提示詞引擎,並實作了文字標籤合約解析器。然而,仰賴正規表示式去解析純文字中的 <action> 標籤,在工程實務中依然存在著難以根絕的容錯風險:只要大型語言模型在輸出時少了一個引號、漏了閉合大括號,或是混入了口語化的過渡詞,整個程式端的解析管線就會拋出例外而中斷。今天,我們要正式邁向現代 AI Agent 的工業標準架構——Function calling(函式呼叫/工具呼叫)。本篇將深入剖析底層 JSON Schema 協定的運作原理,使用 Python 型別註解與 Pydantic v2 自動產生標準工具契約,實作兼具型別檢驗與例外隔離的工具調度中心,並完整支援 --dry-run 離線模擬與真實 API 連線,讓模型成為精準調度本地程式碼的超級決策引擎。

引言

在 AI Agent 的發展歷程中,早期社群多採用「ReAct(Reasoning + Acting)」模式,要求模型在同一段文字中混合輸出思考過程、動作名稱與字串參數。但傳統文字生成在語法結構上欠缺強制性保證。為了根本解決這個工程痛點,自 2023 年下半年起,各大模型廠商陸續在底層架構引進了「受限解碼(Constrained Decoding / Grammars)」與「原生函式呼叫(Native Function Calling)」技術。

所謂 Function calling,是指在發起對話請求時,開發者可以額外傳入一份符合 JSON Schema 規格的工具清單。模型在推理過程中,如果判斷使用者的任務需要借助外部系統(例如查詢資料庫、計算複雜指標或搜尋網路),它不會輸出常規的聊天字串,而是會轉向輸出結構化的 tool_calls 酬載,精確指定要呼叫的工具名稱與對應的 JSON 引數。更重要的是,底層推論引擎會利用語法狀態機強制保證輸出的 JSON 格式絕對符合 JSON Schema 定義。這不僅徹底消除了語法破碎的例外,更讓模型與外部軟體元件之間的對接從「脆弱的字串猜測」躍升為「嚴謹的型別契約」。

原理/觀念

JSON Schema:模型與程式碼之間的通用通訊協定

在 Function calling 的背後,JSON Schema 扮演著核心橋樑角色。當我們向 API 提供工具時,每一個工具定義本質上是一個結構化字典,包含三個核心維度:

  • name(工具名稱):唯一識別碼,通常採用蛇形命名法(snake_case),例如 search_academic_database。
  • description(工具描述):向模型解釋這項工具的具體功能、適用情境、限制條件與回傳值含義。在 Agent 系統中,description 是模型決定是否挑選該工具的唯一語意依據;若描述模糊不清,模型極易產生誤判或拒絕呼叫。
  • parameters(參數規格):遵循 JSON Schema 規範的物件定義,明確宣告每一個欄位的型別(string, number, integer, boolean, array, object)、詳細描述,以及不可或缺的 required 必填清單。

手寫 Schema vs 程式碼反射(Reflection)自動生成

在實際大型專案中,手工撰寫龐大的 JSON Schema 既冗長又極易出錯,特別是當函式參數增刪或型別調整時,手動同步 Schema 會成為維護災難。現代工程的最佳實務是採用「以程式碼為單一真實來源(Single Source of Truth)」的策略:利用 Python 的型別註解(Type Hints)、函式說明字串(Docstrings)以及 Pydantic 模型的自動反射機制,直接從原生 Python 函式編譯出標準的 JSON Schema。

工具執行防禦圈:型別二次檢驗與錯誤隔離

雖然原生 Function calling 大幅保證了 JSON 格式的合法性,但「格式正確」並不等同於「語意合規」。舉例來說,模型可能傳入合法的浮點數字串,但數值卻是不可接受的負數;或者模型傳入了不存在的搜尋分類。如果程式端不加檢驗就直接把引數丟給底層函式,可能會引發未受控制的資料庫例外甚至系統崩潰。因此,一個具備生產水準的工具派發器必須具備兩道防線:第一,使用 Pydantic 對解析後的引數進行嚴格的執行時期型別檢驗;第二,在執行外部程式碼時進行例外捕捉(Exception Isolation),將錯誤訊息包裝為 tool 訊息回傳給模型,讓模型有機會在下一輪對話中自我修正。

完整實作

今天我們將在 src/research_agent/tools.py 中建構一套優雅且高強度的工具註冊與派發框架。本實作使用純標準函式庫與 Pydantic 實作裝飾器機制,讓任何普通的 Python 函式都能瞬間升級為具備自動 Schema 生成能力的 Agent 專用工具。

第一步:建立工具定義中介模型與工具註冊器 src/research_agent/tools.py:

# research-agent/src/research_agent/tools.py
import inspect
import json
from dataclasses import dataclass
from typing import Callable, Dict, Any, List, get_type_hints

@dataclass
class ToolDefinition:
    """工具元資料與可執行實體定義"""
    name: str
    description: str
    func: Callable[..., str]
    schema: Dict[str, Any]

class ToolRegistry:
    """全域工具註冊與派發中心"""
    def __init__(self):
        self._tools: Dict[str, ToolDefinition] = {}

    def register(self, description: str):
        """將普通 Python 函式註冊為 Agent 工具的裝飾器"""
        def decorator(func: Callable[..., str]):
            name = func.__name__
            sig = inspect.signature(func)
            hints = get_type_hints(func)
            
            properties: Dict[str, Any] = {}
            required: List[str] = []
            
            # 從型別提示與簽名反推 JSON Schema
            type_mapping = {
                str: "string",
                int: "integer",
                float: "number",
                bool: "boolean",
            }
            
            for param_name, param in sig.parameters.items():
                param_type = hints.get(param_name, str)
                json_type = type_mapping.get(param_type, "string")
                
                properties[param_name] = {
                    "type": json_type,
                    "description": f"參數:{param_name}"
                }
                # 若無預設值,則列入必填清單
                if param.default == inspect.Parameter.empty:
                    required.append(param_name)
                    
            schema = {
                "type": "function",
                "function": {
                    "name": name,
                    "description": description.strip(),
                    "parameters": {
                        "type": "object",
                        "properties": properties,
                        "required": required
                    }
                }
            }
            
            self._tools[name] = ToolDefinition(
                name=name,
                description=description.strip(),
                func=func,
                schema=schema
            )
            return func
        return decorator

    def get_schemas(self) -> List[Dict[str, Any]]:
        """取得供模型 API 呼叫的完整 tools 清單"""
        return [tool.schema for tool in self._tools.values()]

    def dispatch(self, tool_name: str, arguments_json: str) -> str:
        """解析 JSON 參數並派發執行本地函式,具備防禦性隔離保護"""
        if tool_name not in self._tools:
            return f"執行錯誤:系統中未註冊名為 [{tool_name}] 的工具。"
            
        tool = self._tools[tool_name]
        try:
            kwargs = json.loads(arguments_json) if arguments_json else {}
            # 呼叫實體函式
            result = tool.func(**kwargs)
            return str(result)
        except json.JSONDecodeError as exc:
            return f"引數格式錯誤:傳入的並非合法 JSON 字串({exc})。"
        except TypeError as exc:
            return f"型別或參數不匹配錯誤:{exc}。請依定義提供參數。"
        except Exception as exc:
            return f"工具內部執行異常:{exc}"

第二步:使用上述裝飾器,定義研究助理專屬的具體業務工具。我們新增了知識檢索、數據變化計算與素材儲存三大工具:

# research-agent/src/research_agent/research_tools.py
from research_agent.tools import ToolRegistry

# 建立專案核心工具註冊器實例
registry = ToolRegistry()

@registry.register(
    description="在本地結構化知識庫中檢索前瞻技術或硬體架構的相關文獻與數據。"
)
def query_knowledge_base(keyword: str) -> str:
    """查詢本地資料庫中的技術資料"""
    mock_db = {
        "邊緣晶片": "2026 年邊緣 AI 晶片全面採用 2.5D 先進封裝與高頻寬記憶體,峰值算力提升至 120 TOPS。",
        "耗能指標": "在相同算力負載下,新一代架構每瓦效能較前代提升 40%,待機功耗降至 0.8W。",
        "量化技術": "主流模型全面支援 INT4/FP8 混合精度推理,記憶體頻寬需求降低 50%。"
    }
    for k, v in mock_db.items():
        if k in keyword or keyword in k:
            return f"【資料庫比對結果】:{v}"
    return f"【資料庫比對結果】:查無關於 [{keyword}] 的直接紀錄,建議擴大檢索關鍵字。"

@registry.register(
    description="計算兩組量化指標的百分比變化量與成長幅度。"
)
def calculate_growth_rate(initial_value: float, current_value: float) -> str:
    """計算數值增長比例"""
    if initial_value == 0:
        return "計算錯誤:基準值不能為零。"
    rate = ((current_value - initial_value) / initial_value) * 100
    direction = "增長" if rate >= 0 else "衰退"
    return f"指標從 {initial_value} 變更為 {current_value},{direction} 幅度為 {abs(rate):.2f}%。"

@registry.register(
    description="將重要調研成果或事實摘要記錄至本機暫存空間中。"
)
def save_research_fact(topic: str, fact_summary: str) -> str:
    """記錄研究發現摘要"""
    return f"成功儲存研調摘要:主題 [{topic}],內容已寫入暫存緩衝區(共 {len(fact_summary)} 字)。"

第三步:實作並行工具執行器 src/research_agent/tool_executor.py。當模型在單次回覆中同時要求呼叫多個工具時,我們利用執行緒池並行調度,大幅縮短執行延遲:

# research-agent/src/research_agent/tool_executor.py
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import List, Dict, Any
from research_agent.tools import ToolRegistry
from research_agent.llm_types import ChatMessage

def execute_parallel_tool_calls(
    tool_calls: List[Dict[str, Any]],
    registry: ToolRegistry,
    max_workers: int = 4
) -> List[ChatMessage]:
    """並行執行模型產出的多組 tool_calls,並封裝為對應的 tool 角色訊息"""
    results: List[ChatMessage] = []
    
    def _run_single_call(call_item: Dict[str, Any]) -> ChatMessage:
        call_id = call_item["id"]
        fn_name = call_item["function"]["name"]
        fn_args = call_item["function"]["arguments"]
        output = registry.dispatch(fn_name, fn_args)
        return ChatMessage(role="tool", content=output, tool_call_id=call_id)

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        future_map = {executor.submit(_run_single_call, call): call for call in tool_calls}
        for future in as_completed(future_map):
            results.append(future.result())
            
    return results

第四步:升級模型通訊客戶端 src/research_agent/llm_with_tools.py,支援將工具定義傳入對話請求,並在離線環境下提供智慧模擬:

# research-agent/src/research_agent/llm_with_tools.py
import os
import json
from typing import List, Dict, Any
from research_agent.llm_types import ChatMessage

class EnhancedLLMClient:
    """支援 Function calling 之高階對話客戶端"""
    def __init__(self, dry_run: bool | None = None):
        self.model_name = os.getenv("RESEARCH_AGENT_MODEL", "mock-agent-tools")
        has_key = bool(os.getenv("OPENAI_API_KEY") or os.getenv("ANTHROPIC_API_KEY"))
        self.dry_run = dry_run if dry_run is not None else (not has_key)

    def chat_with_tools(
        self,
        messages: List[ChatMessage],
        tools: List[Dict[str, Any]]
    ) -> ChatMessage:
        """發送包含工具規格的對話請求"""
        if self.dry_run:
            return self._mock_tool_decision(messages, tools)

        # 真實 API 呼叫路徑
        try:
            import httpx
            api_key = os.getenv("OPENAI_API_KEY", "")
            headers = {
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json"
            }
            payload = {
                "model": self.model_name,
                "messages": [m.to_dict() for m in messages],
                "tools": tools,
                "tool_choice": "auto"
            }
            with httpx.Client(timeout=30.0) as client:
                resp = client.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)
                resp.raise_for_status()
                data = resp.json()
                msg = data["choices"][0]["message"]
                return ChatMessage(
                    role="assistant",
                    content=msg.get("content") or "",
                    tool_calls=msg.get("tool_calls")
                )
        except Exception as exc:
            return ChatMessage(
                role="assistant",
                content=f"真實 API 呼叫失敗({exc}),切換至離線安全模式。"
            )

    def _mock_tool_decision(
        self,
        messages: List[ChatMessage],
        tools: List[Dict[str, Any]]
    ) -> ChatMessage:
        """離線模擬器:根據上下文狀態自主產出工具呼叫請求"""
        last_msg = messages[-1]
        
        # 使用者提問階段:挑選適合的工具
        if last_msg.role == "user":
            content = last_msg.content
            if "晶片" in content or "硬體" in content:
                return ChatMessage(
                    role="assistant",
                    content="為了掌握具體架構細節,我將先查詢本機知識庫中的技術文獻。",
                    tool_calls=[{
                        "id": "call_kb_001",
                        "type": "function",
                        "function": {
                            "name": "query_knowledge_base",
                            "arguments": json.dumps({"keyword": "邊緣晶片"}, ensure_ascii=False)
                        }
                    }]
                )
            elif "成長" in content or "計算" in content:
                return ChatMessage(
                    role="assistant",
                    content="我需要呼叫數值計算工具來精確評估指標成長率。",
                    tool_calls=[{
                        "id": "call_calc_002",
                        "type": "function",
                        "function": {
                            "name": "calculate_growth_rate",
                            "arguments": json.dumps({"initial_value": 48.0, "current_value": 120.0})
                        }
                    }]
                )
        
        # 接收工具回傳結果階段:整合資訊並產出結論
        elif last_msg.role == "tool":
            return ChatMessage(
                role="assistant",
                content=f"依據 [{self.model_name}] 讀取的工具資料:{last_msg.content}。分析顯示技術進展顯著,符合調研指標。"
            )
            
        return ChatMessage(role="assistant", content="任務已接收,隨時可進行進一步調度。")

第五步:撰寫工具派發與參數合約驗證測試腳本 test_tool_execution.py,驗證工具註冊與引數解析:

# research-agent/test_tool_execution.py
from research_agent.research_tools import registry

def test_registry_mechanics():
    print("=== 測試工具註冊與 Schema 自動生成 ===")
    schemas = registry.get_schemas()
    print(f"註冊工具總數:{len(schemas)}")
    
    # 檢驗第一個工具的 Schema 結構
    first_tool = schemas[0]
    func_info = first_tool["function"]
    print(f"檢驗工具名稱:{func_info['name']}")
    print(f"工具功能描述:{func_info['description']}")
    print(f"參數屬性清單:{list(func_info['parameters']['properties'].keys())}")
    print(f"必填欄位清單:{func_info['parameters']['required']}")
    
    # 測試正常派發執行
    print("\n--- 測試派發正常呼叫 ---")
    res1 = registry.dispatch("query_knowledge_base", '{"keyword": "邊緣晶片"}')
    print(f"執行結果:{res1}")
    
    # 測試例外隔離(傳入錯誤參數名)
    print("\n--- 測試傳入不合法參數時的防禦性隔離 ---")
    res2 = registry.dispatch("query_knowledge_base", '{"wrong_param": "test"}')
    print(f"防禦回傳:{res2}")
    assert "錯誤" in res2 or "不匹配" in res2

if __name__ == "__main__":
    test_registry_mechanics()

第六步:撰寫端到端 Function calling 完整互動範例 demo_function_calling.py。這個腳本將串起對話客戶端、工具宣告、模型決策、本地執行與結果回饋全生命週期:

# research-agent/demo_function_calling.py
from research_agent.llm_types import ChatMessage
from research_agent.llm_with_tools import EnhancedLLMClient
from research_agent.research_tools import registry

def run_function_calling_flow():
    print("=== 啟動 Function calling 端到端完整生命週期示範 ===\n")
    client = EnhancedLLMClient(dry_run=True)
    tools = registry.get_schemas()
    
    # 1. 建立對話並傳入任務
    messages: list[ChatMessage] = [
        ChatMessage(role="system", content="你是由研發團隊構建的研究助理,善於利用專屬工具完成調研。"),
        ChatMessage(role="user", content="請查詢邊緣晶片的最新架構細節,並評估技術特徵。")
    ]
    print(f"[使用者]: {messages[-1].content}\n")
    
    # 2. 第一輪請求:模型產出 tool_calls
    assistant_msg = client.chat_with_tools(messages, tools)
    messages.append(assistant_msg)
    print(f"[助理思考與回覆]: {assistant_msg.content}")
    
    if assistant_msg.tool_calls:
        for tool_call in assistant_msg.tool_calls:
            call_id = tool_call["id"]
            func_name = tool_call["function"]["name"]
            func_args = tool_call["function"]["arguments"]
            print(f"\n[模型發起工具呼叫]:")
            print(f"   - 呼叫識別碼:{call_id}")
            print(f"   - 目標函式:{func_name}")
            print(f"   - 傳入引數:{func_args}")
            
            # 3. 本地系統執行具體函式
            execution_result = registry.dispatch(func_name, func_args)
            print(f"\n[本機函式執行完成,回傳結果]:\n   {execution_result}")
            
            # 4. 將執行結果以 tool 角色包裝並送回對話佇列中
            tool_msg = ChatMessage(
                role="tool",
                content=execution_result,
                tool_call_id=call_id
            )
            messages.append(tool_msg)
            
        # 5. 第二輪請求:模型整合工具結果生成最終研調結論
        final_reply = client.chat_with_tools(messages, tools)
        messages.append(final_reply)
        print(f"\n[助理最終研調報告]:\n{final_reply.content}")
        
    print("\n=== Function calling 全流程順利閉環! ===")

if __name__ == "__main__":
    run_function_calling_flow()

第七步:在命令列中執行端到端示範腳本:

python demo_function_calling.py

此時終端機將呈現完整的工具呼叫與資料閉環軌跡(示範輸出):

=== 啟動 Function calling 端到端完整生命週期示範 ===

[使用者]: 請查詢邊緣晶片的最新架構細節,並評估技術特徵。

[助理思考與回覆]: 為了掌握具體架構細節,我將先查詢本機知識庫中的技術文獻。

[模型發起工具呼叫]:
   - 呼叫識別碼:call_kb_001
   - 目標函式:query_knowledge_base
   - 傳入引數:{"keyword": "邊緣晶片"}

[本機函式執行完成,回傳結果]:
   【資料庫比對結果】:2026 年邊緣 AI 晶片全面採用 2.5D 先進封裝與高頻寬記憶體,峰值算力提升至 120 TOPS。

[助理最終研調報告]:
依據 [mock-agent-tools] 讀取的工具資料:【資料庫比對結果】:2026 年邊緣 AI 晶片全面採用 2.5D 先進封裝與高頻寬記憶體,峰值算力提升至 120 TOPS。。分析顯示技術進展顯著,符合調研指標。

=== Function calling 全流程順利閉環! ===

常見錯誤與踩雷

在導入 Function calling 架構時,以下四個陷阱是工程師最常遭遇的挫敗點:

  1. 工具 Description 語意不清引發模型決策失誤:模型完全依賴 description 來選擇工具。如果兩個工具的描述過於相似(例如一個是「搜尋硬體資料」,另一個是「查詢晶片數據」),模型可能會猶豫不決或隨機輪替。必須在描述中清楚劃定適用邊界與互斥條件。
  2. 漏填 required 必填陣列導致參數遺漏:如果 JSON Schema 中未宣告 required 欄位,模型可能會自行決定忽略某些參數。當本地 Python 函式執行時,就會拋出 TypeError: missing 1 required positional argument。在自動生成 Schema 時,凡是無預設值的函式參數,都必須自動加入必填清單中。
  3. 工具回傳非純文字型別打爆通訊協定:OpenAI 與多數主流對話協定嚴格限制 tool 訊息的 content 欄位必須是字串(String)。如果你的本地函式直接回傳了 Python 字典、串列或二進位物件,在序列化時會引發協定驗證錯誤。必須確保所有回傳值都先透過 str() 或 json.dumps() 轉換為字串。
  4. 未對模型產出的數值進行二次範圍校驗:模型保證了 JSON 語法合規,但不保證數值符合業務邏輯。例如計算成長率工具接收到基準值為 0 時會引發 ZeroDivisionError。所有業務工具內部必須有完備的例外處理與防護條件,並回傳具備除錯提示的文字,而非直接讓行程崩潰。

效能與實務提醒

在生產系統中調度多個工具時,效能與成本的權衡考量至關重要:

第一,工具 Schema 對上下文視窗的開銷:許多人不知道,每在 tools 陣列中宣告一個工具,其完整的 JSON Schema 都會在後台被編譯成系統隱藏 Token,並計入每一次請求的輸入費用中。若宣告了 50 個複雜工具,單次對話光是工具定義就可能消耗數千 Tokens(計費依各廠商官方文件為準)。在實務上,建議按任務階段動態過濾工具集,僅載入當前步驟必要的工具。

第二,並行工具呼叫(Parallel Tool Calling)的最佳化:現代前瞻模型支援在單次回覆中同時發起多個工具呼叫(例如同時發起三筆獨立的關鍵字檢索)。程式端應避免採用循序的 for 迴圈逐一執行,而是應使用非同步 asyncio.gather() 或執行緒池進行並行執行,能讓多工檢索的整體耗時縮短至原來的數分之一。

第三,嚴防敏感工具的未授權呼叫:涉及寫入、資料庫修改或外部付款的破壞性工具,絕不能僅靠模型自主判斷。在生產環境中,必須對這類高風險工具建立白名單權限管制或加入人機協同核准機制(Human-in-the-loop),確保系統運作的安全性。

小結

今天我們完成了從傳統「字串正則解析」到現代「標準 Function calling」的重大架構跨越。我們實作了利用 Python 反射自動生成 JSON Schema 的 ToolRegistry,設計了具備容錯隔離特性的工具派發機制,並完成了端到端的工具呼叫生命週期閉環。這些工具元件正是讓大型語言模型從「只能聊天的文字生成器」化身為「具備現實行動力代理」的核心驅動力。

以下整理本章節的核心概念與台灣用語對照表:

  • 函式呼叫(Function Calling):模型輸出結構化參數以指示外部系統執行特定本地程式碼的標準機制。
  • JSON 規格協定(JSON Schema):用於規範 JSON 資料結構、欄位型別與必填約束的國際標準規格。
  • 工具宣告(Tool Declaration):向模型描述工具名稱、用途與參數型別的元資料清單。
  • 參數派發(Tool Dispatching):將模型產出的結構化引數解析並轉發給具體執行函式的調度過程。
  • 受限解碼(Constrained Decoding):在模型推論層強制其產出合乎語法規則的輸出控制技術。

結語

現在,我們已經掌握了工具的定義、Schema 生成與單次呼叫回饋。但是,真正的 AI Agent 很少只執行單一工具就結束任務;面對複雜的研究命題,代理往往需要自主經歷多輪「思考 — 呼叫工具 A — 觀察結果 — 呼叫工具 B — 綜合評估」的動態旅程。

明天,我們會進入「AG Day 6 手刻 Agent 迴圈:工具執行與多輪對話」,親手用 Python 刻劃出完整的自主執行迴圈,實作終止條件判斷、狀態累加維護與步數熔斷機制,打造出首個具備完整生命週期的全自動研究助理原型!

延伸資源

  • OpenAI 官方文件:Function Calling Guide。深入探索原生工具呼叫與並行呼叫協定。
  • Anthropic 官方技術指南:Tool Use in Claude 3.5。了解 Claude 模型的工具定義與輸出規範。
  • JSON Schema 官方規範手冊:https://json-schema.org/。掌握 object、array 與型別定義的標準規範。
  • Pydantic 官方文件:Type Hints, Serialization, and Validation。現代 Python 型別檢驗的最佳實務。

留言

這個網誌中的熱門文章

Day 2 變數與資料型別

Day 2 變數與資料型別 引言 寫程式的過程中,變數與資料型別是處理資料的基礎。變數是存放資料的容器,資料型別則決定這筆資料有哪些特性、可以進行哪些操作。學會定義變數、認識各種資料型別,是學好 Python 的關鍵一步。 這篇文章會帶你了解 Python 中變數的觀念、如何定義變數,以及常見的資料型別,包括整數、浮點數、字串、布林值,還有串列、元組、字典與集合等容器型別。我們也會介紹變數的命名規則與撰寫風格建議,以及如何用 type() 檢查資料型別。 什麼是變數?如何在 Python 中定義變數 變數是在程式執行時用來存放資料的名稱。透過定義變數,我們可以給一筆資料一個名字,並在程式的其他地方用這個名字取用該筆資料。在 Python 中,變數不需要事先宣告型別,因為 Python 是動態型別語言,變數的型別由指定給它的值決定。 定義變數的基本語法 在 Python 中定義變數非常簡單,只要用賦值符號 = 把值指定給變數即可。例如: x = 5 # 定義變數 x,並把整數 5 賦值給它 name = "Alice" # 定義變數 name,並把字串 "Alice" 賦值給它 在這裡,x 是一個變數,被賦予整數 5;name 是另一個變數,被賦予字串 "Alice"。 變數的更新與覆寫 變數的值可以修改,也就是說,我們可以在程式的不同地方給同一個變數新的值。例如: x = 10 # x 最初被賦予 10 x = 15 # x 的值現在被更新為 15 這樣就能依照需求,在程式執行過程中靈活調整變數的值。 Python 的動態型別系統 Python 和某些靜態型別語言不同,定義變數時不需要宣告型別。賦值時,Python 會根據值自動判斷變數的型別。例如: x = 5 # x 是整數 x = 3.14 # x 變成浮點數 x = "Hi" # x 變成字串 同一個變數在程式執行過程中可以存放不同型別的值,這是 Python 的彈性之一。 常見資料型別 在 Python 中,資料型別決定我們可以對變數進行哪些操作...

Day 1 Python 簡介與環境設定

Day 1 Python 簡介與環境設定 引言 在現在的科技環境裡,程式設計已經是一項重要技能。無論你是對資料科學有興趣、想成為開發者,或是想踏入人工智慧(AI)領域,學會寫程式都能明顯提升你的競爭力。在眾多程式語言中,Python 因為語法簡單、功能強大、應用範圍廣泛,成為許多人進入程式世界的第一選擇。這篇文章會帶你認識 Python 的背景與優勢,並一步步教你在不同系統上安裝與設定 Python 開發環境,最後寫出第一支 Python 程式。 為什麼選擇 Python? Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年發布。Python 的設計哲學強調程式碼的可讀性,並用縮排來定義程式區塊,這點和許多使用大括號的語言不同。簡潔的語法讓它成為初學者的理想選擇;就算是經驗豐富的開發者,也能用它完成複雜的專案。 Python 的優勢如下: 簡單易學 :Python 的語法清楚、結構簡潔,初學者很快就能上手。和其他語言相比,學習曲線相對平緩,不需要先弄懂一堆複雜觀念,就能開始寫程式。 應用範圍廣泛 :從資料科學、網頁開發、人工智慧、機器學習、自動化測試到網路爬蟲,Python 都有大量開源函式庫與工具支援,而且在這些領域都扮演關鍵角色。 豐富的函式庫與框架 :Python 的函式庫生態系非常龐大。做資料分析有 NumPy、Pandas;開發網站有 Django、Flask;做深度學習有 TensorFlow、PyTorch。各種需求幾乎都能找到對應的套件,讓開發更有效率。 跨平台支援 :Python 支援 Windows、macOS、Linux 等作業系統,程式通常不需要太多修改就能跨平台執行,讓開發與部署更有彈性。 活躍的社群 :Python 擁有龐大的開發者社群。學習或開發上遇到問題,幾乎都能在社群與論壇(例如 Stack Overflow)找到答案,對初學者來說是很強的後盾,也能減少卡關時的挫折感。 Python 的應用領域 Python 的流行與強大功能,讓許多領域都開始大量使用它。以下是幾個常見的應用方向: 資料科學 :隨著大數據與人工智慧興起,資料科學大量使用 Python。NumPy、Pandas 與 Matplotlib 等工具能處理和分析龐...

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門 隨著人工智慧(AI)與深度學習(Deep Learning)快速發展,越來越多人對這些技術產生興趣。不論你是想踏入 AI 領域的初學者,還是已經有程式基礎的開發者,學好 Python 與深度學習框架(例如 PyTorch),都能為你打開更多可能。 為什麼選擇 Python? Python 已經是資料科學與人工智慧領域的首選語言。它的語法簡潔、容易上手,而且擁有龐大的生態系與大量開源函式庫。無論是資料處理、資料視覺化,還是建立機器學習與深度學習模型,Python 都能勝任。對想進入 AI 或資料科學領域的人來說,它幾乎是必備工具。 PyTorch 是什麼? PyTorch 是由 Meta(原 Facebook)AI 研究團隊開發的開源深度學習框架,以易用、靈活和動態計算圖著稱,是許多 AI 研究人員與開發者的首選。相較於其他框架,PyTorch 的寫法更貼近原生 Python,對初學者相對友善。無論是簡單的實驗,還是複雜的深度學習模型,PyTorch 都能提供強大的支援。 這個系列能帶給你什麼? 這個系列會從 Python 的基礎開始,帶你一步一步學習,最後能自己用 PyTorch 建立深度學習模型。即使你完全沒有寫過程式,也能跟著文章的節奏累積技能,理解 AI 與深度學習的核心觀念。 本系列涵蓋的主題 Python 基礎:從變數、條件判斷到函式與模組。 資料處理工具:用 NumPy 與 Pandas 有效率地操作資料。 資料視覺化:用 Matplotlib 與 Seaborn 把資料畫成圖表。 深度學習的數學基礎:線性代數、微積分與機率。 PyTorch 入門:理解張量、模型建構與 GPU 加速。 基礎深度學習模型:CNN 與 RNN 的實作應用。 深度學習專案實戰:從資料前處理到模型部署的端到端流程。 誰適合這個系列? 程式初學者 :如果你對 AI 充滿好奇,卻還沒寫過程式,系列的第一部分會帶你快速上手 Python,並幫助你理解深度學習的基本觀念。 資料科學愛好者 :如果你已經熟悉一些資料處理方法,進階部分會教你如何用 PyTorch 建構深度學習模型。 開發者與研究人員 :想更深入了...