first commit
This commit is contained in:
235
back_src/simple_gemini_analyzer.py
Normal file
235
back_src/simple_gemini_analyzer.py
Normal file
@@ -0,0 +1,235 @@
|
||||
# To run this code you need to install the following dependencies:
|
||||
# pip install google-genai
|
||||
|
||||
"""
|
||||
간단한 Gemini 이미지 분석기
|
||||
getcode.py의 프롬프트를 그대로 사용하여 PDF 이미지를 분석합니다.
|
||||
|
||||
Author: Claude Assistant
|
||||
Created: 2025-07-14
|
||||
Version: 1.0.0
|
||||
Based on: getcode.py (original user code)
|
||||
"""
|
||||
|
||||
import base64
|
||||
import os
|
||||
import logging
|
||||
from google import genai
|
||||
from google.genai import types
|
||||
from typing import Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
|
||||
# 로깅 설정
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SimpleGeminiAnalyzer:
|
||||
"""
|
||||
getcode.py 스타일의 간단한 Gemini 이미지 분석기
|
||||
구조화된 JSON 스키마 대신 자연어 텍스트 분석을 수행합니다.
|
||||
"""
|
||||
|
||||
def __init__(self, api_key: Optional[str] = None):
|
||||
"""
|
||||
간단한 Gemini 분석기 초기화
|
||||
|
||||
Args:
|
||||
api_key: Gemini API 키 (None인 경우 환경변수에서 로드)
|
||||
"""
|
||||
self.api_key = api_key or os.environ.get("GEMINI_API_KEY")
|
||||
self.model = "gemini-2.5-flash" # getcode.py와 동일한 모델
|
||||
|
||||
# getcode.py와 동일한 프롬프트 사용
|
||||
self.default_prompt = "pdf 이미지 분석하여 도면인지 어떤 정보들이 있는지 알려줘."
|
||||
|
||||
if not self.api_key:
|
||||
raise ValueError("Gemini API 키가 설정되지 않았습니다. GEMINI_API_KEY 환경변수를 설정하거나 api_key 매개변수를 제공하세요.")
|
||||
|
||||
try:
|
||||
self.client = genai.Client(api_key=self.api_key)
|
||||
logger.info(f"Simple Gemini 클라이언트 초기화 완료 (모델: {self.model})")
|
||||
except Exception as e:
|
||||
logger.error(f"Gemini 클라이언트 초기화 실패: {e}")
|
||||
raise
|
||||
|
||||
def analyze_pdf_image(
|
||||
self,
|
||||
base64_data: str,
|
||||
custom_prompt: Optional[str] = None,
|
||||
mime_type: str = "application/pdf"
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Base64로 인코딩된 PDF 데이터를 분석합니다.
|
||||
getcode.py와 동일한 방식으로 동작합니다.
|
||||
|
||||
Args:
|
||||
base64_data: Base64로 인코딩된 PDF 데이터
|
||||
custom_prompt: 사용자 정의 프롬프트 (None인 경우 기본 프롬프트 사용)
|
||||
mime_type: 파일 MIME 타입
|
||||
|
||||
Returns:
|
||||
분석 결과 딕셔너리 또는 None (실패 시)
|
||||
{
|
||||
'analysis_result': str, # 분석 결과 텍스트
|
||||
'success': bool, # 성공 여부
|
||||
'timestamp': str, # 분석 시각
|
||||
'prompt_used': str, # 사용된 프롬프트
|
||||
'model': str, # 사용된 모델
|
||||
'error_message': str # 오류 메시지 (실패 시)
|
||||
}
|
||||
"""
|
||||
try:
|
||||
prompt = custom_prompt or self.default_prompt
|
||||
logger.info(f"이미지 분석 시작 - 프롬프트: {prompt[:50]}...")
|
||||
|
||||
# getcode.py와 동일한 구조로 컨텐츠 생성
|
||||
contents = [
|
||||
types.Content(
|
||||
role="user",
|
||||
parts=[
|
||||
types.Part.from_bytes(
|
||||
mime_type=mime_type,
|
||||
data=base64.b64decode(base64_data),
|
||||
),
|
||||
types.Part.from_text(text=prompt),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
# getcode.py와 동일한 설정 사용
|
||||
generate_content_config = types.GenerateContentConfig(
|
||||
temperature=0,
|
||||
top_p=0.05,
|
||||
thinking_config=types.ThinkingConfig(
|
||||
thinking_budget=0,
|
||||
),
|
||||
response_mime_type="text/plain", # JSON이 아닌 일반 텍스트
|
||||
)
|
||||
|
||||
# 스트리밍이 아닌 일반 응답으로 수정 (CSV 저장을 위해)
|
||||
response = self.client.models.generate_content(
|
||||
model=self.model,
|
||||
contents=contents,
|
||||
config=generate_content_config,
|
||||
)
|
||||
|
||||
if response and hasattr(response, 'text') and response.text:
|
||||
result = {
|
||||
'analysis_result': response.text.strip(),
|
||||
'success': True,
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'prompt_used': prompt,
|
||||
'model': self.model,
|
||||
'error_message': None
|
||||
}
|
||||
logger.info(f"분석 완료: {len(response.text)} 문자")
|
||||
return result
|
||||
else:
|
||||
logger.error("API 응답에서 텍스트를 찾을 수 없습니다.")
|
||||
return {
|
||||
'analysis_result': None,
|
||||
'success': False,
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'prompt_used': prompt,
|
||||
'model': self.model,
|
||||
'error_message': "API 응답에서 텍스트를 찾을 수 없습니다."
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"이미지 분석 중 오류 발생: {str(e)}"
|
||||
logger.error(error_msg)
|
||||
return {
|
||||
'analysis_result': None,
|
||||
'success': False,
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'prompt_used': custom_prompt or self.default_prompt,
|
||||
'model': self.model,
|
||||
'error_message': error_msg
|
||||
}
|
||||
|
||||
def analyze_image_from_bytes(
|
||||
self,
|
||||
image_bytes: bytes,
|
||||
custom_prompt: Optional[str] = None,
|
||||
mime_type: str = "image/png"
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
바이트 형태의 이미지를 직접 분석합니다.
|
||||
|
||||
Args:
|
||||
image_bytes: 이미지 바이트 데이터
|
||||
custom_prompt: 사용자 정의 프롬프트
|
||||
mime_type: 이미지 MIME 타입
|
||||
|
||||
Returns:
|
||||
분석 결과 딕셔너리
|
||||
"""
|
||||
try:
|
||||
# 바이트를 base64로 인코딩
|
||||
base64_data = base64.b64encode(image_bytes).decode('utf-8')
|
||||
return self.analyze_pdf_image(base64_data, custom_prompt, mime_type)
|
||||
except Exception as e:
|
||||
error_msg = f"이미지 바이트 분석 중 오류: {str(e)}"
|
||||
logger.error(error_msg)
|
||||
return {
|
||||
'analysis_result': None,
|
||||
'success': False,
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'prompt_used': custom_prompt or self.default_prompt,
|
||||
'model': self.model,
|
||||
'error_message': error_msg
|
||||
}
|
||||
|
||||
def validate_api_connection(self) -> bool:
|
||||
"""API 연결 상태를 확인합니다."""
|
||||
try:
|
||||
test_content = [
|
||||
types.Content(
|
||||
role="user",
|
||||
parts=[types.Part.from_text(text="안녕하세요")]
|
||||
)
|
||||
]
|
||||
|
||||
config = types.GenerateContentConfig(
|
||||
temperature=0,
|
||||
response_mime_type="text/plain"
|
||||
)
|
||||
|
||||
response = self.client.models.generate_content(
|
||||
model=self.model,
|
||||
contents=test_content,
|
||||
config=config
|
||||
)
|
||||
|
||||
if response and hasattr(response, 'text'):
|
||||
logger.info("Simple Gemini API 연결 테스트 성공")
|
||||
return True
|
||||
else:
|
||||
logger.error("Simple Gemini API 연결 테스트 실패")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"Simple Gemini API 연결 테스트 중 오류: {e}")
|
||||
return False
|
||||
|
||||
|
||||
# 사용 예시
|
||||
if __name__ == "__main__":
|
||||
# 테스트 코드
|
||||
analyzer = SimpleGeminiAnalyzer()
|
||||
|
||||
# API 연결 테스트
|
||||
if analyzer.validate_api_connection():
|
||||
print("✅ API 연결 성공")
|
||||
|
||||
# 샘플 이미지 분석 (실제 사용 시에는 PDF 파일에서 추출한 이미지 사용)
|
||||
sample_text = "테스트용 간단한 텍스트 분석"
|
||||
|
||||
# 실제 사용 예시:
|
||||
# with open("sample.pdf", "rb") as f:
|
||||
# pdf_bytes = f.read()
|
||||
# base64_data = base64.b64encode(pdf_bytes).decode('utf-8')
|
||||
# result = analyzer.analyze_pdf_image(base64_data)
|
||||
# print("분석 결과:", result)
|
||||
else:
|
||||
print("❌ API 연결 실패")
|
||||
Reference in New Issue
Block a user