- TensorZeroをオープンソースのプロキシとして活用し、CursorとLLMプロバイダー(OpenAIなど)の間のトラフィックを傍受・分析して、プロンプト・モデル・推論結果をリアルタイムで観察し最適化実験を行った経験を共有
- CursorはLLM呼び出し時にBase URLとモデル名をオーバーライドできるため、自前のプロキシ(TensorZero)を容易に接続可能
- 内部的にCursorは独自サーバーを経由してLLMを呼び出すため、完全なプロキシ構成にはNgrok + NginxリバースプロキシおよびCORSヘッダー設定が必要
- プロキシを通じてCursorが実際にLLMへ送るsystem prompt、user prompt、インラインコード編集リクエストまですべて観察でき、さまざまなLLMでリアルタイムに切り替え/実験が可能
- Cursorのsystem promptを分析した結果、わずか642トークン程度のプロンプトだけで大半のソフトウェアエンジニアリング文脈をLLMが理解・処理している。コード編集は別の"apply model"(より知能の低い補助モデル)が担当
- TensorZeroのようなプロキシ構成により、ユーザーごとに最適化されたLLM実験やフィードバックベースの最適化が可能になり、この構成はコード支援ツールの品質評価(A/Bテスト)、プロンプト最適化、実運用モニタリングに最適
紹介
- TensorZeroオープンソースフレームワークをCursorと各種LLM(大規模言語モデル)の間にプロキシゲートウェイとして接続した経験と、そこから得られた観察、実験、最適化のポイントを扱う
- TensorZeroはフィードバック信号(生産指標、ユーザー行動など)を活用してLLMアプリケーションの品質向上を支援するオープンソース
- Cursorユーザーとして、最も多く使うLLMベースIDEにこの技術を適用し、実際にどのようなAPIリクエストがやり取りされているのか、そしてどのように最適化を直接試せるのかを実験した
全体概要と目的
- Cursorはユーザー全体を基準に最適化されたコーディングアシスタントだが、個人ごとの最適化実験やデータ観察はほとんど不可能
- TensorZeroをプロキシとして置くことで、CursorのリクエストとLLMレスポンス、プロンプト、モデル、推論過程全体を透過的に観察し、実験し、最適化まで拡張できる
- ほとんどの最適化・評価・実験手法には実際の推論データが不可欠であるため、それを収集する実践的な方法と自動化のやり方を具体的に紹介する
連携プロセス: LLMゲートウェイの構築
- CursorはOpenAI base URLとモデル名をユーザー定義で変更できるようサポートしている
- TensorZeroはOpenAI互換の推論エンドポイントを提供するため、CursorをOpenAIの代わりにTensorZeroへ接続できる
- TensorZero内で
cursorzero関数を登録することで、さまざまなモデル/プロンプト実験と、プロバイダー非依存の推論およびフィードバックデータの自動保存が可能
最初の障害: Cursor独自サーバー
- CursorがローカルのTensorZeroへ直接接続を試みたが失敗した
- Cursorは常にまず独自サーバーへリクエストを送り、内部で追加処理を行った後にLLM呼び出しへ進む
- その結果、認証情報がCursorサーバーへ渡され、そのサーバーがすべてのリクエストおよびコードベースに関するデータを収集できるようになる
- 代替案として、OpenRouterへ接続し、Cursor内の一部インタラクションで外部モデルが利用可能かを確認した
- CursorのTab自動補完は独自の非公開モデルで動作し、他のLLMと組み合わせて使える
- 最終的にreverse proxyとNgrokを活用し、外部公開エンドポイント経由で内部TensorZeroへリクエストをプロキシする構成で解決した
- Nginxを前段に置いて認証を追加しセキュリティを強化、カスタムTensorZero関数でLLMルーティングまで完了した
- 最終構成:
- Cursor → Ngrok → Nginx(認証) → TensorZero(ローカル) → LLM Provider
2つ目の障害: CORS
- 認証時に**CORS preflight(OPTIONS)**リクエストがNginxに到達し、初期認証が行われない現象が発生
- NginxでOpenAI APIと同じCORSヘッダーを返すよう設定し、ElectronベースのCursor IDEの要件を満たした
- 認証とCORSの問題を解決した後、すべての実際のリクエストはCursorサーバー経由で行われる
- (Nginx設定例コードを含む)
最終結果: Cursorの内部をのぞけるようになった
- すべてのLLMリクエスト/レスポンス、system prompt、user prompt、添付コード/ファイル内容をリアルタイムで観察可能
- system promptの例には、コード編集用の別個の"apply model"を起動する命令まで明記されている(二重モデル階層構造)
- Cursorプロンプトの主な構造:
- ユーザーセッション情報、ファイル・カーソル位置などの文脈を提供
- コメントブロックなどでセクションを区切る
- コード修正要求時には「変更部分のみを最小限に」コードブロックを生成するよう指示
- Cursorのプロンプトエンジニアリング
- 642トークンの大きなシステムプロンプト1つだけでも、大半のソフトウェアエンジニアリング業務が自動化される
- コード変更作業に特化した、より知能の低いapply model(補助モデル)が別途存在し、メインLLMに対して適用対象とルールを明確に指定している
- さまざまなLLM階層構造(知能、機能分離)が実際にプロンプト内部に実装されていることを確認した
結論と示唆
- Cursorは最新LLMの基本的な内蔵知識と簡潔なプロンプトだけで、ソフトウェアエンジニアリング文脈を処理できる
- TensorZeroなどのプロキシにより、ユーザーごとのフィードバックや実運用データにもとづく最適化(A/Bテスト、プロンプト/モデル調整)構造を容易に構築できる
- コードエディタ支援AIやLLM導入企業は、この方法によりプロンプト設計、性能改善、ユーザーごとの最適化を迅速に実験できる
- 次回の記事では、実際の利用データ収集方法、Tree-sitter、git hookの活用法など、後続の実験を予定している
1件のコメント
Hacker Newsのコメント
Cursorは、20年以上使ってきたサービスの中で、サポートがまったく機能しないために購読を解約した唯一の製品だ。
数週間にわたって請求に関する質問を何度もメールで送ったが、一度も返信をもらえなかった。
単なるVS Code関連の問い合わせではなく、Cursorチームの関与が必須な問題だった。
それなのに宣伝メールだけはきちんと届く。
Cursorの「価値」が早く他のサービスにも広がってほしい。
次のチームはメールに返信してくれることを期待する。
このプロンプトには抜けている内容が多い。
最も目立つのはtool call descriptorsがないことだ。
1年前のjailbreakingプロンプトと直接比較してみるといい。
それでも、cursor rulesなど他の部分の設定はアイデアとして良い。
参考までに、関連するプロンプト資料はここで見られる。
Cursorでは、ユーザーが取るアクションに応じて異なるプロンプトを使っている。
今回はサンプルだけを提供したが、根本的な目的はさまざまなモデルをA/Bテストし、プロンプトとモデルを最適化することだ。
再現できるようにコードも提供してあり、そこから他のプロンプトも参照できる。
君が共有したGist資料もかなり有用だ。
もしかすると何らかの最適化ロジックがあって、ユーザーのクエリに本当に必要なツール情報だけをプロンプトに含めているのではないかと思う。
おそらくトークン節約のために、不要なtool descriptorは思い切って省く戦略を取っているのだろう。
関連資料はここにある。
では……wiresharkはもう使えないのか?
記事の最後に、どう使うかを決める前にざっと見ていく最初の投稿にすぎないと明記されている。
ちなみに最近は、単にパケットを見る用途ならmitmproxyがかなり優秀になっている。mitmproxy docs
wiresharkは、デスクトップアプリからCursorサーバーへ向かうリクエスト(実質的にLLMへ送られるリクエスト)を見るのには使える。
ただし、CursorのサーバーからLLMへ実際にどうリクエストが送られているかを見たいなら、別の設定が必要だ。
そうした設定があれば、こちらでリクエストを変えながらA/Bテストもできる。
CursorやさまざまなIDEモダリティソリューションは興味深いが、コンテキストを雑に扱う癖を身につけさせてしまう点は残念だ。
Cursorのプロンプトから抜粋した文を見ると、
「ユーザーがメッセージを送るたびに、現在の状態、セッション内の編集履歴、リンターエラーなどの追加情報をこちらで自動的に付けられる。この情報はコーディング作業に関係するかもしれないし、しないかもしれない。適切かどうかは君が判断せよ」という感じだ。
こうした「コンテキストの肥大化」は、LLMが本当に難しい問題を解く際の性能を大きく制限する。
例に挙がっていた.envの問題は単純な部類なのでCursorでもうまく扱えるが、この程度の複雑さではソフトウェアエンジニアを継続して雇う理由にはならない。
個人的には、AIと作業するときはまずチャットインターフェースで会話の文脈をきれいに管理する方法から考えることを勧めたい。
複雑な問題では、会議、Slackでの会話、社内文書、外部コンテンツ、コードなどが文脈として絡み合うからだ。
私はFileKitty(リンク)や最近ではslackprep(リンク)のようなツールを作って、問題解決に関係のある情報だけを絞り込み、より意図的に使えるようにしている。
「自動で添付できる」ではなく、実際に添付したものだけを含める形で指示文を書く必要があった。
「関係するかもしれないし、しないかもしれないので君が判断しろ」ではなく、関係がある場合とない場合にそれぞれどうすべきかを明確に指示した方が効果的だ。
文脈が短い場合はそれほど問題にならないが、長く複雑な問題ではこうした細かな指示が大きな違いを生む。
おそらくCursorは、キャッシュされたトークン価格の利点を生かすために指示をできるだけ一般化しているのだろう。
まだ多くの部分が実験段階で、今後プロンプトやモデルにはかなりの改善が入ると思う。
Cursorのプロンプトに関する別の分析はここで見られる。
長い会話の中で関連する文脈をどう選別しているのか、ずっと気になっていた。
実際にそのロジックをリバースエンジニアリングして、変換履歴をどう切り詰めているのか、ファイルの最新状態をどう表現しているのかを突き止めた人がいるのか知りたい。
今後もこの点は調査を続け、TensorZeroを使ってモデルとプロンプトの最適化実験を続けるつもりだ。
mitmproxyを使って同じ方法で分析している。関連する議論
これでプロンプト情報が分かったのだから、Cursorサーバーを再実装して完全ローカル版(あるいは一種のクラック版)を作れるのか気になる。
あるいは、そもそもClineやRoo Codeのようなオープンソースでエージェントコーディングに特化したプロジェクトがあるのだから、そちらを使う方がよい。
プロンプトが出てくるのを待ってからこの試みをしたというのは、少し意外だ。
Cursorのapplyモデルはサーバー上で動く構造に見える。
ローカルのapplyモデルを自前で実装するのがどれほど難しいのか気になる。
MacBookで動かせば、むしろずっと速いかもしれない。
間違いなく可能だ。