Local Ollama를 사용하여 SEO 메타 제목 및 설명을 자동 생성하는 방법
구조화된 SEO 제목과 메타 설명을 일괄 생성하고, 결과물을 검증하고, 사람이 검토해야 할 결과를 표시하는 로컬 Ollama 워크플로를 구축하세요.
자동화된 송장 처리 에이전트는 처음부터 거대한 자율 AI 시스템일 필요는 없습니다. 처음 유용한 버전을 만들려면, 송장을 입력받아 관련 문서 및 AI 도구를 호출하고, 결과를 검증하고, 사람 의 검토가 필요한지 판단한 후, 승인된 데이터만 저장하거나 내보내는 제어된 소프트웨어 워크플로로 생각하면 됩니다.
금융 분야에서는 이러한 구분이 중요합니다. 언어 모델은 복잡한 송장 형식을 구조화된 필드로 변환하는 데 도움이 될 수 있지만, 송장의 유효성이나 안전한 게시 여부를 결정하는 유일한 요소가 되어서는 안 됩니다. 이 가이드에서 소개하는 초보자 친화적인 설계 방식은 데이터 추출은 확률적으로, 중요한 회계 검사는 확정적으로 수행합니다.
최종적으로는 PDF 또는 이미지 형식의 송장을 입력받아 공급업체, 송장 번호, 날짜, 통화, 합계, 품목 등의 필드를 추출하고, 해당 필드를 규칙에 따라 검증하고, 문제가 있는 문서는 검토를 위해 전달하고, 감사 추적 기록을 저장하고, API를 통해 해당 프로세스를 공개하는 로컬 프로토타입을 구축하게 됩니다.
알아두면 유용한 용어가 네 가지 있습니다.
2026년 9월 현재, 여러 활발하게 유지 관리되는 오픈 소스 프로젝트가 이러한 계층을 다루고 있습니다. Docling은 PDF, 이미지, 오피스 문서 및 기타 문서 형식을 지원하고, PaddleOCR은 OCR 및 문서 이해 파이프라인을 제공하며 Apache 2.0 라이선스로 배포됩니다. 또한 Tesseract 프로젝트는 공식 Tesseract 매뉴얼 에서 현재 5.x 버전을 오픈 소스 OCR 엔진으로 설명하고 있습니다 .
로컬 모델 추론의 경우, llama.cpp 서버 문서에는 OpenAI 호환 엔드포인트와 스키마 제약 조건이 있는 JSON 출력에 대한 설명이 있습니다. 따라서 로컬에서 호스팅되는 모델에 제약 없는 산문 대신 정의된 객체를 반환하도록 요청할 수 있으므로 추출 서비스에 유용합니다.
라이선스 관련 중요한 주의사항이 있습니다. 오픈 소스 추론 엔진이라고 해서 모든 모델 가중치가 자동으로 오픈 소스가 되는 것은 아닙니다. 특히 상업적 용도로 사용할 경우, 배포하는 정확한 모델 체크포인트의 라이선스를 확인하십시오.
| 층 | 실용적인 선택 | 이것이 여기에 있는 이유 |
|---|---|---|
| 문서 변환 | 도킹 | PDF 파일과 이미지를 구조화된 문서 형태로 변환하고 내보낼 수 있는 텍스트로 변환합니다. |
| OCR 대체 | PaddleOCR 또는 Tesseract | 청구서가 스캔 파일이나 사진이고 텍스트 추출에 OCR이 필요한 경우에 유용합니다. |
| 로컬 AI 추출 | llama.cpp + 적절한 명령어 모델 | 가변적인 송장 텍스트를 안정적인 JSON 스키마에 매핑하면서 추론은 로컬에서 수행합니다. |
| 스키마 유효성 검사 | 피단틱 | 선언된 필드 유형 및 제약 조건에 따라 Python 데이터의 유효성을 검사합니다. |
| API | FastAPI | 송장 업로드를 허용하고 처리 결과를 반환합니다. |
| 저장 | 프로토타입 제작에는 SQLite, 공유 서비스에는 PostgreSQL을 사용합니다. | 정규화된 데이터, 검토 상태, 소스 파일 ID 및 감사 이벤트를 저장합니다. |
| 관현악법 | 먼저 순수 파이썬을 배우고, LangGraph는 나중에 선택적으로 사용하세요. | 결정론적 함수는 디버깅이 더 쉽습니다. 분기 및 사람 검토가 복잡해지면 상태 저장 에이전트 프레임워크를 추가하세요. |
Pydantic의 공식 문서에 따르면 모델은 `Class`를 상속받고 BaseModel, 들어오는 데이터를 검증하며, `Class`를 통해 JSON 스키마를 출력할 수 있습니다 model_json_schema(). 자세한 내용은 Pydantic 모델 유효성 검사를 참조하세요 . 나중에 영구적인 상태 저장 분기가 필요한 경우, LangGraph 참조 문서에서 장기 실행 상태 저장 에이전트, 영구 저장 및 휴먼 인 더 루프 워크플로 지원에 대한 설명을 확인할 수 있습니다.
"매입채무 자동화"부터 시작하지 마세요. 문서 유형 하나와 출력 계약서 하나부터 시작하세요. 좋은 최소 기능 제품(MVP)은 다음과 같습니다: 영문 공급업체 송장, PDF 또는 이미지 입력, 법인 하나, 통화 설정 하나, 그리고 자동 지급 실행 기능은 제외.
mkdir invoice-agent
cd invoice-agent
python -m venv .venv
# Linux/macOS
source .venv/bin/activate
pip install docling pydantic fastapi uvicorn httpx python-multipart
OCR 엔진이 필요한 경우 별도로 설치하십시오. Docling의 최신 설치 가이드에서는 를 사용하고 pip install docling, PaddleOCR의 최신 설치 문서에서는 기본 OCR 패키지와 선택적 문서 구문 분석 및 정보 추출 종속성 그룹을 구분합니다. 이전 종속성 목록을 복사하는 대신 Docling 설치 가이드 또는 PaddleOCR 3.x 설치 가이드를 참조하십시오.
새로 생성된 PDF 파일에는 이미 사용 가능한 텍스트가 포함되어 있을 수 있습니다. 스캔한 PDF 파일이나 사진은 OCR 처리가 필요합니다. 파서는 이러한 차이점을 파이프라인의 나머지 부분에서 드러내지 않도록 해야 합니다. 이후 단계에서는 정규화된 문서 텍스트와 유용한 레이아웃 또는 표 정보를 함께 처리해야 합니다.
최소한의 도킹 변환은 다음과 같습니다.
from docling.document_converter import DocumentConverter
converter = DocumentConverter()
def parse_document(path: str) -> str:
result = converter.convert(path)
return result.document.export_to_markdown()
Docling의 공식 빠른 시작 가이드는 동일한 변환 후 내보내기 패턴을 사용합니다. OCR 처리량이 많은 컬렉션의 경우, 직접 스캔한 파일에 PaddleOCR 또는 Tesseract를 테스트해 보세요. PaddleOCR 프로젝트 문서에서는 문서 분석에 최신 PP-StructureV3 제품군을 권장하며, Tesseract는 인쇄된 텍스트 OCR을 위해 명령줄 또는 API를 통해 호출할 수 있습니다.
데이터 추출 스키마는 AI와 회계 로직 간의 계약과 같습니다. "송장에 나타날 수 있는 모든 것"을 담는 거대한 스키마는 피해야 합니다. 유효성 검사가 가능한 필드부터 시작하세요.
from datetime import date
from decimal import Decimal
from pydantic import BaseModel, Field, ConfigDict
class LineItem(BaseModel):
description: str
quantity: Decimal | None = None
unit_price: Decimal | None = None
amount: Decimal
class Invoice(BaseModel):
model_config = ConfigDict(extra="forbid")
vendor_name: str
invoice_number: str
invoice_date: date
due_date: date | None = None
currency: str = Field(min_length=3, max_length=3)
subtotal: Decimal | None = None
tax: Decimal | None = None
total: Decimal
line_items: list[LineItem] = []
extra="forbid"이 맥락에서 유용한 이유는 예상치 못한 LLM 필드가 회계 기록에 자동으로 추가되는 것을 방지하기 위해서입니다. 또한 Pydantic 유효성 검사는 구조와 유형을 확인하는 것이지, 추출된 공급업체나 금액이 송장 이미지와 일치하는지 증명하는 것은 아니라는 점에 유의하십시오.
llama.cpp의 HTTP 서버 뒤에서 적절한 명령어 모델을 실행하세요. 정확한 모델 크기는 하드웨어와 송장 복잡성에 따라 달라집니다. 모델 크기가 크다고 해서 자동으로 성능이 향상되는 것은 아니므로, 자체 송장 데이터셋을 사용하여 필드 정확도, 지연 시간 및 메모리 사용량을 벤치마킹하세요.
llama.cpp는 현재 스키마 제약 조건이 있는 JSON 응답을 지원합니다. Pydantic에서 해당 스키마를 추출하여 추출 요청과 함께 전송할 수 있습니다.
import json
import httpx
def extract_invoice(document_text: str) -> Invoice:
schema = Invoice.model_json_schema()
prompt = f"""
Extract one supplier invoice from the text below.
Do not invent values. If an optional field is absent, use null.
Currency must be a three-letter code.
Return only data that fits the required schema.
DOCUMENT:
{document_text}
"""
payload = {
"model": "local-model",
"messages": [{"role": "user", "content": prompt}],
"temperature": 0,
"response_format": {
"type": "json_schema",
"schema": schema
}
}
r = httpx.post(
"http://127.0.0.1:8080/v1/chat/completions",
json=payload,
timeout=120
)
r.raise_for_status()
content = r.json()["choices"][0]["message"]["content"]
return Invoice.model_validate_json(content)
스키마 제약 조건 생성은 유효한 구조를 만드는 데 도움이 되지만 의미론적 진실성을 보장하지는 않습니다. 완벽하게 유효한 JSON 객체라도 잘못된 총합을 포함할 수 있습니다. 그렇기 때문에 다음 단계가 필수적입니다.
LLM에게 "자신 있습니까?"라고 묻고 그 답변을 맹목적으로 신뢰하지 마십시오. 모델에 대한 자체 보고식 자신감은 검증된 기준이 아닙니다. 추출된 데이터와 시스템을 이용하여 재계산할 수 있는 검증 절차를 구축하십시오.
유용한 첫 번째 규칙은 다음과 같습니다.
from decimal import Decimal
def validate_business_rules(inv: Invoice) -> list[str]:
errors = []
if inv.subtotal is not None and inv.tax is not None:
expected = inv.subtotal + inv.tax
if abs(expected - inv.total) > Decimal("0.02"):
errors.append("subtotal_plus_tax_does_not_match_total")
line_sum = sum((x.amount for x in inv.line_items), Decimal("0"))
if inv.subtotal is not None and abs(line_sum - inv.subtotal) > Decimal("0.02"):
errors.append("line_items_do_not_match_subtotal")
if inv.due_date and inv.due_date < inv.invoice_date:
errors.append("due_date_before_invoice_date")
return errors
실패한 모든 검사는 검토 대기열로 보내십시오. 초기 배포 시에는 추출 품질을 측정하는 동안 모든 송장을 검토 대기열로 보내는 것이 좋습니다 . 자동화 임계값은 다른 시스템에서 복사한 일반적인 백분율이 아니라 자체적으로 라벨링된 송장에서 수집한 증거를 기반으로 설정해야 합니다.
API를 사용하면 업로드 양식, 이메일 발송 도구, 공유 폴더 감시 도구 또는 회계 통합 기능이 동일한 처리 함수를 호출할 수 있습니다. FastAPI의 공식 파일 업로드 가이드에서는 UploadFile업로드된 파일에 대해 스풀링된 파일을 사용하는 것을 권장하며, 이는 대용량 파일을 메모리에 완전히 로드하는 것보다 더 적합하다고 설명합니다.
from pathlib import Path
from tempfile import NamedTemporaryFile
from fastapi import FastAPI, UploadFile, HTTPException
app = FastAPI()
@app.post("/invoices")
async def process_upload(file: UploadFile):
if file.content_type not in {
"application/pdf",
"image/png",
"image/jpeg"
}:
raise HTTPException(415, "Unsupported file type")
suffix = Path(file.filename or "").suffix
with NamedTemporaryFile(suffix=suffix, delete=False) as tmp:
tmp.write(await file.read())
path = tmp.name
result = process_invoice(path)
return result
지원되는 업로드 패턴에 대한 자세한 내용 은 최신 FastAPI 요청 파일 문서를 참조하십시오 . 실제 운영 환경에서는 파일 크기 제한, 필요한 경우 악성코드 검사, 인증된 호출자, 요청 ID, 그리고 안전한 임시 파일 삭제 기능을 적용해야 합니다.
최종 JSON 데이터만 저장하지 마십시오. 발생한 상황을 재구성할 수 있도록 충분한 증거를 보관하십시오. 여기에는 원본 파일 ID, 해시값, 파서 버전, 모델 식별자, 프롬프트 버전, 추출된 JSON 데이터, 유효성 검사 결과, 검토 결정, 타임스탬프, 그리고 변경 사항을 승인한 사용자 또는 서비스가 포함됩니다.
간단한 프로토타입은 SQLite를 사용할 수 있습니다. 다중 사용자 서비스는 고유성 및 외래 키 제약 조건을 사용하여 PostgreSQL을 사용할 수 있습니다. PostgreSQL의 최신 문서는 테이블 제약 조건 에 대해 다루고 있으며 , 이는 AI 파이프라인과 별개로 키와 관계를 보호하는 데 유용합니다.
CREATE TABLE invoices (
id BIGSERIAL PRIMARY KEY,
vendor_id BIGINT NOT NULL,
invoice_number TEXT NOT NULL,
invoice_date DATE NOT NULL,
currency CHAR(3) NOT NULL,
total NUMERIC(18,2) NOT NULL,
status TEXT NOT NULL,
source_sha256 TEXT NOT NULL,
extracted_json JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (vendor_id, invoice_number)
);
소스 해시는 실수로 재전송된 경우를 감지하는 두 번째 방법을 제공합니다. 송장에는 주소, 은행 정보, 세금 ID 및 기타 기밀 데이터가 포함되는 경우가 많으므로 파일 저장 권한을 일반 애플리케이션 로그보다 더 엄격하게 관리해야 합니다.
다섯 개의 깨끗한 PDF 파일에서 작동하는 프로토타입은 실제 사용에 적합하지 않습니다. 실제 사용 환경에서 접하는 다양한 입력값을 나타내는 레이블이 지정된 평가 세트를 구축하십시오. 여기에는 여러 공급업체, 스캔 파일, 회전된 페이지, 작은 글꼴, 여러 페이지로 구성된 송장, 할인, 마이너스 금액, 세금, 배송비, 여러 통화, 누락된 구매 주문서 및 중복 제출 등이 포함됩니다.
필드별 지표는 별도로 추적하세요. "송장 정확도"라는 용어는 공급업체 이름은 쉽게 확인할 수 있지만 품목 수량은 신뢰할 수 없다는 사실을 가릴 수 있습니다. 최소한 다음 사항을 측정하세요.
오류를 테스트 케이스로 저장하세요. 파서 규칙, 프롬프트, 스키마 또는 모델을 수정할 때마다 전체 평가 세트를 다시 실행하세요. 이렇게 하면 한 공급업체의 개선 사항이 다른 공급업체의 레이아웃을 조용히 망가뜨리는 것을 방지할 수 있습니다.
상태 머신을 명시적으로 표현하세요. 처음에는 "에이전트"를 일반 파이썬 함수로 구현해도 됩니다.
def process_invoice(path: str) -> dict:
text = parse_document(path)
invoice = extract_invoice(text)
errors = validate_business_rules(invoice)
if errors:
status = "needs_review"
else:
status = "validated"
record_id = save_invoice(
source_path=path,
invoice=invoice,
validation_errors=errors,
status=status,
)
return {
"id": record_id,
"status": status,
"invoice": invoice.model_dump(mode="json"),
"validation_errors": errors,
}
이는 이미 도구를 조율하고 분기를 선택하기 때문에 에이전트와 유사한 기능을 합니다. 모든 다음 단계를 선택하기 위해 LLM이 필요한 것은 아닙니다. 지속적인 다단계 검토, 재시도, 비동기 콜백 또는 사례별로 실행 순서가 변경되는 여러 특수 도구가 필요한 경우 LangGraph 또는 다른 오케스트레이션 프레임워크를 추가하십시오.
모델은 데이터를 추출하고 정규화해야 하며, 코드와 신뢰할 수 있는 시스템 데이터는 검증되어야 합니다. 산술 연산, 중복 검사, 공급업체 상태 확인, 구매 주문서 대조 및 승인 한도 설정은 결정론적 논리에 속해야 합니다.
원본 송장 또는 송장에 대한 관리된 참조 자료를 보관하십시오. 검토자는 증거가 필요하며, 모델이나 파서 업그레이드 후 오류를 재현할 수 있는 방법이 필요합니다.
처리된 각 송장에 프롬프트 버전과 모델 식별자를 저장하십시오. 그렇지 않으면 몇 달 간격으로 처리된 두 송장이 다르게 동작한 이유를 설명할 수 없습니다.
JSON 유효성이 송장 유효성을 보장하는 것은 아닙니다. 우선 사람이 직접 검토한 후, 평가를 통해 성능이 만족스러운 수준이라고 판단되면 위험도가 낮은 경우에만 자동화를 진행하십시오.
라이브러리와 모델 가중치는 서로 다른 라이선스를 가질 수 있습니다. PaddleOCR과 Tesseract는 오픈 소스 라이선스를 공개하고 있지만, llama.cpp를 통해 실행하는 모델의 라이선스는 해당 체크포인트에 따라 다릅니다. 배포 전에 라이선스를 확인하십시오.
아무리 잘 만들어진 대시보드라도 잘못된 수치를 보완할 수는 없습니다. 문서 구문 분석, 스키마 추출 및 유효성 검사를 먼저 테스트하고, 검토자가 실제로 필요로 하는 정보를 파악한 후에 검토 인터페이스를 추가하십시오.
| 접근하다 | 가장 적합한 | 주요 제한 사항 |
|---|---|---|
| OCR + 규칙 | 안정성이 매우 높은 소수의 벤더 템플릿 | 레이아웃이 다양해지면 규칙이 모호해집니다. |
| 문서 레이아웃 모델 | 위치가 중요한 테이블, 폼 및 필드 | 특정 작업에 대한 교육이나 후처리 작업이 필요할 수 있습니다. |
| OCR/문서 파서 + 로컬 LLM | 공통 대상 스키마를 사용하는 다양한 송장 형식 | 제약 조건을 설정하고 검증해야 하며, 추론에 더 많은 컴퓨팅 비용이 소요됩니다. |
| 시각-언어 모델 | 텍스트와 시각적 레이아웃이 긴밀하게 연관된 복잡한 문서 | 하드웨어 요구 사양이 높아지고 평가가 더욱 복잡해집니다. |
Hugging Face의 최신 LayoutLMv3 문서에서는 텍스트와 시각적 레이아웃 정보를 결합하는 문서 AI 모델을 설명합니다. PaddleOCR의 PP-StructureV3 문서 역시 레이아웃, 표, 구조화된 문서 분석에 중점을 두고 있습니다. 이러한 모델들은 일반 텍스트와 LLM만으로는 충분하지 않을 때 고려할 수 있는 옵션입니다.
단계적으로 진행하십시오. 첫째, 레이블이 지정된 송장 폴더에서 로컬로 실행합니다. 둘째, API와 영구 저장소를 추가합니다. 셋째, 담당자 검토 대기열을 도입합니다. 넷째, 공급업체 마스터 또는 구매 주문과 같은 읽기 전용 조회 기능을 통합합니다. 다섯째, 회계 스테이징 영역으로 제어된 내보내기를 허용합니다. 모니터링을 통해 제어 기능이 검증된 후에만 엄격하게 정의된 저위험 사례에 대해 자동 게시를 고려하십시오.
모든 단계에서 다음 세 가지를 보존하십시오. 증거 (원본 문서 및 추출된 소스), 결정성 (재실행 가능한 비즈니스 규칙), 추적성 (어떤 파서, 모델, 프롬프트 및 검토자가 최종 기록을 생성했는지).
이러한 제어 기능이 제대로 갖춰져 있다면, 단순한 OCR 데모를 넘어 신뢰할 수 있는 송장 처리 시스템의 기반을 마련한 셈입니다. 오픈 소스 구성 요소는 시간이 지남에 따라 변경될 수 있지만, 증거를 분석하고, 스키마로 추출하고, 코드로 유효성을 검사하고, 불확실한 사항은 담당자에게 전달하고, 모든 결정을 기록하는 아키텍처는 변함없이 견고하게 유지됩니다.
구조화된 SEO 제목과 메타 설명을 일괄 생성하고, 결과물을 검증하고, 사람이 검토해야 할 결과를 표시하는 로컬 Ollama 워크플로를 구축하세요.
Use this free modern real estate listing presentation PowerPoint blueprint to organize pricing, marketing, property prep, agent value, and seller next steps.
인건비, 자재비, 수식, 마크업, 제외 항목 및 인쇄 가능한 고객 총액을 명확하게 표시하는 인쇄 가능한 건설 공사 견적서 템플릿을 Excel에서 만드세요.
실용적인 영화 조명 공식, 재사용 가능한 레시피, 예제 및 빠른 문제 해결 체크리스트를 활용하여 Luma Dream Machine 비디오 프롬프트를 더욱 효과적으로 만드세요.
적절한 슬라이드 순서, 명확한 디자인 규칙, 성과 지표, 그리고 투자자에게 보여줄 수 있는 부록을 포함하여, 간결한 기술 스타트업 투자 유치용 프레젠테이션 자료를 파워포인트로 제작하세요.
Excel에서 코드, ID 및 분수를 날짜로 변환하는 것을 방지하세요. 텍스트 서식, 작은따옴표, 가져오기 컨트롤 및 현재 Microsoft 365 옵션을 사용하세요.
샘플링 작업 감소, 해상도 및 배치 크기 제어, 노드 단순화, 캐싱 사용, VRAM 및 어텐션 안전 조정 등을 통해 ComfyUI SDXL 렌더링 속도를 향상시키세요.
명확한 범주, 수식, 월별 요약 및 세금 신고에 필요한 기록 관리 지침을 포함하는 실용적인 임대 부동산 수입 및 지출 추적 도구를 Excel로 만들어 보세요.
Ollama, AnythingLLM, 로컬 임베딩 및 RAG를 사용하여 로컬 AI 지식 기반을 구축하세요. 4단계 설정, 개인정보 보호 점검, 테스트 및 백업 방법을 알아보세요.
긴 문서 분석에서 컨텍스트 창 오류를 수정하려면 입력값을 다듬고, 파일을 분할하고, 검색 기능을 사용하고, 최종 결과가 출처를 제대로 반영하는지 확인해야 합니다.