在前一篇測試中, 我們在 PS 視窗裡使用 curl.exe 程式向 Ollama 建立的 REST API 伺服器提出請求, 本篇則是要改用 Python 程式來存取 REST API 端點 (使用 requests 套件).
茲將常用之 Ollama REST API 端點鈔錄如下 :
| POST 操作端點 | 說明 |
|---|---|
| /api/generate | 文字生成 (用於單次提示詞的輸入與基本文字接龍)。 |
| /api/chat | 多輪對話 (用於需要記錄上下文, 用 user/assistant/system 區分角色)。 |
| /api/embeddings | 使用 Embedding 模型將文字轉成可用於 RAG 語意搜尋的嵌入向量。 |
| /api/pull | 從 Ollama 官方模型庫下載指定的 LLM 模型到本機。 |
| /api/push | 將模型推入 Ollama 官方模型庫 (需登入 & 輸入金鑰)。 |
| /api/show | 顯示模型的詳細資訊。 |
| /api/create | 透過傳入 Modelfile 的內容從本機檔案建立或自訂一個全新的模型。 |
| /api/copy | 在本地將一個現有的模型複製並重新命名為另一個名稱。 |
| GET 操作端點 | 說明 |
|---|---|
| /api/tags | 列出本地所有模型。 |
| /api/ps | 查看目前有哪些模型正載入在記憶體 (DRAM/VRAM)。 |
| /api/version | 取得 Ollama 的版本資訊。 |
| DELETE 操作端點 | 說明 |
|---|---|
| /api/delete | 刪除本地指定之模型 (使用 name 鍵指定)。 |
2. 使用 requests 提出請求 :
requests 套件提供 get(), post(), 與 delete() 等相對於 GET, POST, 與 DELETE 方法的函式, 首先來測試 GET 方法, 例如呼叫 /a[i/tags 端點來取得函式清單. 由於 get() 無法指定模型, 因此需先手動載入模型, 開啟一個 CMD 或 PS 視窗, 輸入下列指令載入執行 gemma4:e4b 模型 :
PS C:\Users\USER> ollama run gemma4:e4b
然後進入 Python 執行環境匯入 requests 套件, 呼叫 requests.get() 函式向 /api/tags 端點提出 GET 請求, requests 套件會將 Ollama 回應的 HTTP 封包打包成一個 Response 物件傳回 :
>>> import requests
>>> url='http://localhost:11434/api/tags'
>>> reply=requests.get(url)
>>> reply
<Response [200]>
>>> type(reply)
<class 'requests.models.Response'>
可呼叫 Response 物件的 json() 方法轉成字典, 為了整齊顯示字典結構, 可用 pprint.print() 來輸出 :
>>> from pprint import pprint
>>> result=reply.json()
>>> pprint(result)
{'models': [{'details': {'families': ['gemma4'],
'family': 'gemma4',
'format': 'gguf',
'parameter_size': '8.0B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': 'c6eb396dbd5992bbe3f5cdb947e8bbc0ee413d7c17e2beaae69f5d569cf982eb',
'model': 'gemma4:e4b',
'modified_at': '2026-05-28T22:36:46.3502486+08:00',
'name': 'gemma4:e4b',
'size': 9608350718},
{'details': {'families': ['mllama'],
'family': 'mllama',
'format': 'gguf',
'parameter_size': '10.7B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': '6f2f9757ae97e8a3f8ea33d6adb2b11d93d9a35bef277cd2c0b1b5af8e8d0b1e',
'model': 'llama3.2-vision:11b',
'modified_at': '2026-05-25T11:30:36.0322613+08:00',
'name': 'llama3.2-vision:11b',
'size': 7816589186},
{'details': {'families': ['phi3'],
'family': 'phi3',
'format': 'gguf',
'parameter_size': '14.7B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': 'ac896e5b8b34a1f4efa7b14d7520725140d5512484457fab45d2a4ea14c69dba',
'model': 'phi4:14b',
'modified_at': '2026-05-24T17:23:24.1907029+08:00',
'name': 'phi4:14b',
'size': 9053116391},
{'details': {'families': ['deepseek2'],
'family': 'deepseek2',
'format': 'gguf',
'parameter_size': '15.7B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': 'a6f5c73087ad25fc8666929492449eb0dc694326e4ca5b2313fef75b66645583',
'model': 'dagbs/deepseek-coder-v2-lite-instruct:q4_k_m',
'modified_at': '2026-05-24T00:17:21.5900783+08:00',
'name': 'dagbs/deepseek-coder-v2-lite-instruct:q4_k_m',
'size': 10364417401},
{'details': {'families': ['deepseek2'],
'family': 'deepseek2',
'format': 'gguf',
'parameter_size': '15.7B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': '6171206208d0529a47806ebcf8ed37a88fe322859e269396dd16fdd98a56a102',
'model': 'mannix/deepseek-coder-v2-lite-instruct:q4_k_m',
'modified_at': '2026-05-23T21:15:32.5340567+08:00',
'name': 'mannix/deepseek-coder-v2-lite-instruct:q4_k_m',
'size': 10364432240},
{'details': {'families': ['qwen2'],
'family': 'qwen2',
'format': 'gguf',
'parameter_size': '14.8B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': 'c333b7232bdb521236694ffbb5f5a6b11cc45d98e9142c73123b670fca400b09',
'model': 'deepseek-r1:14b',
'modified_at': '2026-05-23T16:43:35.5527992+08:00',
'name': 'deepseek-r1:14b',
'size': 8988112209},
{'details': {'families': ['qwen3'],
'family': 'qwen3',
'format': 'gguf',
'parameter_size': '14.8B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': 'bdbd181c33f2ed1b31c972991882db3cf4d192569092138a7d29e973cd9debe8',
'model': 'qwen3:14b',
'modified_at': '2026-05-22T00:30:36.3395998+08:00',
'name': 'qwen3:14b',
'size': 9276198565},
{'details': {'families': ['gemma4'],
'family': 'gemma4',
'format': 'gguf',
'parameter_size': '8.0B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': 'c6eb396dbd5992bbe3f5cdb947e8bbc0ee413d7c17e2beaae69f5d569cf982eb',
'model': 'gemma4:latest',
'modified_at': '2026-05-20T11:45:08.2471048+08:00',
'name': 'gemma4:latest',
'size': 9608350718}]}
呼叫 /api/ps 端點會傳回目前載入記憶體之模型資訊 (相當於下 ollama ps 指令) :
>>> url='http://localhost:11434/api/ps'
>>> reply=requests.get(url)
>>> result=reply.json()
>>> pprint(result)
{'models': [{'context_length': 4096,
'details': {'families': ['gemma4'],
'family': 'gemma4',
'format': 'gguf',
'parameter_size': '8.0B',
'parent_model': '',
'quantization_level': 'Q4_K_M'},
'digest': 'c6eb396dbd5992bbe3f5cdb947e8bbc0ee413d7c17e2beaae69f5d569cf982eb',
'expires_at': '2026-05-30T08:51:38.2129288+08:00',
'model': 'gemma4:e4b',
'name': 'gemma4:e4b',
'size': 10579079040,
'size_vram': 10579079040}]}
可見呼叫 /api/tags 端點會列出目前 Ollama 已下載的全部模型.
但若呼叫距離前一次存取模型超過逾時時間 (預設 5 分鐘), Ollama 會自動將模型會從記憶體中清除, 這時呼叫 /api/ps 端點會得到 models 鍵為空串列的回應 :
>>> pprint(result)
{'models': []}
這時只要用 POST 方法呼叫 /api/generate 或 /api/chat, Ollama 便會觸發 Ollama 自動將指定之模型載入記憶體 (毋須手動在命令列用 ollama run 指令載入).
注意, 呼叫 get() 無法指定模型, 必須呼叫 post() 才能指定模型, 因為呼叫 post() 時可傳入一個 json 參數, 用字典來打包要傳給 Ollama 端點之酬載資訊 (payload), 其中的 model 鍵便是用來指定要載入之模型, 例如下面是呼叫文字接龍端點 /api/generate 的酬載資訊 :
payload={
"model": "gemma4:e4b",
"prompt": "請簡介量子糾纏",
"stream": False
}
例如 :
>>> url='http://localhost:11434/api/generate'
>>> payload={
"model": "gemma4:e4b",
"prompt": "你是誰",
"stream": False
}
>>> reply=requests.post(url, json=payload)
>>> result=reply.json()
>>> pprint(result)
{'context': [2,
105,
9731,
107,
... (略) ...
237169,
240975,
239967,
236918,
238463,
237536],
'created_at': '2026-05-30T01:28:46.9601674Z',
'done': True,
'done_reason': 'stop',
'eval_count': 443,
'eval_duration': 5984802600,
'load_duration': 229697200,
'model': 'gemma4:e4b',
'prompt_eval_count': 18,
'prompt_eval_duration': 235963400,
'response': '我叫 **Gemma 4**。\n'
'\n'
'我是一個大型語言模型(Large Language Model, LLM),由 Google DeepMind 開發。\n'
'\n'
'我的設計目的是用來理解和生成人類語言,我可以協助您回答問題、撰寫不同類型的文本、總結資訊,或進行創意性的對話。\n'
'\n'
'您有什麼問題需要我幫忙的呢?',
'total_duration': 6698511600}
可見對於單一問答 (接龍) 呼叫, Response 物件中包含一長串的 context 訊息, 而模型實際的回應則是放在 resposne 鍵裡 :
>>> print(result['response'])
我叫 **Gemma 4**。
我是一個大型語言模型(Large Language Model, LLM),由 Google DeepMind 開發。
我的設計目的是用來理解和生成人類語言,我可以協助您回答問題、撰寫不同類型的文本、總結資訊,或進行創意性的對話。
您有什麼問題需要我幫忙的呢?
如果是呼叫對話端點 /api/chat, 則可在 messages 鍵中放入包含 role 與 content 鍵之對話字典, role 可以是 system/user/assistant, 格式與 OpenAI API 類似 :
payload={
"model": "gemma4:e4b",
"messages": [
{"role": "system", "content": "請一律用台灣用語與繁體中文回答"},
{"role": "user", "content": "請用 100 個字簡介量子糾纏"}
],
"stream": False
}
例如 :
>>> url='http://localhost:11434/api/chat'
>>> payload={
"model": "gemma4:e4b",
"messages": [
{"role": "system", "content": "請一律用台灣用語與繁體中文回答"},
{"role": "user", "content": "請用 100 個字簡介量子糾纏"}
],
"stream": False
}
>>> reply=requests.post(url, json=payload)
>>> result=reply.json()
>>> pprint(result)
{'created_at': '2026-05-30T01:39:36.5316751Z',
'done': True,
'done_reason': 'stop',
'eval_count': 595,
'eval_duration': 8100674200,
'load_duration': 4374553000,
'message': {'content': '量子糾纏是一種奇特的量子現象,描述兩個或多個粒子之間存在的緊密關聯。無論這些粒子相距多遠,牠們的量子狀態都會形成一個不可分割的整體。\n'
'\n'
'當我們測量其中一個粒子的某個性質(例如自旋)時,另一個粒子的狀態會瞬間、同步地確定,彷彿有無形的超距聯繫一般。愛因斯坦曾戲稱為「幽靈般的超距作用」。\n'
'\n'
'這種現象是量子計算和量子密碼學的基礎技術,是未來尖端科技不可或缺的核心概念。它挑戰了我們對物理世界空間和資訊傳輸的傳統認知。',
'role': 'assistant',
'thinking': "Here's a thinking process to ensure the response "
'meets the criteria (Taiwanese Mandarin, Traditional '
'Chinese, approximately 100 characters, and '
'scientifically accurate description of quantum '
'entanglement):\n'
'\n'
'1. **Analyze the Request:**\n'
' * Topic: Quantum Entanglement (量子糾纏).\n'
' * Length: Approximately 100 characters.\n'
' * Style: Use Taiwanese terminology and '
'Traditional Chinese (台灣用語與繁體中文).\n'
'\n'
'2. **Identify Key Concepts (Quantum '
'Entanglement):**\n'
' * Definition: A unique connection between two '
'or more quantum particles.\n'
' * Feature: Their fates are linked, regardless '
'of the distance separating them.\n'
' * Measurement Effect: Measuring a property '
'(like spin) of one instantly tells you the property '
'of the other.\n'
' * Paradox/Implication: Einstein called it '
'"spooky action at a distance" (幽靈般的超距作用).\n'
' * Application: Crucial for quantum computing '
'and quantum cryptography.\n'
'\n'
'3. **Drafting the Content (Focusing on the '
'"Taiwanese Tone" and Flow):**\n'
' * *Goal:* Make it accessible yet precise.\n'
' * *Initial Draft Check (Mental Outline):* '
'Start with the definition, explain the link, mention '
'the distance independence, and end with the '
'application/impact.\n'
'\n'
'4. **Refining and Polishing (Character Count and '
'Tone):**\n'
' * *Self-Correction/Refinement:* Ensure the '
'language feels natural for a Taiwanese audience '
'(using common Taiwanese scientific phrasing, but '
'remaining formal).\n'
' * *(Structuring the 100 characters):*\n'
' * Introduction (What it is).\n'
' * Mechanism (The spooky link).\n'
' * Conclusion (Why it matters).\n'
'\n'
'5. **Final Polish (Review against constraints):**\n'
' * Taiwanese/Traditional Chinese: Yes.\n'
' * Length: Close to 100 characters (The target '
'is an *approximation*).\n'
' * Accuracy: Yes, captures the core idea.\n'
'\n'
'6. **Final Output Generation.** (This leads to the '
'provided good answer.)'},
'model': 'gemma4:e4b',
'prompt_eval_count': 40,
'prompt_eval_duration': 35168300,
'total_duration': 12994831300}
模型的實際回應是放在 message 鍵的 content 鍵裡 :
>>> print(result['message']['content'])
量子糾纏是一種奇特的量子現象,描述兩個或多個粒子之間存在的緊密關聯。無論這些粒子相距多遠,牠們的量子狀態都會形成一個不可分割的整體。
當我們測量其中一個粒子的某個性質(例如自旋)時,另一個粒子的狀態會瞬間、同步地確定,彷彿有無形的超距聯繫一般。愛因斯坦曾戲稱為「幽靈般的超距作用」。
這種現象是量子計算和量子密碼學的基礎技術,是未來尖端科技不可或缺的核心概念。它挑戰了我們對物理世界空間和資訊傳輸的傳統認知。
或者連續呼叫字典的 get() 方法亦可 :
>>> print(result.get('message').get('content'))
量子糾纏是一種奇特的量子現象,描述兩個或多個粒子之間存在的緊密關聯。無論這些粒子相距多遠,牠們的量子狀態都會形成一個不可分割的整體。
當我們測量其中一個粒子的某個性質(例如自旋)時,另一個粒子的狀態會瞬間、同步地確定,彷彿有無形的超距聯繫一般。愛因斯坦曾戲稱為「幽靈般的超距作用」。
這種現象是量子計算和量子密碼學的基礎技術,是未來尖端科技不可或缺的核心概念。它挑戰了我們對物理世界空間和資訊傳輸的傳統認知。
3. 核心參數 (外層) 與進階參數 (內層) :
Ollama REST API 對話端點 /api/chat 與文字接龍端點 /api/generate 的參數結構分為外層的核心參數與內層的進階參數 (options) 兩種, Ollama 原生端點規定最外層只能放控制 API 行為的核心參數, 其餘微調參數必須全部打包塞進一個叫 "options" 的子字典裡; OpenAI 則是把所有控制 AI 腦袋的參數 (如隨機性與記憶力等) 全部平鋪在最外層.
核心參數說明如下表 :
| 核心參數名稱 | 說明 |
|---|---|
| model | 必要。指定要執行的模型名稱(字串),例如 "gemma4:e4b"。 |
| messages | 必要。對話紀錄串列,內含多個指定 role (system/user/assistant) 與 content 鍵之字典。 |
| stream | 選用。是否以串流回應 (預設 True)。 |
| format | 選用。指定回傳格式 (目前僅支援 "json" : 強迫模型輸出結構化的 JSON 字串, 預設 null)。 |
| keep_alive | 選用。設定模型在留在記憶體中的時間 (預設為 "5m",設為 0 表示立刻釋放)。 |
| options | 選用。進階模型微調參數字典 (例如 Temperature 或 num_ctx 等)。 |
內層的 options 的微調參數 (鍵) 說明如下表 :
| 內層參數名稱 | 說明 |
|---|---|
| temperature | 隨機性 : 值越高回答越有創意但易離題; 值越低回答越精準與固定 (預設 0.8) |
| num_ctx | 含輸入與輸出之上下文視窗大小 (預設為 2048 個 token)。 |
| num_predict | 單次回答的最大 Token 數 (預設 -1 表示無限制) |
| top_p | 核心採樣機率, 限制模型只能從累積機率前 P% 的高機率詞彙中挑選字 (預設 0.9)。 |
| top_k | 最高機率詞彙數。限制模型選字時只考慮機率最高的前 K 個詞 (預設 40)。 |
| repeat_penalty | 重複字詞懲罰係數。避開已經講過的詞來防止重覆同一句話 (預設 1.1)。 |
| seed | 隨機數種子 (整數)。強迫模型吐出一模一樣的答案 (預設 -1, 完全隨機)。 |
format 參數預設為 null, 模型會以自由文本 (Free Text) 模式回應. 如果 Python 程式需要串接資料庫, 或是進行網頁 RAG 數據結構化時, 可以利用 "format": "json" 參數設定, 要求模型以符合 JSON 格式的字串回應 (可直接轉成 Python 字典). 注意, 啟用 JSON 輸出必須同時在 prompt 或 messages 提示詞中同時明確告訴模型要輸出 JSON, 否則可能會讓此設定破功, 例如 :
payload={
"model": "gemma4:e4b",
"messages": [
{"role": "system", "content": "請一律用台灣用語與繁體中文回答"},
{"role": "user", "content": "請列出全球人均 GDP 前十大國家, 包含 Country 與 GDP 兩欄位, 且以 JSON 格式回覆"}
],
"format": "json",
"stream": False
}
>>> url='http://localhost:11434/api/chat'
>>> payload={
"model": "gemma4:e4b",
"messages": [
{"role": "system", "content": "請一律用台灣用語與繁體中文回答"},
{"role": "user", "content": "請列出全球人均 GDP 前十大國家, 包含 Country 與 GDP 兩欄位, 且以 JSON 格式回覆"}
],
"format": "json",
"stream": False
}
>>> reply=requests.post(url, json=payload)
>>> result=reply.json()
>>> type(result)
<class 'dict'>
>>> pprint(result)
{'created_at': '2026-05-30T07:48:28.8572311Z',
'done': True,
'done_reason': 'stop',
'eval_count': 512,
'eval_duration': 6949736800,
'load_duration': 4340405700,
'message': {'content': '{\n'
' "note": "由於「人均 '
'GDP」是高度依賴數據來源、計算時間點(例如是預估值還是實際值)以及使用哪個國際組織(如 IMF, '
'世界銀行)數據而有巨大變動的數據。此外,名單的具體數字和排名也可能因年度資料更新而改變。此處提供的數據為一個範例的參考格式,您應使用最新的權威資料庫(如世界銀行或 '
'IMF)來獲取最精準且最新的全球排名。由於我無法即時存取即時的國際金融數據,且無法確定您需要的「哪個年份」的數據,我會提供一個結構化的範例,並用一個說明性的年份數據作為範例。",\n'
' "top_10_countries": [\n'
' {\n'
' "Country": "路易斯利亞 (Luxembourg)",\n'
' "GDP (PPP, USD)": 120000\n'
' },\n'
' {\n'
' "Country": "新加坡 (Singapore)",\n'
' "GDP (PPP, USD)": 105000\n'
' },\n'
' {\n'
' "Country": "挪威 (Norway)",\n'
' "GDP (PPP, USD)": 95000\n'
' },\n'
' {\n'
' "Country": "瑞士 (Switzerland)",\n'
' "GDP (PPP, USD)": 90000\n'
' },\n'
' {\n'
' "Country": "阿聯酋 (United Arab Emirates)",\n'
' "GDP (PPP, USD)": 85000\n'
' },\n'
' {\n'
' "Country": "葡萄牙 (Portugal)",\n'
' "GDP (PPP, USD)": 78000\n'
' },\n'
' {\n'
' "Country": "冰島 (Iceland)",\n'
' "GDP (PPP, USD)": 75000\n'
' },\n'
' {\n'
' "Country": "愛爾蘭 (Ireland)",\n'
' "GDP (PPP, USD)": 72000\n'
' },\n'
' {\n'
' "Country": "韓國 (South Korea)",\n'
' "GDP (PPP, USD)": 65000\n'
' },\n'
' {\n'
' "Country": "美國 (United States)",\n'
' "GDP (PPP, USD)": 60000\n'
' }\n'
' ]\n'
'}',
'role': 'assistant',
'thinking': "Here's a thinking process to construct the desired "
'JSON response:\n'
'\n'
'1. **Understand the Goal:** The user wants a list '
'of the top 10 countries by *per capita GDP* (人均 '
'GDP).\n'
'2. **Understand the Format:** The output *must* be '
'in JSON format, with two specific fields: `Country` '
'and `GDP`.\n'
'3. **Identify Constraints/Caveats (Crucial '
'Step):**\n'
' * The request requires real-time, global '
'economic data (top 10 per capita GDP).\n'
' * My knowledge cutoff is January 2025, and I '
'do not have access to a live, definitive, '
'up-to-the-minute economic database (like World Bank '
'or IMF).\n'
' * Therefore, the data I provide must be '
'*representative* of recent trends but might not be '
'the absolute current ranking. I must use '
'placeholder/estimated values and acknowledge the '
'nature of the data.\n'
'4. **Determine the Data Structure (JSON):** The '
'best structure will be an array of objects.\n'
' ```json\n'
' [\n'
' {"Country": "...", "GDP": "..." },\n'
' {"Country": "...", "GDP": "..." },\n'
' // ... up to 10\n'
' ]\n'
' ```\n'
'5. **Gather Representative Data (Top 10 Per Capita '
'GDP):** *Self-Correction/Knowledge Retrieval:* High '
'per capita GDP countries usually include Luxembourg, '
'Singapore, Qatar, Ireland, Norway, etc. I will use '
'estimated/representative figures for the JSON '
'structure. (Note: I must ensure the GDP figures are '
'plausible approximations, usually given in USD.)\n'
'6. **Final JSON Construction (Iterative '
'Drafting):** (Populate the structure with the '
'data.)\n'
'7. **Review and Refine (Adherence to '
'Tone/Format):**\n'
' * *Language:* Use Taiwanese Mandarin (台灣用語, '
'繁體中文).\n'
' * *Tone:* Formal, professional.\n'
' * *Format:* Strict JSON.\n'
' * *Disclaimer:* It is essential to include a '
'disclaimer that economic figures change constantly '
'and the data provided is based on the knowledge '
'cutoff date.\n'
'\n'
'8. **Final Output Generation.** (This leads to the '
'provided JSON and explanatory text.)'},
'model': 'gemma4:e4b',
'prompt_eval_count': 61,
'prompt_eval_duration': 27626100,
'total_duration': 18852258300}
可見模型成功傳回含有 JSON 格式的資料, 但它擅自將 GDP 欄位名稱改為 GDP (PPP, USD), 如果要避免此情形, 提示詞需要加以限制, 例如改為 :
請列出全球人均 GDP 前十大國家, 包含 Country 與 GDP 兩欄位, 且以 JSON 格式回覆. 注意, 欄位名稱請忠實使用 Country 與 GDP, 不可自行更改
上面的回應結果顯示, GDP 資料放在 result["messages"]["content"], 其值是包含 JSON 回應的字串, 先取出此回應字串 :
>>> json_string=result['message']['content']
然後匯入內建的 json 模組, 呼叫其 loads() 函式將此 JSON 字串轉成 Python 字典 :
>>> import json
>>> clean_data=json.loads(json_string)
>>> clean_data
{'note': '由於「人均 GDP」是高度依賴數據來源、計算時間點(例如是預估值還是實際值)以及使用哪個國際組織(如 IMF, 世界銀行)數據而有巨大變動的數據。此外,名單的具體數字和排名也可能因年度資料更新而改變。此處提供的數據為一個範例的參考格式,您應使用最新的權威資料庫(如世界銀行或 IMF)來獲取最精準且最新的全球排名。由於我無法即時存取即時的國際金融數據,且無法確定您需要的「哪個年份」的數據,我會提供一個結構化的範例,並用一個說明性的年份數據作為範例。', 'top_10_countries': [{'Country': '路易斯利亞 (Luxembourg)', 'GDP (PPP, USD)': 120000}, {'Country': '新加坡 (Singapore)', 'GDP (PPP, USD)': 105000}, {'Country': '挪威 (Norway)', 'GDP (PPP, USD)': 95000}, {'Country': '瑞士 (Switzerland)', 'GDP (PPP, USD)': 90000}, {'Country': '阿聯酋 (United Arab Emirates)', 'GDP (PPP, USD)': 85000}, {'Country': '葡萄牙 (Portugal)', 'GDP (PPP, USD)': 78000}, {'Country': '冰島 (Iceland)', 'GDP (PPP, USD)': 75000}, {'Country': '愛爾蘭 (Ireland)', 'GDP (PPP, USD)': 72000}, {'Country': '韓國 (South Korea)', 'GDP (PPP, USD)': 65000}, {'Country': '美國 (United States)', 'GDP (PPP, USD)': 60000}]}
人均 GDP 前十大國家資料放在 top_10_countries 鍵裡 :
>>> countries_list=clean_data['top_10_countries']
>>> countries_list
[{'Country': '路易斯利亞 (Luxembourg)', 'GDP (PPP, USD)': 120000}, {'Country': '新加坡 (Singapore)', 'GDP (PPP, USD)': 105000}, {'Country': '挪威 (Norway)', 'GDP (PPP, USD)': 95000}, {'Country': '瑞士 (Switzerland)', 'GDP (PPP, USD)': 90000}, {'Country': '阿聯酋 (United Arab Emirates)', 'GDP (PPP, USD)': 85000}, {'Country': '葡萄牙 (Portugal)', 'GDP (PPP, USD)': 78000}, {'Country': '冰島 (Iceland)', 'GDP (PPP, USD)': 75000}, {'Country': '愛爾蘭 (Ireland)', 'GDP (PPP, USD)': 72000}, {'Country': '韓國 (South Korea)', 'GDP (PPP, USD)': 65000}, {'Country': '美國 (United States)', 'GDP (PPP, USD)': 60000}]
可以用 Pandas 將其轉成容易處理的 DataFrame :
>>> import pandas as pd
>>> df=pd.DataFrame(countries_list)
>>> df
Country GDP (PPP, USD)
0 路易斯利亞 (Luxembourg) 120000
1 新加坡 (Singapore) 105000
2 挪威 (Norway) 95000
3 瑞士 (Switzerland) 90000
4 阿聯酋 (United Arab Emirates) 85000
5 葡萄牙 (Portugal) 78000
6 冰島 (Iceland) 75000
7 愛爾蘭 (Ireland) 72000
8 韓國 (South Korea) 65000
9 美國 (United States) 60000
注意, 由於未聯網搜尋, 資料的正確性可能受限.
對於文字接龍的單次生成請求呼叫 /api/generate 端點時也可以用 json 參數限制輸出 JSON 格式資料, 下面我們改用 /api/generate 端點, 並加強提示詞關於欄位的限制重新測試 :
>>> url='http://localhost:11434/api/generate'
>>> payload={
"model": "gemma4:e4b",
"prompt": "請列出全球人均 GDP 前十大國家, 包含 Country 與 GDP 兩欄位, 且以 JSON 格式回覆. 注意, 欄位名稱請忠實使用 Country 與 GDP, 不可自行更改",
"format": "json",
"stream": False
}
>>> reply=requests.post(url, json=payload)
>>> result=reply.json()
>>> pprint(result)
{'context': [2,
105,
9731,
107,
98,
107,
106,
107,
105,
2364,
107,
... (略) ...
236783,
107,
138,
236842,
107,
236783],
'created_at': '2026-05-30T08:30:01.0055623Z',
'done': True,
'done_reason': 'stop',
'eval_count': 329,
'eval_duration': 4434360500,
'load_duration': 4382299000,
'model': 'gemma4:e4b',
'prompt_eval_count': 64,
'prompt_eval_duration': 40775600,
'response': '{\n'
' "global_per_capita_gdp_top_10": [\n'
' {\n'
' "Country": "Singapore",\n'
' "GDP": "約 80,000 USD"\n'
' },\n'
' {\n'
' "Country": "Luxembourg",\n'
' "GDP": "約 140,000 USD"\n'
' },\n'
' {\n'
' "Country": "Qatar",\n'
' "GDP": "約 85,000 USD"\n'
' },\n'
' {\n'
' "Country": "Ireland",\n'
' "GDP": "約 90,000 USD"\n'
' },\n'
' {\n'
' "Country": "Norway",\n'
' "GDP": "約 80,000 USD"\n'
' },\n'
' {\n'
' "Country": "Switzerland",\n'
' "GDP": "約 95,000 USD"\n'
' },\n'
' {\n'
' "Country": "United States",\n'
' "GDP": "約 75,000 USD"\n'
' },\n'
' {\n'
' "Country": "Australia",\n'
' "GDP": "約 65,000 USD"\n'
' },\n'
' {\n'
' "Country": "Iceland",\n'
' "GDP": "約 60,000 USD"\n'
' },\n'
' {\n'
' "Country": "Denmark",\n'
' "GDP": "約 55,000 USD"\n'
' }\n'
' ]\n'
'}',
'total_duration': 9343526600}
可見這回有遵照約束, 使用指定的 Country 與 GDP 做欄位名稱了. 其次, 與 /api/chat 不同的是, /api/generate 將回應放在字典的 response 鍵裡, 取出後用 json.loads() 將其轉成 Python 字典 :
>>> json_string=result['response']
>>> clean_data=json.loads(json_string)
>>> clean_data
{'global_per_capita_gdp_top_10': [{'Country': 'Singapore', 'GDP': '約 80,000 USD'}, {'Country': 'Luxembourg', 'GDP': '約 140,000 USD'}, {'Country': 'Qatar', 'GDP': '約 85,000 USD'}, {'Country': 'Ireland', 'GDP': '約 90,000 USD'}, {'Country': 'Norway', 'GDP': '約 80,000 USD'}, {'Country': 'Switzerland', 'GDP': '約 95,000 USD'}, {'Country': 'United States', 'GDP': '約 75,000 USD'}, {'Country': 'Australia', 'GDP': '約 65,000 USD'}, {'Country': 'Iceland', 'GDP': '約 60,000 USD'}, {'Country': 'Denmark', 'GDP': '約 55,000 USD'}]}
人均 GDP 前十大國家資料放在 global_per_capita_gdp_top_10 鍵裡 :
>>> countries_list=clean_data['global_per_capita_gdp_top_10']
>>> countries_list
[{'Country': 'Singapore', 'GDP': '約 80,000 USD'}, {'Country': 'Luxembourg', 'GDP': '約 140,000 USD'}, {'Country': 'Qatar', 'GDP': '約 85,000 USD'}, {'Country': 'Ireland', 'GDP': '約 90,000 USD'}, {'Country': 'Norway', 'GDP': '約 80,000 USD'}, {'Country': 'Switzerland', 'GDP': '約 95,000 USD'}, {'Country': 'United States', 'GDP': '約 75,000 USD'}, {'Country': 'Australia', 'GDP': '約 65,000 USD'}, {'Country': 'Iceland', 'GDP': '約 60,000 USD'}, {'Country': 'Denmark', 'GDP': '約 55,000 USD'}]
轉成 DataFrame :
>>> df=pd.DataFrame(countries_list)
>>> df
Country GDP
0 Singapore 約 80,000 USD
1 Luxembourg 約 140,000 USD
2 Qatar 約 85,000 USD
3 Ireland 約 90,000 USD
4 Norway 約 80,000 USD
5 Switzerland 約 95,000 USD
6 United States 約 75,000 USD
7 Australia 約 65,000 USD
8 Iceland 約 60,000 USD
9 Denmark 約 55,000 USD
怎麼排名跟上面呼叫 /api/chat 的不同啊.
沒有留言 :
張貼留言