516d44081d
- BM25로 데이터 검색 - 유사도 검색 - 질문 + 문서를 보내 질문과 관련 내용만 추출LLMChainExtractor - pdf ocr이 없는 경우 이미지로 변환하여 ocr처리하여 텍스트 인식 - 정규식으로 데이터 정제
730 lines
26 KiB
Plaintext
730 lines
26 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "initial_id",
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": "#### 소비자보호원 서비스집단 분쟁조정 사례집 RAG"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T06:59:17.174441968Z",
|
|
"start_time": "2026-06-01T06:59:17.163725951Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from langchain_ibm import ChatWatsonx\n",
|
|
"from langchain_core.prompts import PromptTemplate, ChatPromptTemplate\n",
|
|
"from langchain_core.output_parsers import StrOutputParser, JsonOutputParser, PydanticOutputParser\n",
|
|
"from dotenv import load_dotenv\n",
|
|
"import os\n",
|
|
"\n",
|
|
"from langchain_community.document_loaders import PyPDFLoader\n",
|
|
"from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
|
|
"from langchain_ibm import WatsonxEmbeddings\n",
|
|
"from langchain_chroma import Chroma\n",
|
|
"\n",
|
|
"from pydantic import BaseModel, Field\n",
|
|
"from langchain_core.runnables import RunnablePassthrough\n",
|
|
"\n",
|
|
"import re\n",
|
|
"from pprint import pprint"
|
|
],
|
|
"id": "89613f4fba03e277",
|
|
"outputs": [],
|
|
"execution_count": 2
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T06:59:53.576580670Z",
|
|
"start_time": "2026-06-01T06:59:53.567626272Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# .env 내용 가져오기\n",
|
|
"load_dotenv()\n",
|
|
"\n",
|
|
"apikey = os.getenv(\"WATSONX_API_KEY\")\n",
|
|
"project_id = os.getenv(\"WATSONX_PROJECT_ID\")\n",
|
|
"watsonx_ai_url = os.getenv(\"WATSONX_URL\")"
|
|
],
|
|
"id": "d17eeb20eda6afa3",
|
|
"outputs": [],
|
|
"execution_count": 3
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:00:17.195193931Z",
|
|
"start_time": "2026-06-01T07:00:12.976471076Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"watson_llm = ChatWatsonx(\n",
|
|
" model_id=\"ibm/granite-4-h-small\",\n",
|
|
" url = f\"{watsonx_ai_url}\",\n",
|
|
" api_key = f\"{apikey}\",\n",
|
|
" project_id=f\"{project_id}\",\n",
|
|
" max_tokens = 2000,\n",
|
|
" params = {\n",
|
|
" \"temperature\":0\n",
|
|
" }\n",
|
|
")\n",
|
|
"\n",
|
|
"watson_embedding = WatsonxEmbeddings(\n",
|
|
" model_id=\"ibm/granite-embedding-278m-multilingual\",\n",
|
|
" url = f\"{watsonx_ai_url}\",\n",
|
|
" api_key = f\"{apikey}\",\n",
|
|
" project_id=f\"{project_id}\"\n",
|
|
")"
|
|
],
|
|
"id": "f132cf54f019bcfa",
|
|
"outputs": [],
|
|
"execution_count": 4
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "### 1. 문서 로드",
|
|
"id": "3f5ffbefabd51421"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:04:30.219884334Z",
|
|
"start_time": "2026-06-01T07:04:25.149502303Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"pdf_path = \"./data/2018 서비스·집단 분쟁조정 사례집.pdf\"\n",
|
|
"\n",
|
|
"# loader 선택 - pdf loader 선택 가능\n",
|
|
"loader = PyPDFLoader(pdf_path)\n",
|
|
"docs = loader.load()\n",
|
|
"len(docs)"
|
|
],
|
|
"id": "30842892e90d6b3f",
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"200"
|
|
]
|
|
},
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"execution_count": 6
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:06:54.314061593Z",
|
|
"start_time": "2026-06-01T07:06:54.303104782Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# page_content / metadata 확인\n",
|
|
"\n",
|
|
"pprint(docs[0].page_content)\n",
|
|
"pprint(docs[0].metadata)"
|
|
],
|
|
"id": "cec836d370caf7b5",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"'소비자분쟁조정위원회\\n2018\\n서비스·집단 \\n분쟁조정 사례집'\n",
|
|
"{'author': 'PC_A2',\n",
|
|
" 'creationdate': '2019-06-05T11:33:24+09:00',\n",
|
|
" 'creator': 'PScript5.dll Version 5.2.2',\n",
|
|
" 'moddate': '2019-06-05T11:58:31+09:00',\n",
|
|
" 'page': 0,\n",
|
|
" 'page_label': '1',\n",
|
|
" 'producer': 'Acrobat Distiller 9.0.0 (Windows)',\n",
|
|
" 'source': './data/2018 서비스·집단 분쟁조정 사례집.pdf',\n",
|
|
" 'title': '<32303139303630355FBCD2BAF1C0DABFF820BBE7B7CAC1FD5BBCADBAF1BDBA5D5FB3BBC1F65FC6EDC1FDBABB76657231312E687770>',\n",
|
|
" 'total_pages': 200}\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 9
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:07:22.227432695Z",
|
|
"start_time": "2026-06-01T07:07:22.209750745Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 첫번째 사건 가져오기\n",
|
|
"pprint(docs[10].page_content)\n",
|
|
"pprint(docs[10].metadata)"
|
|
],
|
|
"id": "1b72feac194a7a49",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"('제1장\\n'\n",
|
|
" '일\\n'\n",
|
|
" '반\\n'\n",
|
|
" '분\\n'\n",
|
|
" '쟁\\n'\n",
|
|
" '조\\n'\n",
|
|
" '정\\n'\n",
|
|
" ' 사\\n'\n",
|
|
" '례 (\\n'\n",
|
|
" '서\\n'\n",
|
|
" '비\\n'\n",
|
|
" '스 )\\n'\n",
|
|
" '제1장 일반분쟁조정 사례(서비스) ● 3\\n'\n",
|
|
" '사\\n'\n",
|
|
" '례 01 사건번호 2018일나565 | 결정일자 2018. 8. 7.\\n'\n",
|
|
" '세탁 후 갑피 마모 및 경화된 가죽 \\n'\n",
|
|
" '운동화에 대한 손해배상 요구\\n'\n",
|
|
" '주 문\\n'\n",
|
|
" '1. 신청인은 2018. 10. 16.까지 피신청인에게 이 사건 제품(제품명 : ○○○○ 가죽 \\n'\n",
|
|
" '운동화, 색상 : 흰색) 1켤레를 반환한다. \\n'\n",
|
|
" '2. 피신청인은 신청인으로부터 제1항 제품을 반환받음과 동시에 신청인에게 71,000원\\n'\n",
|
|
" '을 지급한다.\\n'\n",
|
|
" '이 유\\n'\n",
|
|
" '1. 기초사실\\n'\n",
|
|
" '가. 신청인은 2017. 6. 6. 가죽 운동화(제품명 : ○○○○ 가죽 운동화, 색상 : 흰색, \\n'\n",
|
|
" '이하 ‘이 사건 제품’) 1켤레를 160,200원에 구매하여 착화하였고, 2018. 1. 10. \\n'\n",
|
|
" '피신청인에게 이 사건 제품의 세탁을 의뢰(세탁비 4,000원)하였는데 수령 후 갑피 \\n'\n",
|
|
" '마모 및 경화된 사실(이하 ‘이 사건 현상’)을 확인하여 피신청인이 재세탁을 하였\\n'\n",
|
|
" '으나, 이후에도 경화현상만 다소 개선될 뿐 갑피 마모 현상이 개선되지 않아 피신\\n'\n",
|
|
" '청인에게 손해배상(세탁비 환급 포함)을 요구하였으며, 피신청인은 세탁과실이 없\\n'\n",
|
|
" '다는 이유로 이를 거부하였다.\\n'\n",
|
|
" '나. 한국소비자원 신발제품심의위원회 심의 결과는 다음과 같다.\\n'\n",
|
|
" ' \\n'\n",
|
|
" '신청인이 주장하는 갑피 벗겨짐(스크래치 등) 증상은 관찰되나 현 제품 상태만\\n'\n",
|
|
" '으로는 제품 훼손의 원인이 세탁 과정상 발생한 것인지 착화 환경에 따른 문제\\n'\n",
|
|
" '인지 단정하기 어려운바, 판단 불가하다.')\n",
|
|
"{'author': 'PC_A2',\n",
|
|
" 'creationdate': '2019-06-05T11:33:24+09:00',\n",
|
|
" 'creator': 'PScript5.dll Version 5.2.2',\n",
|
|
" 'moddate': '2019-06-05T11:58:31+09:00',\n",
|
|
" 'page': 10,\n",
|
|
" 'page_label': '11',\n",
|
|
" 'producer': 'Acrobat Distiller 9.0.0 (Windows)',\n",
|
|
" 'source': './data/2018 서비스·집단 분쟁조정 사례집.pdf',\n",
|
|
" 'title': '<32303139303630355FBCD2BAF1C0DABFF820BBE7B7CAC1FD5BBCADBAF1BDBA5D5FB3BBC1F65FC6EDC1FDBABB76657231312E687770>',\n",
|
|
" 'total_pages': 200}\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 10
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### 전처리\n",
|
|
"- 정규식을 이용한 내용 추출"
|
|
],
|
|
"id": "ae4c70c9333416ce"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:16:39.554724455Z",
|
|
"start_time": "2026-06-01T07:16:39.540073666Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"pattern = (r\"사\\n례\\s*\\d+.*사건번호.*결정일자.*\\d{4}\\.\\s?\\d{1,2}\\.\\s?\\d{1,2}\\.\")\n",
|
|
"\n",
|
|
"split_text = re.findall(pattern, \"\".join(docs[10].page_content))\n",
|
|
"split_text"
|
|
],
|
|
"id": "a785b6b9de3621b8",
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"['사\\n례 01 사건번호 2018일나565 | 결정일자 2018. 8. 7.']"
|
|
]
|
|
},
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"execution_count": 12
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:19:05.532627365Z",
|
|
"start_time": "2026-06-01T07:19:05.519326765Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 패턴이 존재한다면 패턴을 기준으로 문서를 분리\n",
|
|
"if split_text:\n",
|
|
" parts = re.split(pattern, \"\".join(docs[10].page_content))\n",
|
|
"\n",
|
|
"parts"
|
|
],
|
|
"id": "c99bf389a324e659",
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"['제1장\\n일\\n반\\n분\\n쟁\\n조\\n정\\n 사\\n례 (\\n서\\n비\\n스 )\\n제1장 일반분쟁조정 사례(서비스) ● 3\\n',\n",
|
|
" '\\n세탁 후 갑피 마모 및 경화된 가죽 \\n운동화에 대한 손해배상 요구\\n주 문\\n1. 신청인은 2018. 10. 16.까지 피신청인에게 이 사건 제품(제품명 : ○○○○ 가죽 \\n운동화, 색상 : 흰색) 1켤레를 반환한다. \\n2. 피신청인은 신청인으로부터 제1항 제품을 반환받음과 동시에 신청인에게 71,000원\\n을 지급한다.\\n이 유\\n1. 기초사실\\n가. 신청인은 2017. 6. 6. 가죽 운동화(제품명 : ○○○○ 가죽 운동화, 색상 : 흰색, \\n이하 ‘이 사건 제품’) 1켤레를 160,200원에 구매하여 착화하였고, 2018. 1. 10. \\n피신청인에게 이 사건 제품의 세탁을 의뢰(세탁비 4,000원)하였는데 수령 후 갑피 \\n마모 및 경화된 사실(이하 ‘이 사건 현상’)을 확인하여 피신청인이 재세탁을 하였\\n으나, 이후에도 경화현상만 다소 개선될 뿐 갑피 마모 현상이 개선되지 않아 피신\\n청인에게 손해배상(세탁비 환급 포함)을 요구하였으며, 피신청인은 세탁과실이 없\\n다는 이유로 이를 거부하였다.\\n나. 한국소비자원 신발제품심의위원회 심의 결과는 다음과 같다.\\n \\n신청인이 주장하는 갑피 벗겨짐(스크래치 등) 증상은 관찰되나 현 제품 상태만\\n으로는 제품 훼손의 원인이 세탁 과정상 발생한 것인지 착화 환경에 따른 문제\\n인지 단정하기 어려운바, 판단 불가하다.']"
|
|
]
|
|
},
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"execution_count": 14
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:22:27.264658276Z",
|
|
"start_time": "2026-06-01T07:22:27.257468833Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# metadata 로 사용할 정보 추출\n",
|
|
"# 사례번호, 사건번호, 결정일자 추출\n",
|
|
"\n",
|
|
"split_text[0]\n",
|
|
"\n",
|
|
"# 사례번호\n",
|
|
"re.findall(r\"례\\s?(\\d+)\\s?사건번호\",split_text[0])[0]\n"
|
|
],
|
|
"id": "ce6951444d08f2b6",
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"'01'"
|
|
]
|
|
},
|
|
"execution_count": 21,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"execution_count": 21
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:52:06.045867563Z",
|
|
"start_time": "2026-06-01T07:52:06.002473096Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 사건번호, 결정일자 추출\n",
|
|
"class CaseMetadata(BaseModel):\n",
|
|
" case_number:str = Field(description=\"사건번호 예 : 2018일나565\")\n",
|
|
" decision_data:str = Field(description=\"결정일자 예 : 2018. 8. 7.\")"
|
|
],
|
|
"id": "3307d7b5484784ad",
|
|
"outputs": [],
|
|
"execution_count": 22
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T07:59:40.356630127Z",
|
|
"start_time": "2026-06-01T07:59:38.540410130Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"metadata_prompt = PromptTemplate.from_template(\n",
|
|
" \"\"\"\\\n",
|
|
"다음은 분쟁 조정 사례에 대한 텍스트입니다.\\n\\n\n",
|
|
"- case_number : 사건번호\n",
|
|
"- decision_data : 결정일자\n",
|
|
"\n",
|
|
"반드시 Json 으로만 반환하세요\n",
|
|
"{case_text}\n",
|
|
" \"\"\"\n",
|
|
")\n",
|
|
"\n",
|
|
"structed_llm = watson_llm.with_structured_output(CaseMetadata)\n",
|
|
"\n",
|
|
"chain = metadata_prompt | structed_llm\n",
|
|
"\n",
|
|
"case_metadata = chain.invoke({\"case_text\":split_text[0]})\n",
|
|
"print(case_metadata)\n",
|
|
"print(dict(case_metadata))"
|
|
],
|
|
"id": "4e881737f5b80b60",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"case_number='2018일나565' decision_data='2018. 8. 7.'\n",
|
|
"{'case_number': '2018일나565', 'decision_data': '2018. 8. 7.'}\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 24
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "#### page_content 내용 추출",
|
|
"id": "12f8b3079b5aaa19"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T08:04:16.872277043Z",
|
|
"start_time": "2026-06-01T08:04:16.863977311Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 주 문 ~~~~\n",
|
|
"parts[1]\n",
|
|
"\n",
|
|
"# 주 문 위치 찾기\n",
|
|
"re.search(r\"주 문\\n\",parts[1]).span()\n",
|
|
"\n",
|
|
"# 제목 추출\n",
|
|
"title = parts[1][:re.search(r\"주 문\\n\",parts[1]).span()[0]].strip()\n",
|
|
"# 내용 추출\n",
|
|
"content = parts[1][re.search(r\"주 문\\n\",parts[1]).span()[0]:].strip()"
|
|
],
|
|
"id": "9f78f350f0583c6b",
|
|
"outputs": [],
|
|
"execution_count": 40
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T08:06:05.158453784Z",
|
|
"start_time": "2026-06-01T08:06:05.144784923Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"pprint(title)\n",
|
|
"pprint(content)"
|
|
],
|
|
"id": "b460a6f62007935a",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"'세탁 후 갑피 마모 및 경화된 가죽 \\n운동화에 대한 손해배상 요구'\n",
|
|
"('주 문\\n'\n",
|
|
" '1. 신청인은 2018. 10. 16.까지 피신청인에게 이 사건 제품(제품명 : ○○○○ 가죽 \\n'\n",
|
|
" '운동화, 색상 : 흰색) 1켤레를 반환한다. \\n'\n",
|
|
" '2. 피신청인은 신청인으로부터 제1항 제품을 반환받음과 동시에 신청인에게 71,000원\\n'\n",
|
|
" '을 지급한다.\\n'\n",
|
|
" '이 유\\n'\n",
|
|
" '1. 기초사실\\n'\n",
|
|
" '가. 신청인은 2017. 6. 6. 가죽 운동화(제품명 : ○○○○ 가죽 운동화, 색상 : 흰색, \\n'\n",
|
|
" '이하 ‘이 사건 제품’) 1켤레를 160,200원에 구매하여 착화하였고, 2018. 1. 10. \\n'\n",
|
|
" '피신청인에게 이 사건 제품의 세탁을 의뢰(세탁비 4,000원)하였는데 수령 후 갑피 \\n'\n",
|
|
" '마모 및 경화된 사실(이하 ‘이 사건 현상’)을 확인하여 피신청인이 재세탁을 하였\\n'\n",
|
|
" '으나, 이후에도 경화현상만 다소 개선될 뿐 갑피 마모 현상이 개선되지 않아 피신\\n'\n",
|
|
" '청인에게 손해배상(세탁비 환급 포함)을 요구하였으며, 피신청인은 세탁과실이 없\\n'\n",
|
|
" '다는 이유로 이를 거부하였다.\\n'\n",
|
|
" '나. 한국소비자원 신발제품심의위원회 심의 결과는 다음과 같다.\\n'\n",
|
|
" ' \\n'\n",
|
|
" '신청인이 주장하는 갑피 벗겨짐(스크래치 등) 증상은 관찰되나 현 제품 상태만\\n'\n",
|
|
" '으로는 제품 훼손의 원인이 세탁 과정상 발생한 것인지 착화 환경에 따른 문제\\n'\n",
|
|
" '인지 단정하기 어려운바, 판단 불가하다.')\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 42
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T08:43:23.992589505Z",
|
|
"start_time": "2026-06-01T08:43:23.973999681Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 사례번호, 사건번호, 결정일자, 제목은 metadata로 추가\n",
|
|
"# 내용은 page_content update\n",
|
|
"\n",
|
|
"pdf_docs = []\n",
|
|
"case_metadata = {}\n",
|
|
"\n",
|
|
"# 사건이 시작되는 페이지 ~ 마지막에서 -2 페이지까지 반복\n",
|
|
"for doc in docs[10:-2]:\n",
|
|
"\n",
|
|
" split_text = re.findall(pattern, \"\".join(doc.page_content))\n",
|
|
"\n",
|
|
" if split_text:\n",
|
|
" # 사례번호 추출\n",
|
|
" case_metadata[\"case_id\"] = re.findall(r\"례\\s?(\\d+)\\s?사건번호\",split_text[0])[0]\n",
|
|
"\n",
|
|
" # 패턴 기준으로 텍스트 분할\n",
|
|
" parts = re.split(pattern, \"\".join(doc.page_content))\n",
|
|
"\n",
|
|
" if re.search(r\"주 문\\n\",parts[1]):\n",
|
|
" # 제목 추출\n",
|
|
" case_metadata[\"title\"] = parts[1][:re.search(r\"주 문\\n\",parts[1]).span()[0]].replace(\"\\n\",\"\").strip()\n",
|
|
" # 내용 추출 후 기존 내용 업데이트\n",
|
|
" doc.page_content = parts[1][re.search(r\"주 문\\n\",parts[1]).span()[0]:].strip()\n",
|
|
" else:\n",
|
|
" case_metadata[\"title\"] = \"\"\n",
|
|
"\n",
|
|
" i = 0\n",
|
|
" while i < 10:\n",
|
|
" try:\n",
|
|
" # 사건번호, 결정일자 추출\n",
|
|
" response = chain.invoke({\"case_text\":split_text[0]})\n",
|
|
" for k, v in dict(response).items():\n",
|
|
" case_metadata[k] = v.replace(\"\\n\",\"\").replace(\" \",\"\")\n",
|
|
" break\n",
|
|
"\n",
|
|
" except:\n",
|
|
" i += 1\n",
|
|
" continue\n",
|
|
"\n",
|
|
" doc.metadata.update(case_metadata)\n",
|
|
"\n",
|
|
" pdf_docs.append(doc)\n",
|
|
" else:\n",
|
|
" doc.metadata.update(case_metadata)\n",
|
|
" pdf_docs.append(doc)\n",
|
|
"\n",
|
|
"len(pdf_docs)\n"
|
|
],
|
|
"id": "373a5284a8b88e6b",
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"188"
|
|
]
|
|
},
|
|
"execution_count": 68,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"execution_count": 68
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T08:43:27.932428458Z",
|
|
"start_time": "2026-06-01T08:43:27.925707032Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"pdf_docs[10].metadata\n",
|
|
"pprint(pdf_docs[9].page_content)"
|
|
],
|
|
"id": "66a5877582de43f3",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"('주 문\\n'\n",
|
|
" '신청인과 피신청인 사이의 이 사건 분쟁조정 신청에 대하여는 조정하지 아니한다.\\n'\n",
|
|
" '이 유\\n'\n",
|
|
" '1. 기초사실\\n'\n",
|
|
" '신청인은 피신청인의 인천-도쿄 왕복항공권 4매(탑승객 : 이○○, 오○○, 이 ∆∆, 이\\n'\n",
|
|
" '□□, 2017. 12. 18. 10:10 ○○703편 인천 출발, 2017. 12. 21. 17:00 ○○002 편 \\n'\n",
|
|
" '도쿄 출발)를 628,200원에 구입하였고, 2018. 12. 18. 10:10 출발 예정이던 출국 항\\n'\n",
|
|
" '공편(이하 ‘이 사건 항공편’이라고 함)이 기상악화로 인하여 지연되어 도착예정시간 \\n'\n",
|
|
" '12:30보다 4시간 10분 지연된 16:40 도쿄에 도착하였다.\\n'\n",
|
|
" '2 . 판 단\\n'\n",
|
|
" '신청인은 이 사건 항공편이 4시간 이상 지연되었고, 이 사건 항공편보다 늦게 출발이 \\n'\n",
|
|
" '예정되어 있는 항공기(오사카, 나고야행 등)가 먼저 출발하는 것을 확인하였으며, 기상\\n'\n",
|
|
" '상황으로 인한 연결편 연착에 따른 지연이라는 피신청인의 주장을 납득할 수 없는바, \\n'\n",
|
|
" '관련 법률에 따른 손해배상을 요구한다.\\n'\n",
|
|
" '이에 대하여 피신청인은 이 사건 항공편 운송지연의 원인이 당시 인천공항에 강설로 \\n'\n",
|
|
" '인한 극심한 혼잡과 제빙작업에 의한 것으로, 이는 기상상황으로 인한 지연에 해당하\\n'\n",
|
|
" '여 「소비자분쟁해결기준」상 손해배상 사유에서 제외되는바, 신청인의 요구를 수용할 \\n'\n",
|
|
" '수 없다고 주장한다.')\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 69
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "#### 2. 분할",
|
|
"id": "824f2e5d6e5c66e9"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T08:46:16.624643520Z",
|
|
"start_time": "2026-06-01T08:46:16.607920862Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 500 / 50\n",
|
|
"\n",
|
|
"splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)\n",
|
|
"splite_docs = splitter.split_documents(docs)\n",
|
|
"\n",
|
|
"print(splite_docs[0].page_content)"
|
|
],
|
|
"id": "baa5c4785395d7cb",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"소비자분쟁조정위원회\n",
|
|
"2018\n",
|
|
"서비스·집단 \n",
|
|
"분쟁조정 사례집\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 74
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T08:47:24.940997646Z",
|
|
"start_time": "2026-06-01T08:47:24.928360960Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": "print(splite_docs[1].page_content)",
|
|
"id": "b398473d9c9a0655",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2018 분쟁조정 사례집\n",
|
|
"소비자 관련 분쟁은 소액이라는 특징 때문에 법원의 소송으로 해결하기 어려운 면이 있습니다. 이러한 점 때문에 \n",
|
|
"소송 외 분쟁해결기구로서 설립된 소비자분쟁조정위원회는 원만한 합의가 이루어지지 않은 소비자와 사업자에게 \n",
|
|
"객관적이고 공정한 조정안을 제시함으로써 분쟁이 합리적이고 원활히 해결될 수 있도록 노력하고 있습니다.\n",
|
|
"소비자기본법에 근거하여 1987년 설립된 소비자분쟁조정위원회는 설립 첫 해 20건의 사건 조정을 시작으로, 2004년 \n",
|
|
"이후부터는 매년 1,000건이 넘는 사건을 조정하였으며, 2018년에는 3,080여건을 처리하는 등 그 역할을 충실히 \n",
|
|
"수행하고 있습니다.\n",
|
|
"특히, 분쟁조정 사건을 신속하고 공정하게 처리하기 위해 2017년에는 소비자기본법 개정을 통해 조정위원을 50명\n",
|
|
"에서 150명으로 확대하는 등 관련 법·제도 개선으로 소비자권익증진에 기여하고 있습니다.\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 76
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-01T08:51:45.142963478Z",
|
|
"start_time": "2026-06-01T08:51:45.132501776Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 마침표 뒤에 나오는 줄바꿈 문자는 그대로 두고 나머지 줄바꿈 문자만 제거\n",
|
|
"pprint(splite_docs[18].page_content)\n",
|
|
"\n",
|
|
"text = splite_docs[18].page_content\n",
|
|
"text = re.sub(r'(?<!\\.)\\n', '', text)\n",
|
|
"pprint(text)"
|
|
],
|
|
"id": "cd3eee4ca0b60fe4",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"('주 문\\n'\n",
|
|
" '1. 신청인은 2018. 10. 16.까지 피신청인에게 이 사건 제품(제품명 : ○○○○ 가죽 \\n'\n",
|
|
" '운동화, 색상 : 흰색) 1켤레를 반환한다. \\n'\n",
|
|
" '2. 피신청인은 신청인으로부터 제1항 제품을 반환받음과 동시에 신청인에게 71,000원\\n'\n",
|
|
" '을 지급한다.\\n'\n",
|
|
" '이 유\\n'\n",
|
|
" '1. 기초사실\\n'\n",
|
|
" '가. 신청인은 2017. 6. 6. 가죽 운동화(제품명 : ○○○○ 가죽 운동화, 색상 : 흰색, \\n'\n",
|
|
" '이하 ‘이 사건 제품’) 1켤레를 160,200원에 구매하여 착화하였고, 2018. 1. 10. \\n'\n",
|
|
" '피신청인에게 이 사건 제품의 세탁을 의뢰(세탁비 4,000원)하였는데 수령 후 갑피 \\n'\n",
|
|
" '마모 및 경화된 사실(이하 ‘이 사건 현상’)을 확인하여 피신청인이 재세탁을 하였\\n'\n",
|
|
" '으나, 이후에도 경화현상만 다소 개선될 뿐 갑피 마모 현상이 개선되지 않아 피신\\n'\n",
|
|
" '청인에게 손해배상(세탁비 환급 포함)을 요구하였으며, 피신청인은 세탁과실이 없\\n'\n",
|
|
" '다는 이유로 이를 거부하였다.\\n'\n",
|
|
" '나. 한국소비자원 신발제품심의위원회 심의 결과는 다음과 같다.')\n",
|
|
"('주 문1. 신청인은 2018. 10. 16.까지 피신청인에게 이 사건 제품(제품명 : ○○○○ 가죽 운동화, 색상 : 흰색) 1켤레를 '\n",
|
|
" '반환한다. 2. 피신청인은 신청인으로부터 제1항 제품을 반환받음과 동시에 신청인에게 71,000원을 지급한다.\\n'\n",
|
|
" '이 유1. 기초사실가. 신청인은 2017. 6. 6. 가죽 운동화(제품명 : ○○○○ 가죽 운동화, 색상 : 흰색, 이하 ‘이 사건 '\n",
|
|
" '제품’) 1켤레를 160,200원에 구매하여 착화하였고, 2018. 1. 10. 피신청인에게 이 사건 제품의 세탁을 의뢰(세탁비 '\n",
|
|
" '4,000원)하였는데 수령 후 갑피 마모 및 경화된 사실(이하 ‘이 사건 현상’)을 확인하여 피신청인이 재세탁을 하였으나, 이후에도 '\n",
|
|
" '경화현상만 다소 개선될 뿐 갑피 마모 현상이 개선되지 않아 피신청인에게 손해배상(세탁비 환급 포함)을 요구하였으며, 피신청인은 세탁과실이 '\n",
|
|
" '없다는 이유로 이를 거부하였다.\\n'\n",
|
|
" '나. 한국소비자원 신발제품심의위원회 심의 결과는 다음과 같다.')\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 85
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "code",
|
|
"outputs": [],
|
|
"execution_count": null,
|
|
"source": "",
|
|
"id": "dc310d37f63d8776"
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 2
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython2",
|
|
"version": "2.7.6"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|