LLMを使うようにコード変更

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

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です