gRPC は、強力で高性能なリモート プロシージャ コール (RPC) フレームワークであり、REST ほど一般的には使用されていませんが、特定のシナリオでは大きな利点を提供します。
さらに、言語に依存せず、あらゆる環境で実行できるため、サーバー間通信に理想的な選択肢となります。
詳しくは説明しませんが、gRPC の一般的なリンクは次のとおりです。実践的なチュートリアルを提供します
私たちの Go はクライアントですが、フロントエンド アプリ React、Svelte などのサーバーであることをイメージしてみましょう。
func getFirstArg() (string, error) { if len(os.Args) < 2 { return "", fmt.Errorf("expected 1 argument, but got none") } return os.Args[1], nil } func main() { filePath, err := getFirstArg() if err != nil { log.Fatalf("Failed to get file path from arguments: %v", err) } fileData, err := ioutil.ReadFile(filePath) if err != nil { log.Fatalf("Failed to read file: %v", err) } ... }
例として、React フロントエンドはファイルをアップロードし、Go でそれを処理しますが、Excel からの回答が必要なので、GPT API を使用します。 Go でも実行できますが、一方で Python には、langchan_openai、Excel 用のパンダなど、私たちの生活を楽にするパッケージがたくさんあります。
できれば virtualenv .venv に gRPC をインストールすることから始めましょう
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest $ export PATH="$PATH:$(go env GOPATH)/bin"
次に、OS にプロトコル バッファをインストールする必要があります。
プロトコル バッファ ファイルを保存する proto ディレクトリを作成しましょう。それに excel.proto という名前を付けて、これを貼り付けます:
syntax = "proto3"; option go_package = "client-gRPC/proto"; service ExcelService { rpc UploadFile(FileRequest) returns (FileResponse); } message FileRequest { string file_name = 1; bytes file_content = 2; } message FileResponse { bytes file_content = 1; }
この gRPC サービスである ExcelService を使用すると、クライアントは名前と内容を送信してファイルをアップロードできます。サーバーは同じファイル内容で応答します。
Go の場合、Python で go_package を渡すことが不可欠です。この行は必要ありません。
vscode-proto3 は、VSCode を使用する場合にダウンロードするのに適した拡張機能です。
これらすべてが完了したら、proto ファイルを生成できます。prot dir と同じレベルに置くことをお勧めします。そのためには、次のコマンドを実行します。
プロトコル --go_out=。 --go_opt=paths=source_relative --go-grpc_out=。 --go-grpc_opt=paths=source_relative proto/excel.proto
成功すると 2 つのファイルが生成されますが、多くの調整がある場合はオプションで Makefile を追加し、proto + upper コマンドとして定義します。
import ( .... "google.golang.org/grpc" pb "client-gRPC/proto" "github.com/xuri/excelize/v2" ) func main() { .... conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatalf("Failed to connect to gRPC server: %v", err) } defer conn.Close() client := pb.NewExcelServiceClient(conn) req := &pb.FileRequest{ FileName: filePath, FileContent: fileData, } res, err := client.UploadFile(context.Background(), req) if err != nil { log.Fatalf("Failed to upload file: %v", err) } outputFile := "output.xlsx" err = saveBytesAsExcel(outputFile, res.FileContent) if err != nil { log.Fatalf("Failed to save bytes as Excel file: %v", err) } fmt.Printf("Excel file saved as: %s\n", outputFile) } func saveBytesAsExcel(filePath string, fileContent []byte) error { f, err := excelize.OpenReader(bytes.NewReader(fileContent)) if err != nil { return fmt.Errorf("failed to open Excel file: %v", err) } if err := f.SaveAs(filePath); err != nil { return fmt.Errorf("failed to save Excel file: %v", err) } return nil }
Python サーバーとなる 50051 をリッスンするための接続を作成します。&pb.FileRequest は proto コマンドを使用して事前に生成されており、今メソッドをインポートしています。走れば受信できますか? Python サーバーがまだ確立されていないため。
Failed to upload file: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp 127.0.0.1:50051: connect: connection refused"
Python はサーバーとして機能するため、アプローチは少し異なりますが、本質的にはパッケージフィールドとは別に同じプロトファイルは必要ありません。 GPT が Excel に質問をどのように入力するかを一目でわかるように、gRPC を使用せずにベースの main.py を作成することから始めましょう。
import os import openai import pandas as pd from dotenv import load_dotenv def get_answer_from_gpt(apikey: str, question: str): openai.api_key = apikey response = openai.ChatCompletion.create( model="gpt-4", messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": question} ] ) return response['choices'][0]['message']['content'].strip() def answer_questions_df(df: pd.DataFrame, apikey: str): answers = [] for question in df.iloc[:, 0]: answer = get_answer_from_gpt(apikey, question) answers.append(answer) return answers if __name__ == "__main__": load_dotenv() openai_api_key = os.getenv("OPENAI_API_KEY", "OpenAI API key hasn't been set.") df = pd.read_excel('Book1.xlsx') df['Answer'] = answer_questions_df(df, openai_api_key
Go が送信する質問に答えるシンプルなスクリプトですが、専用の openai ライブラリにより LOC が少なくなり、簡単になります。
まず、上記と同じファイルで proto dir を追加します。オプション セクションは、説明したように削除できます。できれば virtualenv に gRPC をインストールし、ここで私が実行したプロト生成のインストールに従ってください。
python3 -m grpc_tools.protoc --proto_path=proto --python_out=proto --grpc_python_out=proto proto/excel.proto
私の proto ディレクトリと同じレベルにするには、忘れずに __init.py を追加してください!
ファイルが生成されたら、次に進みましょう。
import io import grpc from proto import excel_pb2_grpc as excel_grpc from proto import excel_pb2 class ExcelService(excel_grpc.ExcelServiceServicer): def UploadFile(self, request, context): try: # Convert bytes to a file-like object file_like_object = io.BytesIO(request.file_content) # Load the workbook from the file-like object workbook = openpyxl.load_workbook(file_like_object) # Access the first sheet (or use appropriate logic to get the sheet you need) sheet = workbook.active # Convert the sheet to a DataFrame data = sheet.values columns = next(data) # Get the header row df = pd.DataFrame(data, columns=columns) print("Loaded DataFrame:") print(df.head()) # Ensure that the DataFrame is not empty and has questions if df.empty or df.shape[1] < 1: print("DataFrame is empty or does not have the expected columns.") return excel_pb2.FileResponse(file_content=b'') # Get answers and add them to the DataFrame answers = answer_questions_df(df, openai_api_key) df['Answer'] = answers # Write the updated DataFrame back to a BytesIO object output = io.BytesIO() with pd.ExcelWriter(output, engine='openpyxl') as writer: df.to_excel(writer, index=False, sheet_name='Sheet1') # Reset the buffer's position to the beginning output.seek(0) # Return the modified file content response = excel_pb2.FileResponse(file_content=output.read()) return response except Exception as e: print(f"Error processing file: {e}") return excel_pb2.FileResponse(file_content=b'') def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) excel_grpc.add_ExcelServiceServicer_to_server(ExcelService(), server) server.add_insecure_port('[::]:50051') server.start() print("Server running on port 50051.") server.wait_for_termination() if __name__ == "__main__": load_dotenv() openai_api_key = os.getenv("OPENAI_API_KEY", "OpenAI API key hasn't been set.") serve()
サーバーを定義し、proto ファイルによって生成されたメソッドを含む ExcelService クラスを追加します。ファイルをバイト単位で受信するため、io バイト リーダーを使用してファイルのさらなる処理を開始し、2 番目の列に入力する必要があります。
response = excel_pb2.FileResponse(file_content=output.read())
最後に、Go クライアントが受け取るために ☝️ を返します。
Python で proto ファイルを見つけられるようにするには、エクスポート パスを定義する必要があります
エクスポート PYTHONPATH=$PYTHONPATH:mnt/c/own_dev/gRPC/server/proto
If all is good you can run #First comes server python3 -m main #Then client go run client.go Book1.xlsx
そして、Go クライアント側で更新された .xlsx ファイルを取得する必要があります。
この記事では、Python サーバーと Go クライアント間の gRPC 通信の設定の基礎について説明しました。 gRPC を活用することで、Go アプリケーションから Python サーバーに Excel ファイルを送信し、OpenAI の GPT API を使用してファイルを処理し、変更されたファイルを Go クライアントに返すシームレスな方法を確立しました。
以上がGo と Python 間の gRPC 通信の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。