대규모 기업 공시 문서에서 지속가능성 리스크 문단 정밀 추출
금융 분석가, ESG 전문가 또는 투자 연구원이라면 매년 수백 건의 상장사 공시 보고서를 검토해야 하는 부담을 경험했을 것이다. 한 문서만 해도 수백 페이지에 달하며, 핵심 정보는 단편적인 문단에 숨겨져 있다. 전통적인 키워드 검색은 "환경 위험"이라는 표현이 없으면 관련 내용을 놓치기 쉽다.
이제는 이 문제를 해결할 수 있는 실용적 접근 방식이 존재한다. Qwen3-Reranker라는 의미 기반 재정렬 모델을 활용해, 긴 보고서 내에서 "환경·사회·지배구조(ESG) 위험"과 관련된 문장을 정교하게 식별하고, 관련성 순으로 정렬하는 시스템을 구축할 수 있다.
이 시스템은 단순한 텍스트 매칭이 아니라, 실제 의미를 이해한다. 예를 들어, "탄소 배출 초과로 인한 행정 제재 가능성"이나 "노동 분쟁이 회사 명성에 미칠 수 있는 영향", "이사회 구성의 취약점" 등이 명시적으로 "ESG"라는 단어를 사용하지 않아도, 해당 위험 요소로 판단된다.
본 글에서는 이 기술을 실제로 적용하는 과정을 단계별로 설명한다. 환경 설정, 문서 전처리, 코드 구현, 결과 시각화까지 포함하며, 기술적 깊이와 실용성을 모두 갖춘 사례를 소개한다.
1. 핵심 도구: Qwen3-Reranker의 작동 원리
Qwen3-Reranker는 대화형 생성 모델과는 다르게, 주어진 질문과 후보 문서 사이의 관련성을 평가하고 정렬하는 전용 도구이다. 이를 비유하자면, 각 문서를 직접 읽고 평가하는 전문 리뷰어라고 할 수 있다.
기존의 벡터 기반 검색은 질의와 문서를 별도로 임베딩한 후 유사도를 계산하는 방식이며, 두 항목 간의 깊은 상호작용이 불가능하다. 반면, Cross-Encoder 구조를 채택한 Qwen3-Reranker는 질의와 문서를 하나의 입력으로 결합하여, 양쪽의 의미적 관계를 종합적으로 분석한다.
예를 들어:
- 벡터 검색: "지원금"과 "재정 지원" 같은 키워드가 일치하는지 확인 → 용어 일치 여부 중심
- Cross-Encoder: "정부가 제공하는 재정 지원 프로그램에 참여할 수 있는 조건은?"과 "지원금 신청 절차가 복잡하다"를 함께 고려 → 맥락 이해 기반 평가
따라서 실제 검색 시스템에서는 먼저 벡터 검색으로 후보 문서를 확보한 후, 최종 결과를 정교하게 재정렬하기 위해 이 모델을 사용하는 것이 일반적이다.
2. 구현: 기업 공시 보고서에서 리스크 문단 추출
2.1 환경 준비 및 모델 실행
이 작업에는 Qwen3-Reranker 0.6B 버전을 사용하며, 하드웨어 요구사항이 낮아 CPU에서도 동작 가능하다. 대부분의 클라우드 플랫폼에서는 간단한 스크립트로 시작할 수 있다.
bash /root/build/start.sh
실행 후 `http://localhost:8080` 에 접속하면 다음과 같은 인터페이스를 확인할 수 있다:
- 질의 입력란: "ESG 위험"과 같이 검색어 입력
- 문서 입력란: 각 줄이 하나의 문단으로 처리됨
- 실행 버튼: 재정렬 시작
- 결과 출력: 관련성 점수 기준 정렬된 문단 표시
2.2 PDF 문서 전처리
PDF 형식의 보고서는 직접 처리할 수 없으므로, 텍스트로 변환하고 적절한 크기로 분할해야 한다.
import PyPDF2
import re
def extract_text_from_pdf(pdf_path):
text = ""
with open(pdf_path, 'rb') as file:
reader = PyPDF2.PdfReader(file)
for page in reader.pages:
text += page.extract_text() + "\n"
return text
def split_into_chunks(full_text, chunk_size=200):
sentences = re.split(r'(?<=[.!?])', full_text)
chunks = []
current_chunk = ""
for sentence in sentences:
if len(current_chunk) + len(sentence) <= chunk_size:
current_chunk += sentence
else:
if current_chunk:
chunks.append(current_chunk.strip())
current_chunk = sentence
if current_chunk:
chunks.append(current_chunk.strip())
# 중복 제거
unique_chunks = list(dict.fromkeys(chunks))
return unique_chunks
# 사용 예시
# raw_text = extract_text_from_pdf("company_2023_annual_report.pdf")
# passages = split_into_chunks(raw_text, chunk_size=200)
2.3 의미 기반 재정렬 로직 구현
웹 인터페이스와 동일한 기능을 코드로 구현할 수 있다. 아래는 기본적인 호출 로직 예시이다.
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
import numpy as np
class ESGReranker:
def __init__(self, model_name="qwen/Qwen3-Reranker-0.6B"):
print(f"모델 로드 중: {model_name}...")
self.tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
self.model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True, torch_dtype=torch.float16)
self.model.eval()
if torch.cuda.is_available():
self.model.cuda()
print("GPU 사용 가능")
else:
print("CPU에서 실행 (느림)")
def rank(self, query, candidates):
scores = []
for doc in candidates:
prompt = f"질의: {query}\n문서: {doc}"
inputs = self.tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512)
if torch.cuda.is_available():
inputs = {k: v.cuda() for k, v in inputs.items()}
with torch.no_grad():
outputs = self.model(**inputs)
logits = outputs.logits[:, -1, :]
score = logits[0, 0].item() # 예시: 첫 번째 토큰 점수 사용
scores.append(score)
ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
return ranked
# 사용 예시
if __name__ == "__main__":
reranker = ESGReranker()
query = "환경·사회·지배구조 위험"
docs = [
"회사는 지난해 환경 오염 사고 없이 운영했다.",
"이사회는 전략위원회, 감사위원회, 보상위원회 등을 운영 중이다.",
"글로벌 기후 정책 강화로 인해 고에너지 소비 생산라인이 전환 부담과 탄소세 증가 위험을 안고 있다.",
"직원 복지 향상을 위해 연간 만족도 조사에서 점수 상승을 기록했다.",
"데이터 보안 및 개인정보 보호 리스크에 대응해 정보 보안 시스템을 업그레이드했다."
]
results = reranker.rank(query, docs)
print("\n===== 상위 5개 결과 =====")
for i, (text, score) in enumerate(results, 1):
print(f"{i}. [점수: {score:.4f}] {text[:80]}...")
3. 결과 시각화 및 분석
실제 공시 보고서에서 추출한 10개 문단을 기준으로 검색을 수행한 결과를 살펴보자.
| 순위 | 점수 | 내용 요약 |
|---|---|---|
| 1 | 0.91 | 공급망 일부에서 탄소 배출 데이터 수집 불완전성이 있어 전체 탄소 발자국 산정에 영향을 줄 수 있음 |
| 2 | 0.87 | 국제 개인정보 보호 규정 준수에 대한 도전이 커지고 있으며, 준수 비용 증가 가능성 있음 |
| 3 | 0.84 | 극단적인 기상 현상이 해안 지역 물류 센터 운영에 물리적 위협을 줄 수 있음 |
| 4 | 0.42 | 동남아시아에 신규 공장 건설 완료, 환경 영향 평가 통과 |
| 5 | 0.29 | 이사회 구성원 7명 중 외부 이사 3명 |
분석:
- 상위 3위는 모두 환경 리스크와 지배구조 리스크에 해당하는 문장으로, 의미 기반 이해를 통해 정확히 식별됨.
- "환경 영향 평가 통과"라는 긍정적 문장은 환경 주제와 관련되어 있으므로 낮은 점수지만 상위권에 포함됨 → 의미 넓이 인식 능력 입증.
- 연구 개발, 시장 점유율, 우수 직장 인정 등은 관련성이 낮아 자연스럽게 하위에 배치됨.
4. 결론: 전문 문서 분석의 새로운 패러다임
이 시스템은 단순한 검색 도구를 넘어, 분석가의 사고 방식을 모방하는 지능형 도구로 진화한다. 그 가치는 다음과 같다:
- 시간 절약: 수 시간 소요되는 문서 스캔을 몇 분 내에 완료.
- 정확도 향상: 키워드 누락을 방지하고, 암시적 리스크도 포착.
- 확장성: ESG 외에도 재무 리스크, 법적 분쟁, 기술 혁신 등 다양한 주제에 적용 가능.
- 접근성: GUI 인터페이스와 오픈소스 모델 덕분에 비개발자도 쉽게 활용 가능.
단, 문서의 품질(출력 정확도, 문단 분할 기준)에 따라 성능이 좌우되며, 특수 용어나 복잡한 기술적 표현에는 추가 튜닝이 필요할 수 있다. 그러나 대부분의 금융 및 경영 문서 분석 시나리오에서는 이미 매우 효과적인 솔루션으로 자리 잡고 있다.