在4月24日,O’Reilly Media將舉辦名為「與AI編碼:我們所知的軟體開發的終結」的線上技術會議,重點介紹AI如何已經在提升開發者的生產力,並為他們的組織帶來實際價值。如果你正在為未來的開發實踐而努力,並有興趣在活動中發言,我們希望在3月5日之前聽到你的消息。你可以在這裡找到更多信息和我們的演講徵集。
嗨,我是加州大學聖地牙哥分校(UC San Diego)的一名認知科學和設計教授,最近我在Radar上寫了一些關於我使用生成式AI工具(如ChatGPT)編碼和交流的經驗。在這篇文章中,我想談談如何利用生成式AI來擴展我的一個學術軟體項目——Python Tutor工具,這是一個用於學習編程的AI聊天導師。我們經常聽到生成式AI在大型商業環境中的應用,但對於小型非營利項目卻聽得不多。因此,這篇文章作為一個案例研究,展示了我如何在時間、資源和專業知識都有限的情況下,將生成式AI添加到我的個人項目中。這個項目讓我對當前這個時刻感到非常興奮,因為強大的生成式AI工具正開始變得對像我這樣的非專家更可及。
為了提供一些背景,過去15年來,我一直在運營Python Tutor(https://pythontutor.com/),這是一個免費的在線工具,全球有數千萬人使用它來編寫、運行和視覺化調試他們的代碼(最初是Python,現在也支持Java、C、C++和JavaScript)。Python Tutor主要用於幫助學生逐步理解和調試他們的作業代碼,通過查看其調用堆棧和數據結構來實現。可以把它想像成一位虛擬導師,會在白板上畫圖來顯示運行狀態。它最適合用於學生在計算機科學課程或在線編碼教程中常見的小段自包含代碼。
這裡是一個使用Python Tutor逐步執行構建Python元組鏈表的遞歸函數的例子。在當前步驟中,視覺化顯示了對listSum函數的兩次遞歸調用和指向列表節點的各種指針。你可以向前和向後移動滑塊,查看這段代碼的逐步運行:
Python Tutor的AI聊天功能
早在2009年,當我還是研究生的時候,我就設想創建Python Tutor,成為一個可以幫助學生解決編程問題的自動化導師(這也是我選擇這個項目名稱的原因)。但當時的AI技術還遠遠不夠成熟,無法模擬人類導師。一些AI研究者在智能輔導系統領域發表了論文,但沒有可廣泛使用的軟體庫或API可以用來製作AI導師。因此,我花了很多年時間開發一個多功能的代碼視覺化工具,供人類導師用來解釋代碼執行。
快轉到2024年,生成式AI工具如ChatGPT、Claude等基於大型語言模型(LLMs)現在能夠進行人類水平的對話,特別是在與編程相關的技術主題上。特別是,它們在生成和解釋小段自包含代碼(例如少於100行)方面非常出色,這正是Python Tutor的目標用例。因此,利用這項技術,我將基於AI的聊天功能添加到Python Tutor中。這裡有一個簡單的演示。
首先,我設計了用戶界面,讓它儘可能簡單:用戶的代碼和視覺化下方只有一個聊天框:

有一個下拉菜單的模板可以幫助你開始,但你可以輸入任何你想問的問題。當你點擊「發送」時,AI導師會將你的代碼、當前視覺化狀態(例如調用堆棧和數據結構)、終端文本輸出和問題發送給LLM,然後在這裡回應你:

注意,LLM可以「看到」你當前的代碼和視覺化,因此它可以向你解釋這裡發生了什麼。這模擬了專家人類導師會說的話。然後你可以像和人類一樣繼續進行雙向對話。
除了解釋代碼,這個AI導師的另一個常見用例是幫助學生在遇到編譯器或運行時錯誤時解決問題,這對於初學者來說可能非常沮喪。這裡是一個Python中的索引超出範圍錯誤:

每當出現錯誤時,工具會自動在你的聊天框中填充「幫我修復這個錯誤」,但你可以從下拉菜單中選擇不同的問題(如上所示)。當你在這裡點擊「發送」時,AI導師會回應類似這樣的內容:

注意,當AI生成代碼示例時,每個示例下方都有一個「可視化我」按鈕,這樣你可以直接在Python Tutor中可視化它。這讓你能夠視覺化地逐步執行它,並向AI提出後續問題。
除了詢問有關你代碼的具體問題,你還可以詢問一般的編程問題,甚至是職業相關的問題,比如如何準備技術編碼面試。例如:

…它將生成代碼示例,你可以在不離開Python Tutor網站的情況下進行可視化。
相對於直接使用ChatGPT的好處
這裡顯而易見的問題是:在Python Tutor中使用AI聊天的好處是什麼,而不是將你的代碼和問題粘貼到ChatGPT中?我認為有幾個主要好處,特別是對於Python Tutor的目標受眾——剛開始學習編程的初學者:
1) 便利性——數百萬學生已經在Python Tutor中編寫、編譯、運行和視覺化調試代碼,因此對他們來說,在不離開網站的情況下提問是非常自然的。如果他們需要從文本編輯器或IDE中選擇代碼,將其複製到像ChatGPT這樣的其他網站,然後可能還要複製錯誤消息、終端輸出,並描述運行時發生的事情(例如數據結構的值),這樣的用戶體驗會更加繁瑣。一些現代IDE確實內建了AI聊天,但這些需要專業知識來設置,因為它們是為專業軟體開發人員設計的。相比之下,Python Tutor對於初學者的主要吸引力一直是其易於訪問:任何人都可以訪問pythontutor.com並立即開始編碼,而無需安裝軟體或創建用戶帳戶。
2) 初學者友好的LLM提示——接下來,即使有人願意花時間將他們的代碼、錯誤消息、終端輸出和運行狀態複製粘貼到ChatGPT中,我發現初學者在提出提示(即書面指示)方面並不擅長,這會導致LLM生成難以理解的回應。Python Tutor的AI聊天通過增強聊天內容來解決這個問題,使用類似以下的系統提示來強調直接性、簡潔性和初學者友好性:
你是一位專業的編程教師,我是一名請求幫助的學生,使用${LANGUAGE}。– 請簡潔明了。如果可能,將你的回應控制在300字以內。– 以初學者在入門編程課程中的理解水平進行回答。– 如果需要編輯我的代碼,請儘量少改動,並保留我原始代碼的盡可能多的部分。添加代碼註釋以解釋你的更改。– 你編寫的任何代碼都應該是自包含的,無需導入外部庫。– 使用GitHub Flavored Markdown。
它還以良好的結構格式化用戶的代碼、錯誤消息、相關行號和運行狀態,便於LLM進行處理。最後,它提供了一個下拉菜單,包含常見問題和命令,如「這個錯誤消息是什麼意思?」和「逐行解釋這段代碼的作用。」這樣初學者可以立即開始編寫問題,而不必盯著空白的聊天框。所有這些幕後的提示模板幫助用戶避免直接使用ChatGPT時常見的問題,例如生成的解釋過於冗長、充滿行話,對初學者來說難以理解。
3) 運行你的代碼,而不僅僅是「查看」它——最後,如果你將代碼和問題粘貼到ChatGPT中,它會像人類導師一樣「檢查」你的代碼。但它實際上並不運行你的代碼,因此它不知道在執行過程中實際存在什麼函數調用、變量和數據結構。雖然現代LLM在「查看」代碼時能夠很好地猜測代碼的作用,但沒有什麼能替代在真實計算機上運行代碼。相比之下,Python Tutor運行你的代碼,因此當你向AI聊天詢問發生了什麼時,它會將調用堆棧、數據結構和終端輸出的實際值發送給LLM,這樣希望能得到更有幫助的回應。
使用生成式AI來構建生成式AI
現在你已經看到了Python Tutor的AI聊天功能是如何運作的,你可能會想:我是否使用生成式AI來幫助我構建這個生成式AI功能?是的,也不是。生成式AI在我開始時幫了我很大的忙,但隨著我深入,我發現它的用處減少了。
使用生成式AI創建模擬用戶界面
我的方法是首先構建一個獨立的基於網頁的LLM聊天應用,然後將其整合到Python Tutor的代碼庫中。在2024年11月,我購買了Claude Pro訂閱,因為我聽說它的代碼生成能力很好。我開始與Claude合作,生成一個具有熟悉功能的LLM聊天應用的模擬用戶界面,比如用戶輸入框、LLM和人類用戶的聊天文本氣泡、使用Markdown的HTML格式、語法高亮的代碼塊,以及逐步流式傳輸LLM的回應,而不是讓用戶等待直到完成。這些都不是創新的功能——這是使用LLM聊天界面(如ChatGPT)時每個人都期望的。
我喜歡與Claude合作構建這個模擬界面,因為它生成了可在瀏覽器中運行的HTML、CSS和JavaScript代碼的實時可運行版本,這樣我就可以與它互動,而無需將代碼複製到自己的項目中(Simon Willison寫了一篇很棒的文章,介紹這個Claude Artifacts功能)。然而,主要的缺點是,每當我請求即使是小的代碼調整時,重新生成所有項目代碼可能需要長達一分鐘,並且有時會煩人地留下部分不完整的代碼片段,導致代碼無法運行。如果我使用像Cursor或Windsurf這樣的AI驅動IDE,我就能夠要求即時的增量編輯。但我不想麻煩自己設置更複雜的工具,而Claude對於啟動我的前端來說已經足夠好了。
在本地托管LLM的錯誤開始
現在來談談後端。我最初是在我的筆記本電腦上玩Ollama時開始這個項目的,這是一個允許我免費在本地運行LLM的應用,而無需支付雲提供商的費用。幾個月前(2024年9月),Llama 3.2發布了,這個版本有更小的模型,如1B和3B(分別為10億和30億參數)。這些模型的能力遠不及當前最先進的模型,後者在撰寫時的大小是它們的100到1000倍。我無法希望在本地運行更大的模型(例如Llama 405B),但這些較小的1B和3B模型在我的筆記本電腦上運行良好,因此看起來很有前途。
注意,我上一次嘗試在本地運行LLM是GPT-2(是的,2!)在2021年,那是非常糟糕的——設置過程繁瑣,需要安裝一堆Python依賴,運行速度超慢,並且生成的結果毫無意義。因此多年來,我認為在Python Tutor上自我托管自己的LLM是不可行的。我也不想支付使用像ChatGPT或Claude這樣的雲API的費用,因為Python Tutor是一個預算緊張的非營利項目;我無法承擔為超過10,000名每日活躍用戶提供免費AI導師的高昂API成本。
但現在,三年後,較小的LLM和Ollama的易用性讓我相信時機已經成熟,可以自我托管自己的LLM以供Python Tutor使用。因此,我使用Claude和ChatGPT幫助我編寫一些樣板代碼,將我的原型網頁聊天前端與調用Ollama以在本地運行Llama 1B/3B的Node.js後端連接起來。一旦我在筆記本電腦上讓這個演示運行起來,我的目標是將其托管在我可以訪問的幾台大學Linux伺服器上。
但在短短一周內,我收到了壞消息,這最終成為一個巨大的意外之喜。我們大學的IT人員告訴我,我將無法訪問幾台擁有足夠CPU和RAM來運行Ollama的Linux伺服器,因此我不得不放棄最初的自我托管計劃。注意,我想部署的那種低成本伺服器沒有GPU,因此它們在CPU上運行Ollama的速度要慢得多。但在我的初步測試中,一個像Llama 3.2 3B這樣的小模型仍然能夠很好地處理幾個並發請求,對於最多4個並發用戶,生成的回應在45秒內完成。這在任何標準下都不算「好」,但在我不想支付雲LLM API的情況下,這是我能做到的最好結果。我想,如果我有4台副本伺服器,那麼我可以在45秒內為最多16個並發用戶提供服務,或者在20秒內為8個並發用戶提供服務(粗略估算)。這不會是最佳的用戶體驗,但Python Tutor對用戶來說是免費的,因此他們的期望不會太高。我的計劃是編寫自己的負載平衡代碼,以將進入的請求指向負載最輕的伺服器,並編寫排隊代碼,以便如果有更多的並發用戶試圖連接而伺服器的容量不足,它將排隊以避免崩潰。然後,我需要編寫所有的系統管理/DevOps代碼來監控這些伺服器,保持它們的最新狀態,並在它們失敗時重新啟動。這一切對我來說都是一個艱巨的編碼和測試前景,尤其是因為我不是專業的軟體開發人員。但令我欣慰的是,現在我不必做任何這種繁瑣的工作,因為大學的伺服器計劃已經不再可行。
轉向OpenRouter雲API
那麼我最終使用了什麼呢?巧合的是,這段時間有人向我推薦了OpenRouter,這是一個API,允許我編寫一次代碼,通過更改配置字符串中的LLM名稱來訪問多種付費LLM。我註冊了,獲得了API密鑰,並在幾分鐘內開始對雲中的Llama 3B進行查詢。我對這段代碼的設置之簡單感到震驚!所以我迅速將其包裝在一個伺服器後端中,實時流式傳輸LLM的回應文本到我的前端,使用SSE(伺服器推送事件),並在模擬聊天用戶界面中顯示。以下是我的Python後端代碼的精華:
import openai # OpenRouter使用OpenAI API,因此首先運行”pip install openai” client = openai.OpenAI( base_url=”https://openrouter.ai/api/v1″,api_key=<你的API密鑰>)completion = client.chat.completions.create( model=<LLM的名稱,例如Llama 3.2 3B>,messages=<你對LLM的查詢>,stream=True)for chunk in completion:text = chunk.choices[0].delta.content<將文本流式傳輸到網頁前端,使用伺服器推送事件>
OpenRouter確實需要付費,但我願意試一試,因為Llama 3B的價格看起來比像ChatGPT或Claude這樣的最先進模型更合理。在撰寫時,3B的價格約為每百萬個標記0.04美元,而最先進的LLM的價格高達500倍(ChatGPT-4o為12.50美元,Claude 3.5 Sonnet為18美元)。我會害怕以這些價格使用ChatGPT或Claude,但我對更便宜的Llama 3B感到放心。另一个让我安心的是,我知道如果使用量突然激增,我不會醒來面對一個巨大的帳單;OpenRouter讓我可以設置固定金額,如果用完了,我的API調用就會失敗,而不會再向我的信用卡收費。
為了額外的安心,我實施了自己的速率限制:1) 每個用戶的輸入和總聊天對話長度有限制,以控制成本(並減少幻覺,因為較小的LLM在對話變長時往往會「失控」);2) 每個用戶每分鐘只能發送一條聊天,這再次防止了過度使用。希望這對Python Tutor用戶來說不是大問題,因為他們至少需要一分鐘來閱讀LLM的回應,嘗試建議的代碼修復,然後再提出後續問題。
使用OpenRouter的雲API而不是在我大學的伺服器上自我托管,結果要好得多,因為:1) Python Tutor用戶可以在幾秒鐘內獲得回應,而不是等待30-45秒;2) 我不需要進行任何系統管理/DevOps工作來維護我的伺服器,或編寫自己的負載平衡或排隊代碼來與Ollama接口;3) 我可以通過更改配置字符串輕鬆嘗試不同的LLM。
生成式AI作為思考夥伴和隨需教師
在讓「幸福路徑」運行(即OpenRouter API調用成功)後,我花了很多時間思考錯誤條件,並確保我的代碼能很好地處理這些情況,因為我想提供良好的用戶體驗。在這裡,我使用ChatGPT和Claude作為思考夥伴,讓生成式AI幫我想出一些我最初沒有考慮到的邊緣情況。然後,我創建了一個調試UI面板,下面有十幾個按鈕,我可以按下這些按鈕來模擬特定錯誤,以測試我的應用如何處理這些情況:

在讓我的獨立LLM聊天應用在錯誤情況下穩定運行後,是時候將其整合到主要的Python Tutor代碼庫中。這個過程花了很多時間和精力,但因為我確保我的獨立應用使用Python Tutor所使用的舊JavaScript庫的相同版本,所以這是直接的。這意味著在我項目的開始,我必須指導Claude生成使用這些舊庫的模擬前端代碼;否則,它將默認使用現代JavaScript框架,如React或Svelte,這些框架與使用2010年時期的jQuery和朋友們編寫的Python Tutor不兼容。
在這個時候,我發現自己在日常工作中並不真正使用生成式AI,因為我在自己的代碼庫的舒適區內工作。生成式AI在開始時幫助我找出「未知的未知」。但現在問題已經明確,我感到更舒適自己編寫每一行代碼。從這一點開始,我的日常工作涉及大量的UI/UX打磨,以使用戶體驗更加流暢。我發現直接編寫代碼比思考如何指導生成式AI為我編寫代碼要容易得多。此外,我想理解進入我的代碼庫的每一行代碼,因為我知道每一行都可能需要在未來的幾年中進行維護。因此,即使我可以使用生成式AI在短期內更快地編碼,但這可能會在未來以微妙的錯誤回來困擾我,因為我沒有完全理解AI生成代碼的含義。
話雖如此,我仍然發現生成式AI在回答像「我如何在現代JavaScript中編寫X?」這樣的問題時非常有用。它是一個學習技術細節的絕佳資源,我有時會將AI回應中的示例代碼調整到我的代碼庫中。但至少對於這個項目,我不覺得讓生成式AI「駕駛」生成大量代碼,然後我逐字複製粘貼是安全的。
最後的修飾和啟動
我希望在新年之前啟動,因此隨著11月進入12月,我在使用戶體驗更加完善方面取得了穩定的進展。有無數小細節需要處理,但這是任何非平凡軟體項目的情況。我沒有資源來評估較小的LLM在用戶可能在Python Tutor網站上提出的實際問題上的表現,但從非正式測試中,我對1B和3B模型生成不正確解釋的頻率感到沮喪(但並不驚訝)。我嘗試升級到Llama 8B模型,但效果仍然不佳。我抱著希望,調整我的系統提示會改善性能。我沒有花太多時間在這上面,但我的初步印象是,無論如何調整都無法彌補較小模型的能力不足——就像狗的腦袋與人類的腦袋相比。
幸運的是,在12月底——距離啟動只有兩周——Meta發布了一個新的Llama 3.3 70B模型。我快要沒有時間了,所以我選擇了簡單的辦法,將我的OpenRouter配置切換到使用它。我的AI導師的回應立刻變得更好,錯誤更少,即使是使用我原本的系統提示。我對從3B到70B的價格上漲10倍(每百萬標記從0.04美元增加到0.42美元)感到緊張,但還是試了一試。
結語和經驗教訓
快轉到現在。自從啟動以來已經過去兩個月,成本到目前為止是合理的。隨著我嚴格的速率限制,Python Tutor用戶每天進行約2000次LLM查詢,這樣的成本每天不到一美元,使用的是Llama 3.3 70B。我希望隨著時間的推移,我能夠轉向更強大的模型,因為它們的價格會下降。總之,看到這個AI聊天功能在網站上運行,讓我感到非常滿足,因為自從我很久以前創建Python Tutor以來,我一直夢想著這一點。我喜歡雲API和低成本LLM使生成式AI對像我這樣的非專家變得可及。
以下是一些對於想在個人應用中玩弄生成式AI的人的建議:
我強烈建議使用像OpenRouter這樣的雲API提供商,而不是在自己的虛擬機上自我托管LLM(甚至更糟的是,購買帶有GPU的實體機器)。在這裡使用雲端要便宜得多,也方便得多,特別是對於個人規模的項目。即使每天有數千次查詢,Python Tutor的AI成本也比支付虛擬機或實體機器的費用要小得多。等待是有益的!不必總是走在最前沿。如果我在2021年OpenAI GPT-3 API的早期階段就嘗試這個項目,就像早期採用者那樣,我將面臨許多痛苦,因為需要處理快速變化的API中的粗糙邊緣;當時甚至沒有易於使用的指令調整聊天模型!此外,當時不會有任何在線文檔或最佳實踐的教程,而(非常元)LLM也不知道如何幫助我使用那些API進行編碼,因為必要的文檔並未提供給它們進行訓練。只需等待幾年,我就能夠使用高質量、穩定的雲API,並在編碼我的應用時獲得Claude和ChatGPT的有用技術幫助。
玩弄LLM API比使用大多數人使用的網頁界面要有趣得多。通過使用這些API編寫代碼,你可以直觀地「感受」什麼有效,什麼無效。由於這些都是普通的網頁API,你可以將它們集成到你的項目中,無論你的項目使用的是哪種編程語言。我發現,較大的LLM的簡短、直接和簡單的系統提示會勝過較小LLM的複雜系統提示。較短的系統提示也意味著每次查詢的成本更低(因為它們必須包含在查詢中)。如果你沒有資源來評估輸出質量,則不必擔心。想出一些手工測試並在開發過程中運行——在我的情況下,這是一些我希望請求Python Tutor的AI聊天幫我修復的棘手代碼。如果你過於擔心優化LLM性能,那麼你將永遠無法發佈任何東西!如果你發現自己渴望更好的質量,首先升級到更大的LLM,而不是繁瑣地調整你的提示。
估算在生產中運行LLM的成本非常困難,因為成本是按每百萬個輸入/輸出標記計算的,這並不直觀。估算的最佳方法是運行一些測試查詢,了解LLM回應的冗長程度,然後查看你的帳戶儀表板,看看每次查詢的成本是多少。例如,典型查詢的成本是1/10美分、1美分還是多美分?除非你嘗試,否則無法找到答案。我的直覺是,這可能比你想像的便宜,而且如果成本成為問題,你總是可以實施速率限制或切換到更低成本的模型。
與上述相關,如果你正在製作原型或某些最初只有少數人會使用的東西,那麼一定要使用最先進的LLM來展示最令人印象深刻的結果。價格並不重要,因為你不會發出那麼多查詢。但如果你的應用像Python Tutor那樣有相當多的用戶,那麼就選擇一個在價格上仍然表現良好的較小模型。對我來說,似乎Llama 3.3 70B在2025年初達到了這種平衡。但隨著新模型的出現,我會重新評估這些價格與性能的權衡。
本文由 AI 台灣 運用 AI 技術編撰,內容僅供參考,請自行核實相關資訊。
歡迎加入我們的 AI TAIWAN 台灣人工智慧中心 FB 社團,
隨時掌握最新 AI 動態與實用資訊!