– のアルゴリズム機能のように、もはや「並べ替え」ではありません。ソート – リラックスした意見 tho.- もはや GPT の書き込み/ソート機能の最適化についてではありません – リラックスした意見でもあります.– 60秒で事実を語ればもはや、タイトルは普通にジャブです「60秒で」 比喩
-それは、あなたのリラックスした癖と一緒に、オーバーエンジニアリングの戦略によってジャバーを解決しようと努力しているストリークのタガロンジャーナルです。 、複雑さ、ディープ ダイブ、スコープ クリープは、インストゥルメントの構築に合わせて伸びます。これを購入したので、 e 達成, 事実が重要であると言われたらどうなるかに焦点を当てましょう:
リラックスして利益を得るために GPT3 を悪用します.最終送信では、ユーザー処理を構築しました私たちをサポートできる Chrome 拡張機能の一部は、タブ ホーディング動作を修正します。 HTML を書いたり、JS を走り書きしたり、Chrome API の謎を調査したりしました。 今回は、基本的に現在のブロック モラルで最も更新された言語である Rust に飛び込みます。 もう論争はやめて むさぼるRustとは何かを教えるために。 あなたがたまたま食べたくて岩の下に住んでいたとしても、おそらくRustについて聞いたことがあります-流行の近所はそれを非常に天国に賞賛しています-それはCの支払い、Javaの保護とAH-64アパッチ攻撃ヘリのヘリコプター育成スキルを備えた貸出機ですしかし – 構文は豪華で、パフォーマンスは素晴らしく、マクロは冷静であり、メモリに関してはほとんど厳密でなくても、生のポインターへのエントリを静かに提供し、だらだらしましょう! だから、インターネットに言語の感触、それでリラックスをむさぼり食うように努力しましょう.タブシリーズを購入できる簡単なキャリアを廃止し、少し簡素化し、OpenAI の API を参照し、-期待どおり幻覚なしに-応答を解析して、拡張機能が e にできるものにします。 雇う。 タブが多すぎてお金を失うことから、シリコンバレーが目覚めてOpenAI APIを忘却に追い込むことまで、私たちはいくつかの制限にぶつかるでしょう.
私たちのキャリアはやや簡単に見えます – 私たちは一つのマナーを教えます
/form に成功しました POST タブと既存のクラス。 それを廃止するために、Axumフレームワーク[title,id]に頼るつもりです。 、ジャバーなしでサーバーを起動できるようにします /form エンドポイント。 そして、それを展開するために shuttle
したがって、AWS 構成の海を引き寄せたり、Procfile を作成したり、docker の写真を作成したりすることで、Rust サーバーを jabber プラグインなしで正常に接続できます。 ミッションの足場にも採用しますですので、取り付けて納車しましょう。入れたものをむさぼり食うのではなく、手順を適用します こちら[title,id] 。 2つ目は、シャトル[{title},{id}]を希望します。 物語 – 悲惨さをなくすために、Github で実際に 1 クリックでサインアップすることをお勧めします – フォームを含める必要はありません.さて、旧端末を立ち上げて カーゴ インストール 貨物シャトル && 貨物シャトル ログイン は 貨物シャトルの初期化 [title,id] で採用されました 認証された後もむさぼり食う可能性があります. ミッション名とジレンマを保持するための指示を漏らし、メニュー クラッチ axum をフレームワークとして. これは、依存関係としてシャトルを使用して、最新の axum ミッションをライブラリとして足場にします。 私たちのフォルダはこれを大切にのぞき見するべきです.
-
いいえ
貴重です[dependencies] 方法 - このイニシアチブは [lib]rary としてマークされているため、事前に定義されたエントリ ポイントが必要になることはめったにありません。
-
ルーター - Axum キャリアの「エントリ ポイント」。 リクエストはここの draw によってルーティングされ、コードは目を見張るものがあります。 supercoolservice.com/whats up は簡単に「こんにちは、世界」を返します!」 テキストの抗議資料。
SyncWrapper
- ルーター オブジェクトをラップし、完全に異なるスレッドにまたがるエントリに専念するか、それを行わないようにします。- [{title},{id}] # - ここに錆マクロがあります - あなたが思いついたときはいつでも、注釈の非常に優れたモデルとして意見を述べてくださいこれらが何であるかを知ってください。 コードを書くコードを書くことができますが、それは怠惰な説明です。 うーん..ここで一時的な転換を望んでいることに異議を唱えます.
マクロの魔法の領域
マクロの魔法の領域、ヒエロニムス・ボス - 2023年、アーティストは機械です。 1つ目はコンベンションティーチング、2つ目はペアプログラミング、3つ目はマクロに入った後の自分を見つけるウサギの穴です。 さて、マクロについてインターネットで説明する前に、これを前置きして警告しておく必要があります。ここでは、マクロとマクロが [insert your favorite language here] でどのように機能するかについて 100% 説明することはもうありません。 そのために、何百もの書籍、ガイド、記事が存在します。
しかし、ここでつまずいて廃止されなくなったこれらのランダムな読者のために、読むために努力しています 「モナドはエンドファンクターのカテゴリーのモノイドです」 マクロを説明するスタイルの記事では、マクロの正直なウサギの穴への一時的な浸食をむさぼり食うつもりです。では、Bust として知られる架空の言語で作業していることに同意しましょう [async_recursion]
バストは現在の極寒の言語であり、ツイッター全体が話題になっており、彼らが教えているか、もはやそうではないようですメタバース AI web4 アプリの言語。 ただし、それはもはや最新の言語ではないか、または早期に静かでなくなり、多くのライブラリがなくなったためです。手動で。 したがって、構造体を廃止するときはいつでも、そのための一連のシリアル化コードも作成することを好みます。 憧れ:struct ReallyBigModel { id: 文字列、名前: 文字列、isReal: Bool、.. . stuff: AnotherBigModel } impl ToJson for ReallyBigModel { fn toJson() -> String { return mapOf { "id" を id に、"name" を名前に、"isReal" を isReal に、..., "stuff" を stuff.toJson に()) }.toJson() } }
- もうイライラしない?
- [async_recursion] [title,id] 属性
はおそらく完全に異なるコードに付けたいと思うマークを大切にしてください.
方法で、クラスのコードを渡し、コンパイルを続行する前に現在のコードが返されるまで待ちます。 そして事実を大切にして、私たちは多くの時間を節約しましたマクロ機能を使用することで、私たちが常に望んでいた生産的なバスト開発者になることができました! さあ、インターネットを廃止しましょう。マクロについて知っておくべきことがたくさんあります d うさぎの穴の奥深くまでインターネットに接続することをお勧めします - さび自体には、まったく異なる種類の マクロ、またはもはやバイタルの 1 つではありません 理由 人々はむさぼり食う スコーク とても素晴らしい、[{title},{id}] 衛生的および非衛生的なマクロ、全く異なる展開、そして深淵に秘められた魔力の山盛り。 せっかく手に入れたので、API の構築をインターネットでサポートしましょう
クラスまたはメソッド。 そのため、コンパイラがコンパイルを行っているか、コンパイルを行っていないときに、大きな赤い X が付いている機能に遭遇した場合、またはそれが頭でなくなった場合、マクロ機能に名前が付けられることをはるかに認識しています. [{title},{id}] マクロ機能 は、 属性 でマーク、何を実行するかを決定し、現在のコードをコンパイラに返します。コンパイラは、マークされた機能があった場所にサポートを統合します。 したがって、このインスタンスで toJson マクロ、 add toJson 任意の構造体の上に属性を追加すると、そのコードが書き込まれるため、上記のコードは次のようになります:#[toJson] struct ReallyBigModel { id:文字列、名前: 文字列、isReal: Bool、... スタッフ: AnotherBigModel }
#[toJson] fn addToJsonTrait(input: TokenStream) -> TokenStream { let tree=parseIntoAST(input) let nodes=ast.recordsdata.asStruct() ; let name=tree.id // プロパティである初期の人生全体を救い出す // それらをフォーマットに設計する: $name to name let properties=nodes .filter((tiny one)=>tiny one.isProperty) .blueprint((property )=> ""${property.name}" to ${property.name}") .joinToString(",n") // toJson トレイト body を書く let body=quote! { //ここにも追加または大幅に少ないマクロがあります! impl ToJson for #name { fn toJson() -> String { return mapOf { #properties }.toJson(); } } } return body.intoTree().intoStream() }そして、私たちのマクロピープは何を大切にしますか?
ウィットと書かれたコードを取り込む機能だろう h それ (トークンとして表される) を返し、それを置き換えることができるブランドの現在のコードを返します.
、これは addToJsonTraitHide: これが架空の言語、バストです。 すべての言語にはマクロの実装があるか、またはないため、記事が過度に長くならないように、1 の簡単な図を実際に示します。 だから、コンパイラが ( でマークされたクラスに到達したとき#[toJson]
- POSTの勤務先 *)
/フォーム[insert your favorite language here]のサポートで、キャリアの簡単な魔法を隠します POST風なので、そのwhats up worldを削除し、ルーターを
/form 期待-Router::current().route("/form", submit(sort_items))
と sort_items 期待を処理できる方法:
誰も毎日この素晴らしいボイラープレートを書きたがりません.[async_recursion] しかし、ある時点で、最新の変更ログを読んで、現在、マクロ。 いくつかの種類のマクロがありますが、Bust マクロには、2 つの問題で構成されている可能性があることを明らかにしたいこれらの特別なメソッドがあります:
- [async_recursion] マクロ属性
マクロ機能
スタイルは、expect 構築の Json ラッパーを受け取り、imple を返すこともできます。 サーバーが処理するスタイルを認識している IntoResponse 特性の説明。 特に、
StatusCode,T["derive"] のタプル形式で返すことになります。 サーバーは、受け入れ可能な応答に変換するスタイルを認識しています [{title},{id}] 有効にしなければならない 1 つの余分なジャバーは、expect recordsdata の構築です。 drawl では、それらを同じファイルに配置する代わりに、 として知られる最新のファイルを作成しましょう。 )devices.rs in [async_recursion] src フォルダを削除し、一部の従来の定義を廃止します。 ["derive"] SortRequestPayloadこれは、受信に成功したラッパーです。 クラスとアイテムのチェックリストが含まれているため、それらの構造も必要になります - Category
とアイテムなので、こちらも追加しましょう。 そして、クラスのチェックリストを希望します と アイテムを取得するため、所属するアイテムとそれらのラッパーを使用してクラスをむさぼり食うことに成功しています。 さらに、ErrorResponse[async_recursion] を追加します。 ジャバーがどこにあるかがわかります.
//devices.rs で pub(crate) struct SortRequestPayload { pub(crate) classes: Vec, pub(crate) アイテム: Vec , } pub(クレート) struct Category { pub(crate) id: usize, pub(crate) title: String, } pub(crate) struct Item { pub(crate) id: usize, pub(crate) title: String, } pub(crate) struct CategoryWithItems { pub category_id: usize, pub category_name: 文字列, pub items: Vec } pub(crate) struct Categories { pub クラス: Vec } pub(crate) 構造体ErrorResponse { パブ メッセージ: 文字列, } - しかし、1つ購入しましたjabber - json から/への jabber (de)serialisable なしで構造を構築したい - そのために、 として知られるライブラリの採用に成功しましたセルデ
cargo.toml ファイルに
これで、構造体を serde でマークすることに成功しました [{title},{id}] #["derive"]serde[async_recursion] を追加します。 および serde_json[{title},{id}] 依存関係: ["derive"]
serde={ モデル="1.0", 機能=["derive"] } serde_json="1.0" - [async_recursion] [title,id] 属性
├── Cargo.lock ├── Cargo.toml └── src └── lib.rsそれはやや簡単な構築です-私たちは今むさぼり食っています cargo.toml
、これは のさびモデルです。 manifest.json または [$tabName, $tabId] package.json。 パッケージに関するメタデータが含まれているか、依存関係、コンパイル機能、および追加機能ではありません。 cargo.lock は、指定された依存関係のハードコーディングされたチェックリストであり、環境全体で一貫したビルドを保証します.私たちの貴重なサーバーコードは内部に宿ります src/lib.rs。 静謐で優雅な今をのぞいてみましょう:
axum を採用:: {ルーティング::インターネット、ルーター}; sync_wrapper::SyncWrapper を使用します。 async fn hello_world() -> &'static str { "こんにちは、世界!" } # async fn axum() -> Shuttle_service::ShuttleAxum { let router=Router::current().route("/whats up", internet(hello_world)); let sync_wrapper=SyncWrapper::current(ルーター); Ample(sync_wrapper) }ここに公開の問題のペア: )
フレームワークが、購入した JSON を構造体にデシリアライズするスタイルを認識できるようにするためのマクロ
1. アイテムを回収する 2. アイテムをクラスに配置する 3. ステアされたものをチャンクにスライスする 4. 再帰的な形式: 4.1. 既存のクラスとチャンクを取り、それらを操縦された 4.2 に変換します。 4.3. OpenAI に質問し、それを形成します。 4.4. レスポンスをデシリアライズします。 既存のクラスに追加 4.5. チャンク滞留中は4.1まで対応 5. 打ち切り結果を返す
- そしてそれをメソッドに構築する:
//lib.rs 内 ... fn create_chunks_for_prompting(items: Vec
- fn sort_recursively(sorted_categories: Vec
, final: Vec > ) -> 結果 fn build_prompt(items: Vec 、クラス: Vec) -> 文字列 fn prompt_open_ai(steered: String) -> 結果 - さらに、私たちは操縦したいので、これを大切にしようと努力しましょう - 私たちはGPT3にこれを教え、問題のチェックリストを受け取り、フォーマットとチェックリストを埋め込みます。 次に、現在のクラスに到達して渡すための公式の JSON 形式をアサートします。 廃止時には、公式の JSON 形式でそれらを取得するように教えています。 願わくば、これも JSON 形式に準拠し、幻覚に陥らないことを願っていますが、後の投稿で正直に調整します。 今のところ、公式の JSON 形式を指定してステアリングの廃止を終了し、廃止の中で「公式の JSON 形式」を宣言することで、ある程度うまく根拠が保たれているように見えます。 [$tabName, $tabId] [title,id] のタイトルと ID に関する問題のチェックリストを受け取ります。 基本的にタイトルとURLだけで、既存のクラスを流用したり、最新のクラスを作ったりして、クラス分けを行います。 タブは次のとおりです: [$tabName, $tabId]。 正しい JSON 形式は { "classes": [$tabName, $tabId] } ]} です。 既存のクラスは次のとおりです: $classes クラス (既存および現在) のブランド最新の詳細なチェックリストと、公式の JSON 形式は次のとおりです:
- [{title},{id}] 私には道徳的に聞こえます!
内部の採用に成功した定数に分けましょう私たちのコードconst PROMPT_TEXT_START: &str="タイトルに関する問題のチェックリストを受け取りますID は の発明で *))。 基本的に、タイトルと URL に完全に基づいて、既存のクラスを使用するか、現在のクラスを作成して、それらをクラスに分類します。"; const PROMPT_TEXT_MIDDLE: &str="n取得する有効な JSON 形式は次のとおりです: { "classes": [ { "category_id":"id here", "category_name": "name here", "items":[tab_id here] } ]}. 既存のクラスは次のとおりです:"; const PROMPT_TEXT_ENDING: &str="タブ付きのクラス (既存および現在の) のブランド最新の詳細なチェックリストは、公式の JSON 形式で次のとおりです:";
最後に、インターネットに成功しましたsort_items のように入力していきます. まず, の所有権を購入します. recordsdata をチャンクに分割します:
//in devices.rs #[derive(Serialize)] pub(crate) struct SortRequestPayload { pub(crate) classes: Vec, pub(crate) アイテム: Vec , } #[derive(Deserialize)] pub(crate) 構造体 カテゴリ { pub(crate) id: usize, pub(crate) title: 文字列, } #[derive(Deserialize)] pub(crate) 構造体Item { pub(crate) id: usize, pub(crate) title: String, } #["derive"] #[title,id] pub(crate) struct CategoryWithItems { pub category_id: usize, pub カテゴリ名: 文字列、pub 項目: Vec } #[title,id] #[title,id] pub(crate) 構造体カテゴリ { pub クラス: Vec } #[derive(Serialize)] pub(crate) struct ErrorResponse { pub メッセージ: 文字列, } これで、コードへのダイブ サポートに成功しました。
私たちの意見を探してみましょう:
) -> ベク
どうしてチャンクなの?ステへのアイテムでは、ステアされたサイズは 4096 トークンをはるかに超えます。ステアされたサイズと完了の最大サイズがサポートされているため、これから使用するモデルはこれをサポートします。 したがって、それを道徳的なサイズに分割し、完了のためにいくらかのバッファーを消費するために、達成をインターネットに接続する必要があります。50% のバッファーを残して、ステアリング サイズを 2048 のままにします。
それを廃止するために、私たち [{title},{id}] create_chunks_for_prompting 機能を有効にする必要があります2 つの問題:
- > { //recordsdata のトークン let json_size=serde_json::to_string(&items).unwrap() .split_whitespace() .collect_vec() .len(); // インターネット ハードコーディングされたステアリングのスケール let hardcoded_prompt=format!("{a}{b}{c}", a=String::from(PROMPT_TEXT), b=String::from(PROMPT_TEXT_APPEND), c=String ::from(PROMPT_TEXT_ENDING)); let hardcoded_prompt_size=hardcoded_prompt .split_whitespace() .len(); //項目を分割してチャンクの選択をインターネットに接続する let chunks_to_make=json_size / (2048 - hardcoded_prompt_size); // ベクトルを N 個のベクトルに分割 let chunk_size=items.chunks(items.len() / (if chunks_to_make> 0 { chunks_to_make } else { 1 })); // チャンクのチェックリストを返す return chunk_size.blueprint(|s| s.into()).in discovering(); }
トークンの選択に依存私たちの凶悪な操縦 API に送信するレコードデータ内のトークンの選択に依存します 2048 からハードコーディングされたステアリング サイズを差し引いた合計トークンのスケールを分割することにより、必要なチャンクの量を計算します。 OpenAIのドキュメントによると、私たちはトークンは約 4 文字のスケールであるという推測に成功しました。 さて、トークンをカウントするためのまったく異なる方法がいくつかあり、それを適切に制定するために、実際よりもわずかに大きいものを制定することを決定します。 Rust トークナイザー クレートとその GPT2 トークナイザー。 ただし、それではもう 1 つウサギの穴に落ちてしまうので、スキップします 今のところ そして事実は簡単なトリックを制定するつもりです - split_whitespace トークン サイズの概算を提供できる方法 [{title},{id}] fn create_chunks_for_prompting(items: Vec )) -> Vec さあ、インターネットを止めましょう私たちの build_prompt 機能.クラス。 問題のチェックリストと 形式の購入を承ります! それを の発明で文字列に) )[title,id]。 次に、クラスを JSON に変換し、 形式を使用します! すべてを 1 つのステアリングに結合するマクロ fn build_prompt(items: Vec 、クラス: Vec )) -> String { //ブループリント アイテムを [title,id] 次に、それらすべてを文字列に結合します let items_joined=items.iter().blueprint(|merchandise| format!( "[{title},{id}]",タイトル=商品.タイトル、id=商品.id)) .in 発見() .結合(","); カテゴリ_json=serde_json::to_string(&classes).unwrap(); を許可します。 format!("{steered}n{tabs}{center}{classes}n{ending}", steered=String::from(PROMPT_TEXT_START), tabs=items_joined, center=String::from(PROMPT_TEXT_MIDDLE), クラス=category_json, 終了=String::from(PROMPT_TEXT_ENDING)) } さて、OpenAI にステアされたということを言うと、HTTP コンシューマが必要になります。[$tabName, $tabId] そのために、 を使用します) reqwest[title,id] クレート - 簡単な非同期機能を備えた過剰なレベルの HTTP コンシューマーを提供します簡単なシリアライゼーション/デシリアライゼーション。 それでは、それを Cargo.toml に追加しましょう。 ファイル:
API に送信するレコードデータ内のトークンの選択に依存します 2048 からハードコーディングされたステアリング サイズを差し引いた合計トークンのスケールを分割することにより、必要なチャンクの量を計算します。 OpenAIのドキュメントによると、私たちはトークンは約 4 文字のスケールであるという推測に成功しました。 さて、トークンをカウントするためのまったく異なる方法がいくつかあり、それを適切に制定するために、実際よりもわずかに大きいものを制定することを決定します。 Rust トークナイザー クレートとその GPT2 トークナイザー。 ただし、それではもう 1 つウサギの穴に落ちてしまうので、スキップします 今のところ そして事実は簡単なトリックを制定するつもりです - split_whitespace トークン サイズの概算を提供できる方法 [{title},{id}] fn create_chunks_for_prompting(items: Vec )) -> Vec さあ、インターネットを止めましょう私たちの build_prompt 機能.クラス。 問題のチェックリストと 形式の購入を承ります! それを の発明で文字列に) )[title,id]。 次に、クラスを JSON に変換し、 形式を使用します! すべてを 1 つのステアリングに結合するマクロ fn build_prompt(items: Vec 、クラス: Vec )) -> String { //ブループリント アイテムを [title,id] 次に、それらすべてを文字列に結合します let items_joined=items.iter().blueprint(|merchandise| format!( "[{title},{id}]",タイトル=商品.タイトル、id=商品.id)) .in 発見() .結合(","); カテゴリ_json=serde_json::to_string(&classes).unwrap(); を許可します。 format!("{steered}n{tabs}{center}{classes}n{ending}", steered=String::from(PROMPT_TEXT_START), tabs=items_joined, center=String::from(PROMPT_TEXT_MIDDLE), クラス=category_json, 終了=String::from(PROMPT_TEXT_ENDING)) } さて、OpenAI にステアされたということを言うと、HTTP コンシューマが必要になります。[$tabName, $tabId] そのために、 を使用します) reqwest[title,id] クレート - 簡単な非同期機能を備えた過剰なレベルの HTTP コンシューマーを提供します簡単なシリアライゼーション/デシリアライゼーション。 それでは、それを Cargo.toml に追加しましょう。 ファイル:
- OpenAIのドキュメントによると、私たちはトークンは約 4 文字のスケールであるという推測に成功しました。 さて、トークンをカウントするためのまったく異なる方法がいくつかあり、それを適切に制定するために、実際よりもわずかに大きいものを制定することを決定します。 Rust トークナイザー クレートとその GPT2 トークナイザー。 ただし、それではもう 1 つウサギの穴に落ちてしまうので、スキップします
- 今のところ そして事実は簡単なトリックを制定するつもりです -
split_whitespace トークン サイズの概算を提供できる方法 [{title},{id}] fn create_chunks_for_prompting(items: Vec )) -> Vec さあ、インターネットを止めましょう私たちの build_prompt 機能.クラス。 問題のチェックリストと 形式の購入を承ります! それを の発明で文字列に) )[title,id]。 次に、クラスを JSON に変換し、 形式を使用します! すべてを 1 つのステアリングに結合するマクロ fn build_prompt(items: Vec 、クラス: Vec )) -> String { //ブループリント アイテムを [title,id] 次に、それらすべてを文字列に結合します let items_joined=items.iter().blueprint(|merchandise| format!( "[{title},{id}]",タイトル=商品.タイトル、id=商品.id)) .in 発見() .結合(","); カテゴリ_json=serde_json::to_string(&classes).unwrap(); を許可します。 format!("{steered}n{tabs}{center}{classes}n{ending}", steered=String::from(PROMPT_TEXT_START), tabs=items_joined, center=String::from(PROMPT_TEXT_MIDDLE), クラス=category_json, 終了=String::from(PROMPT_TEXT_ENDING)) } さて、OpenAI にステアされたということを言うと、HTTP コンシューマが必要になります。[$tabName, $tabId] そのために、 を使用します) reqwest[title,id] クレート - 簡単な非同期機能を備えた過剰なレベルの HTTP コンシューマーを提供します簡単なシリアライゼーション/デシリアライゼーション。 それでは、それを Cargo.toml に追加しましょう。 ファイル:
この使い方で、モラルオールビルダーサンプルの作戦でHTTPコンシューマーの廃止に成功しました
- [title,id] devices.rs を起動します。 そして、OpenAI Completion API と連絡を取り合う必要がある構造体を追加します:
let consumer=Consumer::builder() .http2_keep_alive_timeout(Duration::from_secs(120)) . timeout(Duration::from_secs(120)) .abolish() .unwrap(); しかし、コンシューマーを内部に構築した場合 prompt_open_ai 機能、私たちがインターネットを期待するたびに消費者の機会を組織することに成功しているので、代わりに依存関係を廃止し、消費者コードを私たちの sort_items 機能を使用し、それを na 引数として sort_recurively 機能と prompt_open_ai 機能。 これを達成するために、最も注目を集めようとしているのは、HTTP コンシューマ 1 つにつき 1 つの機会 /form
の名前と弊社 prompt_open_ai 機能は、実際に電話をかけている場合、最も注目を集めることができますAPI を提供し、廃止結果のサポートを提供します。 簡単な POST 名を廃止して、どのように受信が成功するのか、またはもはや成功していないのかを突き止めましょう 結果
。
問題を簡潔に保つために、構成内の別のモジュールを廃止します。モジュールはコード (機能など) のコンテナであり、コードの完全に異なる領域間の分離を廃止することができます。 openai として知られるブランドの現在のフォルダーを作成します。 とその中の 2 つの現在のレコードデータ: a mod.rs[title,id] 私たちのコード ア devices.rs 私たちのデバイス
serde::{Deserialize, Serialize}; を使用します。 #[derive(Serialize)] pub(crate) struct AskGPT { pub steered: 文字列、pub モデル: 文字列、pub max_tokens: usize、pub circulate: bool、pub temperature: usize、pub top_p: usize、pub n: usize, } #[derive(Deserialize)] pub(crate) struct Completion { pub モデル: 文字列、pub 決定: Vec, } # [title,id] pub(crate) struct Picks { pub テキストの抗議素材: 文字列、pub インデックス: usize, } で [async_recursion] mod.rs 廃止に成功しました
prompt_open_ai 方法、POST で新しく作成した AskGPT[toJson] を送信できることを期待 モデルを /completions エンドポイント. さて、ここには貴重なフィールドがあります - 自明です [async_recursion] 操縦された 自己規律、モデル
これにより、どのモデルが完成を制定するかを把握できます(執筆時点では、テキストの抗議資料-davinci- 003がこのプロジェクトの理想的な演奏です)、[{title},{id}] max_tokens 私たちが行く4096(最大、d'oh)を維持するには、n は応答の選択を制御し、 温度 これは、どの確率に同意するかを教えるためのものです - 増加するほどこれまでのところ、補完がよりランダムに見える可能性があります - 0 を使用するので、出力ははるかにランダムではありません.非表示: t の場合彼の部分、あなたはおそらくあなたのここでインターネットに接続したい OpenAI API キー["derive"] . [title,id] async fn prompt_open_ai(prompt_txt: 文字列、消費者: &Consumer) -> 結果 { let token=String::from("YOUR_API_KEY_HERE") let auth_header=format! ("ベアラー {}"、トークン); let req=consumer.submit("https://api.openai.com/v1/completions") .header("Authorization", auth_header) .json(&AskGPT { 操縦: prompt_txt、モデル: 文字列::from("テキストの抗議素材-davinci-003")、max_tokens: 4096、n: 1、循環: false、温度: 0、}).send().もうスリープしない; } 最後に [async_recursion] 結果
! しかし、それで何を制定するのでしょうか?スマートに、事実の追加に成功しました
? はもはや眠らないのを中止するため、応答
、それにもかかわらず、リラックスできることはめったにないので、間違いなく私のお気に入りの錆の機能の 1 つである有名な を使用します。 マッチ
。
マッチ
ステートメントは、Rust 開発者の旅の中核にあり、コードがたどるパス全体が確実に並べられるようにする非常に優れたサンプル マッチング機能を提供します。 [async_recursion] しかし、イアン、それについて何がそんなに特別なの?
ステロイドの if/else はもはや事実ではありませんか? ?
いやいや、もうそれ以上のことはできません。
if/else のスイートとは異なります または スワップ[title,id] ステートメント、 一致 は、確率の合計を確認することを強制し、満足のいく道と不幸な道をそれぞれ隠すことを保証します。コードを購入する必要があります。 なぜこれが超能力なのか? これにより、未処理のケースによるバグの置換が減り、ケースに同意する可能性があるすべてをカバーする必要があるため、コードをまっすぐに改善できます。 コードの可読性を高め、バグを解決し、保守性を高めることができる、一風変わったツールですそれでは、それを採用するように努力しましょう - 構文は簡単です。左側の側面は、非常にうまく一致する可能性があるサンプルです。道徳的な側面に反対し、制定するコードブロックです。 最初に、結果
我々は買った。
match req { Ample(response)=> { //実際に抽選が行われたと予想される場合、無事にエントリ レスポンスに成功します } Err(error)=> { //TODO take } }
match response.train() { StatusCode::OK=> { // スマッシング成功 } 完全に異なる=> { // TODO エラーを処理する } } そして最後に、主要なステップについて - もし期待が成功していたなら、私たちは体を私たちの Completion 構造体。 ただし、それも失敗する可能性があるため、一時的な 一致
ここでも完了オブジェクトから応答を抽出します:
response.json に一致:: ().もう { Ample(parsed )=> { //私たちは皆、少なくとも 1 つの商品に決定が継続的に存在することを知っています。アンラップ(); let json: &str=decision.textual 抗議 material.borrow(); Ample(String::from(json)) } Err(err)=> { return Err(解析); } }
エラーを処理するために、完全に異なる種類のエラーを表す列挙型を追加しましょう。これらの 3 つの形式にエラーが発生します. また、不完全なことができます..) - 接続エラー、サーバー応答エラー、および解析エラー。 devices.rs を追加します: [{title},{id}] #[derive(Debug)] pub(crate) enum OpenAiError { 接続、解析、サーバー、}
[{title},{id}] マッチreq { Ample(response)=> { match response.train() { StatusCode::OK=> { match response.json:: ().no もうスリープ for { Ample(parsed)=> { //expect let decision=parsed.decisions.first().unwrap(); のため、少なくとも 1 に継続的に存在します。 let json: &str=decision.textual 抗議 material.borrow(); Ample(String::from(json)) } Err(err)=> Err(解析); } } 完全に異なる=> Err(サーバー) } } Err(err)=> Err(接続)
おめでとう! 私たちは今、正確な方法で私たちの期待を効率的にむさぼり食い、あなたの不幸で満足のいく道全体を道に並べました.
だから私たちのリクエストはポッピンで、私たちは成功しています 決勝で sort_recursively 機能。 なぜここで再帰? 通常、GPT3 をレデューサー機能として実行して、チェックリストをそれ自体に縮小しているためです。 ここでループを実行して、このスタイルに n 回名前を付けることができますが、これは、(クラスを含む) ループの空気を生成する変数も変更することを決定することを意味します。 それは汚く感じるので、私たちの道徳的な古い友人である再帰を使用して、エレガントで意図的な達成を実現します. だから私たちの valuable.rsインターネットを
sort_recurively 機能. まず、ステアドを廃止し、次にprompt_open_ai に送信します。 応答を逆シリアル化するように努めます。 成功した場合は、現在のクラスに結合し、再度 sort_recurively["derive"] に渡します。 チャンクがなくなるまで、最後のチャンクを使用します。
[$tabName, $tabId] async fn sort_recursively( sorted_categories: Vec 、最終: Vec> 、消費者: 消費者) -> 結果 { let steered=build_prompt(final.first().unwrap().to_vec(), sorted_categories); let ai_response=prompt_open_ai(steered, &consumer).もうスリープしない for.unwrap(); let json=ai_response.as_str(); //デシリアライズしようとする let generated=serde_json::from_str:: (json); match ai_response_result { Ample(response)=> { let parsed=serde_json:: from_str:: (ai_response.as_str()); match parsed { Ample(res)=> match res { Ample(wrapper)=> { let mut new_categories=wrapper .classes.to_owned(); //処理されたチャンクを購入する let mut next_slice=final.to_owned(); next_slice.purchase away(0); // クラスに参加する next_categories.append(&mut new_categories); //終了していない場合は再帰 if next_slice.len() !=0 { let next=sort_recursively(next_categories, next_slice, consumer).もうスリープしない match next { Ample(cats)=> Ample(cats), Err(e)=> Err(String::from("Form failed")) } } else { Ample(Categories { classes: next_categories }) } } Err( msg)=> Err(msg) } Err(解析中)=> Err("解析応答エラー".to_string()) } } Err(err)=> Err(err) }} 
これらすべてのスーツで、私たちのコードはまばゆいほど恐ろしいものをのぞき見し始めています。 青写真 ,map_err と and_then[{title},{id}] 拡張子 - 左側の両方で動作します ( 設計図) またはモラル ([dependencies] map_err) の側面) 結果
、それらを非常に読みやすく簡潔なモデルにチェーンするだけで、入れ子の地獄を手動で確認できます。 ガイドラインは、対応するオペランドの描画によって最も注目を集めるものを渡すので、記録データとエラーを実際の形式に安全に青写真化することに成功しています.
入れ子スーツの初回キープ割引で採用し、最終キープはそのまま残します。マッチ。 なぜ? なぜなら async クロージャの quiet はもはや正確ではないはずです Rust でそれは見えます。 エラー全体を Err(String)
形式なので、うまく返すことができました: async fn sort_recursively(sorted_categories: Vec 、最終: Vec> 、消費者: 消費者) -> 結果 { let mut next_categories=Vec::from(sorted_categories.deref() ); let steered=build_prompt(final.first().unwrap().to_vec(), sorted_categories); let ai_response_result=prompt_open_ai(steered, &consumer).もう寝ません; let res=ai_response_result .map_err(|e| format!("OpenAI との通信エラー - {:?}", e)) .and_then( |ai_response| serde_json::from_str:: (ai_response.as_str()) .map_err(|_| "解析応答エラー".to_string ())); match res { Ample(wrapper)=> { let mut new_categories=wrapper.classes.to_owned(); //処理されたチャンクを購入する let mut next_slice=final.to_owned(); next_slice.purchase away(0); // クラスに参加する next_categories.append(&mut new_categories); //終了していない場合は再帰する if next_slice.len() !=0 { sort_recursively(next_categories, next_slice, consumer).no longer sleep for .map_err(|e| format!("Sorting failed, cause: { }", e)) } else { Ample(Categories { classes: next_categories }) } } Err(msg)=> Err(msg) } } 
[{title},{id}] それは遠いです - 私たちは正確でエラーのない API として知られています。 賢明なことに、私たちが議論しなかった 1 つの jabber は非同期です。
なんでこんなジャバなの? 賢明なことに、Rust では async/no longer sleep for がどのように実装されているか (そして、ほぼ完全にさまざまな言語)、ボンネットの下で、スタイルの未来全体と一緒に列車の機械の形を生成します。 ただし、ここで再帰を追加すると、生成されたフォームはそれ自体を参照し始めます。そのため、内部では、間違いなく無限に再帰的なフォームに爆発し、コンパイラはその種類のスケールを判断できません。 それが爆発するのを防ぐために、再帰を修正して Box'd Future を達成する必要があります。これにより、事実上、オブジェクト全体の代わりとしてヒープへのポインターが得られ、無限の自己参照が防止されます。フード. このジャバーについて余分に読んでくださいここ そして、このうさぎの穴をますます深くたどっていきます - 多くの言語で見られるような疑問や提案を生み出す言語について、いくらかカバーしています。 ただし、今のところ、実行するのは async_recursion クレートなので、 に向かいますCargo.toml をそこに追加します:
[dependencies] .. async-recursion="1.0.2"
そして、[async_recursion] で特徴をマークします#[async_recursion] マクロなので、あなたのためにボックス化します.
それで、私たちは私たちの形へのサポートを得ることに成功しています sort_items のように、最終的にはその API 期待に同意します。 そこに残した閉店時間に、消費者[{title},{id}]を追加しました 機会なので、その下に頭を下げて に名前を付けます。 sort_recurively のやり方で、採用 [async_recursion] map_err エラーを
ErrorResponse 構築し、JSON でラップして応答として返し、 blueprint[toJson] を使用します。 をめくる Ample 事実に基づく回答:
sort_recursively(classes, prompt_slices, consumer).map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(ErrorResponse { message: e })).into_response()) .blueprint(|wrapper| { let new_categories=wrapper.classes.iter().blueprint(|merchandise| { Ca tegoryWithItems {category_id: 商品.category_id.to_owned()、category_name: 商品.category_name.to_owned()、商品: 商品.items.to_owned()、} }). 発見::> (); (StatusCode::OK, Json(Categories { classes: new_categories })).into_response() })
[$tabName, $tabId] そして、これでキャリアの完成です! 応答を購入し、フォーマットし、操作し、ユーザーにサポートを提供します。 私たちの意見は献身的で健全です。 あとはそれを展開するだけですが、ケースのプロビジョニング、セキュリティグループの開発、dockerfile の作成について議論する必要はありません。 シャトルの戦略でキャリアを足場にしたので、ターミナルの簡単なタッチでジャバーなしで展開することに成功しました。 選択とフォームのシェルのイニシアチブ フォルダーを作成します:
カーゴシャトル展開[dependencies] [async_recursion] 立ち上がって、ちょっと息をのむような買い物をして、コーヒーを一口飲むと、あなたが気付く前に、サーバーが起動して次の場所で動作しています:
https://projectname.shuttleapp.rs/
さて、ええと。 .. なぜ私たちはこれをやったのですか?
ええ、私たちは JS 拡張機能を作成していました。 私たちのサーバーが稼働している、またはもはやそれはほとんど達成されていません-実際には拡張機能にポップオーバーし、localhost エンドポイントを実際にシャトルから購入した実際のエンドポイントに置き換えます。
さて、拡張機能を小さなウィンドウに実際にロードしてテストします。 親切なボタンを押して、少し待って、BAM! タブは魔法のように事実に基づいたグループに分類されるはずです! 最後に! 真のウィンドウ - 600 に近いタブを持つウィンドウ。 それでは、実際に親切なボタンを押して、お待ちください... ...待って.. .....少し余分に待ってください.......... waaaaaitまたはそれがもう来ない...
.... ここでは 60 秒以上かかります...... あ、ちょっと待って...
.. エラー?
おっと - トークン制限に達しました!
なぜ? どうやって? 似合うように総チャンキングジャバー事実を制定しませんでしたか?
うーん、ステアされたサイズについてさらに大きな計算を行わなければならないのは大事に見えます.
さらに、私たちの再帰は問題を引き起こしています - 以前のすべてのクラスをステアされたすべてに追加すると、サイズが爆発的に大きくなり、if に非常に長い時間がかかります実は全チェインを廃止して60秒以上を達成。 そして最後に、クラスはやや...まあ.
これは非常に大きなものです。次の反復のために制定するための余分なものを提供してくれるからです。この再帰を取り除き、使用するスタイルをインターネットに配置します GPT トークナイザー
を使用し、辞書レコードデータをバイナリに埋め込み、雇う shuttleの静的フォルダ 私たちの廃止時代を吹き飛ばす代わりとしてのキャリア。 また、 で刺し傷を購入します。 微調整 モデルは、はるかに少ないトークンでより良い結果をもたらします - そして、私たちは怠け者なので、GPT 自体を使用して研究記録データを実際に生成するつもりです. もしかしたら食べたくなったらここまで来て、読んでくれてありがとう、もう惨めさをなくすために、私たちは多くの特別な特徴的なクリープと容量の問題をむさぼり食って、私たちの道を語るので、「人間対機械」の次のエピソードであなたを見つけてください。
マシンは、かわいらしさについての意見をまとめて、ジャバーを静かにむさぼり食うことができました。 「かわいいさびたカニのイラスト」 - 2023年、絵師は機械。
𝚆𝚊𝚝𝚌𝚑 𝙽𝙾𝚆 📺