Document AI로 제품 데이터시트 분석하기
Document AI로 제품 데이터시트 분석하기 (Product Datasheet Analysis using Document AI)
제품 데이터시트를 자동으로 분석하는 방법을 다루는 쿡북이에요. 특히 리튬 배터리 PDF 데이터시트에서 구조화된 데이터를 뽑아내고, 설계 요구사항과 비교한 뒤 전문적인 기술 리포트까지 만들어 볼게요. Mistral AI의 Document AI만으로 전 과정이 끝납니다.
출처: 문서
본문
개요 (Overview)
이 쿡북은 Mistral AI의 Document AI를 사용해 제품 데이터시트 분석을 자동화하는 방법을 보여줍니다.
활용 사례: 배터리 조달과 공급업체 검증
휴대용 기기에 쓰일 리튬이온 배터리를 조달한다고 상상해 볼게요. 공급업체는 수백 개의 사양이 담긴 PDF 데이터시트를 보내옵니다. 매번 이걸 설계 요구사항과 일일이 비교하는 건 시간도 오래 걸리고 실수도 많죠.
이 쿡북이 그 과정을 자동화해요:
- 구조화된 데이터 추출 — Document AI(Mistral OCR + Document Annotations)로 리튬 배터리 PDF 데이터시트에서 데이터를 추출
- 사양 비교 — 설계 요구사항과 비교
- 상세 기술 리포트 생성 — 각 파라미터에 대한 종합적인 분석 리포트 생성
필요한 입력 파일
- 📄 제품 데이터시트 PDF (
lithium_iron_cell_datasheet.pdf)- 기술 사양, 안전 정보, 성능 데이터가 담긴 공급업체 제공 사양 문서
- 📋 설계 요구사항 (
battery_requirements.txt)- 용량, 전압, 온도, 안전 등 허용 범위를 정의한 프로젝트의 사양 기준
기술 스택
- ✅ Mistral OCR (
mistral-ocr-latest) — document annotations를 사용한 PDF 파싱 - ✅ Mistral Medium (
mistral-medium-latest) — 기술 리포트 생성
주요 특징
- OCR + 구조화 추출을 위한 Document AI
- Pydantic 스키마 직접 추출
- 배터리 사양 전반을 아우르는 종합적인 커버리지
- 안전 중심 검증
- 전문적인 기술 리포트 생성
장점: 조달 결정을 위한 전문 문서를 빠르고 정확하게 생성해 줘요.
1. 설정과 임포트 (Setup and Imports)
# Install required packages (uncomment if needed)
# !pip install mistralai
import base64
import os
import json
from mistralai.client import Mistral
from mistralai.extra import response_format_from_pydantic_model
from pydantic import BaseModel, Field
from typing import List, Optional
print("✓ All imports successful")
# Initialize Mistral client
api_key = os.getenv("MISTRAL_API_KEY")
if not api_key:
raise ValueError("MISTRAL_API_KEY environment variable not set. Please set it before running.")
client = Mistral(api_key=api_key)
print("✓ Mistral client initialized")
2. 데이터 스키마 정의 (Define Data Schemas)
용량, 전압, 전류, 온도, 치수, 안전 기능을 포함한 리튬 배터리 사양의 종합적인 Pydantic 스키마를 정의해요.
# Schema for lithium battery specifications
class CapacitySpec(BaseModel):
"""Battery capacity specifications."""
normal_capacity: float = Field(..., description="Normal capacity in mAh")
minimum_capacity: float = Field(..., description="Minimum capacity in mAh")
unit: str = Field("mAh", description="Capacity unit")
class VoltageSpec(BaseModel):
"""Voltage specifications."""
nominal_voltage: float = Field(..., description="Nominal voltage in Volts")
charge_voltage: float = Field(..., description="Charge voltage in Volts")
discharge_cutoff_voltage: float = Field(..., description="Discharge cut-off voltage in Volts")
class CurrentSpec(BaseModel):
"""Current specifications."""
standard_charge_current: float = Field(..., description="Standard charge current in mA")
maximum_charge_current: float = Field(..., description="Maximum charge current in mA")
standard_discharge_current: float = Field(..., description="Standard discharge current in mA")
maximum_discharge_current: float = Field(..., description="Maximum discharge current in mA")
max_instantaneous_discharge: float = Field(..., description="Maximum instantaneous discharge current in mA")
class TemperatureRange(BaseModel):
"""Temperature range specifications."""
min_temp: float = Field(..., description="Minimum temperature in °C")
max_temp: float = Field(..., description="Maximum temperature in °C")
condition: str = Field(..., description="Condition (e.g., 'Charge', 'Discharge', 'Storage')")
class DimensionsSpec(BaseModel):
"""Physical dimensions specifications."""
height: float = Field(..., description="Cell height in mm")
diameter: float = Field(..., description="Diameter in mm")
weight: float = Field(..., description="Weight in grams")
class PerformanceSpec(BaseModel):
"""Performance test results."""
test_name: str = Field(..., description="Name of the performance test")
criteria: str = Field(..., description="Performance criteria/requirement")
result: str = Field(..., description="Test result status")
class LithiumBatterySpec(BaseModel):
"""Complete specification for a lithium battery cell."""
model_name: str = Field(..., description="Model name or number")
product_type: str = Field(..., description="Product type (e.g., 'Lithium-ion Cell Battery')")
capacity: CapacitySpec = Field(..., description="Capacity specifications")
voltage: VoltageSpec = Field(..., description="Voltage specifications")
current: CurrentSpec = Field(..., description="Current specifications")
internal_impedance: str = Field(..., description="Internal impedance specification")
dimensions: DimensionsSpec = Field(..., description="Physical dimensions")
cycle_life: int = Field(..., description="Cycle life (number of cycles)")
operating_temperatures: List[TemperatureRange] = Field(..., description="Operating temperature ranges")
storage_temperatures: List[TemperatureRange] = Field(..., description="Storage temperature ranges")
performance_tests: List[PerformanceSpec] = Field(default=[], description="Performance test results")
certifications: List[str] = Field(default=[], description="Certifications and standards")
manufacturer: str = Field(..., description="Manufacturer company name")
distributor: str = Field(..., description="Distributor/vendor information")
warnings: List[str] = Field(default=[], description="Key safety warnings and precautions")
class LithiumBatterySchema(BaseModel):
"""Wrapper for extracted lithium battery specifications."""
specs: List[LithiumBatterySpec] = Field(
..., description="List of extracted lithium battery specifications"
)
print("✓ Pydantic schemas for lithium battery defined")
3. 헬퍼 함수 (Helper Functions)
def encode_pdf(pdf_path: str) -> str:
"""Encode PDF file to base64 string.
Args:
pdf_path: Path to the PDF file
Returns:
Base64 encoded string of the PDF
"""
try:
with open(pdf_path, "rb") as pdf_file:
return base64.b64encode(pdf_file.read()).decode('utf-8')
except FileNotFoundError:
raise FileNotFoundError(f"PDF file not found: {pdf_path}")
except Exception as e:
raise Exception(f"Error encoding PDF: {str(e)}")
print("✓ Helper functions defined")
4. 파일 설정 (File Setup)
필요한 파일이 존재하는지 확인해요.
# Define file paths
PDF_PATH = "lithium_iron_cell_datasheet.pdf"
REQUIREMENTS_PATH = "battery_requirements.txt"
# Verify files exist
if os.path.exists(PDF_PATH):
print(f"✓ Found PDF: {PDF_PATH}")
else:
raise FileNotFoundError(f"❌ PDF not found: {PDF_PATH}")
if os.path.exists(REQUIREMENTS_PATH):
print(f"✓ Found requirements: {REQUIREMENTS_PATH}")
else:
raise FileNotFoundError(f"❌ Requirements not found: {REQUIREMENTS_PATH}")
5. Document Annotations로 구조화된 데이터 추출
이게 이 쿡북의 핵심 기능이에요. Mistral OCR의 document_annotation_format 파라미터를 사용해서, PDF에서 배터리 사양을 단 한 번의 API 호출로 직접 구조화해 추출합니다.
동작 방식:
- PDF를 base64로 인코딩
- Mistral OCR이 문서를 처리
document_annotation_format파라미터가 OCR에 우리의 종합적인 배터리 스키마에 맞는 데이터 추출을 지시- 용량, 전압, 전류, 온도, 치수, 안전 사양을 포함한 구조화된 데이터를 반환
장점:
- ✅ 단일 API 호출 (별도의 LLM 호출 불필요)
- ✅ OCR 과정에서 스키마를 직접 추출
- ✅ 더 정확 (전체 문서 컨텍스트로 추출 진행)
- ✅ 복잡한 중첩 사양도 포착
- ✅ 안전에 중요한 검증 가능
참고:
Document annotations는 8페이지로 제한돼요. 더 큰 문서는 청크로 나눠 처리하세요.
print("📄 Extracting structured data from battery datasheet...")
print(f" Processing: {PDF_PATH}")
# Encode PDF to base64
base64_pdf = encode_pdf(PDF_PATH)
print(" ✓ PDF encoded to base64")
# Extract structured data using Mistral OCR with document annotations
print(" 🔍 Running Mistral OCR with document annotations...")
annotations_response = client.ocr.process(
model="mistral-ocr-latest",
pages=list(range(8)), # Document Annotations limited to 8 pages
document={
"type": "document_url",
"document_url": f"data:application/pdf;base64,{base64_pdf}"
},
document_annotation_format=response_format_from_pydantic_model(LithiumBatterySchema),
include_image_base64=True
)
print(f" ✓ OCR completed - {len(annotations_response.pages)} pages processed")
print(" ✓ Structured data extracted successfully")
# Parse the extracted data into our Pydantic model
extracted_data = LithiumBatterySchema(**json.loads(annotations_response.document_annotation))
print("\n" + "="*60)
print("🔋 EXTRACTED BATTERY SPECIFICATIONS")
print("="*60)
print(json.dumps(extracted_data.model_dump(), indent=2))
6. 비교 리포트 생성 (Generate Comparison Report)
이제 구조화된 배터리 데이터를 얻었으니, Mistral LLM으로 설계 요구사항과 비교하고 상세한 안전·성능 리포트를 생성해 볼게요.
# Load design requirements
print("📋 Loading battery design requirements...")
with open(REQUIREMENTS_PATH, 'r') as f:
requirements = f.read()
print(f" ✓ Requirements loaded from {REQUIREMENTS_PATH}")
print("\nDesign Requirements:")
print(requirements)
print("\n📊 Generating detailed technical report with Mistral LLM...")
# Prepare the comparison prompt for narrative report generation
comparison_prompt = f"""You are an expert battery engineer specializing in lithium-ion battery safety, performance validation, and technical documentation.
I need you to write a comprehensive technical evaluation report comparing a lithium battery's specifications against design requirements.
Design Requirements:
{requirements}
Extracted Battery Specifications:
{json.dumps(extracted_data.model_dump(), indent=2)}
Please write a detailed technical report with the following sections:
# BATTERY VALIDATION REPORT
## 1. EXECUTIVE SUMMARY
Provide a 2-3 paragraph summary of the battery model, manufacturer, and overall compliance status. Include the final recommendation (APPROVED/REJECTED/CONDITIONAL APPROVAL).
## 2. BATTERY IDENTIFICATION
- Model Number
- Manufacturer
- Product Type
- Distributor
## 3. SPECIFICATION ANALYSIS
### 3.1 Capacity Analysis
Compare the normal and minimum capacity against requirements. Explain if it meets or fails the criteria with actual values.
### 3.2 Voltage Characteristics
Analyze nominal voltage, charge voltage, and discharge cut-off voltage. Discuss compliance with safety margins.
### 3.3 Current Capabilities
Evaluate standard and maximum charge/discharge currents. Discuss whether the battery can handle the required load profiles.
### 3.4 Physical Specifications
Verify dimensional compliance (diameter, height, weight) for 18650 standard format.
### 3.5 Performance Characteristics
Assess cycle life and internal impedance against requirements. Discuss implications for product lifetime.
### 3.6 Operating Conditions
Evaluate temperature ranges for charging, discharging, and storage. Identify any limitations or concerns.
## 4. SAFETY EVALUATION
Review safety certifications, protection features (over-charge, over-discharge, short-circuit), and compliance with standards (UN38.3, IEC62133).
## 5. QUALITY ASSESSMENT
Evaluate manufacturing facility certification and performance test results.
## 6. RISK ASSESSMENT
Identify any specification gaps, safety concerns, or operational limitations. Discuss potential risks and mitigation strategies.
## 7. FINAL RECOMMENDATION
Provide clear recommendation: APPROVED, REJECTED, or CONDITIONAL APPROVAL with specific conditions.
Write the report in professional technical language suitable for engineering documentation and procurement decisions. Be thorough, objective, and include specific values and comparisons throughout."""
# Generate narrative report using Mistral LLM (NO response_format - free text)
comparison_response = client.chat.complete(
model="mistral-medium-latest",
messages=[
{"role": "user", "content": comparison_prompt}
],
temperature=0.3 # Slightly higher for more natural writing
)
# Extract the narrative report
narrative_report = comparison_response.choices[0].message.content
print(" ✓ Technical report generated successfully")
7. 결과 표시 (Display Results)
print("\n" + "="*80)
print("📋 BATTERY TECHNICAL EVALUATION REPORT")
print("="*80)
print(narrative_report)
8. 결과 내보내기 (Export Results)
향후 참조와 규정 준수 기록을 위해, 완성된 배터리 분석 결과를 JSON 파일로 저장해요.
# Export complete results including narrative report
output_json = "battery_analysis_results.json"
output_report = "battery_technical_report.md"
# Save JSON results
results = {
"extracted_data": extracted_data.model_dump(),
"narrative_report": narrative_report,
"requirements": requirements
}
with open(output_json, 'w') as f:
json.dump(results, f, indent=2)
# Save narrative report as markdown
with open(output_report, 'w') as f:
f.write(narrative_report)
print(f"\n💾 Complete analysis saved to: {output_json}")
print(f"📄 Technical report saved to: {output_report}")
결론 (Conclusion)
우리가 만든 것:
이 쿡북은 순수한 Mistral AI 기능만으로 리튬 배터리 데이터시트를 분석하는 프로덕션 준비 워크플로우를 보여줬어요:
- ✅ 종합적인 데이터 추출 — 용량, 전압, 전류, 온도, 치수, 안전 사양
- ✅ 안전 중심 검증 — 보호 기능, 인증, 동작 한계
- ✅ 자동 규정 준수 — 산업 표준과 설계 요구사항 비교
- ✅ 상세 리포트 — 각 사양 범주별 통과/실패 분석
주요 장점:
- 추출에 Document AI 사용 (별도 OCR/LLM 처리 불필요)
- 모든 핵심 배터리 사양을 다루는 종합적인 스키마
- 충전/방전 한계와 온도 범위에 대한 안전 중요 검증
기술 스택:
- Mistral OCR (
mistral-ocr-latest) + document annotations - 비교 리포트용 Mistral Large (
mistral-medium-latest) - 종합 스키마 검증용 Pydantic
활용 사례:
이 워크플로우는 다음에 딱 맞아요:
- 배터리 조달 — 공급업체 사양 검증
- 품질 관리 — 설계 요구사항 준수 확인
- 안전 검증 — 보호 기능과 동작 한계 확인
- 제품 개발 — 여러 배터리 옵션 비교
- 규정 준수 리포트 — 검증 기록 생성
이 쿡북 확장하기:
이 워크플로우는 쉽게 다음에도 적용할 수 있어요:
- 다른 전자 부품 (커패시터, 저항, IC)
- 다른 배터리 화학 (LiFePO4, NiMH 등)
- 이력서와 직무 설명 매칭
제한 사항:
- Document annotations는 8페이지로 제한
- 더 큰 문서는 청크로 나눠 별도 처리 필요