Progrobot:プログラミング言語ヘルプボット

コードを記述するとき、特定の関数、モジュールなどに関するヘルプを参照する必要があります。 私は通常cppreference.comまたはdocs.python.orgにアクセスしますが、通常は瞬時ではありません-少なくとも数ページが必要です。また、Pythonのドキュメントでは、言うまでもなく、ページで必要な情報を見つけることも困難です。 Googleはしばしば2番目のバージョンのドキュメントを参照しますが、3番目のバージョンのドキュメントは参照しないため、手動で切り替える必要があります。



したがって、テレグラムボットは有用であると考えました。テレグラムボットは、このすべての情報を知っており、特定の機能、クラス、モジュールなどの要求に応じてヘルプを発行します。



これが@Progrobotボットの結果です。 彼に関数の名前を送信してその簡単な説明を取得できます。モジュールの名前(Pythonの場合)またはヘッダーファイル(c ++の場合)を送信して、このモジュール内のすべての関数のリストを取得できます。 これまでのところ、c ++(cppreferenceを使用)およびpython3(docs.python.orgを使用)に関するヘルプがあります。 また、stackoverflowで検索を行う予定でしたが、API検索がうまく機能しないことがわかりました。また、リクエストの数にも厳密な制限があります。つまり、オフにした後、オフラインデータベースをデフレートして終了します。



ボット自体について



データをmongoに保存します。各言語には2つのテーブルがあります。 最初は、実際にはオブジェクト(関数、クラス、モジュールなど)のヘルプがあります。「標準」名、ドキュメントの取得元のページへのリンク、オブジェクトが属するモジュール(Pythonモジュールまたはcpp-header)、フォーマット使用法、説明、子のリスト(クラスのメソッドなど)および文字列の著作権。 子要素ごとに短い説明も保存されます。これは、この要素の説明の最初の文として取りました。 (さらに、最初の文の検出も簡単な作業ではありませんでした。)



2番目のテーブルにインデックスを保存します。たとえば、std :: vector :: push_backのように、オブジェクトごとに名前を保存します。インデックスには、「push_back」、「push_back vector」、「push_back std vector」が含まれます。最初のテーブルのヘルプへのリンク。 つまり、オブジェクトの完全な名前をトークンに分割し、結果のリストのすべてのサフィックスを取得し、サフィックスごとにトークンをアルファベット順に並べ替えます。 インデックスの各行には、複数のドキュメントが存在する場合があります(たとえば、push_backはベクター内だけではありません)。



これで、ボットのロジックは非常に単純になりました。リクエストをトークンに分割し、アルファベット順にソートして、インデックス内の対応するエントリを探します。 見つかった-乾杯、見つかりませんでした-明らかに、そのようなオブジェクトはありません。 関連するエントリが複数ある場合、それらから最も適切なエントリを選択します(簡単にするために、「正規」名に最小数のトークンが含まれるエントリを選択することを決定しました。たとえば、「get」リクエストはxmlではなくstd :: getを返します.etree.ElementTree.Element.get)。 一般に関連するすべてのエントリは、/ listコマンドで表示できます。



データベースには、コードのフォーマットなどを保存するための説明がhtmlにあります。 Telegramを使用すると、メッセージでhtmlの単純なサブセットを使用できるため、サポートされていないタグをすべて破棄し、適切な場所に改行を挿入するコンバーターを作成しました。 ここの特殊効果のうち、説明にはローカルリンク(<a href="#anchor-------->)がありました。 私はそれらを残して、すべてが機能しました、そのようなリンクは電報クライアントでは機能しませんでしたが、それも怖くはありませんでした。 翌日、ボットはほとんどメッセージを送信できないことを発見しました。 どうやら、電報は、リンク内のアドレスの正確性に関する追加チェックを追加し、ローカルリンクのスキップを停止したようです。 完全なアドレスのリンクのみを残す必要がありました。



また、電報ではメッセージの長さが4096文字に制限されているため(電報のドキュメントでは定数を見つけることができませんでした)、一部のオブジェクトの説明が長くなることが判明したため、少し工夫する必要がありました。 適切な場所で長いメッセージを短いメッセージにカットするちょっとしたコードと、継続を取得する/ contコマンドを追加しました。 ここでの予想外のジョークの中から-メッセージのカットオフ部分のすべての括弧がバランスが取れていることを確認しました。 それから、ランダムなPythonモジュールに出くわしました。その説明では、「...セミオープン範囲[0.0、1.0)で一様にランダムフロートを生成します」というフレーズがあります。 正方形と括弧を同等と見なさなければなりませんでした。



解析について



cppreferenceを使用してhtmlを解析することは本当に嬉しかったです。 エンティティごとに1ページ、正確な参照スタイルの適切なテキスト、htmlタグに適切なクラスとID、ページ上の直接の子オブジェクトのリストなど。 例として3つのページを取り上げ、BeautifulSoupを使用してこれらのページを適切に解析する非常に簡単なコードを記述しました。 それから彼はささいなことをひねりました。 現在、手で修正することができない粗さもありますが、一般的にはすべてが機能します。 些細なことではありませんが、ヘッダーファイルの説明と子を入力しました(「アルゴリズム」のリクエストで、このファイル内のすべての関数のリストを取得できるようにするため)。 bool、その結果、boolの要求に応じて、トークン化の前に特殊化を破棄する必要がありました)。



しかし、Pythonドキュメントの解析ははるかに楽しかったです。 それは連続して読むことができる本として書かれています。 その結果、イデオロギー、使用法のヒント、例、実際に必要な参照がそこに混在しており、さらに、「pprintモジュールは1つのクラスを定義します」などのフレーズがあります。これは、後続のモジュールの説明と区別できません そのため、すべてが3つのサンプルページで機能した後、Pythonドキュメントの解析を長時間完了する必要がありましたが、今ではcppよりも多くの問題があります。 たとえば、pprintに関するこのフレーズは現在、ボットの応答に含まれており、奇妙に見えます。



修正しなければならなかった問題のうち、多くのエンティティの説明は「バージョンxxの新機能」または「ソースコード:...」という単語で始まり、このエンティティの簡単な説明として最初の文を取りました。 この種の行は簡単な説明にできないというハードコーディングよりも良い解決策は見つかりませんでした。 デコレータは、場所で@記号をトリミングする必要がありました。 新しいエンティティの説明の始まりは、クラス「class」または「classmethod」または「exception」または他の何かを持つタグによって決定され、9つのオプションのみがあり、それらすべてをすぐには見つけませんでした(そしてcppでは各ファイルは個別のエンティティです) 、そして問題はありません)。 私のスクリプトは、2つの場所でいくつかのエンティティを一度に検出しました(unittest.mockモジュールはここここで検出されまし )。 テキストには表やその他の構造があり、テレグラムメッセージ形式への翻訳が不十分です(翻訳したくない)。そのような構造によれば、リーダーであるitertoolsは 、完全に太字の行が見つかったときに説明が終了することを見つけなければなりませんでした。 最後に、docs.python.orgでは、どのライセンスがドキュメント自体に適用されるかを理解することは非常に困難です。 私もdocs@python.orgに書き込む必要がありました。 しかし、ここではテンプレートの専門化にこれらの問題はなく、「ヘッダーファイル」という概念もまったくありません。各オブジェクトに対して、「親」は一意かつ自然に定義されています。



フレームワークについて



Telegram APIを直接プルしないように、 テレポットテレグラムボットにPythonフレームワークを使用します。 彼は、ユーザーとの会話をサポートするまで、多くのことを知っていて、その上でボットを書くことは非常に簡単であることがわかりました。 確かに、定期的に更新され、想像を超える数のユースケースがあります。そのため、特定のケースでどのオプションが必要かを判断するのは非常に困難です。



テレグラムからのさまざまなメッセージが大幅に異なる構造を持つことが、ある種のセットアップであることが判明しました。 一部のオブジェクトにはidフィールドのみがあり、フィールド名でid(message_idまたはfile_id)を示すものもあります。 または、たとえば、Messageオブジェクトにはチャットフィールドとテキストフィールドがありますが、CallbackQueryオブジェクトにはチャットフィールドがなく、テキストフィールドの代わりにデータフィールドがあります。 メッセージとコールバックを同じ方法で処理する必要がありますが、これは機能しません。小さなハックを追加する必要があります。 確かに、私は夏の初めにこれを書きました。フレームワーク自体は夏に積極的に最終決定されました。



コード



Github: github.com/petr-kalinin/progrobot 、そこにあるコードはかなり- いです -これは、テレポットインターフェースに対処するための多くの試みの結果です。



All Articles