Created
July 23, 2024 01:53
-
-
Save danishi/ed73943e0d7fa8a7a72d0e4e787071a9 to your computer and use it in GitHub Desktop.
Get answers from Gemini with context caching across your Git repositories.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "nbformat": 4, | |
| "nbformat_minor": 0, | |
| "metadata": { | |
| "colab": { | |
| "provenance": [] | |
| }, | |
| "kernelspec": { | |
| "name": "python3", | |
| "display_name": "Python 3" | |
| }, | |
| "language_info": { | |
| "name": "python" | |
| } | |
| }, | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "# Get answers from Gemini with context caching across your Git repositories\n", | |
| "## Reference\n", | |
| "* [Practical Guide: Using Gemini Context Caching with Large Codebases](https://medium.com/google-cloud/practical-guide-using-gemini-context-caching-with-large-codebases-08d46d946c3d)\n" | |
| ], | |
| "metadata": { | |
| "id": "RumJursAlRAA" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "id": "4l1LpSkalQPW" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "!pip install GitPython==\"3.1.43\"" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "import git\n", | |
| "import os\n", | |
| "\n", | |
| "def list_and_read_repo_files(repo_url, branch=\"main\"):\n", | |
| " \"\"\"\n", | |
| " Clones a Git repository, lists all files (excluding .git folder), and reads their contents.\n", | |
| "\n", | |
| " Args:\n", | |
| " repo_url (str): URL of the Git repository.\n", | |
| " branch (str, optional): Branch to checkout. Defaults to \"main\".\n", | |
| "\n", | |
| " Returns:\n", | |
| " dict: A dictionary where keys are file paths and values are their contents.\n", | |
| " \"\"\"\n", | |
| " try:\n", | |
| " # Temporary directory for the clone\n", | |
| " repo_dir = \"temp_repo\"\n", | |
| "\n", | |
| " # Clone the repository\n", | |
| " print(f\"Cloning repository from {repo_url}...\")\n", | |
| " git.Repo.clone_from(repo_url, repo_dir, branch=branch)\n", | |
| " print(\"Cloning complete!\")\n", | |
| "\n", | |
| " file_contents = {}\n", | |
| " for root, _, files in os.walk(repo_dir):\n", | |
| " for file in files:\n", | |
| " ##print(file)\n", | |
| " # Exclude .git folder and its contents\n", | |
| " if \".git\" not in root:\n", | |
| " ##print(\".git not in root\")\n", | |
| " file_path = os.path.join(root, file)\n", | |
| " try:\n", | |
| " with open(file_path, \"r\", encoding=\"utf-8\") as f:\n", | |
| " file_contents[file_path] = f.read()\n", | |
| " except Exception as e: # Catch any unexpected errors\n", | |
| " print(f\"An unexpected error occurred: {e}\")\n", | |
| "\n", | |
| " return file_contents\n", | |
| "\n", | |
| " except git.exc.GitCommandError as e:\n", | |
| " print(f\"Error cloning repository: {e}\")\n", | |
| " except UnicodeDecodeError as e:\n", | |
| " print(f\"Error reading file: {e}\")\n", | |
| " except Exception as e: # Catch any unexpected errors\n", | |
| " print(f\"An unexpected error occurred: {e}\")\n", | |
| " finally:\n", | |
| " # Clean up the temporary repository directory\n", | |
| " if os.path.exists(repo_dir):\n", | |
| " git.rmtree(repo_dir)" | |
| ], | |
| "metadata": { | |
| "id": "qzNXG5QZlkXZ" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "repo_url = \"https://github.com/danishi/dynamodb-csv.git\" # Replace with actual URL\n", | |
| "branch = \"master\" # Replace if different\n", | |
| "\n", | |
| "file_data = list_and_read_repo_files(repo_url, branch)" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "UOayP8zklmRk", | |
| "outputId": "544d72e2-9aab-4e34-9ae6-f15db2d1498f" | |
| }, | |
| "execution_count": null, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Cloning repository from https://github.com/danishi/dynamodb-csv.git...\n", | |
| "Cloning complete!\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "if file_data:\n", | |
| " output_file = \"fullcode.text\"\n", | |
| " with open(output_file, \"w\", encoding=\"utf-8\") as outfile:\n", | |
| "\n", | |
| " for file_path, content in file_data.items():\n", | |
| " outfile.write(f\"<file path={file_path}>\")\n", | |
| " outfile.write(f\"{content}\")\n", | |
| " outfile.write(\"</file>\")\n", | |
| " outfile.close()\n", | |
| " #print(f\"File: {file_path}\\nContent:\\n{content}\\n---\")" | |
| ], | |
| "metadata": { | |
| "id": "cgdTUsNEl-RI" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "size_in_bytes = os.path.getsize(output_file)\n", | |
| "\n", | |
| "print(f\"File Size: {size_in_bytes/1024/1024} MB\")" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "FPnWPKRfm84O", | |
| "outputId": "58ef420d-066b-45db-f6dc-3f63a76059ca" | |
| }, | |
| "execution_count": null, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "File Size: 0.09016227722167969 MB\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "!pip install --upgrade google-cloud-aiplatform==\"1.59.0\"" | |
| ], | |
| "metadata": { | |
| "id": "5l1zpPk_nG3v" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "from google.colab import auth\n", | |
| "auth.authenticate_user()" | |
| ], | |
| "metadata": { | |
| "id": "0IAcilUFn8DM" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "import vertexai\n", | |
| "from vertexai.preview import caching\n", | |
| "\n", | |
| "project_id = \"<USE YOUR PROJECT ID HERE>\"\n", | |
| "\n", | |
| "vertexai.init(project=project_id, location=\"asia-northeast1\")\n", | |
| "\n", | |
| "system_instruction = \"\"\"\n", | |
| "あなたは優秀なソフトウェアエンジニアです。提供されたソース内の事実に常に従い、新しい事実を作り上げることは決してありません。\n", | |
| "では、このプロジェクトのコードベースを見て、次の質問に答えてください。\n", | |
| "\"\"\"" | |
| ], | |
| "metadata": { | |
| "id": "Gg5eyVisnXph" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "with open(\"fullcode.text\", \"r\", encoding=\"utf-8\") as f:\n", | |
| " fullcode_as_string = f.read()\n", | |
| "\n", | |
| "contents = [\n", | |
| " fullcode_as_string\n", | |
| "]" | |
| ], | |
| "metadata": { | |
| "id": "BttyzCDonzKY" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "import datetime\n", | |
| "\n", | |
| "cached_content = caching.CachedContent.create(\n", | |
| " model_name=\"gemini-1.5-pro-001\",\n", | |
| " system_instruction=system_instruction,\n", | |
| " contents=contents,\n", | |
| " ttl=datetime.timedelta(minutes=10),\n", | |
| ")" | |
| ], | |
| "metadata": { | |
| "id": "JOpqJgVSn0Iz" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "from vertexai.preview.generative_models import GenerativeModel\n", | |
| "\n", | |
| "cache_id=cached_content.name\n", | |
| "cached_content = caching.CachedContent(cached_content_name=cache_id)\n", | |
| "\n", | |
| "model = GenerativeModel.from_cached_content(cached_content=cached_content)" | |
| ], | |
| "metadata": { | |
| "id": "B_337eiuoIAD" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "from IPython.display import Markdown\n", | |
| "\n", | |
| "response = model.generate_content(\"このプロジェクトは何をしていますか?\")\n", | |
| "Markdown(response.text)" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 713 | |
| }, | |
| "id": "H00HA2JOoQ7c", | |
| "outputId": "d8c2a74c-be4c-41cc-dfdb-397aae398d62" | |
| }, | |
| "execution_count": null, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "<IPython.core.display.Markdown object>" | |
| ], | |
| "text/markdown": "このPythonプロジェクトは、CSVファイルとAmazon DynamoDBテーブル間でデータをインポート/エクスポートするためのコマンドラインユーティリティ`dynamodb-csv`を提供します。\n\n**機能**\n\n- **CSVインポート**: CSVファイルをDynamoDBテーブルにインポートします。バッチ書き込みにより高速処理を実現し、キー スキーマの不一致などのエラーが発生した場合にCSVレコードを無視するオプションを提供します。空の値をNullに変換したり、属性自体を設定しないなどのインポートオプションもサポートしています。\n- **CSVエクスポート**: DynamoDBテーブルからCSVファイルにデータをエクスポートします。インデックスやクエリを使用してエクスポートするデータを選択できます。\n- **テーブルの切り捨て**: DynamoDBテーブルからすべてのアイテムを削除します。この操作は元に戻せないので注意が必要です。\n- **テーブルの移動**: あるテーブルから別のテーブルにすべてのアイテムを移動します。事前に同じスキーマを持つテーブルを作成しておく必要があります。テーブルのアイテムは削除されず、コピーのように動作します。\n\n**使い方**\n\n1. **インストール**: `pip install dynamodb-csv`\n2. **設定**: 現在のディレクトリに`config.ini`ファイルを作成し、AWSの認証情報とDynamoDBテーブルのリージョンを指定します。\n3. **CSVとCSV仕様ファイルの作成**: インポートまたはエクスポートするデータの形式を定義するCSVファイルとCSV仕様ファイル(`.spec`拡張子)を作成します。\n4. **DynamoDBテーブルの作成**: CSV仕様に準拠したDynamoDBテーブルを作成します。\n5. **コマンドの実行**: `dynamodb-csv`コマンドを使用して、インポート、エクスポート、切り捨て、または移動の操作を実行します。\n\n**例**\n\n```\n# CSVファイルをDynamoDBテーブルにインポートする\ndynamodb-csv -i -t my_table -f sample.csv\n\n# DynamoDBテーブルをCSVファイルにエクスポートする\ndynamodb-csv -e -t my_table -o sample_exp.csv\n\n# DynamoDBテーブルを切り捨てる\ndynamodb-csv --truncate -t my_table\n\n# あるテーブルから別のテーブルにアイテムを移動する\ndynamodb-csv --move -t my_table_from my_table_to\n```\n\n**追加機能**\n\n- Dockerイメージを使用してユーティリティを実行できます。\n- 開発者向けに、仮想環境の設定とインストール手順が提供されています。\n\n**ライセンス**\n\nMITライセンス" | |
| }, | |
| "metadata": {}, | |
| "execution_count": 18 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "response.usage_metadata" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "o_VJLl9uoXli", | |
| "outputId": "1b5dfae2-cc41-4721-8745-33fad4868d6f" | |
| }, | |
| "execution_count": null, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "prompt_token_count: 36290\n", | |
| "candidates_token_count: 526\n", | |
| "total_token_count: 36816" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "execution_count": 19 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "response = model.generate_content(\"インポート処理のロジックを詳細に解説して\")\n", | |
| "Markdown(response.text)" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 790 | |
| }, | |
| "id": "brYXmWoapArV", | |
| "outputId": "2fdbfa2d-d833-41dc-a94a-92766669a8bb" | |
| }, | |
| "execution_count": null, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "<IPython.core.display.Markdown object>" | |
| ], | |
| "text/markdown": "`app/dynamodb/csv_import.py` ファイルの `csv_import` 関数は、CSV ファイルを DynamoDB テーブルにインポートするロジックを実装しています。\n\n**ステップ 1: CSV 仕様の読み込み**\n1. 最初に、CSV ファイルに対応する `.spec` ファイルを読み込みます。このファイルには、CSV の各カラムのデータ型や区切り文字などの情報が定義されています。\n2. `configparser` を使用して `.spec` ファイルを読み込み、`csv_spec` オブジェクトに格納します。\n3. `DELIMITER_OPTION` セクションが存在する場合は、`DelimiterCharacter` オプションの値を区切り文字として取得します。存在しない場合は、デフォルトの区切り文字としてスペースが使用されます。\n\n**ステップ 2: CSV ファイルの読み込み**\n1. CSV ファイルを UTF-8 エンコーディングで開き、`csv.DictReader` を使用して各行を辞書として読み込みます。\n2. `tqdm` を使用して、インポートの進捗状況を表示します。\n\n**ステップ 3: データの変換とバッチ処理**\n1. 各行に対して、`IMPORT_OPTION` セクションで指定された変換オプションを適用します。\n - `ConvertBlankToNullAttrs` オプション: 指定されたカラムの値が空欄の場合、`None` に変換します。\n - `ConvertBlankToDropAttrs` オプション: 指定されたカラムの値が空欄の場合、カラム自体を削除します。\n2. 各カラムの値を、CSV 仕様で定義されたデータ型に変換します。\n - `convert_column` 関数を使用して、各カラムの値を適切なデータ型 (文字列、整数、10進数、ブール値、JSON、文字列リスト、文字列セット、10進数リスト、10進数セット) に変換します。\n3. 変換された行データを `batch` リストに追加します。\n4. `batch` リストのサイズが `batch_size` に達するか、すべての行が処理されたら、`write_to_dynamo` 関数を使用して DynamoDB に書き込みます。\n\n**ステップ 4: DynamoDB への書き込み**\n1. `write_to_dynamo` 関数は、`batch` リスト内の各行データを DynamoDB テーブルに書き込みます。\n2. `ignore` フラグが True の場合、各行を個別に `put_item` で書き込みます。エラーが発生した場合は無視され、インポート処理は続行されます。\n3. `ignore` フラグが False の場合、`batch_writer` を使用してバッチ書き込みを行います。\n - `overwrite_by_pkeys` オプションを使用して、重複する主キーを持つアイテムを上書きします。\n - エラーが発生した場合は、エラーメッセージを出力します。\n\n**ステップ 5: 結果の返却**\n1. すべての行が処理されたら、インポートされたアイテム数とエラーが発生したアイテム数をメッセージとして返却します。\n\n**追加情報**\n\n- `csv_import` 関数は、最大 25 個のアイテムを一度にバッチ書き込みできます。これは、DynamoDB の `batch_write_item` 操作の制限によるものです。\n- `ignore` フラグを使用すると、エラーが発生したアイテムを無視してインポート処理を続行できます。ただし、この場合、バッチ書き込みは使用されません。\n- CSV 仕様ファイルは、CSV ファイルと同じディレクトリに配置し、ファイル名に `.spec` を追加する必要があります。\n\nこのインポート処理のロジックにより、CSV ファイルから DynamoDB テーブルにデータを効率的かつ安全にインポートできます。\n" | |
| }, | |
| "metadata": {}, | |
| "execution_count": 20 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "response = model.generate_content(\"このリポジトリの改善点を教えて\")\n", | |
| "Markdown(response.text)" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 588 | |
| }, | |
| "id": "mUqD7XAopmWR", | |
| "outputId": "6e0933a2-8a53-4dca-b766-09c62febb804" | |
| }, | |
| "execution_count": null, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "<IPython.core.display.Markdown object>" | |
| ], | |
| "text/markdown": "このリポジトリのコードベースに基づいて、いくつかの改善点を提案します。\n\n**エラー処理**\n\n* いくつかの関数のエラー処理は改善の余地があります。例えば、`app/dynamodb/csv_import.py` の `write_to_dynamo` 関数では、 `Exception` をキャッチしていますが、エラーの種類を特定していません。より具体的なエラータイプをキャッチすることで、エラー処理がより正確になります。\n* `app/dynamodb/csv_export.py` の `csv_export` 関数では、`IOError` と `Exception` をキャッチしていますが、具体的なエラーの内容を表示していません。エラーメッセージに詳細情報を追加することで、デバッグが容易になります。\n\n**型ヒント**\n\n* コードベース全体で型ヒントが使用されていますが、一部の関数では型ヒントが不足しています。例えば、`app/main.py` の `execute` 関数の戻り値は `Tuple` となっていますが、具体的な型を指定する方がより良いでしょう。\n* 型ヒントを追加することで、コードの可読性と保守性を向上させることができます。\n\n**テスト**\n\n* ユニットテストが提供されていますが、テストカバレッジを向上させることができます。例えば、 `app/main.py` の `config_read_and_get_table` 関数はテストされていません。\n* 統合テストを追加することで、モジュール間の連携を確認することができます。\n\n**ドキュメント**\n\n* README.mdは詳細な情報を含んでいますが、いくつかの点が改善できます。\n * 各関数の詳細な説明を追加することで、ユーザーがコードを理解しやすくなります。\n * 例外処理の詳細を説明することで、ユーザーがエラーを適切に処理できるようになります。\n* コードベース全体にdocstringを追加することで、コードの理解を深めることができます。\n\n**コードスタイル**\n\n* コードベース全体で一貫したコードスタイルを採用することで、コードの可読性を向上させることができます。Pythonのコーディング規約に従うことをお勧めします (PEP 8)。\n\n**機能**\n\n* バイナリタイプとバイナリセットタイプのサポートを追加すると、ツールの汎用性が向上します。\n* CSVファイルのヘッダー行を無視するオプションを追加すると、柔軟性が高まります。\n* DynamoDBテーブルを更新する機能を追加すると、より多くのユースケースに対応できます。\n\nこれらの改善により、リポジトリの品質と使いやすさが向上すると考えられます。" | |
| }, | |
| "metadata": {}, | |
| "execution_count": 22 | |
| } | |
| ] | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment