只會 Prompt 已經不夠了:從「下指令」到「蓋系統」的思維進化
前言:別在 Prompt 的死胡同裡打轉 現在只要打開社群媒體,滿地都是「最強 Prompt 指令集」或「這 10 個指令讓 AI 變神級工具」。 剛接觸 AI 的時候,我也沉迷過這種「咒語」的力量。但實戰幾次後你會發現,如果你還在糾結如何微調 Prompt 的那幾個形容詞,那你其實還是在做「手工藝」。這種方式產出的結果不穩定、無法規模化,更重要的是,它非常耗神。 如果你有留意近一兩年的技術演進,你會發現真正的高手已經不再討論怎麼寫咒語了。大家在聊的是 Workflow(工作流)、Agent(代理人) 以及 System(系統)。 這篇文章我想從一個資深開發者與 PM 的視角,拿一個最簡單的任務——**「寫一篇高品質的技術文章」**做案例,帶你看這幾個層級的思維斷層在哪裡。 1. Prompt 層:一次性的「介面」溝通,也是體力活 這是最基礎的使用方式,你打開 ChatGPT,輸入一段話: 「請幫我寫一篇關於 AI Workflow 的技術文章,包含架構說明與範例。」 這就是 Prompt 層。雖然它很強大,但本質上它只是在「調用模型」。它的限制顯而易見: 抽盲盒效應: 成果好壞全看運氣。今天給你 80 分,明天可能只剩 60 分。 孤島式作業: AI 沒辦法讀取你電腦裡的其他資料,也不懂你的審美標準,它只活在那一次的對話框裡。 認知負荷高: 每次遇到新文章,你都要重新把需求、背景、限制條件再描述一遍。 老實說,Prompt 只是個「對話介面」,而非一個「系統」。 它適合處理小型、零碎、一次性的任務(像是修一個小 Bug 或翻譯短句)。但如果你想靠它穩定產出專業內容,那只是在用 AI 換另一種形式的「體力活」罷了。 2. Skill 層:把「手感」封裝成「能力模組」 當你對 AI 寫作有了點心得,你會發現有些要求是重疊的。這時候,你會開始定義一套固定的「寫作標準」。這在開發者眼中,就是所謂的封裝(Encapsulation)。 例如,你會建立一個「技術寫手」的能力: 預設框架: 必須包含摘要、關鍵技術細節、範例程式碼與結論。 統一風格: 語氣要像資深工程師在分享,不准用太過浮誇的形容詞。 工具聯動: 在動筆前,AI 必須先去搜尋網路上的最新趨勢,並讀取你指定的筆記文件。 當你把這些「咒語」固定下來,並賦予它特定的工具存取權,你就建立了一個 Skill(技能)。在這一層,你的角色從「打字員」變成了「教練」。你不再是給一段話,而是定義一套「標準」。 3. Workflow 層:串接能力的「自動化流水線」 但問題來了,寫出一篇能拿得出手的技術文章,真的只靠一個「寫手技能」就能搞定嗎? ...
JSON Formatter: Format and Debug JSON for APIs and Config Files
If you’ve ever tried reading a minified API response by eye, you know how painful it gets. One long line, no indentation, nested objects buried inside nested objects — it’s basically unreadable. That’s the main reason I built a JSON Formatter tool. Paste your JSON in, hit format, and it immediately becomes something a human can actually parse. This post walks through why JSON formatting matters in practice, and covers a few real scenarios where having a formatter nearby saves time. ...
Token 是什麼?LLM 為何只讀 Token?
前言 上篇講到LLM,這片就來說說裡面很常提到的字「Token」。Token 是語言模型可理解的最小單位,它像積木一樣把長句拆成小塊,讓模型逐一處理。這篇文章用更平易近人的方式解釋什麼是 token、為何 LLM 不直接處理完整的字詞,以及常見的斷詞方法,幫助你輕鬆掌握這個看似陌生卻無所不在的概念。 Token 是什麼?為何要用它? LLM 是數學模型,必須把文字轉成向量才能運算。最簡單的做法是把每個單詞賦予一個向量,但這樣會遇到兩個問題: 無法處理新詞或拼錯字:如果訓練時沒有見過某個單字,模型就不知道如何表示它。 忽略語素結構:許多語言中,一個詞可以拆成詞根和詞綴,例如「running」「runner」都來自「run」。 為了兼顧彈性與效率,LLM 會先把輸入拆解成更小的 token。有人將 token 定義是「字、字元或包含標點的組合」。有些文中也強調,token 是模型用來處理文字的原子單位。透過 token,模型得以把複雜的語言拆成固定大小的向量,並對每個 token 指派唯一編號。 幾種常見的斷詞方法 不同 LLM 可能採用不同的分割策略。以下三種是最常見的斷詞方法: 字級(Word):按空格切割。例如 “unbelievable performance” 被當作兩個 token。優點是數量少,但遇到新詞就無法處理。 字元級(Character):每個字母和空白都是一個 token。它能處理任何輸入,但 token 數大幅增加,效率低下。 子詞級(Subword):介於上述兩者之間,把常見詞根或片段視為 token,是現在主流 LLM 的做法。例如 “unbelievable performance” 可以拆成 ["un", "bel", "iev", "able", "per", "form", "ance"]。 圖中展示同一句話經過三種方法切分後的樣子: 把詞拆成小塊,看出不同斷詞方式產生的 token 數量差異。 簡易 Python 範例:手寫子詞切分 以下程式碼示範如何使用簡單的片段詞表(模擬 BPE 結果)把長詞拆成 token。一樣,雖然不是完整的演算法,但能幫你理解 tokenization 的動作。 # 定義一組常見片段 subwords = ["un", "bel", "iev", "able", "per", "form", "ance"] # 簡易子詞切分函式 def tokenize_subwords(text, subwords): tokens = [] i = 0 while i < len(text): match = None for sw in sorted(subwords, key=len, reverse=True): if text[i:].startswith(sw): match = sw break if match: tokens.append(match) i += len(match) else: tokens.append(text[i]) i += 1 return tokens # 輸入與輸出示範 print(tokenize_subwords("unbelievable performance".replace(" ", ""), subwords)) # 可能輸出: ['un', 'bel', 'iev', 'able', 'per', 'form', 'ance'] 每次優先匹配片段詞表中最長的項目,若無匹配則輸出單個字母,呈現出子詞分割的概念。 ...
《大語言模型 LLM:其實做的事情比你想像中更單純》
前言 Introduction 如果你最近有用過 ChatGPT、Claude、Gemini,你已經在跟 LLM(Large Language Model)聊天了。這些模型看起來像懂很多、會推理、甚至比朋友還健談,但它們的核心動作其實無比樸實:預測下一個字。 聽起來太簡單?沒錯,但模型規模一大、資料一多、演算法一調整,這個「下一字遊戲」就能演變成看起來像魔法的語言能力。 這篇文章會用工程師看得順、初學者不會暈的方式,把 LLM 的概念、原理與常見應用一次講清楚。 LLM 是什麼? LLM 的任務比你想像的還簡單 從理論上看,LLM 是一種深度學習模型,被訓練去完成一件事情: 在語境下,挑選「最可能出現的下一個 token」。 token 可以是中文字、英文單字的一部分、符號、甚至數字。 當模型知道怎麼選下一個 token,然後不停重複這件事,就能組出一整段看起來像人寫的句子。 為什麼它看起來「懂很多」? 因為它被餵了大量內容:百科、文章、科技文、論壇討論…… 在海量語料裡找模式後,它自然會「講得像很懂」。 我們的感官上就感覺它懂很多、很能理解。 圖 1:LLM 下一字預測核心概念示意圖 LLM 是怎麼「學會」語言的? LLM 的學習流程大致分成四個步驟,其實蠻務實的: 1. 收集大量文本(資料越多,模型越穩) 來源包含書籍、文章、程式碼、論壇、維基百科等。 資料不是越亂越好,但越多越有機會讀懂語言中的隱性規律。 2. 分詞(Tokenization) 模型不直接處理字,而是處理 token。 你可以把它想像成:「把一個蛋糕切成很多比較好吞的碎片」。 3. 預測下一個 token(核心任務) 模型會計算所有候選 token 的機率: 哪個最可能? 哪個跟前文最適合? 哪個不太會讓模型出糗? 機率最高者 → 輸出。 4. 誤差反向調整(Backpropagation) 預測錯了? → 重新調參 → 再預測 → 再調 → 重複幾十億次 這就是 LLM 的訓練人生。 ...
推薦系統中的冷啟動問題
什麼是冷啟動? 推薦系統主要是把物品推薦給喜歡的使用者,在使用的環境中,物品和使用者皆會持續的增長變化,也因此會持續面對有新物品和新使用者的情境;有新的物品和使用者使得無法做好的推薦就稱為冷啟動,我們要討論在這種情況下如何做合適的推薦。 基本的冷啟動可以分成三類: 使用者冷啟動:新用戶產生時沒有有任何瀏覽購買紀錄,如何推薦用品的問題。 物品冷啟動:新物品如何推薦給合適的用戶。 系統冷啟動:新系統上線時,物品、使用者、資料皆不足的推薦問題。 圖片來源:https://www.researchgate.net/figure/Illustration-of-Cold-Start-problem-in-recommender-systems-New-user-problem-left-and_fig2_332511384 接下來我們介紹幾個常見的解決方式 排行榜推薦 新物品的推薦 秉持著大家會喜新厭舊的心態,推薦新的物品給使用者;像是電影、影集等等就很適合,有新影片上線時,不管是新或舊的使用者都會想看。 熱門物品的推薦 推薦大家都喜歡的物品給使用者,這是非常常見的做法,簡單有效;也可以用作新演算法的AB test或benchmark,等到資料足夠後才做個性化推薦。 常用物品、必需品推薦 推薦生活必需品、常用物品給新使用者;這種情況適合一些居家用品、常用家電、廚房用具等等的情境。 標籤推薦 這種方式是針對前三項作更細微的推薦,像是ott 串流平台可以直接選擇喜劇、動作片、愛情片等等的推薦;但要注意標籤要先設計完整。 圖片來源:https://deepai.org/publication/addressing-the-cold-start-problem-in-outfit-recommendation-using-visual-preference-modelling 簡易的使用者推薦 簡易的使用者推薦 根據使用者簡易的年齡、性別等等資料分出人群進行推薦。 授權平台推薦 導入第三方社交平台facebook、google等等,根據這些平台的歷史數據進行推薦。 問答題推薦 目前有許多平台都是這種方式,註冊登入時會問幾個問題,了解你的喜好,根據你的反饋來推薦物品。 新物品的相似度推薦 新物品推薦系統在不同的平台有不同的重要程度,在新聞媒體等等時效性強的平台就特別重要,必須要快速的推薦出去,不然時間過了這個資訊、消息也就不重要了。 新物品跟用戶的相似度 計算新物品的特徵(標籤、cos相似度、TF-IDF、影像相似度等等)和使用者的行為特徵進行推薦。 新物品和舊物品的相似度 新物品進入平台後,根據平台的標籤、屬性資訊等等,計算出相似的物品,再推薦給喜歡此物品的使用者。 試探策略 這幾年短影片的流行,無論是純做短影片的網站,抑或是一般影音平台的短影片,皆是爆發性的成長;快速試探策略就很適合,快速、隨機推薦影片給使用者,再根據使用者觀看、點擊、滑動瀏覽網站、停留時間等等的行為,快速獲得使用者的資訊,再進行推薦。 結尾 上面是簡單介紹幾個常用的方式,還有許多做法可以解決遇到的冷啟動問題,主要必須先定義好問題,知道自己產品、平台的特徵、類型、使用者如何才會滿意等等的資訊,才能真正的對症下藥。 最後推薦幾篇論文,大家有興趣可以看看他們遇到的問題是什麼又是如何解決的。 Behavior-based popularity ranking on Amazon Video Billion-scale Commodity Embedding for E-commerce Recommendation in Alibaba Performance of recommender algorithms on top-N recommendation tasks ...
Python Chunks
當我們要把list分成好幾個chunk時的幾種做法 yield def chunks1(input_list, n): for i in range(0, len(input_list), n): yield input_list[i:i + n] input_list = [i for i in range(0, 15)] print(list(chunks1(input_list, 4))) ## [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14]] 一行for迴圈 input_list = [i for i in range(0, 15)] n = 3 output_list = [input_list[i:i+ n] for i in range(0, len(input_list), n)] print(output_list) ## [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14]] iterable 針對任何iterable from itertools import islice def chunks2(input_iter, n): input_list = iter(input_iter) return iter(lambda: tuple(islice(input_list, n)), ()) input_list = [i for i in range(0, 15)] n = 4 print(list(chunks2(input_list, n))) ## [(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14)] Numpy import numpy as np input_list = [i for i in range(0, 15)] np.array_split(input_list, 5) ## [array([0, 1, 2]), ## array([3, 4, 5]), ## array([6, 7, 8]), ## array([ 9, 10, 11]), ## array([12, 13, 14])] 上述幾種簡單的方式皆可達成 ...
Python 爬取每日股價(2)
上篇文章Python 爬取每日股價(1)學會了找到所需資料和爬取的方法。 接下來資料要儲存成xlsx格式。 台灣證券交易所 先安裝pandas和xlsxwriter pip install pandas pip install xlsxwriter 如果是colab,使用!pip install xlsxwriter 藉由上篇找到的資料位置"data9",以及觀察到資料是根據每天做儲存。 因此我們使用基於每天的資料處理方式,把所需要的股票資料、開盤價、收盤價等等存放。 import requests import pandas as pd from pprint import pprint as pprint date = "20210827" url = f"https://www.twse.com.tw/exchangeReport/MI_INDEX?response=json&date={date}&type=ALLBUT0999&_=1630244648174" res = requests.get(url) data = res.json() data_list = data["data9"] columns = data["fields9"] df = pd.DataFrame(data_list, columns=columns) writer = pd.ExcelWriter('twse_data.xlsx', engine='xlsxwriter') df.to_excel(writer, sheet_name=date, index=False) writer.save() # pprint(data_list) f-strings in Python PEP 498 打開儲存的"twse_data.xlsx" 每日收盤行情 我們可以依靠改變日期獲得過去的資料, 存成不同分頁或是檔案。 也可以依據未來需要的使用資料方式來改變儲存格式。
How to scrape Yahoo Finance stock data with Python
This time, we are going to learn the hands-on ability to scrape Yahoo financial data. Set-up python environment. Yahoo Finance page. For example, Alphabet Inc. (GOOG). Scrape & parse the page. The page we will be scrape. In the “network” page, we can’t find the json data. You can get all the data from the page source in script. View page source - script - root.App.main from bs4 import BeautifulSoup import re import json import requests response = requests.get("https://finance.yahoo.com/quote/GOOG?p=GOOG&.tsrc=fin-srch") soup = BeautifulSoup(response.text, "html.parser") ## print(soup.prettify()) script = soup.find('script', text=re.compile('root.App.main')).text data = json.loads(re.search("root.App.main\\s+=\\s+({.*})", script).group(1)) stores = data["context"]["dispatcher"]["stores"] print(stores) Response data ...
Python 爬取每日股價(1)
如何取得每日的股價資訊 進入證交所每日收盤行情,選擇全部(不含…),可以看到有許多選項可點。 找到每日收盤行情 110.08.27每日收盤行情 點擊F12進入開發者環境,再點選Network,觀察我們要的數據資訊 Python及時股價 點選XHR找到傳送數據的Requests import requests url = "https://www.twse.com.tw/exchangeReport/MI_INDEX?response=json&date=20210827&type=ALLBUT0999&_=1630244648174" res = requests.get(url) res.json() 得到Json,並在data9找到全部的股票數據 {'alignsStyle1': [['center', 'center', 'center', 'center', 'center', 'center'], ... ... 'data9': [['0050', '元大台灣50', '16,875,047', '9,673', '2,328,482,421', '136.70', '138.50', '136.45', '138.15', '<p style= color:red>+</p>', '1.15', '138.15', '4', '138.20', '103', '0.00'], ['0051', '元大中型100', '17,810', '63', '1,003,448', '56.20', '56.60', '56.20', '56.60', '<p style= color:red>+</p>', '0.35', '56.55', '1', '56.60', '9', '0.00'], ... ... 'subtitle9': '110年08月27日每日收盤行情(全部(不含權證、牛熊證))'} 幾個重要的數據 ['0050', #股票代號 '元大台灣50', '16,875,047', #成交股數 '9,673', '2,328,482,421', '136.70', #開盤價 '138.50', #最高價 '136.45', #最低價 '138.15', #收盤價 '<p style= color:red>+</p>', '1.15', '138.15', '4', '138.20', '103', '0.00'], 輕鬆完成,在爬取過程中還是非常簡單的, ...
Deep Reinforcement learning
Reinforcement learning (RL) is a framework where agents learn to perform actions in an environment so as to maximize a reward. It’s actually training an AI to learn through every mistake and find the correct path without any label. The two main components are the environment and the agent. Deep Reinforcement learning (DRL) combined with deep learning technology is even more powerful. AlphaGo, is a typical application of deep reinforcement learning. ...