実行環境
M1 MacbookAir 16GB
LLMを使うようにコード変更
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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}' に出力しました。" ) |
の処理を汎用性を持たせるため
プロンプトに変えたい
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 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() |
としたが
1 | 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 日付,店名,商品名,数量,金額 となっていて店名などが記載されていない |
なので
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | 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() |
へコード変更
これでもダメ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 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を使わないのならうまく動く