爆火AI編程應用何以單挑微軟?Cursor團隊2小時訪談揭秘
智東西編譯 尹明順 吳浪娜編輯 漠影
智東西10月10日消息,當地時間10月7日,知名播客主持人Lex Fridman和Cursor團隊4名創始成員Michael Truell、Sualeh Asif、Arvid Lunnemark和Aman Sanger進行了一場長達兩個半小時的對話。
Cursor是一個基於VS Code的代碼編輯器,它爲AI輔助編程添加了許多強大的功能,它引起了編程和AI社區的關注和興奮,風頭正盛。那麼Cursor作爲一個初創團隊,如何能夠與科技巨頭微軟的Github Copilot一戰呢?
在播客中,幾人深度討論了Cursor團隊目前的發展以及未來的探索方向,還廣泛談論了編程的未來,以及人類與AI在設計和構建複雜而強大的系統方面達成合作的各種可能。
團隊成員在博客中詳細分享了Cursor如何理解你的代碼庫並以此爲依據預測你下一步要做什麼,然後以驚人的速度生成代碼,從而有效提升了編程效率。
他們還介紹了Cursor更多功能,不僅擅長自動補全代碼,它還引入了影子工作區輔助編寫代碼,並能通過簡單的描述來命令AI編寫更復雜的代碼,完成更多的任務。
此外,團隊成員還對AI編程的技術要領進行了深入分析,並對人與AI編程之間的倫理問題展開探討,提到了希望將OpenAI o1模型集成的願景。
值得一提的是,團隊成員認爲,快速就是有趣(Fast is Fun)。吸引人們在電腦上創造新內容的原因之一就是驚人的迭代速度,而在其他領域,你可能會受到資源或能力的限制,但在編程的世界,只要有你和計算機,你就能非常快速地構建出非常酷的東西。
創始團隊中,Aman Sanger擔任Cursor的CEO,是一位工程師和企業家,此前他曾在Instagram和Facebook擔任領導職位。Arvid Lunnemark是公司的CTO,是一位工程師,曾在Spotify和Google工作。Michael Truell擔任設計主管,Sualeh Asif擔任公司COO。
▲播客現場介紹Cursor團隊成員(來源:YouTube)
以下是對該播客內容的完整編譯(爲提高可讀性,智東西調整了部分問答的順序,並在不違背原意的前提下進行了一定的增刪修改)。
一、類似增強版文字處理器代碼編輯器可處理更多任務
Lex:代碼編輯器有什麼用?
Michael:代碼編輯器主要是構建軟件的地方,長期以來,而在今天或很長一段時間裡,代碼編輯器是指對正式編程語言進行文本編輯的地方。對於非程序員來說,可以將代碼編輯器理解爲程序員專用的增強版文字處理器。之所以說它是增強版,是因爲代碼有很多結構。因此,這個“文字處理器”即代碼編輯器,實際上可以爲你做很多事情,而這些是傳統的文字處理器在文本編輯方面做不到的。
這包括給代碼中不同的元素提供視覺區分,以便快速瀏覽;可以在代碼庫中導航,直接跳轉到用戶正在使用的內容的定義,就像在互聯網上使用超鏈接;還有進行錯誤檢查以捕獲基本錯誤等。傳統上,這就是代碼編輯器的定義。我認爲在未來十年內,隨着構建軟件的方式有所變化,代碼編輯器的定義也將發生很大變化。
Lex:我認爲代碼編輯器也應該很有趣。
Arvid:是的,這非常重要。這實際上是我們決定構建什麼的一個被低估的方面。我們構建的很多東西,通過試用它們,再進行實驗,然後因爲它們不有趣而把它們扔掉。所以,有趣的很大一部分在於很多時候要快。快速就是有趣。
Michael:基本上,我認爲吸引很多人在電腦上構建東西的原因之一是這種驚人的迭代速度,而在其他領域,你可能會受到資源或能力的限制……甚至將一大羣人聚在一起編程也是一件令人驚奇的事情,只有你和計算機,你才能可以非常快速地構建出非常酷的東西。
二、Copilot的粉絲到開發CursorCursor起源的兩個重要時刻
Lex:對於不知道的人來說,Cursor是一個超級酷的新編輯器,它是VS Code的一個分支。聽聽你們對自己編輯器之旅的講述會很有趣。我想你們所有人都是VS Code和Copilot的忠實粉絲。你們是如何接觸到VS Code的,以及這如何引導你們走向Cursor?
Aman:我們最初都是純Vim用戶。沒有Neovim,只有純Vim和終端。至少對我自己來說,當Copilot出來的時候,大約是2021年,我真的很想試試它。所以我進入了VS Code,這是唯一可以使用Copilot的代碼編輯器,儘管我真的很喜歡使用Vim,但VS Code和Copilot的體驗足以說服我發生轉變。所以,這基本上成了默認設置,直到我們開始開發Cursor。
Lex:也許應該解釋一下Copilot的功能。它是一個非常不錯的自動補全工具。當你開始寫東西時,它會建議一到三行代碼來完成它,這是一種有趣的體驗。你知道當你有親密的朋友時,你的朋友會幫你補全你的話一樣。當它做得很好時,會有一種親密的感覺。可能“親密”這個詞不太準確,但有一種很酷的感覺,就像“哇,它懂我”。然而當它不懂你時,就會有一種不愉快的感覺。所以會有這種摩擦。但我想說,對於很多人來說,那種“它懂我”的感覺壓倒了“它不懂我”的感覺。
Arvid:我認爲GitHub Copilot被低估的一點是,即使它出錯了也有點煩人,但並沒有那麼糟糕,因爲你只需再輸入一個字符,也許它就能理解你了,或者你再輸入一個字符,它就能理解你了。所以即使它錯了,也不會那麼糟糕。
Sualeh:你可以進行迭代和修復。我的意思是,對我來說,Copilot的另一個被低估的部分是,它是第一個真正的AI產品,第一個面向消費者的語言模型產品。
Lex:所以Copilot有點像語言模型的第一個殺手級應用。
Michael:是的,它的beta版在2021年發佈。
Lex:那麼Cursor的起源故事是什麼樣的?
Michael:大約在2020年,OpenAI發佈了scaling laws論文,這是一個關鍵時刻,這個領域似乎取得了清晰可預測的進展,即使我們沒有任何新想法,看起來只要有更多的計算能力和更多的數據,就可以讓這些模型變得更好。
Lex:順便說一下,我們可能需要花三到四個小時來討論scaling laws這個話題。但簡而言之,這是一系列論文中的一篇,這些論文提出了一系列觀點,認爲在機器學習領域,模型的大小和數據的大小,越大越好。
Michael:所以在那段時間,我們中的一些人有很多關於這會是什麼樣子的概念性討論。對於所有這些不同知識領域的工作者來說,這項技術的發展將如何讓他們變得更好?然後我認爲有幾個時刻,那篇論文中預測的理論進展開始變得非常具體,開始覺得你可以在AI領域做實際上有用的工作,而不需要去攻讀博士。感覺現在可以構建一整套真正有用的系統。我認爲第一個時刻是玩轉Copilot的早期測試版,那種感覺很棒,很神奇。
我認爲第二個重要時刻是提前獲得了GPT-4的早期訪問權限。大約在2022年底,我們開始修改這個模型,能力的升級感覺非常巨大。在此之前,我們一直在研究一些不同的項目。因爲Copilot,因爲scaling laws,因爲我們之前對這項技術的興趣,我們一直在修改程序員使用的工具,但這些都是非常具體的工具。所以我們正在爲必須在Jupyter Notebook上工作的金融專業人士構建工具,或者嘗試使用這些模型進行靜態分析。
而GPT-4的升級讓我們感覺這確實證實了我們之前預測的理論進展。感覺就像在那個時間點你可以立即構建很多東西。而且,如果我們保持一致,這真的感覺不僅僅是一個點解決方案,這將涉及整個編程領域,所有編程都將通過這些模型進行,而且感覺這需要一種不同類型的編程環境,一種不同的編程方式,所以我們開始構建那種更大的願景。
Sualeh:有一件事我印象非常深刻,我的室友是IMO金牌得主,美國有一個叫Putnam的比賽,這有點像是大學生的IMO,也是一個數學競賽,它非常精彩。我記得Shengtong和Aman在2022年6月左右打賭,賭能否在2024年6月或7月的IMO中獲得金牌。
Lex:IMO是國際數學奧林匹克競賽。
Sualeh:Arvid和我也參加了,儘管我在某種程度上相信進步,但我認爲想拿下IMO金牌,Aman是在異想天開。但老實說我完全錯了,但這可能是團隊中最有先見之明的賭注。
Aman:我清楚地記得我和Michael有一次對話,在那之前我還沒有非常深入和批判性地思考過scaling laws,他提出了一個問題,爲什麼scaling laws就是你需要的一切,或者爲什麼scaling laws不會帶來巨大的進步?我想我經歷了悲傷的五個階段,最後終於接受了。
我想從那以後我一直對進步充滿希望和樂觀。我想要補充的一點是,這也取決於你將在哪些領域看到進步。數學是一個偉大的領域,尤其是形式化定理證明,因爲你可以得到一個很好的信號來實際驗證事物是否正確。所以這意味着像強化學習這樣的東西可以工作得非常好,我認爲你可能會擁有在數學上非常超人的系統,但從技術上講仍然沒有AGI。
三、Cursor預測你下一步或將改變構建軟件的方式
Lex:好的,那麼我們談談Cursor。
Michael:對我們來說,決定做一個編輯器似乎是顯而易見的,至少對於我們想要做的事情和實現的目標來說是這樣的,因爲當我們開始開發編輯器時,想法是這些模型會變得更好,它們的能力會提高,這將徹底改變你構建軟件的方式,這不僅會讓你獲得巨大的生產力提升,而且會帶來根本性的改變,構建軟件的方式也會發生很大的變化。所以,如果你是現有編程環境的一個插件,那麼你對代碼編輯器的控制會非常有限,我們不想被這些限制所束縛。我們希望能夠構建最有用的東西。
Lex:Cursor與Copilot在某種程度上是競爭對手,你們如何取勝?靠速度和功能質量嗎?
Aman:是的,我想這是一個相當有趣,也許非常獨特的領域,如果你看看以前的技術浪潮,也許只有一種主要的事情發生,它解鎖了一波新的公司,但每年,每一個模型能力的跳躍,你就解鎖了一波新的功能,尤其是編程中可能實現的事情。
所以我認爲在AI編程中,即使只是領先幾個月,更不用說一年了,也會讓你的產品變得有用得多。我認爲一年後的Cursor將需要讓今天的Cursor看起來過時。我認爲微軟已經做了很多很棒的事情,但我認爲他們不像一個初創公司那樣有很大的空間真正繼續創新和推動這方面的發展。
Sualeh:我不知道我是否從功能的角度來考慮它,還是從程序員的能力的角度來考慮它。隨着新的o1模型發佈,我相信會有更多不同類型的模型,比如更長上下文的,也許更快,所有這些瘋狂的想法你都可以去嘗試,希望其中10%的瘋狂想法能夠變成某種很酷且有用的東西,我們希望人們能更快地擁有它。換句話說,一個被低估的事實是,我們正在爲自己創造它。
當我們開始構建Cursor時,你真的會感到沮喪,你可以看到模型變得更好,但Copilot的體驗沒有改變。就像,這些傢伙天花板越來越高,爲什麼他們不創造新東西?他們應該創造新東西。那些Alpha功能在哪裡?但沒有那些功能。如果做了新東西,我確信它是一門好生意。我敢肯定這是一項偉大的事業,我是那種真的想嘗試和使用新東西的人,但很長一段時間都沒有做出新東西。
Lex:當你比較Cursor和Copilot時,Copilot很快就開始因爲某種原因而給人一種過時了的感覺。
Arvid:是的,我認爲對我們有幫助的一件事是,我們把所有事情都做成了,我們在開發用戶體驗和與模型交互的方式的同時,也在開發如何讓模型給出更好的答案。所以你如何構建提示,或者你如何找到上下文,對於Cursor Tab來說,你如何訓練模型?所以我認爲這有助於我們讓同一批人來負責整個體驗。
Sualeh:是的,就像製作UI的人和訓練模型的人坐在一起,相距18英尺遠,甚至經常是同一個人。你可以創造出一些如果不交談、不實驗就不可能實現的東西。
Lex:你們用Cursor來寫Cursor?
Arvid:當然。
Lex:我們聊聊無所不能的Tab,堪稱加強版自動補全的功能。Tab是怎麼工作的?它是什麼?
Michael:概括來說,我認爲Cursor目前在兩個方面表現不錯。當然,它還有其他功能,但這兩項功能對程序員來說非常有幫助。一是它就像在你身後觀察,是一個速度很快、可以搶在你前面輸入並預測你下一步要做什麼的同事。這也是一個好的自動補全功能的初衷,預測你下一步要做什麼,但我們可以更進一步,不僅預測Cursor後面的字符,還能預測你要進行的下一個整體更改、下一個差異、接下來要跳轉的位置。
第二個是,能幫助你有時領先於AI,告訴它該做什麼,實現從指令到代碼的轉換。爲了做好這兩件事,我們在提高編輯體驗上下了很多功夫,讓它們既符合人體工程學,又足夠智能和快速。
四、加強版自動補全功能Cursor Tab消除編輯器中的低熵操作
Sualeh:我們真正想要實現的是,讓模型能夠爲我們編輯代碼。這是我們的願望,在擁有能夠編輯代碼的優質模型之前,我們進行了多次嘗試。有了優質模型後,爲了讓使用體驗更加流暢,我們付出了很多努力來加快推理速度,並已經開始整合。
Michael剛纔也提到了這種跳轉到不同位置的能力,我認爲這種跳轉源於一種感覺,即一旦你接受了編輯,下一步要去哪裡應該非常明顯。比如,我做了這個更改,模型應該直接知道下一步要跳轉到第18行。如果你是WIM用戶,你可能會按18JJ之類的快捷鍵,但爲什麼我要這麼做呢?模型應該直接知道。
所以,你只需要按Tab鍵,它就會跳到第18行,然後顯示下一個編輯,你再按Tab鍵,你只需一直按Tab鍵,就能一直這樣操作下去。所以內部競爭就變成了,我們能讓人按多少次Tab鍵?一旦你有了這個想法,更抽象地說,要考慮的是如何使編輯達到零熵狀態。
也就是說,一旦你表達了意圖並且編輯,沒有新的信息片段來完成你的想法,但你仍然需要輸入一些字符來讓計算機理解你真正的想法,那麼模型或許應該“讀懂”你的心思,所有零熵位都應該只是被Tab鍵消除,這就是比較抽象的說法。
Aman:一個有趣的現象是,如果你看不同領域的language model loss,我相信每字節的比特數,這是一種對代碼字符標準化損失的衡量,比語言低,這意味着代碼中有很多token是非常可預測的,很多字符也是非常可預測的。而且,當你不僅僅是試圖自動補全代碼,而是預測用戶在編輯現有代碼時的下一步操作時,這種可預測性會被進一步放大。因此,Cursor Tab的目標是消除編輯器中所有低熵操作。一旦意圖得到有效確定,就讓我們直接跳轉到未來的某個時間點,向前跳過。
Lex:那麼,Tab在近期內應該能夠做什麼?
Aman:我可以講講讓這些功能發揮作用的一些細節。它們的延遲極低,所以你需要在這個任務上訓練小型模型。特別是,它們非常需要預填充token。這意味着它們有非常長的提示,能看到很多代碼,但實際上生成的token並不多。因此,使用MOE模型是最合適的。這是我們取得的一項突破,極大地提高了模型在長上下文中的性能。另一個突破是我們構建的投機解碼的變體,稱爲投機編輯。我認爲,這兩點是使其質量高、速度快的重要因素。
Lex:那麼緩存起作用了嗎?
Aman:緩存起到了巨大的作用。因爲你要處理這麼多輸入token,如果你在給定行中輸入的每個按鍵都要針對所有傳入的token重新運行模型,那麼一是會大大降低延遲,二是會讓GPU負載過高。因此,你需要設計用於模型的實際提示,使其具有緩存意識。然後,你需要跨請求重用KV緩存,以減少計算量。
Sualeh:希望能跳轉到不同的文件。所以,如果你在一個文件中進行了編輯,可能需要轉到另一個文件來完成你的想法,它也應該轉到第二個文件。
Arvid:完整的泛化是下一步行動預測。有時你需要在終端中運行命令,它應該能夠根據你編寫的代碼來建議命令,或者有時它會給出建議,但你很難判斷它是否正確,因爲你需要更多信息來學習。你需要知道類型才能驗證其是否正確。所以它或許應該先帶你到某個定義的地方,然後再帶你回來,這樣你就有了接受下一個補全所需的所有必要知識。
Michael:編程是一門奇特的學科,有時你接下來五分鐘要做什麼,實際上是可以根據你最近所做的事情預測出來的。那麼,我們能否創造一個世界,讓這接下來的五分鐘要麼在你放手的情況下自動完成,要麼在你看到下一步要做什麼並確認無誤後,通過輕觸Tab鍵就能快速實現。
五、增加顯示框提示代碼差異圍繞審查者體驗做設計
Lex:Cursor有一個非常酷且引人注目的功能,那就是整個diff界面情況。所以,模型用紅色和綠色顯示我們將如何修改代碼,然後可以在聊天窗口中應用它,它會向你顯示diff,你可以接受diff。那麼,你能講講這方面的發展方向嗎?
Sualeh:我們可能會有四五種不同的diff。我們爲自動補全功能優化了diff,因此它具有與審查大塊代碼時不同的diff接口。然後,我們正在嘗試優化另一個diff功能,以適應處理多個不同文件的情況。從高層次來看,差異在於,當你進行自動補全時,讀取速度應該非常快。實際上,在所有情況下它的讀取速度都應該非常快,但在自動補全功能中,你的注意力會集中在一個區域,人類無法同時關注太多不同的地方。
在界面方面,我們有當前框,如果你試圖在某個地方刪除代碼並嘗試添加其他代碼,它會嘗試在側面顯示一個框。
我們嘗試了三四種不同的方法來實現這個功能。最初的方法是在旁邊顯示一個帶有藍色刪除線的框。它過去會以Google Docs的風格顯示要刪除的代碼,你會看到一條線穿過,然後看到新代碼,這非常分散注意力。然後我們嘗試了很多不同的方法……有刪除、紅色高亮等。
之後的迭代版本有點有趣,你會按住Mac上的option鍵。所以它會高亮顯示一段代碼,以顯示AI有建議給你。在這個例子中,輸入和值都會變成藍色,藍色是用來高亮顯示AI對你有一個建議。它不會直接顯示建議的內容,而只是提示你AI有一個建議。如果你真的想看到它,就按住option鍵,然後你會看到新的建議,鬆開option鍵後,你又會看到原始代碼。
Arvid:我個人非常期待在這個領域做出很多改進。我們經常把它稱爲驗證問題,這些差異對於小範圍修改來說很好用。但如果是大範圍修改,或者涉及多個文件等情況,審查這些差異就有點費力了。所以這裡有幾個不同的想法。一個想法是,差異中的某些部分很重要,包含了很多信息。而有些部分的信息熵很低,就是重複的內容。
所以,或許可以高亮顯示重要的部分,而將不那麼重要的部分灰度顯示。或者,你可以有一個模型,它查看差異並發現,“哦,這裡可能有個漏洞。”我會用紅色波浪線標記出來,並提示你,“你應該重點審查這部分差異。”我覺得這類想法很令人興奮。
而且,你希望用一個智能模型來完成這項工作。目前的算法只是普通算法,沒有智能性。算法的設計需要智能,但你並不關心它是關於這個還是那個,你只希望模型能做到這一點。
Sualeh:所以我認爲一個普遍的問題是,隨着這些模型變得越來越智能,它們能夠提出的更改也會越來越大。而隨着更改越來越大,人類需要做的驗證工作也越來越多。這變得越來越……你需要幫助他們。我可不想把所有的時間都花在代碼審查上。
Aman:GitHub試圖通過代碼審查來解決這個問題。當你進行代碼審查時,你正在審查多個文件中的多個差異。但就像Arvid之前說的,我認爲你可以做得比代碼審查更好。代碼審查有點糟糕。你花了很多時間去理解那些通常對你來說很陌生的代碼,而且它甚至並不能真正捕捉到很多漏洞。
我認爲,使用語言模型可以顯著改善審查體驗,例如,使用Arvid之前描述的那種技巧,即可能指向實際重要的區域。我還認爲,如果代碼是由這些語言模型生成的,而不是由其他人生成的……代碼審查體驗是同時爲審查者和代碼編寫者設計的。
在代碼編寫者是語言模型的情況下,你就不必那麼關心他們的體驗了,你可以完全圍繞審查者來設計整個體驗,讓審查者的工作儘可能有趣、輕鬆、高效。我覺得,如果只是天真地試圖讓這些東西看起來像代碼審查,那就會出現問題。我認爲你可以更有創造力,並推動可能性的邊界。
Arvid:還有一個想法是,我認爲順序很重要。通常,當你審查一個拉取請求(Pull Request)時,你會看到一個文件列表,並且從上到下依次審查,但實際上,你可能需要先理解這個部分,因爲這部分在邏輯上是先發生的,然後你再理解下一部分,而你不希望自己弄清楚這一點,你希望有一個模型來引導你。
我認爲,並不是所有的編程都會變成自然語言。如果我正在和Sualeh結對編程,Sualeh在電腦前和鍵盤上,有時如果我來主導,我會對Sualeh說,嘿,實現這個功能,這樣就行了。但有時,向Sualeh解釋我想讓他做什麼太麻煩了,所以我會接過鍵盤,給他展示一下。
我寫一部分示例,然後他就明白了,這是最容易的溝通方式。所以我認爲,對AI來說也是這樣。有時,與AI溝通的最簡單方式就是展示一個示例,然後它就會在其他地方執行這個操作。
或者,有時如果你在做網站,例如,向AI展示你想要什麼最容易的方式不是告訴它要做什麼,而是拖動或繪製東西,也許最終我們會實現腦機接口之類的,你就可以讓它理解你在想什麼。所以我認爲自然語言會有一席之地。但我肯定地認爲,它不會是大多數人大部分時間編程的方式。
▲播客現場(來源:YouTube)
六、Apply定製模型創建差異更少的token使用智能的模型
Lex:我在使用這個編輯器時,真的感受到了通用AI(AGI)的存在。感覺它背後有很多機器學習在起作用。能告訴我一些讓它正常工作的機器學習內容嗎?
Aman:Cursor真正發揮作用的地方在於,我們通過這組自定義模型與前沿模型一起訓練,這些模型在推理密集型任務中表現非常出色。Cursor Tab就是一個很好的例子,你可以將這個模型專門化,使其甚至比前沿模型還要好。另一個領域是Apply,令人驚訝的是它需要定製模型,但這是必要的,而且在應用方面效果很好。
這些前沿模型在草擬代碼計劃和生成變化的粗略草圖方面相當出色,但實際上,爲訓練模型創建差異對於前沿模型來說是非常困難的。如果你嘗試用Sonnet、o1或任何其他前沿模型來做這件事,它會在一些愚蠢的事情上出錯,比如計算行數,尤其是在非常大的文件中。爲了解決這個問題,我們讓模型勾勒出這個粗略的代碼塊,表明將發生哪些變化,然後我們訓練一個模型,將該變化應用到文件中。
Lex:我們應該說,Apply模型會查看你的代碼,並給你一個非常好的新操作建議。而看似對人類來說微不足道的將兩者結合起來的步驟,並不容易。
Sualeh:與普遍認知相反,這不是一個確定性算法。
Aman:是的,你會發現其他地方有Apply的淺拷貝,但大多數情況下它都會失效,因爲你覺得可以嘗試進行一些確定性匹配,但它至少會有40%的時間失敗了,這會導致產品體驗非常糟糕。我認爲,隨着模型變得越來越智能,這種趨勢將繼續下去。所以,Apply還能讓你做另一件事,那就是你可以用更少的token來使用最智能的模型。這在生成所有這些token的延遲和成本方面都很昂貴。
所以,你可以給出一個非常粗略的草圖,然後讓你的模型去實現它,因爲實現這個非常粗略的代碼是一個更容易的任務。我認爲這種趨勢將繼續下去,你可以使用越來越智能的模型來進行計劃,然後也許可以由不那麼智能的模型來處理實現細節。也許你可以使用o1,也許它會有更強大的模型,給出更高級別的計劃,該計劃由sauna遞歸應用,然後是apply模型。
Sualeh:也許應該談談如何讓它變快。
Aman:讓它變快的一個主要組成部分是投機編輯。投機編輯是投機解碼的一種變體,也許簡要描述一下投機解碼會很有幫助。在投機解碼中,你可以利用這樣一個事實,大多數情況下,我會加上一個限定,那就是當你在語言模型生成中受到內存限制時,如果你一次處理多個token,這比一次生成一個token要快。
所以我們做的是,不是使用投機解碼通常所做的,即使用一個小模型來預測這些草稿token,然後你的大模型會進去驗證,在代碼編輯中,我們對現有代碼的外觀有非常強的先驗,並且該先驗實際上是完全相同的代碼。所以,你可以做的是,將原始代碼的部分反饋回模型,然後模型大多數情況下都會同意,“好吧,我只是要把這段代碼原樣輸出。”
所以,你可以並行處理所有這些行,只要使用足夠多塊即可。然後最終你會達到一個分歧點,模型現在將預測與原始代碼不同的文本。它會生成這些token,然後,在足夠多的token與原始代碼匹配後,我們會重新開始以代碼塊爲單位進行預測。
這實際上看起來就像是正常編輯代碼的一個更快版本。所以它看起來就像是模型重寫所有代碼的一個更快版本。因此,我們可以使用與diff相同的接口,但它的流式傳輸速度會快得多。
七、GPTClaude編程上哪個更勝一籌?
Lex:哪個大語言模型更擅長編程?GPT和Claude,在編程方面,哪個更勝一籌?
Aman:我認爲沒有哪個模型能在所有我們認爲重要的類別中都優於其他模型,這些類別包括速度、編輯代碼的能力、處理大量代碼的能力、長文本上下文,以及其他幾個因素和編程能力。我現在會說總體上最好的是Sonnet。我認爲這是大家的共識。
o1也非常有趣,它非常擅長推理。所以,如果你給它一些很難的編程面試風格的問題或者領導代碼問題,它能做得很好,但它似乎不如Sonnet那樣能理解你的大致意圖。如果你看看其他很多前沿模型,我有一個疑慮,那就是感覺它們不一定好……我不是說它們在基準測試上訓練,但它們在基準測試中的表現確實非常好,相對於所有中間的東西。
所以如果你嘗試所有這些基準測試和它們評估的分佈中的東西,它們會做得很好。但是,當你把它們稍微推離這個範圍時,Sonnet是我認爲在保持相同能力方面做得最好的。你在基準測試中擁有的能力與嘗試指示它執行任何與編程相關的事情時擁有的能力相同。
Sualeh:順便說一下,這是一個非常困難且至關重要的細節,基準測試與真正的編程之間的區別在於,真正的編程並不是面試風格的編程。人類有時會說半吊子的英語,有時你會說,“哦,按照我之前做的那樣做。”有時你會說,“添加這個東西,然後爲我做這個其他事情,然後製作這個UI元素。”但很多事情都是依賴於上下文的。你真的想要理解人類,然後按照人類的意願去做,而不是……也許抽象地說,面試問題是非常明確具體的。它們在很大程度上依賴於明確說明,而人類的東西則不那麼明確。
Aman:關於Claude,我聽到過一個有趣的觀點,我認爲AWS有不同的芯片,我懷疑它們與Nvidia GPU的數值略有不同,有人推測Claude性能下降可能與在AWS Bedrock上使用的量化版本與Anthropics GPU上運行的版本不同有關。
八、Preempt系統可自動實現預想效果
Lex:在這一切中,一個好的提示(Prompt)扮演着什麼角色?
Arvid:我認爲這取決於你使用的是哪個模型,它們都有細微的差別,對不同的提示反應也不同。但我認爲,最初的GPT-4和去年的某些模型,它們對提示相當敏感,而且它們的上下文窗口也很小。所以我們有很多與代碼庫相關的信息,這些信息可能在提示中會很有用。
你有文檔、你添加的文件、你有對話歷史,然後問題就來了,你如何決定實際上要把什麼放進提示裡,特別是當你的空間有限時?對於今天的模型,即使你有長上下文,填滿整個上下文窗口就意味着它會變慢。這意味着有時模型實際上會感到困惑,而且有些模型比其他模型更容易困惑。
我們內部有一個系統叫做Preempt,它在這方面對我們有一些幫助。我認爲它是爲我們有8000個token上下文窗口的時代建立的,它有點類似於當你在製作一個網站時。你希望它在手機上能正常工作,你希望它在桌面上也能正常工作,而你有這些動態信息,但你沒有固定的佈局。
例如,如果你設計一本印刷雜誌,你知道你可以把東西放在哪裡,但是當你有一個網站或者一個提示時,你有這些輸入,然後你需要格式化它們,以便它們能總是正常工作,即使輸入非常大,你可能必須削減一些內容。所以我們的想法是,好吧,讓我們從中獲得一些啓發。
設計網站的最佳方式是什麼?我們非常喜歡的是React以及它的聲明式方法,你在JavaScript中使用JSX,然後直接聲明:這就是我想要的,我認爲這個部分比其他部分具有更高的優先級或更高的Z軸順序。在網頁設計中,你有一個渲染引擎,就像Chrome一樣,在Cursor中它是一個preempt渲染器,它會將所有內容都放在頁面上。你只需說明你想要的效果,渲染器會自動幫你實現。我們發現這鐘方法非常有幫助,而且它的作用隨着時間的推移已經發生了變化。
最初它是爲了適應較小的上下文窗口,而現在它在拆分進入提示詞的數據和實際生成方面發揮了很大作用。因此,它更容易調試,因爲你可以修改提示詞,然後在舊的提示上進行測試,直接查看你的修改是否真的提升了整個評估集的表現。
Lex:所以你們是真的用JSX來提示嗎?
Arvid:是的。我們有一個文件組件,它接收光標。通常在你的文件中有一行光標所在的位置,那可能是最重要的一行,因爲那是你正在查看的一行。然後你可以給出優先級。而且,如果你有很多來自整個代碼庫的代碼塊,你可以使用檢索和嵌入等重新排序分數來爲這些組件添加優先級。
Lex:那麼當人類提問時,也應該嘗試使用那樣的東西嗎?這是否意味着問題會變得鬆散和混亂,還是這樣的系統應該鼓勵人們更清晰地表達?
Arvid:我認爲我們的目標是,你應該只做對你來說最自然的事情,然後我們的工作就是弄清楚如何實際檢索到相對重要的事情,以便你的思考是有意義的。
Lex:模型選擇迴應與一般迴應有多難?這很難,如何處理不確定性。我是否選擇詢問更多信息以減少歧義?
Sualeh:我們最近爲Cursor添加了一個加入文件的功能。當你在編輯代碼或輸入內容時,模型會嘗試預測你正在做什麼,如果模型發現有不確定的地方,它會猜測你可能在編寫某種API。然後,模型會查看你的歷史記錄,推測哪些文件與當前的編輯內容相關。
這裡有一個技術上的難題,就是如何在所有歷史記錄中找到相關的信息,判斷在當前的提示詞下哪些文件最重要。雖然這個功能還處於試驗階段,但相信我們會逐步完善它,但我們想展示出這個想法:你是否想添加這個文件、那個文件,以便模型幫你編輯?
也許你在編寫一個API,你也應該需要編輯使用這個API的客戶端和服務器代碼,那麼API發生變化時,客戶端和服務器代碼也需要相應更新。
Cursor可以做的是,當你在編寫提示或代碼時,在你按下回車之前,模型可以幫你找到這些可能需要一起修改的部分。這樣做的好處是,可以提前解決一些不確定性,確保所有相關的代碼都被正確更新,而不需要手動去查找和同步這些改動。
九、正在接近AGI時代,但AI Agent還不實用
Lex:你們怎麼看Agent?Agent有多有用?
Arvid:我覺得Agent就像是人類,你能感覺到你正在接近AGI,因爲你能看到一個演示,它表現得就像一個真人,這真的很酷。我認爲Agent在很多事情上還不是特別有用,但我們已經越來越接近它們真正變得有用的階段了。
所以我覺得有些類型的任務,有Agent的話會更好。例如,如果我們有一個bug,有時你不能在聊天輸入框中使用Command+C和Command+V,這是一個非常明確的任務,我只需要用兩句話來說:“這個不能用,請修復它。”然後我會很樂意有一個Agent,它會自動去處理,修復這個bug,然後我回來檢查修復情況。
它會找到正確的文件,嘗試重現bug,修復它,然後驗證它是否正確。這可能是一個需要很長時間的過程。所以我覺得我會很喜歡這樣。而且我覺得在編程中,經常有人認爲Agent會取代所有的編程工作。我不認爲我們這麼認爲,因爲很多編程工作,很多價值在於迭代,或者說你其實不想一開始就明確指定什麼,因爲你真的不知道你想要什麼,直到你看到了初始版本,然後你想在此基礎上進行迭代,然後提供更多的信息。
所以在很多編程工作中,我認爲你實際上想要的是一個即時的系統,它能立即給你一個初始版本,然後你可以非常快速地進行迭代。
Lex:比如最近推出的Replica Agent,它可以設置開發環境,解決軟件包問題,配置一切,包括配置數據庫和部署應用。這也是你夢想中的一部分嗎?
Arvid:我覺得是的,對於某些類型的編程工作,這真的很酷。
Lex:這在Cursor的範圍內嗎?
Arvid:是的,我們目前並沒有積極地在做這件事,但可以肯定的是我們想讓程序員的生活更輕鬆、更有趣,有些事情真的很乏味,你需要經過一系列步驟,你想把這些事情交給Agent去做。然後有些事情,你可以讓一個Agent在後臺工作,同時你也在工作。比如說,你有一個同時涉及後端和前端的PR(Pull Request),你在前端工作,然後你可以讓一個後臺Agent去處理後端部分,當你開始處理後端部分的PR時,你就已經有了一些初始代碼可以迭代了。所以這也會很酷。
十、影子工作區後臺運行代碼
Arvid:首先,我們要明確的是,我們希望在後臺進行大量的操作,並且我們正在嘗試很多內容。目前,除了緩存預熱或找出命令鍵提示所需的正確上下文之外,我們並沒有太多其他後臺操作。但我們的想法是,如果能真的在後臺進行計算,那麼就可以幫助你預測更長時間範圍內的操作,而不僅僅是預測你接下來要寫的幾行代碼。
而是預測在接下來的10分鐘裡,你可能會做什麼。通過在後臺進行計算,我們可以花更多的計算資源來做這件事。所以我們實施的影子工作區(Shadow Workspace)的概念,並在內部進行實驗,是爲了真正利用後臺計算的優勢,我們需要給模型提供某種反饋信號,不然可以通過讓模型思考更長時間來獲得更高的性能,比如o1就是一個很好的例子。
但另一種提高性能的方法是讓模型進行迭代並獲得反饋。對於程序員來說,一個非常重要的反饋來源是語言服務器。它存在於大多數不同的語言中,並且每種語言都有一個單獨的語言服務器。它可以告訴你“你在這裡使用了錯誤的類型”,並給出錯誤提示,或者它還可以跳轉到定義,並理解你的代碼結構。TypeScript語言服務器是由TypeScript團隊開發的,Rust語言服務器是由Rust團隊開發的,它們都通過語言服務器協議與VS Code進行交互。這樣,VS Code就不需要內置所有不同的語言,而是可以使用現有的編譯器基礎結構。
這是爲了代碼檢查、跳轉到定義以及查看你正在使用的正確類型。當你在處理一個大型項目時,類型檢查和引用查找功能都是必不可少的。如果沒有這些功能,就很難在大型項目中編寫代碼。
Lex:在Cursor中是如何使用語言服務器協議進行通信的嗎?
Arvid:在Cursor中,我們使用語言服務器協議向程序員展示信息,就像在VS Code中一樣,但我們的想法是,我們還想將這些信息展示給智能模型,並且我們想在不影響用戶的情況下做到這一點,也就是說,我們想在後臺進行這些操作。
影子工作區的想法是,我們可以創建一個隱藏的Cursor窗口這樣你就可以在它裡面設置這個標誌,然後把它隱藏起來。雖然你看不到它,但它確實存在。在這個窗口中,AI Agent可以隨意修改代碼,只要它們不保存修改,因爲這仍然是同一個文件夾。然後,它們可以從linters(代碼檢查工具)中獲得反饋,跳轉到定義,並對代碼進行迭代。
這是我們最終想要實現的目標,也是我們博客文章主要討論的內容,因爲實現這一點有點棘手。我們希望它在用戶的機器上運行,以便完全模擬用戶的環境。在Linux上,我們可以做一些很酷的事情,比如鏡像文件系統,並讓AI在文件級別上進行操作,但實際上,這些操作是存儲在內存中的。我們可以創建一個類似於內核的擴展來實現這一點。而在Mac和Windows上,這有點難,但這是一個有趣的技術問題,所以我們在進行這項研究。
Aman:一個可能有些粗糙但很有趣的想法是,對保存操作進行鎖定。這樣,你可以讓語言模型在保存到磁盤時鎖定,然後你就不必在保存到磁盤的文件的真實版本上操作,而是在操作影子工作區中的那些未保存的內容。你仍然可以獲得錯誤提示,並可以在其中編寫代碼。然後,當你嘗試運行代碼時,會出現一個小警告,提示有鎖存在,這時你可以從語言服務器或影子工作區中釋放鎖,以便併發地執行其他操作。
十一、模型查詢bug仍有困難,Open o1也不例外
Lex:允許模型修改文件是一個令人興奮的未來,雖然這聽起來也有些嚇人。設想AI agent可以自動執行一系列任務,用戶第二天只需對結果進行審查,AI就好像你的同事一樣。
Aman:我認爲,模型在可運行性方面會有不同情況。執行一些簡單任務時,用戶可以在幾分鐘內順利完成,在本地機器上運行也是合理的。而執行一些需要更長時間以及更大變動的任務時,則需要在遠程的沙盒環境中完成。如何精準將用戶環境重現在遠程沙盒中,並能確保代碼運行結果的一致性是極具挑戰的。
Sualeh:我很好奇,你們(用戶)想要什麼樣的編碼agent?幫助你們找到漏洞?還是實現一些新的功能?
Lex:編碼方面,我認爲應該去關注查找各種級別的bug,尤其是邏輯錯誤,以及實現方向上的錯誤。
Aman:這些模型在簡單地提示下並不善於尋找和發現錯誤。它們的校準非常差,即便是最聰明的模型o1也是如此。
Lex:您能解釋一下嗎?
Aman:我認爲這些模型都能夠很好地反映預訓練數據的分佈,隨着損失函數的降低,模型的泛化能力也在增強。但現在損失函數的降低已足夠多,以至於模型能夠實現全面的泛化。我們主要在前沿領域使用模型,用他們進行代碼生成並對問題進行回答。在預訓練階段,GitHub上的大量代碼,數量高達數萬億個token,Stack Overflow和GitHub Issues等平臺上也有大量問題和答案,都爲任務提供了豐富的數據。
但當你嘗試推動其中一些在網絡上並不常見的事情時,比如根據已有的編輯來預測下一個編輯的Cursor Tab目標,模型的脆弱性就會顯現出來。
另一個很好的例子是bug檢測,因爲實際上並沒有太多真實的檢測bug並提出修復建議的例子,所以模型在這方面會遇到很大的困難。
但我認爲,這同樣是一個模型遷移的問題,我們需要將其他模型遷移到Cursor Tab上,在將非常擅長代碼的通用模型遷移到bug檢測任務時,效果應該也不錯,只是需要我們稍做引導。
Sualeh:很明顯,我認爲模型非常瞭解代碼。當它們在預訓練過程中,或許已經能夠粗略地察覺到代碼的問題所在。這是因爲有些人已經對這些錯誤進行了嚴格的校準。
但當用模型編程的時候,比如編寫數據庫,這是很龐大的數據信息,即便設置了很多嚴格的校準程序,可能錯誤也還是很難被修正。
十二、危險代碼標註存爭議,開發團隊並不看好賞金制度
Lex:人類也很難判斷代碼的重要性。如果某行代碼可能造成嚴重後果,應該添加“這行代碼是危險的”這一註釋。
Arvid:全部大寫,重複十次
Lex:是的,即使是同一個人也可能會忘記單個代碼的危險性。
Arvid:我認爲在一定程度上這也適用於今天的AI模型,如果你真的在每一行中都標註dangerous,dangerment,dangerous的話,模型也會更加關注這些,並且更有可能在該區域發現錯誤。
Lex:明確標註代碼的潛在危害程度是一種良好的實踐。
Arvid:但這種做法存在爭議,例如Sualeh就不太喜歡。
Sualeh:雖然從美學角度來看我不喜歡這種做法,但它確實對模型和容易遺忘代碼危險性的人們很有幫助,可以避免一些小的錯誤導致嚴重的情況,例如服務器宕機。
Aman:即使是普通的文檔字符中,人們在修改代碼時也經常會忽略,因此需要明確指出潛在風險。
Lex:人們在修改代碼時往往只考慮如何改進功能,而忽略了潛在的風險。
Arvid:如果能夠對所有代碼進行形式化驗證,就可以確保不會引入bug。
Aman:這個設想中的未來具體會是什麼樣子?
Arvid:我認爲人們可能不再需要編寫測試了,模型會根據代碼自動生成規範,用戶只需審查規範。同時,智能推理模型會計算出代碼是否符合規範。這種方式適用於大多數函數。
Michael:規範的生成真的容易嗎?爲軟件明確人類的意圖是具有難度的,畢竟有些想法很難指定,也很難證明它是否真的能夠符合你的想法去執行。
Arvid:您認爲規範很難生成?
Michael:對於難以用規範語言描述的需求,形式驗證並不可靠。
Arvid:即使有大量的規範文檔也難以達成?
Michael:規範可以取代單元測試。
Arvid:但規範語言可以不斷髮展,以涵蓋更多需求。
Lex:這一設想是否適用於整個代碼庫,而不僅僅是單個函數?
Arvid:的確,對整個代碼庫進行形式化驗證更難,但這是值得追求的目標,並且從理論上是可行的。例如,最近有一些研究可以對硬件進行形式化驗證,包括C代碼、GCC編譯器和Verilog硬件描述語言。大型代碼庫也類似於多層系統,如果可以分解並分別驗證每個部分,那麼形式化驗證整個代碼庫應該是可能的。不過,規範問題確實是個挑戰。
Aman:如何處理副作用和外部依賴?例如調用Stripe API?
Sualeh:Stripe爲其API編寫了一個規範。
Aman:是否所有外部依賴都可以提供規範?例如,如果程序中使用了語言模型作爲原語,如何將其納入形式化驗證?
Arvid:這也是可能的。
Aman:如何證明語言模型效果?
Arvid:可以證明語言模型的對齊性,或者證明它能夠給出正確的答案。
Sualeh:這是最終的夢想。
Lex:如果這能夠實現,將有助於確保代碼的正確性和AI的安全性。
Lex:既然模型在bug查找方面存在困難,那麼未來的希望在哪裡?
Sualeh:希望模型首先能夠幫助發現一些簡單的bug,例如off-by-one錯誤或註釋與代碼不一致的情況。最終,模型應該能夠發現更復雜的bug。
Michael:強大的bug查找模型對於實現AI編程至關重要。如果AI能夠自動生成代碼,那麼也需要能夠驗證代碼的正確性。這不僅是爲了幫助人類程序員,也是爲了驗證AI生成的代碼。
Arvid:是的,但實際上是怎麼做到的呢?有一個流行的想法是這樣的,引入bug比找到bug更容易,因此可以訓練一個模型並引入一些錯誤代碼,然後就可以訓練一個反向錯誤的模型,並用其中的合成數據去尋找錯誤。這是一個不錯的例子。
Michael:還可以利用大型模型和代碼之外的信息來輔助查找bug,例如通過代碼執行軌跡和調試器信息。bug查找工具可能會有兩種不同的產品形態,其一是在後臺運行的快速模型,用於發現常見的bug。其二是用於解決特定bug的高計算量模型,用戶可以支付一定的費用去使用。
Lex:是否考慮過用資金將這些整合起來?如果模型能夠找到bug或生成高質量的代碼,我願意付費。前幾天,我用Cursor模型生成了三個完美的函數,主要用於與YouTube API交互,爲我提供多語言字幕更新功能。
API文檔不是很好,而且有代碼交叉現象,我用谷歌搜索得不到確切信息,只有一些令人困惑的內容,而Cursor生成得則非常完美。我想,真希望能有一個“打賞”按鈕,寫着“5美元”既可以支持公司發展,也可以向模型發送積極反饋信號比如“Good Job”。在bug查找中,也可以引入類似的賞金機制。你們有考慮嗎?
Arvid:公司內部對此存在爭議。我認爲在某種程度上,這取決於你對人性的信仰程度。我認爲,如果你不花任何錢就找到一個bug那非常棒。如果沒發現錯誤,你就不用花錢,而如果你花錢並找到了一個bug,並且你要點擊的“接受”,那麼它會顯示在括號中,比如1美元。
這會存在一種擔憂,比如,我們在計算中投入了很多,也許人們會複製粘貼代碼,或者付費機制會影響用戶的體驗。我認爲,可以考慮把付費機制與產品進行分離,如果用戶每月支付一定的費用,就可以免費獲得所有的功能。
Lex:可以添加一個“打賞”功能,而不是強制收費。
Arvid:即使是打賞也涉及到金錢,可能會影響用戶體驗。
Aman:用戶在分享模型時,人們就已經在表達對模型的認可了。
Michael:如果能夠開發出一種技術手段來驗證bug是否已被修復,那麼就可以不必依賴那些依賴於榮譽系統的賞金機制了。
十三、AWS基礎設施非常可靠,出現問題的概率微乎其微
Lex:終端和代碼之間有多少交互?在終端中運行代碼可以獲得多少信息?是否可以實現一個循環,讓模型運行代碼並建議如何對代碼進行更改?目前代碼及其實際運行是完全分離的嗎?目前,據我所知是可以在終端中使用“Ctrl+K”來輔助進行代碼編寫。
Aman:可以在Check命令和Ctrl+K中使用終端上下文信息。但目前還沒有實現循環功能,不過這很有意義。關鍵問題在於,這個循環是在前臺進行還是像之前那樣在後臺進行。
Lex:後臺運行的確很酷,因爲它可以支持不同的方式運行代碼。此外,還需要考慮數據庫方面的問題,例如如何防止模型修改數據庫。
Sualeh:有一個不錯的解決方案。即正在開發一個新的API,我認爲PlanetScale和Turbopuffer數據庫都會支持這種功能。當你正在開發一個功能並對數據庫進行測試時,實際上你並不想針對廣泛的數據庫進行測試,你可以向數據庫添加一個分支,而不是去修改主數據庫。
這種技術的實現方式是爲數據庫的預寫日誌添加分支。數據庫公司需要不斷開發新功能,而分支功能可能成爲未來的一個趨勢,AI agent也可以利用數據庫分支進行測試。
Lex:在此可以對基礎設施相關信息提出一些問題,Cursor團隊目前是主要使用AWS(亞馬遜雲科技)嗎?在使用AWS的過程中,都遇到了什麼挑戰?
Arvid:AWS非常出色,無論在何時使用它的產品總是能夠正常工作,雖然完成其設置過程可能超級麻煩。實話說,AWS確實值得信賴,如果出現問題,那很可能是你自己的問題。
十四、擴展問題是公司發展難關,隱私保護也亟待突破
Lex:Cursor作爲一家初創公司,在發展中遇到了哪些挑戰?
Michael:隨着請求量級的不斷提升,緩存和數據庫等通用組件都會遇到瓶頸。例如,我們現在已經遇到遇到了數據表溢出等問題。此外,我們構建的一些定製系統,例如用於代碼語義索引和問答的檢索系統回答有關代碼庫的一些問題,我也一直認爲這是比較棘手的擴展問題之一。
Sualeh:我的超級高級工程師朋友們說,在擴展過程中很難預測系統會在哪裡崩潰。您可以提前嘗試預測,但是在添加這些額外的內容時,總會發生一些奇怪的事情。具體而言,Cursor將所有的代碼進行分塊,然後發送代碼進行嵌入,然後將嵌入代碼儲存在數據庫中,但實際上,並不儲存任何代碼。此後就是我們要確保不引入客戶端bug,因爲我們對這些bug非常嚴格,服務器上存儲了許多細節,一切都是加密的。
因此,技術挑戰之一就是如何確保本地代碼庫狀態與服務器端狀態保持一致。技術層面上來說,我們的做法是將對服務器端的哈希值進行下載,並對比本地的哈希值,計算差額,來確定缺少的文件是什麼。但這會增加網絡開銷。如果您使用了Cursor,沒有人希望有人一直對WiFi施加操作。
而且,這也會對數據庫造成巨大開銷。它將讀取數十TB的數據庫,每秒鐘接近20TB或者更早的數據庫。這太瘋狂。爲此,我們採用了Merkle樹結構,只需要協調單個哈希,即項目的根節點,去查看哈希值不匹配的子項,並以此類推,可以極大地降低開銷。
但隨着使用人數的增多,代碼庫也變得格外龐大。最初,我們對暗代碼庫進行了重新排列,但如今其規模已經遠不如一些擁有龐大文件的公司的規模了。建構一個東西很簡單,但擴展到更多人、更多公司,這是個難題。我們也在努力解決這些問題。
Aman:的確,索引系統有很多需要琢磨的東西。實際上嵌入代碼纔是瓶頸。爲了避免重複嵌入同樣的代碼塊,我們採用了一種緩存機制,即將代碼塊的哈希值與對應的向量緩存起來,這會使得一些公司,在使用Cursor時,代碼嵌入的速度會大大提升,用戶不需要儲存代碼數據,只存儲向量數即可。
Lex:目前,您認爲代碼庫索引帶來的最大受益是什麼?短期來看,代碼庫有什麼用呢?
Arvid:最明顯的一點是,當你向找出大型代碼庫中特定的一些東西時,你可以通過模糊性的提問來進行搜索。比如“我想找到執行X功能的地方。”但是你並不知道在文本搜索中要輸出什麼語言。你只需要請求聊天,按照enter命令來詢問代碼庫進行聊天。很多時候,模型通常都能夠給你提供正確位置。
Lex:爲什麼Cursor不考慮在本地進行代碼嵌入等操作?
Arvid:我們也考慮過這種方案,但實現起來很困難。一些用戶使用的是最新的MacBook Pro,但超過80%的用戶用的是Windows機器,其中許多機器功能並不是非常強大,實際上,本地模型實際僅適用於最新的計算機,並且構建過程也會出現很大的開銷。因此,即使我們向這樣做,但也還是很難做得到。
Aman:是的,龐大的數據庫只會消耗大量的內存與CPU。此外,正如Arvid所說的那樣,本地模型建設存在着巨大阻力,其中似乎都在朝着MOE架構發展,雖然MOE模型對內存帶寬的要求更高,並且有利於本地運行,但整體模型的規模也會變得更大,需要更多臺機器才能運行。我認爲,對於編碼生成而言,用戶希望能夠用到最好、最聰明、最有能力的模型,但在本地實現卻很困難。
Arvid:實際上我很喜歡本地模式的替代方案。我認爲,它仍然處於研究階段,可以把它想象成,爲語言模型推理進行同態加密。用戶可以在本地加密輸入的數據,然後發送給服務器進行推理。服務器可以可以對加密數據進行處理,但無法讀取數據的具體內容,此後服務器會把答案發回給用戶並進行加密處理,用戶只能通過解密查看返還的內容。目前同態加密的成本依然很大,如果能夠降低成本,我相信這會非常值得期待。
世界上有越來越多的信息和數據將流經兩個中心化的參與者,但這會有些令人擔憂,比如傳統黑客的入侵,這是非常可怕的。用戶可能會被黑客監控。人們努力防止不良入侵者使用AI模型,繼而引入一些監控機制,但這些監控機制又可能被濫用,比如用戶的數據可能會被監控。所以我們希望,我們可以解決同態加密問題。
Lex:我想說,這是所有軟件都面臨的挑戰。就像雲可以提供很多便利的功能,人們就越來越依賴它,但是它也存在缺點,這就是爲什麼需要依靠強大的安全措施來抵禦一些攻擊。但是也又一些具有影響力的公司控制着這些數據,這就是我們存在着的現實生活。
Sualeh:是的,我非常擔心。例如Anthropic公司有這種負責任的擴展政策,其中我們是低級別的,當我們進入高級別時,任何模型都會出於合理的安全原因,都會希望對監控有所提示。我認爲這是合理的,但也存在一些弊端,如果所有信息都被見監控,那會非常可怕。
Aman:您認爲它(AI模型監控)與雲服務供應商有何不同?
Arvid:我認爲很多數據一開始並不會流向雲供應商,而通常你會把更多的數據提供給AI。一開始用戶並不會把自己的數據都放在網絡上,給那些公司或者模型。但現在AI模型的監控更加集中,雲服務中的用戶都可以使用加密密鑰,而AWS對此卻無能爲力,但在這裡只有中心化AI模型提供商才能夠看到確切的文本內容。
十五、關於上下文訓練中關於上下文和模型訓練的探討
Lex:在使用Cursor時遇到的一個問題,當我在Python中寫代碼的時候,會導入一些內容,模型怎麼知道我想在上下文中提到哪些內容,弄清楚這一點有多困難?
Michael:我認爲我們將來可以在自動計算上下文方面做的更好。需要注意的是,包含自動上下文需要權衡取捨。因此,你爲這些模型包含的上下文愈多,其速度就越慢,這些請求的成本的就越高,這意味着,你可以調用的模型就會越來越少。此外,對於這類模型來說,如果提示中包含了太多信息,它們會覺得困惑。因此,在上下文中呈現出的信息準確性和相關性的標準要十分高,我們也希望能夠做得更好。
我們在內部也嘗試過一些改進措施,但目前該領域還存在一些問題。讓語言模型真正達到理解新信息語料庫?上下文窗口能否無限擴展?模型能夠真正做到關注無限的上下文嗎?能夠對這些上下文進行緩存而不必重複計算嗎?還有很多想法都在嘗試中,這些想法類似於在模型權重學習過程中進行微調。同事作爲一家公司,我們很高興可以擁有更好的檢索系統,也希望可以做的更好。
Aman:一個有趣證明是VS Code(跨平臺源代碼編輯器)。
我們處於一個分叉節點。VS Code的代碼是開源的,大型語言模型在預訓練過程中已經見過這些代碼,並且經過微調和RLHF(人類反饋)訓練,能夠回答與代碼相關的問題。因此,當用戶詢問關於VS Code的問題時,模型有時能夠給出正確的答案,儘管有時也會出現誤差。如果能夠訓練一個專門的模型併成立一個理解這些問題的代碼庫,這會很有研究價值。
另外,我們對於一個開放性的研究問題充滿興趣,同時也存在着不確定性,即用戶是希望模型在前端執行完所有任務,還是將檢索與代碼生成進行分離?未來的幾個月,可能會出現一些真正有能力的模型,此後用戶可以單獨訓練一個非常優秀的開源模型並將其作爲檢索器,在上下文中爲這些更大的模型提供信息。
Lex:如何針對特定代碼庫進行模型訓練?
Aman:有很多方法可以嘗試,需要通過嘗試確定效果。一件非常幼稚的事情,是嘗試複製VS Code和一些前沿模型做過的事情。所以我們應該繼續進行預訓練。某種持續的預訓練,在繼續預訓練階段加入特定代碼庫的數據,並在指令微調階段加入關於該代碼庫的問題。我們從指令微調開始,建立一個關於代碼的常規指令微調數據集,繼而拋出更多關於該存儲庫中的代碼問題。
你可以獲取更多難以獲得的真實數據,或者可以使用合成數據來執行一些操作,讓模型對代碼各種新構成部分提出問題。因此,獲取代碼片段,並讓模型對此提出問題,再將其添加到指令中對數據點進行微調,從理論上講,這一過程可能會解鎖模型理解該代碼庫問題的能力。
▲播客現場(來源:YouTube)
十六、與OpenAI o1競爭靠什麼?
Lex:想問一些關於OpenAI o1的問題,您認爲測試計算系統在編程中的作用是什麼?
Aman:我認爲測試時間計算非常有趣。因此,隨着數據量和模型大小的擴張,預訓練制度將使損失函數和下游任務中的表現越來越好。但是,我們正在面臨一些數據壁壘。這意味着,繼續擴大數據規模變得更加困難。
因此,擴大測試時間計算是一種有趣的方法,如果現在增加我們使用推理時間的flop計算數量,使用Infer Time時,這些模型總是會有更多的flop,但現在,我們也許可以使用相同大小的模型並運行更長時間,並獲得與更大模型規模相當的回報。
某些查詢可能需要100萬億參數規模的模型才能處理,但這類查詢可能只佔所有查詢的0.1%。在這種情況下,也許有些浪費精力。而訓練一個能夠處理99.9%查詢的模型,然後可以採用一種方法爲那些真正想要更高智能查詢的人延長推理時間。
Lex:如何判斷哪些問題需要更高水平的智能?是否能夠動態地在GPT-4與o1使用之間進行切換?
Aman:確實這是一個問題,也沒有人真正很好地解決它。團隊在Cursor Tab功能中實現了簡單的模型路由,但在GPT-4和o1之間的切換還比較困難。另外,需要什麼級別的AI來確定對於司機模型是否太難,可能需要o1模型,但這很難說得清楚。
此外,還需要考慮如何判斷某個問題對GPT-4來說是否過難,這可能需要o1級別的模型才能判斷。
測試時間計算需要一個完整的訓練策略才能正常執行。此外,在大型實驗室之外,可能只有OpenAI,但沒人知道它是如何工作的,有一些非常有趣的論文顯示了它們可能提供了怎樣的暗示。因此測試時計算可以歸類爲後訓練階段,但未來用於訓練支持測試時計算的模型的算力可能會超過預訓練階段。
Lex:如果要構建一個與o1競爭的模型,應該怎麼做?
Aman:也許我們可以訓練一個流程獎勵模型。其中有結果獎勵模型和過程獎勵模型的區分,結果獎勵模型是人們接受語言建模訓練的傳統獎勵模型,它更重視最終結果。過程獎勵模型則需要對思維鏈進行層層劃分。OpenAI去年發表了一篇關於過程獎勵模型的論文,他們使用人工標註的數據集訓練了一個過程獎勵模型。
目前,過程獎勵模型主要用於從多個模型輸出中選擇最佳答案,但還看不出什麼特別優秀的地方。衆多的學術成果中,人們要做的是從語言模型中抽取一些輸出數據,然後使用過程獎勵模型對這些進行賦分,繼而選出最佳答案。未來,人們就是使用流程獎勵模型及其樹狀結構,探索思維鏈的多個分支,繼而評估分支的質量。
Lex:當分支質量與結果質量密切相關時,就能夠幫助模型選擇用哪個分支更好?
Aman:是的,我認爲也許人們討論開源模型訓練流程獎勵模型時,採用的是更自動化的方式。但目前我並未看到任何東西能夠創造性地使用流程獎勵模型來進行樹狀結構搜索和編碼。
Lex:有一個AI安全問題,它更像是哲學問題。OpenAI曾說,他們向用戶隱藏了思維鏈,這是個艱難的決定,他們會在後臺對思維鏈進行監控,以此確保模型不會試圖對用戶產生干擾,這確實令人震撼。但你們對於隱藏思維鏈這件事有何看法呢?
Michael:我推測,OpenAI可能是爲了防止別人從他們的模型中竊取他們的技術。如果你能夠詳細看到思維鏈的每個步驟,那這個技術就更容易唄獲取。
Lex:所以你也可以用這個來訓練嗎?
Michael:可能大語言模型供應商之間會存在這樣的情況,其中一切API曾經提供了他們的所有記錄概率的訪問權限,但後來又取消了。其中的原因可能就在於,那些訪問了記錄概率的人,可以竊取到模型的技術信息。
同時我們也集成o1到Cursor之中,對於o1我們也有濃厚的興趣,並且我覺得很多程序員也都對此充滿期待。但無論如何,o1都不是Cursor默認體驗的一部分,目前我們還沒有找到將其集成到編輯器中的有效方式。所以我認爲,如何和使用這個模型(o1),還是個未知數。
Sualeh:我們有一些美好想法,但需要找在發佈之前獲得一些適用的場景。
Aman:o1模型還存在很多限制,比如不支持流式輸出,這意味着用戶無法對輸出過程進行監督,只能等待文本的出現。另外,它技術發展還處於早期階段,有很多需要改進的地方,未來會在增加預訓練數據量,擴大模型體量的同時,讓搜索工作也變得越來越好。
Lex:GitHub Copilot似乎正在以某種方式集成o1模型,有人認爲這意味着Cursor要完了?
Michael:我認爲這個領域與2010年代的軟件領域有所不同,此處天花板真的非常非常高,所以我認爲,三到四年內最好的產品很快就會比今天最好的產品更優秀。我認爲即便擁有一個很好的品牌,但不去創新未來還是會失敗。接下來幾年我認爲,關鍵在於建構最好的產品與系統,這需要歸結於建模引擎與編輯體驗。
Aman:是的,我認爲Cursor的優勢在於其不僅僅是快速集成新模型就像o1那樣,同時它也是深度定製的模型,並且很重視用戶體驗。
十七、詳刨三類合成數據分類法
Lex:您能解釋一下,合成數據分類法是什麼嗎?
Aman:合成數據是可以從AI中獲得的一些數據,我認爲合成數據主要有三種。第一類是蒸餾,包括語言模型、輸出token或token的概率分佈,可以用來訓練能力較弱的模型。這種方法無法生成比原始模型更強大的模型,但可以將昂貴的高延遲模型的能力提取到較小或執行特定任務的模型中。
第二類是合成數據利用了某些問題中一個方向比另一個方向更容易的特點。例如,在bug檢測問題中,引入bug比檢測bug更容易。我們需要做的是,在一個未經充分訓練的模型中引入一些bug,然後用這些合成數據訓練一個擅長檢測bug的模型。
最後一類,是使用語言模型生成可以輕鬆驗證的文本。比如,想對系統進行驗證,檢測語言是否能夠達到莎士比亞的水平,你可以讓猴子或者打字機去打字,最終就能夠獲得充分的訓練數據來培養一個莎士比亞級別的語言模型。
對於具體的引導代碼的代碼,可以通過測試結果來判斷這個測試代碼是否合格,我們也可以使用模型生成、通過測試的代碼來對模型進行訓練。但我認爲這種方法很難產生實際效用,在開放式任務或者發雜任務中,很難找到完美的驗證器。
十八、人類反饋聯動AI反饋,共同提升模型訓練效果
Lex:人類反饋的強化學習(RLHF)和AI反饋的強化學習(RLAIF)相比而言如何?對AI模型性能提升都有什麼作用?
Aman:RLHF是根據人類反饋信息來進行訓練的,我認爲,如果能夠爲專注的任務提供充分的人類反饋那麼效果會非常不錯。
RLAIF則比較有趣,它根據約束條件執行工作,比如使用語言模型來驗證解決方案比生成一個解決方案要容易,它更容易奏效,因爲RLAIF可以實現一種遞歸循環。
我們可以將二者進行結合,在兩者之間選擇一個平衡點,比如在某型生成的正確代碼中,加入少量的人工反饋,大概50-100個示例,就能夠讓模型的先驗內容與我們的構想實現一致。
這看起來與普通的RLHF不同,普通的RLHF通常需要大量的示例對獎勵模型進行訓練。
十九、AI會在實現AGI前獲菲爾茨獎?
Lex:根據你的直覺,生成與驗證或者生成與排序哪個更容易呢?
Aman:根據直覺而言…可能是這樣的…既定情況下驗證更容易,而非找到證明。
Sualeh:AI獲得菲爾茲獎的可能性有多大?
Sualeh和Arvid:AI更容易獲得菲爾茨獎。
Aman:雖然AI已經解決了許多難題,但現在還不確定定理證明領域中AI效用如何。其次,對於我們距離解決這些非常非常難的開放性問題還有多遠,我的直覺也不那麼準確了。
Lex:你認爲AI會先獲得菲爾茲獎嗎?而不是物理學或其他的什麼。
Sualeh:我認爲百分之一百是會獲得菲爾茨獎的。我覺得,一些奧數難題,比如伯奇和斯溫納頓-戴德(Birch and Swinnerton-Dyer conjecture)猜想對於AI而言還是非常難的,現在還並不知道如何去解決這些問題。
Aman:AI可能會在實現AGI之前就獲得菲爾茨獎。
Sualeh:如果能獲得,我會非常開心的,我覺得,可能在2028或者2030年就會實現吧。
二十、談縮放規律的未來,“模型越大越好”觀念已失效
Lex:談到縮放規律(scaling laws)的話題,大家可以就此談一下自己看法,對於現狀以及未來的發展有何看法?
Aman:最初OpenAI關於縮放規律的論文存在一些錯誤。他們提到了關於優化學習效率的問題。後來,Chinchilla的論題提到了一個更準確的版本。自那時起,人們開始不再專注於計算優化,而是更加關注在有限的推理預算下獲得更優異的效果。
Aman:我認爲,這些縮放規律曲線的維度遠比我們最初僅用於計算參數數量和數據的維度要豐富得多。比如,推理計算就是一個顯而易見的維度。我認爲,上下文長度是另一個明顯的維度。假設我們關注推理計算和上下文窗口這兩個方面,也許我們想要訓練的是某種狀態空間模型(SSM)。
它們在處理超長上下文時,成本要低得多,速度也要快得多。即使訓練時的擴展屬性可能需要10倍的計算量,也就是說,需要花費10倍的計算資源來訓練模型,以達到相同的能力水平,但這也是值得的。因爲我們最關心的是超長上下文窗口下的推理成本預算。因此,人們未來將會這些維度上進行探索。
Lex:你覺得大家是否還在相信“越大越好”這一理念?
Aman:對於原始性能和原始AI來說,更大的模型肯定更好。我認爲,人們還是會更看好蒸餾技術。如果我們投入大量、大量的資金進行訓練,以獲得最具性價比的模型,那麼我們可以調整多少個參數呢?
這一點確實值得關注。因爲僅僅在推理時間上儘可能多地投入計算,這種天真的做法,人們已經在Llama模型上嘗試過了。或者,僅僅是對7B(70億參數)模型進行過度訓練,使用的token數量也遠遠超過了最優需求。
但是,如果你真的在意這件事,也許我們可以像Gamma所做的那樣,不僅僅是在token上進行訓練,而是實實在在地通過最小化與Gemma 27B分佈的KL散度來進行訓練,這就涉及到了知識蒸餾。實際上是在所有這些token上,花費計算資源來訓練這個擁有270億參數的模型,然後將其中的內容蒸餾到一個更小的模型中。
Lex:蒸餾只給你一個更快的模型,越小意味着越快?
Aman:我認爲,蒸餾在理論上是從你正在訓練的數據中提取更多的信號。這可能是另一種方法,不是完全克服數據牆,而是部分地幫助我們克服數據牆。可以訓練的數據有限,讓我們用所有這些token來訓練這個非常大的模型,然後我們將它蒸餾成這個較小的模型。相比於我們自己去訓練模型,蒸餾能夠讓模型獲得更多的信號。
Lex:如果給你們10萬億美元的預算,你們會如何做?
Aman:我認爲有很多關於訓練這些大型模型的秘密和細節,只有大型實驗室才知道。即使我努力去做,也會浪費很多錢。
Lex:假設獲得所有信息,包括訓練參數以及方式方法,未來五年中你會如何投資才能使你們所說的原始AI實現最大化?
Sualeh:我覺得,答案很簡單。你只需儘可能地購買足夠多的計算機,此後每一天所要做的就是購買GPU,研究人員就可以根據目標來選擇去訓練大模型還是小模型了。
Aman:這涉及到一個問題,我們是真的受到計算和金錢的限制,還是受到其他什麼制約?
Sualeh:更多是受限於自身觀念吧,但也存在其他一些限制因素。
Lex:你們會選擇進行大量的實驗還是選擇使用這些計算資源來訓練一個巨大的模型?
Arvid:可能會選擇通過實驗,我覺得現在我們仍受限於我們目前所持有的觀念。
Aman:我認爲是這樣的,因爲即便擁有了世界上所有的計算能力和可收集的數據,最終還是會受到限制,而且限制的不僅僅是想法,是受制於更卓越的工程技術。即便擁有世界上所有的資金,真正能在這裡有所作爲的人並不多。
研究工作中包含大量純粹的、極其艱難的工程技術工作。舉個例子來說,如果你看看原始的Transformer論文,將文獻中嵌入的許多非常有趣的概念融合在一起,而且還需要編碼,這些過程,都需要傑出的工程師來完成,就像GNOME Azure。
進一步說,讓下一代模型進行並行化工作,這需要龐大的工程量,我認爲要讓所有這些事情都奏效,需要投入大量的工程技術工作。比如,能夠將工程投入成本降低10倍,讓那些擁有美好想法的人真地實現那些結構,提升40%到50%的GPU的利用率,那研究工作的效率可能會大幅提升。
Sualeh:如果能夠看到一個清晰的改進路線,那麼結果就會唾手可得。我認爲,可能OpenAI和其他一些實驗室的做法是對的,它們抓住了這些成果。比如,GPT-4.25。現有方法是有效的,那就不需要考慮創新,只有當現在遇到瓶頸時,才需要創新。我認爲,如果擁有10萬億美元的預算,也許實際上會先去擴大規模,然後再對自身的觀念進行更新。
只要現有的方法有效,就沒有必要嘗試新的想法。只有當現有方法遇到瓶頸時,才需要新的想法。如果擁有10萬億美元的預算,那麼可以先嚐試擴大規模,然後重新評估想法。
Aman:我們都相信,去實現AGI需要全新的觀念。我們也相信,可以在更小的規模內去測試一些新的觀念,而且我們有信心這會奏效。對於當前的實驗室而言,將有限的研究和開發人才投注到開發其他的新想法之中是十分困難的,畢竟現存方案在未來較長時間都有效。
二十一、談編程未來,仍需程序員領航
Lex:你們現在處於編程世界的中心。你們認爲編程,編程的本質在未來幾個月,在未來幾年,甚至十年會發生什麼變化?
Michael:我認爲,我們對未來充滿期待,因爲程序員在很長一段時間內都坐在“歷史的駕駛座”上。我們曾談到過這個問題,這需要程序員有着高效、代理能力與控制能力,他們可以修改任何你想修改的東西,並且對你構建的內容進行快速迭代優化。
此處,與“同計算機對話形的編程”有差別,與計算機對話,就好比你在Slack上與工程部門或工程師進行交談一樣,輸入需求到一個獨立的文本框,AI就會自動爲你完成這些工作。但這也有些問題,首先會有延遲性,其次這也意味着放棄了一些控制力。
從根本上說,工程實際的執行情況,是根據你構建的細微決策來進行的,其中人的關鍵作用是不能被AI取代的,要讓人類坐在“駕駛位”來掌舵。
而未來編程的情況,很可能是程序員可以控制代碼庫的抽象級別,可以通過觀察僞代碼的形式對代碼庫進行編輯。而且程序員也可對編程軟件的邏輯進行修改,保留其控制權,這樣可以大幅度提升生產力。
但這只是一個模糊的想法,還需要很多細節需要解決,最終能否實現還有待觀察。但是人本身的控制力、效率以及以人爲中心觀念是非常重要的。我們認爲,對於一些像Arvid之前提到一樣,某些編程,可以把它交給聊天機器人。但大多數編程任務人需要人深度參與。
Lex:編程的基本技能是否會發生根本性的變化?
Michael:實際上,我認爲現在是開發軟件非常令人興奮的時刻。不管什麼時候,很多代碼依然還是需要查閱很多難以理解的信息。但今天的編程比過去有趣多了,人們開始享受編程。現在的編程讓人具備快速構建事物的能力,人們的控制力也被極大提升了。
對於那些編程人員來說,這也是個充滿意義的時期,人們的創意和趣味會被放大,如果你是程序員,那今天應該更加註意這部分的特殊性。
Arvid:我也同意,最近我們正對代碼庫進行一次比較大的遷移,將Node.js中的Async Local Storage替換爲 Context對象。即使可以藉助AI,這個工作也依然需要我與另一個工程師耗費大概五天的時間。不過未來,我們可能只需要給AI展示幾個例子,然後這個遷移任務,就可以在10分鐘內完成。程序員可以藉助AI更快的工作,而不需要在事先就考慮太多,而且任何事情,其實都可以先去嘗試新方法,嘗試的成本並不高。
Aman:我覺得在編程中有兩種方式,其一是努力思考,仔細尋找解決問題的最佳方法然後用有限時間來驗證。其二是直接執行代碼,看是如何執行的並就此進行更新。我也更認同後一個方案。
Lex:那對於現在想要學習編程的人而言,你們有什麼建議呢?應該學習什麼?比如Java亦或者PHP?
Aman:我認爲,每個人都有學習編程的自身原因。但我覺得,實際上那些真的熱愛編程的人,會是最好的程序員。在我們團隊內部,很多人在工作後依然會用Cursor編寫自己的編程,有的人甚至會熬到凌晨三點去做這件事。當他們難過的的時候,還會說“我需要寫點代碼。”來寬慰自己。
這種對編碼的熱愛,趨勢他們成爲了最好的程序員,我也認爲這些人將會認真投入到那些他們研究的事物之中。我認爲,未來的編程者們需要會更多地關注“你想要創造什麼”。
Sualeh:程序員可以通過更豐富的方式表達自己的意圖。
結語:共建人機協同體系,改善程序員生活
Lex最後運用Cursor團隊的宣言爲本次談話做出總結,在《工程天才》中他們說“我們是一個應用研究實驗室,構建不可思議的生產性人機協同系統。”
宣言中寫道:“首先,我們正在培養未來的工程師,即人類AI程序員這比任何一個工程師的效率都高出一個數量級。這種混合型工程師可以輕鬆地控制代碼庫,並且無需進行低熵鍵盤操作。即使在最複雜的系統中,他們也會以判斷的速度迭代。通過結合AI和人類智慧,他們將比最好的純AI系統更聰明、更工程化。我們是一羣研究人員和工程師。我們構建軟件和模型,在有效性和可能性基礎上進行發明。我們的工作已經改善了成千上萬程序員的生活。”
Lex稱,在這個談話中,至少讓編程更有趣了。
來源:YouTube