logoStephen's 기술블로그

포스트 검색

제목, 태그로 포스트를 검색해보세요

#028 #OPENAI OCR 요금 분석

#028 #OPENAI OCR 요금 분석
Flutter
2024년 11월 19일
목차

👉 주요 OCR서비스 / 라이브러리 비교

  • 네이버 클로바 요금
    • 구분
      서비스
      기본요금
      기본 제공 구간
      추가 과금기준
      추가요금
      영수증
      Standard 플랜
      월 180,000원
      3,000건
      추가 호출 횟수당
      건당 80원
      영수증
      Advanced 플랜
      월 580,000원
      15,000건
      추가 호출 횟수당
      건당 50원
      사업자등록증
      Standard 플랜
      월 180,000원
      3,000건
      추가 호출 횟수당
      건당 80원
      사업자등록증
      Advanced 플랜
      월 580,000원
      15,000건
      추가 호출 횟수당
      건당 50원
      ✅ 높은 정확도
      ⛔️ 커스터 마이징 안됨
      ⛔️ 비싼거 같음
      ⛔️ 절차가 복잡함
       
  • openai 요금
    • 구분
      요금 체계
      토큰 사용량
      한달 사용량
      건당 요금
      gpt-4o-mini
      - 요청 토큰 요금 $0.150 / 1M input tokens - 반환 토큰 요금 $0.600 / 1M output tokens
      - 사업자 등록증 $토큰 사용량 : 대략 37,000 tokens - 영수증 $토큰 사용량 : 대략 17,000 tokens
      건당 과금이지만 네이버 기본 요금제 사용량과 비교시 : 3,000 건 사업자등록증 : 월 24,000원 영수증 : 월 12,000원
      사업자등록증 : 건당 8원 영수증 : 건당 4원
      gpt-4o
      - 요청 토큰 요금 $2.50 / 1M input tokens - 반환 토큰 요금 $10.00 / 1M output tokens
      - 사업자 등록증 $토큰 사용량 : 대략 1,450 tokens - 영수증 $토큰 사용량 : 대략 1,040 tokens
      건당 과금이지만 네이버 기본 요금제 사용량과 비교시 : 3,000 건 사업자등록증 : 월 15,750원 영수증 : 월 10,920원
      사업자등록증 : 건당 5원 영수증 : 건당 4원
      ✅  4o 모델은 정확도 좋음 - 4o모델은 요청 최적화 작업이란게 있어서 요청 토큰 갯수가 되게 적음
      ✅  프롬프트 커스터마이징이 되어서 정확도 발전 시킬수 있음, fine tuning 옵션도 제공함
      ✅  절차가 간편함
      ✅  반환 데이터 형태도 커스터 마이징 가능 (기본주소 + 상세주소 형태 커스터마이징 가능)
      ✅  서버에 먼저 업로드하고 링크로 요청하면 요청 토큰이 1400개에서 1070개로 줄어듬, 3분의 1가량 요금을 줄일 수 있다는 뜻
 
  • tesseract OCR
    • ✅  무료
      ✅  지속적인 업데이트 확인됨
      ⛔️ 정확도 다소 떨어짐
      ⛔️ 커스터마이징 어려움
      ⛔️ 학습 모델이 아님
       
  • paddle OCR
    • ✅  무료
      ✅  정확도는 tesseract보다 약간 좋음
      ⛔️ 최신 라이브러리 업데이트가 3년전
      ⛔️ 커스터마이징 많이 어려움
      ⛔️ 학습 모델이 아님
 

👉 OPENAI api 실제 사용 비교


🔹 계획

JavaScript
1. 캐시에 관한 공식 문서 확인
2. 사업자등록증에서 원하는 데이터를 추출하는 기능으로 테스트
3. 이미지 또는 pdf 파일을 base64변환해서 api 요청 
4. 4o / 4o-mini 모델 토큰과 비용 계산
5. 최적화 방법 (결론)
 

🔹 OpenAIService 구현

JavaScript
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:http/http.dart' as http;
import 'package:logger/logger.dart';
import 'package:image/image.dart' as img;

class OpenAIService {
  Future<String> extractTextFromImage(Uint8List imageBytes) async {
    final image = img.decodeImage(imageBytes);
    final resizedImage = img.copyResize(image!, width: 1000); // 이미지의 크기 조절로 토큰 수를 조절 할 수 있다. 
    final compressedImageBytes = Uint8List.fromList(
        img.encodeJpg(resizedImage, quality: 100)); // 이미지 품질 조절로 토큰 수를 조절 할 수 있다. 

    final base64Image = base64Encode(compressedImageBytes);
    final response = await http.post(
      Uri.parse('https://api.openai.com/v1/chat/completions'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ${dotenv.env['OPENAI_API_KEY']}',
      },
      body: jsonEncode({
        'model': 'gpt-4o',
        'messages': [
          {
            'role': 'user',
            'content': [
              {
                'type': 'text',
                'text':
                    '너는 뛰어난 세무사야. 이 이미지는 사업자 등록증이고, 여기서 사업자 등록번호, 개업연월일, 사업장 주소, 상호명(법인명,단체명)을 추출해서 json으로만 반환해야해.\n너가 채워야 할 필드는 bizNum, openDate, baseAddress, detailAddress, bizName에 매칭해서 한글로 반환해야해.\n그리고 보통 주소는 기본주소와 상세주소로 나누어 지는데, 주소가 --서울특별시 종로구 종로 6, 5층 스타필드 빌리지(서린동, 광화문우체국)-- 이런식으로 되어있으면 \n기본주소는 --서울특별시 종로구 종로 6--이고 상세주소는 --5층 스타필드 빌리지(서린동, 광화문우체국)-- 이런식으로 나누어져야해 \n그리고 모든 주소는 한국에서 실존하는 지역명이어야 해'
              },
              {
                'type': 'image_url',
                'image_url': {'url': 'data:image/jpeg;base64,$base64Image'}
              }
            ],
            'detail': 'high',
          }
        ],
      }),
    );

    if (response.statusCode == 200) {
      final data = jsonDecode(utf8.decode(response.bodyBytes));
      Logger().i('Full Response: ${jsonEncode(data)}');
      final totalTokens = data['usage']['total_tokens'];
      Logger().i('Total tokens: $totalTokens');
      Logger().i(data['choices'][0]['message']['content']);
      return data['choices'][0]['message']['content'];
    } else {
      throw Exception('Failed to extract text: ${response.body}');
    }
  }
}
💡
  • pdf파일이나 이미지를 변환해 Uint8List 타입을 매개변수로 openai-service를 요청하는 과정이다.
 
  • 요청당 128000 토큰을 넘기면 에러가 발생한다.
    • notion image

      notion image
 
  • 그래서 그냥 이미지를 base64로 변환해서 요청하면 1회 최대 토큰수를 초과하는 경우가 많기 때문에, 이미지 사이즈를 줄이기로 했다.
    • notion image
       
  • 이미지 url로 요청을 할 수도 있다 (주석처리된 부분), 이 경우 base64로 요청하는 것보다 조금 더 저렴하다. 이 부분도 확인해보자.
  • 위와 같은 조건으로 비교를 해보았다.
 

🔹 요청이 캐시되는 원리

요청 구조
OpenAI 공식 문서
OpenAI 공식 문서
💡
캐시를 활용하기 위해서는
  • gpt에게 요청할 때 시작하는 첫 부분을 다른 요청과 동일하게 만들면 캐시가 작동한다.
  • 예를들어 gpt 역할 설정같은 첫 부분을 완전 똑같이 요청하면 캐시가 작동하여 비용을 낮출 수 있다.
 
요청이 작동 되는 원리
OpenAI 공식 문서
OpenAI 공식 문서
💡
  • 요청을 받으면 요청의 앞 부분이 일치하는 요청이 있는 지 조회한다.
  • 만약에 요청을 찾게되면, 그 요청의 응답속도를 현저히 낮출 수 있으며, 요금도 줄일 수 있다.
  • 캐시는 보통 5~10분 보관되지만, 사용량이 낮은 시간대에서는 한 시간동안 보관할 수 있다.
 
캐싱 조건
OpenAI 공식문서
OpenAI 공식문서
💡
  • 토큰 수가 1024 이하인 경우에는 캐시가 작동한지 않는다, 특히 cached_tokens부분이 0을 표시하게 된다.
  • 그리고 만약 1024개를 초과하는 경우에는 캐시가 적용되는 부분은 128토큰씩 증가한다.
    • 예를 들어 1500토큰수의 요청을 했다면 그 아래 128토큰수 증가단위인 1408토큰 까지 캐시적용된다.
 
 
캐시가 적용되는 데이터
OpenAI 공식문서
OpenAI 공식문서
💡
  • 여러가지가 있지만 이 블로그에서 중요한 내용은 이미지가 캐시가 되는것인가이다.
  • base64로 된 이미지링크, 그리고 여러개의 파일까지 캐시가 된다
 

👉 model: gpt-4o-mini

요청 형태
JavaScript
'model': 'gpt-4o-mini',
'messages': [
  {
    'role': 'user',
    'content': [
      {
        'type': 'text',
        'text':
            '너는 뛰어난 세무사야. 이 이미지는 사업자 등록증이고, 여기서 사업자 등록번호, 개업연월일, 사업장 주소, 상호명(법인명,단체명)을 추출해서 json으로만 반환해야해.\n너가 채워야 할 필드는 businessNumber, startDate, baseAddress, detailAddress, businessName에 매칭해서 한글로 반환해야해.\n그리고 보통 주소는 기본주소와 상세주소로 나누어 지는데, 주소가 --서울특별시 종로구 종로 6, 5층 스타필드 빌리지(서린동, 광화문우체국)-- 이런식으로 되어있으면 \n baseAddress는 --서울특별시 종로구 종로 6--이고 detailAddress는 --5층 스타필드 빌리지(서린동, 광화문우체국)-- 이런식으로 나누어져야해 \n그리고 모든 주소는 한국에서 실존하는 지역명이어야 해'
      },
      {
        'type': 'image_url',
        'image_url': {'url': 'data:image/jpeg;base64,$base64Image'}
      }
    ],
    'detail': 'high',
  }
],
💡
notion image
💡
 
응답 형태
notion image
💡
 
비용 계산
notion image
💡