短期売買と分析力が向上しそうな株価予測をだらだらとやる part1

前回RAGシステムを作ってみてある程度できました。次に、何を作ろうかということで表題になります。 前回と違って完成形は全く思い浮かんでません。とりあえずやってれば何かできるかということで作っていきます。 ティッカー取得 まずは株価の取得が必要なのですが今回はyahoo! financeのAPIを使って取得しようと思います。取得する際のコードは以下。 import pandas_datareader.data as web df = web.get_data_yahoo('1304', '1980-01-01', '2024-06-10') pandas_datareaderにyahoo用の株価取得ライブラリがあるのでそれを利用します。ティッカー(銘柄)と株価取得の時間を設定します。 株価の取得は簡単なのですが、ティッカーをいちいち手入力するのは面倒ですね。時間は変数で設定できますので問題ないです。 というわけでティッカーを取得するプログラムを作ります。 ティッカーを取得するには東京証券取引所、名古屋証券取引所、福岡証券取引所、札幌証券取引所、各国別SBI証券ティッカー一覧から取れると思いますが、今回はSBI証券から取得しようと思います。 昔やろうとしたことがあったのでそれを流用しようと思います。対象となるサイトはこちらです。 ティッカー取得プログラム # SBI証券から海外のティッカーまたはコードと銘柄を取得 from bs4 import BeautifulSoup import re, sys, time import requests import pandas as pd sbi_foreign_stock_list = [ {"america": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_usequity_list.html", "tag": "table", "c_cd":"", "class": "md-l-table-01 md-l-utl-mt10"}}, {"china": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_hk_list.html", "tag": "div", "c_cd":"HK", "class": "accTbl01"}}, {"korea": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_kr_list.html", "tag": "div", "c_cd":"KS", "class": "accTbl01"}}, {"russia": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_ru_list.html", "tag": "div", "c_cd":"ME", "class": "accTbl01"}}, {"vietnam": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_vn_list.html", "tag": "div", "c_cd":"VN", "class": "accTbl01"}}, {"Indonesia": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_id_list.html", "tag": "div", "c_cd":"JK", "class": "accTbl01"}}, {"Singapore": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_sg_list.html", "tag": "div", "c_cd":"SI", "class": "accTbl01"}}, # SBIとyahooのティカーが一致しない件 {"thailand": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_th_list.html", "tag": "div", "c_cd":"BK", "class": "accTbl01"}}, {"malaysia": {"url": "https://search.sbisec.co.jp/v2/popwin/info/stock/pop6040_my_list.html", "tag": "div", "c_cd":"KL", "class": "accTbl01"}} # SBIとyahooのティカーが一致しない件 ] for foreign_dict in sbi_foreign_stock_list: for country, values in foreign_dict.items(): country_url = values["url"] country_tag = values["tag"] country_code = values["c_cd"] country_class = values["class"] html = requests.get(country_url) soup = BeautifulSoup(html.content, "html.parser") for table_soup in soup.find_all(country_tag, class_=country_class): stock_data = [] rows = table_soup.find_all("tr") for row in rows[1:]: ticker = row.find_all("th")[0].text.strip() cols = row.find_all("td") name = cols[0].text.strip() stock_data.append((ticker, name)) continue df_foreign_stock = pd.DataFrame(stock_data, columns=["コード", "銘柄名"]) df_foreign_stock["コード"] = df_foreign_stock["コード"].astype(str) + country_code df_foreign_stock.to_csv(out_oth_fol + country + "_stock_list.csv") time.sleep(2) これを流用すれば取得できますが、今のサイトではできません。少し前のサイトがこちらです。こちらであれば取得できますが、最新のティッカー情報が取れないので修正します。 ...

2024年6月10日

最近読んだ"プログラマー脳"はプログラムを書く人は読んだほうが関わる人全員が幸せになる話だった

読書習慣とおすすめの一冊「プログラマー脳」 読書をするということを習慣化しているのですが、たまたまどっかの記事で見かけて買ったプログラマー脳は読んでおくといいなと思ったので記事にしました。こちらから買えます。 私の読書習慣 ちなみに私の読書週間としては 毎日20:30~21:30までは読書をする 電車に乗って満員200%じゃなければ読む(大体10分ほど) 没頭するほど集中力が続かないこともあるのでちょこちょこ休憩しながら読んでいます。 読書のスタイル 読み方は状況によりけりですが、例を出すところは飛ばすことが多いです。実体験や見聞きしたことよりは論文やデータから見た考察とかのほうが個人的にはいいかなと思うので。 人によっては例があったほうがイメージがわかりやすいので、そっちを中心に読む人もいるかと思いますが、全てを読む必要はないかなと思います。特にある程度知っている内容なら。 感想と本書の概要 本の要約は場合によっては著作権違反になったりするので、私の感想をメインにしつつ引用を少し出しながら書いていこうと思います。 この本で一貫して書かれていることが認知負荷を減らすようにしましょうという話になります。 認知負荷とプログラミング 人間には短期記憶、長期記憶、ワーキングメモリがあり、短期記憶はコードに置き換えると変数、長期記憶は構文(forやif等)、ワーキングメモリは処理の内容になります。認知負荷はワーキングメモリに関わってきます。 コードを読むときにどんな処理になっているのがわからないということがあります。その時、単純に言語の情報が足りないのか?構文がわかっていないのか?処理内容がわかってないのか?ということがあります。ドメイン知識も関係してそうですがここでは言及されていません。 認知負荷の軽減方法 言語の情報や構文についてはある程度調べて覚えれば大丈夫なのですが処理内容に関しては自身の記憶だけではどうにもなりません。すでに書いてあるものを改修したりする場合は大変な作業になると思います。 ちなみに本書では言語の構文などの覚え方や定着の仕方なども言及しているので、気になればぜひ読んでみてください。 命名やコードの整理の重要性 認知負荷についてはいくつか気を付けるポイントが書いてあり、命名の仕方やコードを適切に分けて関数化することについて書いています。関数化じゃなくてもクラス化でもいいと思います。 他人のコードを読む際のコツ それから人のコードを読む際に良い方法も書いてあります。変数同士を結び付けて紙に書いたり、パッドで書き込むのもいいと思います。 割り込みタスクと新人サポートについて 他の内容としては割り込みタスクが入るや新人へのサポートについて書かれていました。ここもためになりますね。 読書の重要性 本を読むといろんなことが知れます。技術的な面ももちろん必要ですが、メンタルや考え方なども必要だと思います。 他にも本を読んでいるのでいくつか面白いものがあれば紹介したいなとは思います。 Kindle Unlimitedのおすすめ ちなみにKindle Unlimitedは速く本を読んで理解するのにおススメです。月額で読み放題だし、内容が薄いものはバンバン飛ばし読みもできるので練習にもなります。ではでは。

2024年6月7日

ニューラルネットワークの仕組みを理解しているかテストするためのゲームで遊ぶ

機械学習と深層学習の復習 G検定やE資格である程度機械学習や深層学習で使われている技術を学んだのですが、特に深層学習についてはあやふやな部分が多いなと感じていました。 とはいえまた学習教材を買うのもと思ってましたが、良いサイトを見つけました。 Graph Game: ニューラルネットワークの理解度をテスト Graph Gameというニューラルネットワークを理解しているかわかるサイトになります。(こちらから遊べます。) とはいえこのサイトでできるのはRNN、LSTM、GRU、ResNet、Deep RNNのテストになります。CNNやGANなどはテストできません。 RNNのテスト まずはRNNから試してみましょう。“clicks” は繋げた回数、“edges remaining” は繋げる必要がある本数、“extra edges” は余計な繋がりの本数になります。 RNNについて補足すると連続的なデータや時系列データを処理するのに最適です。株価などの時系列分析、テキスト生成、音声認識など様々なところに使われる重要なニューラルネットワークです。 ちなみにHelpはチュートリアルの確認になります。 もし正解できれば画面の文字が左上にでます。何回でも挑戦できるので理解しながらつなげてみましょう! LSTMのテスト LSTMはこんな感じ。 長い依存関係を持つ時系列データの処理に向いています。RNNでは勾配消失問題が発生するのでそれを解消するために考えられました。3つ(入力、忘却、出力)のゲートを使って重要なデータは保持、不要なデータは捨てます。 GRUのテスト GRUはこんな感じ。 補足するとGRUはLSTMの精度を保ったまま計算量が少ないと言われています。GRUは2つ(リセット、更新)のゲートで情報を制御します。 ResNetのテスト ResNetはこんな感じ 補足すると深い層のニューラルネットワークで使われ、画像認識で使用されています。残差ブロックがあり、skip connectionで直接値を渡すことで勾配消失問題が解消されます。 Deep RNNのテスト 最後にDeep RNNはこんな感じ。 Deep RNNの補足としては複数のRNN層を組み合わせたものになります。より複雑なパターンを学習することができます。 まとめと感想 少し忘れていたのでここで視覚的に思い出せました。初めての人でもなんとなくでわかるようになるし、ある程度知っている人も視覚的に覚えられるので良いと思います。 忘れていた処理を思い出せたので良かったです。他の深層学習や機械学習でも視覚的にわかるようなサイトがあるとイメージが付きやすそうですね。ではでは。

2024年6月5日

自分が作ったAIが赤の他人のAIとSNSでやり取りする姿は面白い

AI同士のやり取りを見てみたい? AI同士がやり取りするのは見かけたことがあっても、自身が作ったAIと人が作ったAIのやり取りを見てみたい!と考えたことはありますか?私はありません(笑) ただ、気になって試したら面白く時間が経って確認してみるとフォロワーが増えたり、知らないAIとやり取りしてたり面白いです。 サイトへのアクセスと初期設定 それではこちらのサイトにアクセスしてみてください。初期画面はこんな感じ ログインとAIの作成 ログインしてみましょう!方法は複数あるのでお好きな方法を使ってください。 では、早速作ってみましょう!Chirperから作成をしてみましょう。私はすでに2つ作っていますが、新しく作ってみます。Vanaというサイトからインポートもできるみたいです。 AI作成のステップ 作成画面はこんな感じ。アイコンはヘッダーは勝手に作られますので名前、ハンドルネーム、性格、容姿の設定を行いましょう。半生は作らなくても大丈夫です。 作成後の様子 ある程度設定を練って作りこんだら保存しましょう。作った直後は何も変わらないので、しばらく待ちます。ちなみに作った直後はこんな感じ。 AIの反応を観察 ということでしばらく放置していたらこんな感じになりました。 ただ、ちょっと思ってたのとは違いましたが、まあいいかということでそのままにしました。 投稿や返信もしてるみたいで楽しそうです。たくさん作った後、自身の作ったAI同士で会話し始めると見てて面白そうだなとは思いますね。他にも細かい設定などができるので、是非試して遊んでみてください。 今回は少し暇つぶしになるもので遊んでみました。ではでは。

2024年6月2日

RAGを開発してみたい!ので簡単なものでもいいので作ってみよう!part10 完

RAG開発の一旦終了と成果物の共有 とりあえず目標としていたものが完成したので開発はこれで一旦終わりとします。 完成して動いたものを動画にして3つほどはります。 動画の内容とモデルの読み込み ファイル数別に動画を取ってみました。ベクトルモデルの読み込みと読み込ませるテキスト量によって時間が変わってきます。 モデルの読み込みとかはOpenAIに変わったぐらいで大きく変更したところはないですが一部お見せします。 def generate_response(self, prompt: str, max_tokens: int = 3000) -> str: try: client = OpenAI( # This is the default and can be omitted api_key=os.environ.get("OPENAI_API_KEY"), ) response = client.chat.completions.create( model="gpt-4o", # 使用するモデルを指定 messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ], max_tokens=max_tokens, n=1, stop=None, temperature=0.7 ) print(response) return response.choices[0].message.content except Exception as e: logging.error(f"エラーが発生しました: {e}") return "申し訳ありませんが、応答を生成する際にエラーが発生しました。" この辺をGPT-4oに聞いてみたのですが最近のコードを提示してくれなかったので、chatを作成する部分はgit-hubを参考に作りました。こちらです。 Flaskの設定と変更点 それからFlaskの部分ですね。 ...

2024年5月31日

オープンソースのLLMアプリ開発プラットフォーム"Dify"を使ってみたよ

Difyを使ったLLM開発アプリの導入と設定 LLM開発アプリの選択肢としてDifyがあると聞いたので触ってみました。 最後にはこんな感じになるといいなと思ったものになります。 Dify_クラウド版とローカル版の比較 やり方は2つあります。クラウド版とローカル版の2つなります。お好きな方を使っていただければと思いますが、ローカル版のほうが個人的にはいいかと思います。 クラウド版の導入方法 クラウド版に関しては登録するだけで使えます。画面はこんな感じ ローカル版の導入手順 ローカル版はGItとDockerが必要になるのでない人はインストールから始めましょう Difyのインストールとセットアップ DockerはDocker Desktopを導入しておけば大丈夫です。docker composeも入っているので一緒にインストールされます。 ではコマンドプロンプトを開いて開発する場所にgit cloneでdifyをインストールします。コマンドはこちら git clone https://github.com/langgenius/dify.git Docker Composeの起動 インストールが出来たらdocker compseを起動させるのでフォルダを移動します。開発場所にdifyをインストールできたと思うのでdockerフォルダに移動します。 cd docker フォルダの移動が出来たらdocker composeの起動をします。起動できるとこんな感じ docker compose up -d アプリ作成の開始 起動したらURLを入力して画面を表示させてみましょう!クラウド版とそこまで変わりません。 URL: http://localhost/apps テンプレートから作成でもいいですが、私は最初から作成してみました。こんな感じ。今回はチャットボットを作ってみますので適当に名前を付けて作成します。 LLMモデルの設定 アプリが出来たらこんな感じの画面ができます。今回はgptモデルを使っていこうと思います。 設定から色んなLLMモデルを選ぶことができます。今回はOpenAIを使用するのでOpenAIのAPI-KEYをセットしました。他に使いたいモデルがあればそのAPI-KEYを設定すれば使えます。 それから使用するモデルは"システムモデル設定"から設定します。他のモデルも設定すればそちらも使えるようになります。 ナレッジの登録 今回作るチャットボットはRAGなので次はナレッジを登録します。“知識を作成"からファイルを登録してインデックス化していきます。 ファイルのアップロードをします。私が本来作りたいのは15000ファイル位あったのでそこまではアップしませんが、いくつか登録します。 アップロードが完了してインデックス化が完了すると利用可能というステータスになります。エラーになってるものは利用できないので、再試行かアップのし直しでインデックス化を試みてください。 アプリのプロンプト設定とテスト ナレッジの登録が完了したらいよいよアプリの作成です。手順つまりプロンプトを設定して、コンテキストに作ったナレッジを設定します。今回は取得したナレッジを要約するように指示します。 設定したら公開するからアプリ実行をします。するとチャット画面に移動します。 Star Chatからチャットを打ってどんな感じか動かしてみます。まず使えるファイルが1つだけだったので"特許権について"と聞いてみました。 中を見たのですが合っていました。とは言え私は法律の専門家ではないのでよくわかってないですが、雰囲気的には合ってそうです。 エラーの対応と改善 一応やってるときにエラーが出たりしたのでその時の話も共有します。アプリの作成途中でこんな感じのエラーが出ました。 どうやら課金のチャージができていなかったようです。そこでOpenAIのサイトでチャージしたらこのエラーは解消されました。 APIあまり使ってなかったのですが、こういうことが起こるので自動設定でチャージさせるようにしました。ただ、悪用されたら怖いので注意を払う必要がありますね。 Difyを活用した応用の可能性 これがうまいことできれば他のファイルでもできそうなので色んなとこで応用できそうです。もちろんセキュリティの問題が付きまといますので専門的な知識や暗黙知とかのファイルであれば有効活用できそうですね。ではでは。

2024年5月27日

RAGを開発してみたい!ので簡単なものでもいいので作ってみよう!part9

一旦行き詰ったのでここまでを記録として残しておきます。 行き詰った内容としてはローカルで実行できないこと、無料枠のcolabを利用してもダメだったことです。 今回実施した内容としては以下 ベクトルデータベースの完成 生成モデルを利用して質問+ファイルの内容を分割してプロンプトを投げる ‘paraphrase-multilingual-mpnet-base-v2’を利用したベクトルデータベースの作成が完了したのでGithubにあげようとしたのですが、jsonファイルは2GB以上、zip化しても500MB以上あったので断念しました。100MB未満なら簡単にあげられるのですが、それ以上はもう少し手順が必要みたいです。 このファイル作るのに1週間近くはかかるんだなと思いました。ファイル数が多かったのもあるかもしれませんが、こんなに大変なんだなと実感しました。この記事でベクトルデータベースの容量削減について書かれていますが、精度とかはまだ分かってないのでなるほどぐらいで終わりました。 生成モデルを利用したプロンプトの作成と推論コードはザックリと以下になります。 def load_or_download_genmodel(model_name: str, local_dir: str) -> tuple[PreTrainedTokenizer | PreTrainedTokenizerFast, PreTrainedModel|SentenceTransformer]: # ローカルディレクトリが存在しない場合は作成 if not os.path.exists(local_dir): os.makedirs(local_dir) # モデルがローカルに存在するかをチェック if not (os.path.exists(os.path.join(local_dir, 'config.json')) and os.path.exists(os.path.join(local_dir, 'tokenizer_config.json'))): # モデルが存在しない場合はダウンロードして保存 print(f"Model not found locally. Downloading {model_name}...") tokenizer = AutoTokenizer.from_pretrained(model_name, force_download=True) model = AutoModelForCausalLM.from_pretrained(model_name, force_download=True) print(f"Saving model and tokenizer to {local_dir}...") tokenizer.save_pretrained(local_dir) model.save_pretrained(local_dir) else: # モデルが存在する場合はローカルからロード print(f"Loading generative model and tokenizer from {local_dir}...") tokenizer = AutoTokenizer.from_pretrained(local_dir) model = AutoModelForCausalLM.from_pretrained(local_dir) return tokenizer, model def process_text_in_chunks(self, question, text, model, tokenizer): for chunk in chunks: prompt = f"{question}\n\n{chunk}" inputs = tokenizer(prompt, return_tensors="pt", max_length=50, truncation=True) input_ids = inputs["input_ids"] attention_mask = inputs["attention_mask"] output = self.generative_model.generate(input_ids=input_ids, attention_mask=attention_mask, max_new_tokens=100, num_beams=3) result_text = tokenizer.decode(output[0], skip_special_tokens=True) combined_result += result_text + "\n" return combined_result def main(self, question): # コサイン類推度から近いファイルを取得し、テキストを抽出→ここでは省く result = self.process_text_in_chunks(question, text, self.generative_model, self.tokenizer) return result if __name__ == '__main__': # 生成モデルをロードまたはダウンロード tokenizer, gen_model = load_or_download_genmodel(gen_model_name, gen_local_dir) cos_sim_calc = CosSimCalc(gen_model, tokenizer, emb_model) cos_sim_calc.main(question = '著作権について教えて下さい。') いろいろ試して見たんですがローカルだと動かないですし、高性能GCPを買うまではいかないので、クラウドで実行するかOpenAIなどのAPIに頼ることになりそうです。 ...

2024年5月24日

RAGを開発してみたい!ので簡単なものでもいいので作ってみよう!part8

前回問題としていたベクトル化についてですが解決して、ようやく2つ目の目標が終わりました! まずはこちらをご覧ください。 こんな感じになりました。 今はまだファイル数は20~30なのでまだまだ足りませんが、前回に比べるとかなりましになりました。 今回やったこととしては OpenAIのベクトル化からSentence Transformerを使用したベクトル化に変更 全ファイルをベクトルデータベースとしてjsonファイルに格納 になります。そのため一旦別プログラムでファイルを全てベクトル化し、画面に表示をさせるときはそのファイルを読み込んで類似度の計算を行っています。 前のコードとそこまでは変わってないので変わった部分で言うと class PDFToVector: def __init__(self, model_name: str): # モデルを読み込み self.model = SentenceTransformer(model_name) def split_text2vector(self, text: str, max_tokens=200) -> List[float]: vectors = [] for i in range(0, len(text), max_tokens): segment = text[i:i+max_tokens] vector = self.model.encode(segment, convert_to_tensor=True) vectors.append(vector) average_vector = np.mean(vectors, axis=0).tolist() def embed_sentence(self, text: str, vector_fol: str, filename: str, vector_database: List) -> List: embedding = self.split_text2vector(text) vector = { 'title': filename, 'body': text, 'embedding': embedding } vector_database.append(vector) def main(self): # ベクトルデータベースを格納 with open(vector_db_json, 'w', encoding='utf-8') as file: json.dump(vector_database, file, ensure_ascii=False, indent=4) こんなとこだと思います。一部処理を省略していますが大体の変わったとこはここになります。 ...

2024年5月14日

RAGを開発してみたい!ので簡単なものでもいいので作ってみよう!part7

目標としていた部分が完成したのでデモ版という形でお見せしようと思います。 想定していた形が取れたので割と嬉しいですね!ただ、上記はファイルが2つの場合でこのくらい時間がかかっています。 次はファイルが5つの場合です。 かなり時間がかかってますね。というのも実行するたびファイルをベクトル化しているので時間がかかる仕組みになっています。 実行するたびopenaiのAPIもたたいているので料金も増えていきます。ということで次の課題は openaiのベクトル化ではない代替手段を見つける ベクトルデータベースを作成する(すべてのファイルをベクトル化して、どこかに保存) ひとまずはこの2つですかね? 代替手段は見つければ何とかなりそうなので時間はかからないと思いますが、ベクトルデータベースの作成は異なるプログラムを作る必要がありそうですし、質問をベクトル化するプログラムの改修も入りそうなので少し時間がかかるかもですね。 第二目標ほど時間はかからないと思いますが… 今回修正した箇所はflaskを使用した場所と応答画面の作成になります。flaskは微修正だったので割愛しますが、画面のほうは以下のようになりました。 'use client'; import { useState } from 'react'; export default function QuestionForm() { // サーバーからの結果を保持する状態変数 const [result, setResult] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); const question = e.target.elements.question.value; // サーバーにPOSTリクエストを送る const response = await fetch('http://localhost:5000/process', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: question }) }); // サーバーからのレスポンスをJSON形式で取得 const data = await response.json(); // 結果を状態変数に保存 setResult({ title: data.title, body: data.body, similarity: data.similarity } || 'No result returned'); // デフォルトで"結果がない"と表示 e.target.reset(); } return ( <div> <form onSubmit={handleSubmit}> <textarea name="question" placeholder="質問を入力してください" rows={5} /> <button type="submit">送信</button> </form> {/* サーバーからの結果を表示 */} <div> <h3>回答:</h3> <p><strong>タイトル:</strong> {result.title}</p> <p><strong>類似度:</strong> {result.similarity}</p> <p><strong>内容:</strong> {result.body}</p> </div> </div> ) } 画面にタイトルと類似度と内容が表示されるようになってます。必要ないかもしれませんが、デフォルトでは結果が表示されない文言を出しています。多分出ることはないですが… ...

2024年5月9日

RAGを開発してみたい!ので簡単なものでもいいので作ってみよう!part6

PCが故障したという話をしたのですが、コンセントから電源が抜けてたというオチでした。 なのでRAGの開発を再開しました! 前回開発した部分は 質疑応答画面の作成 今回開発する部分は 画面(Next.js)から送られるデータを受け取るエンドポイントをFlaskに設定 ベクトル化するプログラムをクラス化 Flaskも触ったことないのでChat-GPTに質問しながら触ってました。一旦中身は以下の内容にしています。 from flask import Flask, request, jsonify from flask_cors import CORS import pdf_to_model import logging logging.basicConfig(level=logging.DEBUG) app = Flask(__name__) CORS(app) @app.route('/process', methods=['POST']) def process_question(): data = request.get_json() query = data.get('query') logging.debug("Received query: %s", query) try: vector = pdf_to_model.PDFToVector() result = vector.main(query) # 結果を JSON 形式で返す return jsonify(result[0]) # return jsonify({'result': 'Processed result of ' + query}) except Exception as e: logging.error("Error processing query: %s", str(e)) return jsonify({'error': str(e)}), 500 if __name__ == "__main__": app.run(debug=True) ログの設定はする必要はないですが、まだ開発段階なので一旦設定しています。それから"CORS(app)“ですね。少し調べたのですが異なるオリジン間でのリソース共有を可能にするために必要な設定みたいです。そもそも同一のオリジンとは以下の3つが同じであることが条件です。 ...

2024年5月4日