実行環境
M1 MacbookAir 16GB
LLMを使うようにコード変更
import re import csv from datetime import datetime # ファイルからテキストを読み込む with open('ocr.txt', 'r', encoding='utf-8') as file: text = file.read() # 情報を抽出 date_match = re.search(r'\d{4}年\d{1,2}月\d{1,2}日', text) date = datetime.strptime(date_match.group(), '%Y年%m月%d日').strftime('%Y-%m-%d') shop_name_match = re.search(r'とれたて食楽部', text) shop_name = shop_name_match.group() # 商品情報を正規表現で抽出 items = re.findall(r'内\d+ (.+?) ¥(\d+)', text) # 現在のタイムスタンプを生成 timestamp = datetime.now().strftime('%Y%m%d%H%M%S') # 出力ファイル名にタイムスタンプを付ける csv_filename = f'receipt_data_{timestamp}.csv' # CSVファイルに出力 with open(csv_filename, mode='w', newline='', encoding='utf-8') as csvfile: csv_writer = csv.writer(csvfile) # ヘッダー行を書き込み csv_writer.writerow(["日付", "店名", "商品名", "数量", "金額"]) for item in items: product_name, price = item # 商品名の「/」以降を削除 product_name_clean = product_name.split('/')[0] # 出力: 日付, 店名, 商品名, 数量, 金額 row = f"{date},{shop_name},{product_name_clean},1,{price}" csv_writer.writerow(row.split(',')) print(f"CSVファイル '{csv_filename}' に出力しました。")
の処理を汎用性を持たせるため
プロンプトに変えたい
import re import csv from datetime import datetime import ollama class OCRToCSV: def __init__(self, text): self.text = text self.date, self.shop_name, self.items = self._extract_info_with_llm() def _extract_info_with_llm(self): # プロンプトを作成 prompt = f""" テキストから次の情報を抽出してください: 1. 日付(例: 2024-08-20) 2. 店名(例: とれたて食楽部) 3. 商品情報(例: 商品名、数量、金額) テキスト: {self.text} 出力形式: 日付: 2024-08-20 店名: とれたて食楽部 商品情報: - 商品名1, 1, 500 - 商品名2, 1, 1000 """ # Ollamaでプロンプトを送信 res = ollama.chat( model="elyza:jp8b", messages=[{'role': 'user', 'content': prompt}] ) # 応答から内容を取得 content = res['message']['content'] # 応答を解析して必要な情報を取得 date_match = re.search(r'日付:\s*(\d{4}-\d{2}-\d{2})', content) shop_name_match = re.search(r'店名:\s*(.+)', content) items_match = re.findall(r'-\s*(.+),\s*(\d+),\s*(\d+)', content) date = date_match.group(1) if date_match else None shop_name = shop_name_match.group(1) if shop_name_match else None items = [(item[0], item[1], item[2]) for item in items_match] return date, shop_name, items def generate_csv(self, output_dir='.', timestamp=None): if timestamp is None: timestamp = datetime.now().strftime('%Y%m%d%H%M%S') csv_filename = f'{output_dir}/receipt_data_{timestamp}.csv' with open(csv_filename, mode='w', newline='', encoding='utf-8') as csvfile: csv_writer = csv.writer(csvfile) csv_writer.writerow(["日付", "店名", "商品名", "数量", "金額"]) for item in self.items: product_name, quantity, price = item row = f"{self.date},{self.shop_name},{product_name},1,{price}" csv_writer.writerow(row.split(',')) print(f"CSVファイル '{csv_filename}' に出力しました。") return csv_filename # 使用例 # テキストを読み込んでOCRToCSVインスタンスを作成し、CSVを生成 with open('ocr.txt', 'r', encoding='utf-8') as file: text = file.read() ocr_to_csv = OCRToCSV(text) ocr_to_csv.generate_csv()
としたが
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR I0000 00:00:1724125129.779029 15985491 config.cc:230] gRPC experiments enabled: call_status_override_on_cancellation, event_engine_dns, event_engine_listener, http2_stats_fix, monitoring_experiment, pick_first_new, trace_record_callops, work_serializer_clears_time_cache CSVファイル './receipt_data_20240820123851.csv' に出力しました。 snowpool@kubotasorunoAir ollama % python main_ocr.py WARNING: All log messages before absl::InitializeLog() is called are written to STDERR I0000 00:00:1724125231.314241 15987342 config.cc:230] gRPC experiments enabled: call_status_override_on_cancellation, event_engine_dns, event_engine_listener, http2_stats_fix, monitoring_experiment, pick_first_new, trace_record_callops, work_serializer_clears_time_cache CSVファイル './receipt_data_20240820124054.csv' に出力しました。 となる また cat receipt_data_20240820124054.csv 日付,店名,商品名,数量,金額 となっていて店名などが記載されていない
なので
import re import csv from datetime import datetime import ollama class OCRToCSV: def __init__(self, text): self.text = text self.date, self.shop_name, self.items = self._extract_info_with_llm() def _extract_info_with_llm(self): # プロンプトを作成 prompt = f""" テキストから次の情報を抽出してください: 1. 日付(例: 2024-08-20) 2. 店名(例: とれたて食楽部) 3. 商品情報(例: 商品名、数量、金額) テキスト: {self.text} 出力形式: 日付: 2024-08-20 店名: とれたて食楽部 商品情報: - 商品名1, 1, 500 - 商品名2, 1, 1000 """ # Ollamaでプロンプトを送信 res = ollama.chat( model="elyza:jp8b", messages=[{'role': 'user', 'content': prompt}] ) # 応答内容を表示(デバッグ用) content = res['message']['content'] print("LLMの応答:", content) # 応答を解析して必要な情報を取得 date_match = re.search(r'日付:\s*(\d{4}年\d{1,2}月\d{1,2}日)', content) shop_name_match = re.search(r'店名:\s*(.+)', content) items_match = re.findall(r'-\s*(.+)、\s*(\d+)', content) # 日付を %Y-%m-%d 形式に変換 date = datetime.strptime(date_match.group(1), '%Y年%m月%d日').strftime('%Y-%m-%d') if date_match else None shop_name = shop_name_match.group(1) if shop_name_match else None # 商品情報の数量をデフォルトで1に設定 items = [(item[0], '1', item[1]) for item in items_match] return date, shop_name, items def generate_csv(self, output_dir='.', timestamp=None): if timestamp is None: timestamp = datetime.now().strftime('%Y%m%d%H%M%S') csv_filename = f'{output_dir}/receipt_data_{timestamp}.csv' with open(csv_filename, mode='w', newline='', encoding='utf-8') as csvfile: csv_writer = csv.writer(csvfile) csv_writer.writerow(["日付", "店名", "商品名", "数量", "金額"]) for item in self.items: product_name, quantity, price = item row = f"{self.date},{self.shop_name},{product_name},{quantity},{price}" csv_writer.writerow(row.split(',')) print(f"CSVファイル '{csv_filename}' に出力しました。") return csv_filename # 使用例 with open('ocr.txt', 'r', encoding='utf-8') as file: text = file.read() ocr_to_csv = OCRToCSV(text) ocr_to_csv.generate_csv()
へコード変更
これでもダメ
import re import csv from datetime import datetime import ollama class OCRToCSV: def __init__(self, text): self.text = text self.date, self.shop_name, self.items = self._extract_info_with_llm() def _extract_info_with_llm(self): # プロンプトを作成 prompt = f""" テキストから次の情報を抽出してください: 1. 日付(例: 2024-08-20) 2. 店名(例: とれたて食楽部) 3. 商品情報(例: 商品名、数量、金額) テキスト: {self.text} 出力形式: 日付: 2024-08-20 店名: とれたて食楽部 商品情報: - 商品名1, 1, 500 - 商品名2, 1, 1000 """ # Ollamaでプロンプトを送信 res = ollama.chat( model="elyza:jp8b", messages=[{'role': 'user', 'content': prompt}] ) # 応答内容を表示(デバッグ用) content = res['message']['content'] print("LLMの応答:", content) # 応答を解析して必要な情報を取得 date_match = re.search(r'日付:\s*(\d{4}-\d{2}-\d{2})', content) shop_name_match = re.search(r'店名:\s*(.+)', content) items_match = re.findall(r'-\s*(.+)、\s*(\d+)', content) # 日付をそのまま使用 date = date_match.group(1) if date_match else None shop_name = shop_name_match.group(1) if shop_name_match else None items = [(item[0], '1', item[1]) for item in items_match] return date, shop_name, items def generate_csv(self, output_dir='.', timestamp=None): if timestamp is None: timestamp = datetime.now().strftime('%Y%m%d%H%M%S') csv_filename = f'{output_dir}/receipt_data_{timestamp}.csv' with open(csv_filename, mode='w', newline='', encoding='utf-8') as csvfile: csv_writer = csv.writer(csvfile) csv_writer.writerow(["日付", "店名", "商品名", "数量", "金額"]) for item in self.items: product_name, quantity, price = item row = f"{self.date},{self.shop_name},{product_name},{quantity},{price}" csv_writer.writerow(row.split(',')) print(f"CSVファイル '{csv_filename}' に出力しました。") return csv_filename # 使用例 with open('ocr.txt', 'r', encoding='utf-8') as file: text = file.read() ocr_to_csv = OCRToCSV(text) ocr_to_csv.generate_csv()
に変更することで解決
あとは指定のファイルのみ
main_ocr.pyで固定しているので
これを各ファイルごとにCSVに出力する
もしくはディレクトリ内にあるものを全て対象にするようにする
結局はこれはOCRして商品名を取り出すのがメインの目的で
結果をDBやキーワードリストに使いたい
ということ
ならimagesフォルダの中身を対象に実行するようにすればOK
実行後OCR済みのフォルダに移動するようにすればいい
これをやったらバグった
とりあえずLLMを使わないのならうまく動く