実行環境
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を使わないのならうまく動く