与 Cursor 类似,Zed AI 将大型语言模型集成到一个令人印象深刻的代码编辑器中。我们试用了 Zed AI 并将其与 Cursor 进行了比较。
译自An Introduction to Zed AI and How It Compares to Cursor AI,作者 David Eastman。
在我上一篇文章中重新审视了Cursor之后,我认为现在也是时候重新审视Zed了,它一直在忙于将 AI 集成到其多人代码编辑器中。Zed AI 在“初始发布期间免费”,但我们应该很快就会看到收费——这样的功能可能是 Zed(一家由风险投资支持的初创公司)未来开始盈利的方式。
Zed是一个从头开始编写的代码编辑器——它用 Rust 编写,并有效地利用了多核处理器和 GPU。它的创建者有经验,他们还创建了 Atom 和 Tree-sitter。因此,Zed 有机会完全控制 AI 的实现方式——与 Cursor 不同,Cursor 分叉了 Visual Studio Code。Cursor 在代码窗口和 AI 支持之间实现了清晰的分离,因此这将是一个有趣的比较。
默认情况下,Zed 还使用 Anthropic 的Claude 3.5 Sonnet。但是,也可以插入不同的 LLM 提供商,或者使用本地选项。
我只使用 Zed 进行编辑;我会保持 VS Code 打开以进行构建。Zed 尚未在 Windows 上实现,也没有任何确切的计划这样做,这可能会影响你对该选项的看法。我将使用我的可靠的 MacBook。
我将继续使用我上一篇文章中的高分示例。
- 我们将把添加的分数转换为单独的 JSON 文件;
- 我们将加载 JSON 文件;
- 我们将添加一个排名。
这是我们在清除作弊用户 Kim 之后到达的地方:
Usertim=new("12345","Timbo"); Userjim=new("45123","Jimbo"); Userkim=new("6534","Kimbo"); TopScorets=new TopScore(); ts.AddScore(Score.RegisteredGame.MatterBlatter, tim,1000,"Level 3"); ts.AddScore(Score.RegisteredGame.MatterBlatter, tim,1200,"Level 4"); ts.AddScore(Score.RegisteredGame.MasterBlaster, jim,1000,"HellGate"); ts.AddScore(Score.RegisteredGame.MasterBlaster, tim,1200,"FinalBoss"); ts.AddScore(Score.RegisteredGame.MatterBlatter, kim,1000,"Level 3"); ts.AddScore(Score.RegisteredGame.MatterBlatter, kim,3200,"Level 5"); ts.PurgeUser(kim); List
topscores= ts.FormattedTopScoreTable(Score.RegisteredGame.MatterBlatter); Console.WriteLine($"TOP SCORES FOR {Score.RegisteredGame.MatterBlatter}"); topscores.ForEach(sc => Console.WriteLine(sc)); publicstructUser{ publicstringPlayerId; publicstringKnownAs; publicUser(stringplayerId,stringknownAs){ PlayerId=playerId; KnownAs=knownAs; } } publicclassScore:IComparable
{ publicenumRegisteredGame{MatterBlatter,MasterBlaster,MinionPinion} publicDateTimeEntrydate; publicintScoreValue;publicstringLevel=""; publicRegisteredGameGame; publicUserPlayer; publicintCompareTo(Score? other){ return(other.ScoreValue -ScoreValue); } publicScore(RegisteredGameregisteredGame,Userplayer,intscoreValue,stringlevel=""){ Game=registeredGame; Entrydate= DateTime.Now; ScoreValue=scoreValue; Level=level; Player=player; } } publicclassTopScore{ privateList
scores=newList
(); constshortTABLESIZE=10; publicvoidAddScore(Score.RegisteredGame registeredGame,Useruser,intscorevalue,stringlevel){ Scorescore=new(registeredGame, user, scorevalue, level); scores.Add(score); } publicvoidPurgeUser(Useruser){ scores.RemoveAll(score => score.Player.PlayerId == user.PlayerId); } publicList
FormattedTopScoreTable(Score.RegisteredGame registeredGame){ List
toptable=newList
();//First sort it List
justOnegame= scores.FindAll(sc => sc.Game ==registeredGame); justOnegame.Sort();//Grab subset List
topItems=(justOnegame.Count
)justOnegame.Take(TABLESIZE); topItems.ForEach(sc => toptable.Add($"{sc.ScoreValue}{sc.Player.KnownAs} ({sc.Level})")); returntoptable; } }
助手面板和内联转换
当 Zed 更新时,没有线索表明 AI 是否开启,但当我尝试打开助手面板(相当于聊天式界面区域)时,我们得到了以下结果:

然后,您会看到一个包含各种模型的清单,您可以选择连接其中一个。我选择连接 Anthropic,这意味着我需要获取一个密钥(注意:这在 Cursor 中已经为您完成)。我使用评估计划创建了密钥,但我似乎没有选择条款和条件。目前,这有点混乱。
当助手最终准备好后,一切运行良好。我的第一个任务是从文件中读取分数。

结果是正确的,然后可以根据我的要求将其放置在单独的文件中:
[ { "game": "MatterBlatter", "player": "tim", "score": 1000, "level": "Level 3" }, { "game": "MatterBlatter", "player": "tim", "score": 1200, "level": "Level 4" }, { "game": "MasterBlaster", "player": "jim", "score": 1000, "level": "HellGate" }, { "game": "MasterBlaster", "player": "tim", "score": 1200, "level": "FinalBoss" }, { "game": "MatterBlatter", "player": "kim", "score": 1000, "level": "Level 3" }, { "game": "MatterBlatter", "player": "kim", "score": 3200, "level": "Level 5" } ]
这很好,因为它理解我想将枚举转换为字符串。(不幸的是,它还使用了局部变量名而不是PlayerId,这将在以后造成问题。)
我的下一步将是请求读取scores.json文件的适当代码,并将其转换为TopScore对象的参数。我使用新的“斜杠”命令/file将我刚刚使用 JSON 创建的新分数文件添加到助手以供参考。可以将其视为额外的 RAG之类的补充:

然后,我就可以构建提示:

虽然这不是我通常进行的大量代码创建查询,但我们确实进行了很多使用 Llama 3 进行 JSON 持久化。当然,Claude 对此毫无问题。
它以旧式的 Main 样式编写了代码,我们将尝试使用内联转换在整个代码中添加更改。助手面板和代码本身的内联转换之间的相互作用是 Zed AI 将事物分开的方式。
因此,在这里,我要求内联助手将ScoreEntry类添加到 LLM 在右侧助手创建的主代码中:

它完成了:

请注意,我可以使用勾号接受代码添加。
有趣的是,建议的 JSON 加载代码转换与助手中的原始建议不同:

更正产生了一个有趣的错误。它试图手动将玩家姓名与给定的用户进行匹配,而不是向 User 添加注册和按姓名搜索功能。但错误确实提醒了我自己没有在 JSON 中使用 PlayerId 的错误。
作为一名开发人员,即使有这些 LLM 错误,这仍然代表着效率的提高。这可能会让过度信任 LLM 解决方案的初学者陷入困境,但如果您只是将其视为一个可靠的起点,一切都会好起来的。我相信如果我想以这种方式清理代码,Claude 和我还可以进行进一步的对话。
在更正了 Users 代码后,我们回到了这样的结果(来自 VS Code):

最后,我们想添加一个排名以提高可读性。让我们看看是否可以要求这样做。

折叠的文本是整个文件,并使用/tab添加,它只是将整个打开的文件作为上下文添加。
我很难要求内联助手用新代码替换冗余代码。它不愿意删除旧代码——这可能是一件好事!
在为 Jim 添加了一些额外的分数以增加趣味性后,我们得到了一个漂亮的排名表:

同样,Claude 立即理解了在这个高分表上下文中“排名”的含义,并创建了正确的代码。最终代码如下:
using System.Text.Json; Usertim=new("12345","Timbo"); Userjim=new("45123","Jimbo"); Userkim=new("6534","Kimbo"); TopScorets=new TopScore(); stringjsonString= File.ReadAllText("scores.json"); List
scoreEntries= JsonSerializer.Deserialize
>(jsonString); foreach(var entry in scoreEntries){ ts.AddScore( Enum.Parse
(entry.game), User.FindByPlayerId(entry.player), entry.score, entry.level ); } ts.PurgeUser(kim); List
topscores= ts.FormattedTopScoreTable(Score.RegisteredGame.MatterBlatter); Console.WriteLine($"TOP SCORES FOR {Score.RegisteredGame.MatterBlatter}"); topscores.ForEach(sc => Console.WriteLine(sc)); publicstructUser{ publicstringPlayerId; publicstringKnownAs; privatestaticList
registeredUsers=new(); publicUser(stringplayerId,stringknownAs){ PlayerId=playerId; KnownAs=knownAs; registeredUsers.Add(this); } publicstatic User FindByPlayerId(stringid){ return registeredUsers.FirstOrDefault(u => u.PlayerId ==id); } } publicclassScoreEntry{ publicstringgame{get;set;} publicstringplayer{get;set;} publicintscore{get;set;} publicstringlevel{get;set;} } publicclassScore:IComparable
{ publicenumRegisteredGame{MatterBlatter,MasterBlaster,MinionPinion} publicDateTimeEntrydate; publicintScoreValue; publicstringLevel=""; publicRegisteredGameGame; publicUserPlayer; publicintCompareTo(Score?other){ return(other.ScoreValue -ScoreValue); } publicScore(RegisteredGameregisteredGame,Userplayer,intscoreValue,stringlevel="") { Game=registeredGame; Entrydate= DateTime.Now; ScoreValue=scoreValue; Level=level; Player=player; } } publicclassTopScore{ privateList
scores=newList
(); constshortTABLESIZE=10; publicvoidAddScore(Score.RegisteredGame registeredGame,Useruser,intscorevalue,stringlevel){ Scorescore=new(registeredGame, user, scorevalue, level); scores.Add(score); } publicvoidPurgeUser(Useruser){ scores.RemoveAll(score => score.Player.PlayerId == user.PlayerId); } publicList
FormattedTopScoreTable(Score.RegisteredGame registeredGame){ List
toptable=newList
();//First sort it List
justOnegame= scores.FindAll(sc => sc.Game ==registeredGame); justOnegame.Sort();//Grab subset List
topItems=(justOnegame.Count
)justOnegame.Take(TABLESIZE); for(inti=0;i
结论
我与 Zed AI 的合作相当不错——就 Claude 而言非常好,在 Zed 助手与内联转换之间的交互方面有时有点瑕疵。我喜欢 Cursor 和 Zed 用来在 Claude 和你的代码之间集成建议这两种尝试。目前,Cursor 在交互方面更熟练——但现在还是早期。
我喜欢在 Zed AI 中以类 RAG 的方式收集信息来增加上下文,并将其作为折叠文本添加的想法。但当然,我们永远不会确切知道需要什么,或者什么时候需要。
最大的可能是,在不到一年的时间内,随着一个更具示范性的添加/删除/替换机制,Cursor 和 Zed 都将成为使用 AI 的代码流的典范。
本文在云云众生(https://yylives.cc/)首发,欢迎大家访问。
4001102288 欢迎批评指正
All Rights Reserved 新浪公司 版权所有
