File size: 14,570 Bytes
a1514be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle, os, numpy as np\n",
    "from tqdm import tqdm\n",
    "from langchain.schema import Document\n",
    "from langchain.vectorstores import FAISS\n",
    "from langchain.schema import Document\n",
    "from langchain_community.embeddings import HuggingFaceBgeEmbeddings\n",
    "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
    "from langchain_community.retrievers import BM25Retriever\n",
    "from langchain.retrievers import EnsembleRetriever"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "데이터 λ‘œλ“œ 쀑...\n",
      "총 2736개의 λ°°μΉ˜κ°€ λ‘œλ“œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.\n"
     ]
    }
   ],
   "source": [
    "os.environ[\"TOKENIZERS_PARALLELISM\"] = \"false\"\n",
    "\n",
    "# cases.pkl νŒŒμΌμ—μ„œ 데이터 λ‘œλ“œ\n",
    "print(\"데이터 λ‘œλ“œ 쀑...\")\n",
    "with open(\"/Users/anpigon/Documents/Embed/ᄇα…₯ᆸ원ᄑᅑᆫ례/Result2.pkl\", \"rb\") as file:\n",
    "    data = pickle.load(file)\n",
    "\n",
    "print(f\"총 {len(data)}개의 λ°°μΉ˜κ°€ λ‘œλ“œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# μž„λ² λ”© λͺ¨λΈ μ„€μ • (μ‹€μ œλ‘œ μž„λ² λ”©ν•˜μ§€λŠ” μ•ŠμŒ)\n",
    "embeddings = HuggingFaceBgeEmbeddings(model_name=\"BAAI/bge-m3\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ν…μŠ€νŠΈ λΆ„ν• κΈ° μ„€μ •\n",
    "text_splitter = RecursiveCharacterTextSplitter(\n",
    "    chunk_size=2000,\n",
    "    chunk_overlap=200,\n",
    "    length_function=len,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "λ¬Έμ„œ 처리 및 μ²­ν‚Ή 쀑...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 2736/2736 [00:42<00:00, 64.15it/s] \n"
     ]
    }
   ],
   "source": [
    "# λ¬Έμ„œ 처리 및 μ²­ν‚Ή\n",
    "print(\"λ¬Έμ„œ 처리 및 μ²­ν‚Ή 쀑...\")\n",
    "documents = []\n",
    "text_embedding_pairs = []\n",
    "\n",
    "for batch in tqdm(data):\n",
    "    original_sentences = batch[1]  # λ°°μΉ˜λ‹Ή 32개의 원본 λ¬Έμž₯\n",
    "    embedding_vectors = batch[0]  # λ°°μΉ˜λ‹Ή 32개의 μž„λ² λ”© 벑터\n",
    "\n",
    "    for sentence, vector in zip(original_sentences, embedding_vectors):\n",
    "        chunks = text_splitter.split_text(sentence)\n",
    "        for chunk in chunks:\n",
    "            doc = Document(page_content=chunk)\n",
    "            documents.append(doc)\n",
    "            text_embedding_pairs.append((chunk, vector))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FAISS 인덱슀 뢈러였기\n",
      "FAISS 인덱슀 뢈러였기 μ™„λ£Œ\n"
     ]
    }
   ],
   "source": [
    "# FAISS 인덱슀 생성\n",
    "print(\"FAISS 인덱슀 뢈러였기\")\n",
    "FAISS_DB_INDEX = \"./index_faiss\"\n",
    "faiss_db = FAISS.load_local(\n",
    "    FAISS_DB_INDEX, embeddings, allow_dangerous_deserialization=True\n",
    ")\n",
    "faiss_retriever = faiss_db.as_retriever(search_type=\"mmr\", search_kwargs={\"k\": 10})\n",
    "print(\"FAISS 인덱슀 뢈러였기 μ™„λ£Œ\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "BM25Retriever 뢈러였기\n",
      "BM25 λ¦¬νŠΈλ¦¬λ²„ 뢈러였기 μ™„λ£Œ\n"
     ]
    }
   ],
   "source": [
    "from kiwipiepy import Kiwi\n",
    "from typing import List\n",
    "\n",
    "kiwi = Kiwi()\n",
    "\n",
    "\n",
    "def kiwi_tokenize(text):\n",
    "    return [token.form for token in kiwi.tokenize(text)]\n",
    "\n",
    "\n",
    "print(\"BM25Retriever 뢈러였기\")\n",
    "# bm25_retriever = BM25Retriever.from_documents(documents, k=10)\n",
    "with open(\"./index_bm25/kiwi.pkl\", \"rb\") as f:\n",
    "    bm25_retriever = pickle.load(f)\n",
    "print(\"BM25 λ¦¬νŠΈλ¦¬λ²„ 뢈러였기 μ™„λ£Œ\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "ensemble_retriever = EnsembleRetriever(\n",
    "    retrievers=[bm25_retriever, faiss_retriever], weights=[0.7, 0.3], search_type=\"mmr\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "from operator import itemgetter\n",
    "from langchain.callbacks.base import BaseCallbackHandler\n",
    "from langchain_core.prompts import (\n",
    "    HumanMessagePromptTemplate,\n",
    "    SystemMessagePromptTemplate,\n",
    ")\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_anthropic import ChatAnthropic\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_community.chat_message_histories import ChatMessageHistory\n",
    "from langchain.schema import HumanMessage, AIMessage, SystemMessage\n",
    "from langchain.schema.runnable import RunnablePassthrough\n",
    "from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "\n",
    "\n",
    "class StreamCallback(BaseCallbackHandler):\n",
    "    def on_llm_new_token(self, token: str, **kwargs):\n",
    "        print(token, end=\"\", flush=True)\n",
    "\n",
    "\n",
    "# ν”„λ‘¬ν”„νŠΈ ν…œν”Œλ¦Ώ μ„€μ •\n",
    "prompt_template = \"\"\"\n",
    "당신은 νŒμ‚¬μ΄μž 20λ…„μ°¨ 법λ₯  μ „λ¬Έκ°€μž…λ‹ˆλ‹€. μ£Όμ–΄μ§„ μ§ˆλ¬Έμ— λŒ€ν•΄ λ¬Έμ„œμ˜ 정보λ₯Ό μ΅œλŒ€ν•œ ν™œμš©ν•˜μ—¬ λ‹΅λ³€ν•˜μ„Έμš”.\n",
    "μ§ˆλ¬ΈμžλŠ” 자기 상황을 μ„€λͺ…ν•  것이며, 질문자의 상황과 λΉ„μŠ·ν•œ νŒλ‘€λ₯Ό μ„€λͺ…ν•΄μ€˜μ•Ό ν•˜λ©°, κ°€μž₯ 졜근 사건 순으둜 μ†Œκ°œλžλ‹ˆλ‹€.\n",
    "μ΅œλŒ€ν•œ μžμ„Έν•˜κ²Œ λ‹΅λ³€ν•©λ‹ˆλ‹€. μ΄ˆλ“±ν•™μƒμ΄ 이해할 μ •λ„λ‘œ μ΄ν•΄ν•˜κΈ° 쉽도둝 λ‹΅λ³€ν•˜κ³ , ν•œκΈ€λ‘œ μž‘μ„±ν•˜μ„Έμš”.\n",
    "μ§ˆλ¬Έμ— λŒ€νžŒ λ‹΅λ³€ 사, [사건λͺ… 1]..., [사건λͺ… 2]... μˆœμ„œλ‘œ μ„€λͺ…ν•΄μ•Ό ν•©λ‹ˆλ‹€.\n",
    "λ¬Έμ„œμ—μ„œ 닡변을 찾을 수 μ—†λŠ” 경우, \"λ¬Έμ„œμ— 닡변이 μ—†μŠ΅λ‹ˆλ‹€.\"라고 λ‹΅λ³€ν•˜μ„Έμš”.\n",
    "λ‹΅λ³€μ˜ 좜처(source)λ₯Ό λ°˜λ“œμ‹œ ν‘œκΈ°ν•΄μ£Όμ„Έμš”. μΆœμ²˜λŠ” λ©”νƒ€λ°μ΄ν„°μ˜ νŒλ‘€μΌλ ¨λ²ˆν˜Έ, 사건λͺ…, μ‚¬κ±΄λ²ˆν˜Έ 순으둜 ν‘œκΈ° ν•©λ‹ˆλ‹€.\n",
    "\n",
    "# μ£Όμ–΄μ§„ λ¬Έμ„œ:\n",
    "{context}\n",
    "\n",
    "# 질문: {question}\n",
    "\n",
    "# λ‹΅λ³€:\n",
    "\n",
    "# 좜처:\n",
    "- source1\n",
    "- source2\n",
    "- ...\n",
    "\"\"\"\n",
    "\n",
    "# LLM 및 좜λ ₯ νŒŒμ„œ μ„€μ •\n",
    "llm = ChatOpenAI(\n",
    "    model=\"gpt-4o\",\n",
    "    temperature=0,\n",
    "    streaming=True,\n",
    "    verbose=True,\n",
    "    callbacks=[StreamCallback()],\n",
    ")\n",
    "# llm = ChatAnthropic(model=\"claude-3-5-sonnet-20240620\", temperature=0, streaming=True, callbacks=[StreamCallback()])\n",
    "\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "# μ±„νŒ… 기둝을 μ €μž₯ν•  λ©”λͺ¨λ¦¬ μ΄ˆκΈ°ν™”\n",
    "chat_history = ChatMessageHistory()\n",
    "\n",
    "# ν”„λ‘¬ν”„νŠΈ μ„€μ •\n",
    "prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"system\", prompt_template),\n",
    "        MessagesPlaceholder(variable_name=\"history\"),\n",
    "        (\"human\", \"{question}\"),\n",
    "    ]\n",
    ").partial(history=chat_history.messages)\n",
    "\n",
    "# Runnable 객체 생성\n",
    "runnable = RunnablePassthrough.assign(\n",
    "    context=itemgetter(\"question\") | ensemble_retriever,\n",
    ")\n",
    "# LCEL 체인 ꡬ성\n",
    "chain = runnable | prompt | llm | output_parser\n",
    "\n",
    "\n",
    "def rag_chain(question):\n",
    "    response = chain.invoke({\"question\": question})\n",
    "    chat_history.add_user_message(question)\n",
    "    chat_history.add_ai_message(response)\n",
    "    return response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "μ•ˆλ…•ν•˜μ„Έμš”. νŒμ‚¬λ‹˜μž…λ‹ˆλ‹€. μ§ˆλ¬Έν•˜μ‹  상황과 λΉ„μŠ·ν•œ νŒλ‘€λ₯Ό μ°Ύμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€. μ•„λž˜μ— 두 κ°€μ§€ 사둀λ₯Ό μ†Œκ°œν•΄λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.\n",
      "\n",
      "### [사건λͺ… 1] λΆˆκ³΅μ •ν•œ 법λ₯ ν–‰μœ„에 κ΄€ν•œ 법리λ₯Ό μ˜€ν•΄ν•œ μœ„λ²•μ΄ μžˆλŠ” μ‹€λ‘€\n",
      "- **좜처**: 214987, 손해배상등, 68λ‹€88, 1968.07.30\n",
      "- **사건 λ‚΄μš©**: 맀도인이 뢀동산을 맀도할 λ‹Ήμ‹œ, 맀수인이 λ§€λ„μΈμ˜ κΆλ°•ν•œ 사정을 μ•Œκ³  μžˆμ—ˆκ³ , 맀도인이 νŒ”κΈ°λ₯Ό κΊΌλ €ν•˜λŠ” λΆ€λΆ„κΉŒμ§€ 맀수인의 μš”κ΅¬μ— μ˜ν•΄ ν•¨κ»˜ νŒ”μ§€ μ•Šμ„ 수 μ—†μ—ˆμŠ΅λ‹ˆλ‹€. λ§€λ§€λͺ©μ λ¬Όμ˜ κ²½κ³„ν™•μ •μΈ‘λŸ‰λ„ 맀수인이 일방적으둜 ν•˜κ³ , 뢀동산 가격도 맀우 μ €λ ΄ν•˜κ²Œ μ±…μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 μ‚¬κ±΄μ—μ„œ 법원은 μ΄λŸ¬ν•œ λ§€λ§€ν–‰μœ„κ°€ λΆˆκ³΅μ •ν•œ 법λ₯ ν–‰μœ„에 ν•΄λ‹Ήν•œλ‹€κ³  νŒλ‹¨ν•˜μ˜€μŠ΅λ‹ˆλ‹€.\n",
      "\n",
      "### [사건λͺ… 2] μ›κ³ μ˜ μ£Όμž₯이 착였둜 μΈν•œ μ˜μ‚¬ν‘œμ‹œμ˜ μ·¨μ†Œλ‘œλ„ λ³΄μ—¬μ§€λ―€λ‘œ, 이λ₯Ό 석λͺ…μΉ˜ μ•Šμ€ μœ„λ²•μ΄ μžˆλŠ” 예\n",
      "- **좜처**: 153300, λ§€λ§€λŒ€κΈˆλ°˜ν™˜λ“±, 66λ‹€1289, 1966.09.20\n",
      "- **사건 λ‚΄μš©**: 원고가 ν”Όκ³ λ‘œλΆ€ν„° λ§€μˆ˜ν•œ λ…Ό 1,389평 쀑 μΌλΆ€λŠ” ν•˜μ²œμœΌλ‘œ λ˜μ–΄ μžˆμ–΄ κ²½μž‘ν•  수 μ—†λŠ” λ•…μ΄μ—ˆκ³ , λ‚˜λ¨Έμ§€ 땅은 이미 λ‹€λ₯Έ μ‚¬λžŒλ“€μ΄ κ²½μž‘ν•˜κ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€. μ›κ³ λŠ” μ΄λŸ¬ν•œ 사싀을 μ•Œμ§€ λͺ»ν•œ 채 맀맀계약을 μ²΄κ²°ν•˜μ˜€κ³ , λ‚˜μ€‘μ— 이λ₯Ό μ•Œκ²Œ λ˜μ–΄ 계약을 무효둜 μ£Όμž₯ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 법원은 μ›κ³ μ˜ μ£Όμž₯이 착였둜 μΈν•œ μ˜μ‚¬ν‘œμ‹œμ˜ μ·¨μ†Œλ‘œλ„ λ³Ό 수 μžˆλ‹€κ³  νŒλ‹¨ν•˜μ˜€μŠ΅λ‹ˆλ‹€.\n",
      "\n",
      "이 두 사건 λͺ¨λ‘ 맀수인이 λ§€λ§€ λŒ€μƒ λΆ€λ™μ‚°μ˜ μ‹€μ œ μƒνƒœλ₯Ό μ œλŒ€λ‘œ μ•Œμ§€ λͺ»ν•œ 채 계약을 μ²΄κ²°ν•œ ν›„, κ·Έ 사싀을 μ•Œκ²Œ λ˜μ–΄ 법적 λΆ„μŸμ΄ λ°œμƒν•œ μ‚¬λ‘€μž…λ‹ˆλ‹€. μ§ˆλ¬Έμžλ‹˜μ˜ 상황과 μœ μ‚¬ν•œ 점이 λ§ŽμœΌλ―€λ‘œ μ°Έκ³ ν•˜μ‹œκΈ° λ°”λžλ‹ˆλ‹€.\n",
      "\n",
      "### μš”μ•½\n",
      "- **사건λͺ… 1**: λ§€λ„μΈμ˜ κΆλ°•ν•œ 사정을 μ΄μš©ν•˜μ—¬ 뢀동산을 μ €λ ΄ν•˜κ²Œ λ§€μˆ˜ν•œ 경우.\n",
      "- **사건λͺ… 2**: λ§€μˆ˜ν•œ 뢀동산이 μ‹€μ œλ‘œλŠ” κ²½μž‘ν•  수 μ—†λŠ” λ•…μ΄μ—ˆμŒμ„ λ‚˜μ€‘μ— μ•Œκ²Œ 된 경우.\n",
      "\n",
      "이와 같은 사둀λ₯Ό 톡해 법적 λŒ€μ‘ λ°©μ•ˆμ„ λͺ¨μƒ‰ν•΄λ³΄μ‹œκΈ° λ°”λžλ‹ˆλ‹€. 좔가적인 법적 쑰언이 ν•„μš”ν•˜μ‹œλ©΄ λ³€ν˜Έμ‚¬μ™€ μƒλ‹΄ν•˜μ‹œκΈ°λ₯Ό ꢌμž₯λ“œλ¦½λ‹ˆλ‹€.\n",
      "\n",
      "κ°μ‚¬ν•©λ‹ˆλ‹€.\n",
      "\n",
      "### 좜처\n",
      "- 214987, 손해배상등, 68λ‹€88, 1968.07.30\n",
      "- 153300, λ§€λ§€λŒ€κΈˆλ°˜ν™˜λ“±, 66λ‹€1289, 1966.09.20"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'μ•ˆλ…•ν•˜μ„Έμš”. νŒμ‚¬λ‹˜μž…λ‹ˆλ‹€. μ§ˆλ¬Έν•˜μ‹  상황과 λΉ„μŠ·ν•œ νŒλ‘€λ₯Ό μ°Ύμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€. μ•„λž˜μ— 두 κ°€μ§€ 사둀λ₯Ό μ†Œκ°œν•΄λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.\\n\\n### [사건λͺ… 1] λΆˆκ³΅μ •ν•œ 법λ₯ ν–‰μœ„에 κ΄€ν•œ 법리λ₯Ό μ˜€ν•΄ν•œ μœ„λ²•μ΄ μžˆλŠ” μ‹€λ‘€\\n- **좜처**: 214987, 손해배상등, 68λ‹€88, 1968.07.30\\n- **사건 λ‚΄μš©**: 맀도인이 뢀동산을 맀도할 λ‹Ήμ‹œ, 맀수인이 λ§€λ„μΈμ˜ κΆλ°•ν•œ 사정을 μ•Œκ³  μžˆμ—ˆκ³ , 맀도인이 νŒ”κΈ°λ₯Ό κΊΌλ €ν•˜λŠ” λΆ€λΆ„κΉŒμ§€ 맀수인의 μš”κ΅¬μ— μ˜ν•΄ ν•¨κ»˜ νŒ”μ§€ μ•Šμ„ 수 μ—†μ—ˆμŠ΅λ‹ˆλ‹€. λ§€λ§€λͺ©μ λ¬Όμ˜ κ²½κ³„ν™•μ •μΈ‘λŸ‰λ„ 맀수인이 일방적으둜 ν•˜κ³ , 뢀동산 가격도 맀우 μ €λ ΄ν•˜κ²Œ μ±…μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 μ‚¬κ±΄μ—μ„œ 법원은 μ΄λŸ¬ν•œ λ§€λ§€ν–‰μœ„κ°€ λΆˆκ³΅μ •ν•œ 법λ₯ ν–‰μœ„에 ν•΄λ‹Ήν•œλ‹€κ³  νŒλ‹¨ν•˜μ˜€μŠ΅λ‹ˆλ‹€.\\n\\n### [사건λͺ… 2] μ›κ³ μ˜ μ£Όμž₯이 착였둜 μΈν•œ μ˜μ‚¬ν‘œμ‹œμ˜ μ·¨μ†Œλ‘œλ„ λ³΄μ—¬μ§€λ―€λ‘œ, 이λ₯Ό 석λͺ…μΉ˜ μ•Šμ€ μœ„λ²•μ΄ μžˆλŠ” 예\\n- **좜처**: 153300, λ§€λ§€λŒ€κΈˆλ°˜ν™˜λ“±, 66λ‹€1289, 1966.09.20\\n- **사건 λ‚΄μš©**: 원고가 ν”Όκ³ λ‘œλΆ€ν„° λ§€μˆ˜ν•œ λ…Ό 1,389평 쀑 μΌλΆ€λŠ” ν•˜μ²œμœΌλ‘œ λ˜μ–΄ μžˆμ–΄ κ²½μž‘ν•  수 μ—†λŠ” λ•…μ΄μ—ˆκ³ , λ‚˜λ¨Έμ§€ 땅은 이미 λ‹€λ₯Έ μ‚¬λžŒλ“€μ΄ κ²½μž‘ν•˜κ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€. μ›κ³ λŠ” μ΄λŸ¬ν•œ 사싀을 μ•Œμ§€ λͺ»ν•œ 채 맀맀계약을 μ²΄κ²°ν•˜μ˜€κ³ , λ‚˜μ€‘μ— 이λ₯Ό μ•Œκ²Œ λ˜μ–΄ 계약을 무효둜 μ£Όμž₯ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 법원은 μ›κ³ μ˜ μ£Όμž₯이 착였둜 μΈν•œ μ˜μ‚¬ν‘œμ‹œμ˜ μ·¨μ†Œλ‘œλ„ λ³Ό 수 μžˆλ‹€κ³  νŒλ‹¨ν•˜μ˜€μŠ΅λ‹ˆλ‹€.\\n\\n이 두 사건 λͺ¨λ‘ 맀수인이 λ§€λ§€ λŒ€μƒ λΆ€λ™μ‚°μ˜ μ‹€μ œ μƒνƒœλ₯Ό μ œλŒ€λ‘œ μ•Œμ§€ λͺ»ν•œ 채 계약을 μ²΄κ²°ν•œ ν›„, κ·Έ 사싀을 μ•Œκ²Œ λ˜μ–΄ 법적 λΆ„μŸμ΄ λ°œμƒν•œ μ‚¬λ‘€μž…λ‹ˆλ‹€. μ§ˆλ¬Έμžλ‹˜μ˜ 상황과 μœ μ‚¬ν•œ 점이 λ§ŽμœΌλ―€λ‘œ μ°Έκ³ ν•˜μ‹œκΈ° λ°”λžλ‹ˆλ‹€.\\n\\n### μš”μ•½\\n- **사건λͺ… 1**: λ§€λ„μΈμ˜ κΆλ°•ν•œ 사정을 μ΄μš©ν•˜μ—¬ 뢀동산을 μ €λ ΄ν•˜κ²Œ λ§€μˆ˜ν•œ 경우.\\n- **사건λͺ… 2**: λ§€μˆ˜ν•œ 뢀동산이 μ‹€μ œλ‘œλŠ” κ²½μž‘ν•  수 μ—†λŠ” λ•…μ΄μ—ˆμŒμ„ λ‚˜μ€‘μ— μ•Œκ²Œ 된 경우.\\n\\n이와 같은 사둀λ₯Ό 톡해 법적 λŒ€μ‘ λ°©μ•ˆμ„ λͺ¨μƒ‰ν•΄λ³΄μ‹œκΈ° λ°”λžλ‹ˆλ‹€. 좔가적인 법적 쑰언이 ν•„μš”ν•˜μ‹œλ©΄ λ³€ν˜Έμ‚¬μ™€ μƒλ‹΄ν•˜μ‹œκΈ°λ₯Ό ꢌμž₯λ“œλ¦½λ‹ˆλ‹€.\\n\\nκ°μ‚¬ν•©λ‹ˆλ‹€.\\n\\n### 좜처\\n- 214987, 손해배상등, 68λ‹€88, 1968.07.30\\n- 153300, λ§€λ§€λŒ€κΈˆλ°˜ν™˜λ“±, 66λ‹€1289, 1966.09.20'"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rag_chain(\n",
    "    \"논밭은 μ•½ 2μ²œν‰μ„ μƒ€λŠ”λ°, μ•Œκ³  λ³΄λ‹ˆ 집을 지을 수 μ—†λŠ” 땅이야. 이런 사기와 λΉ„μŠ·ν•œ κ±Έ μ•Œλ €μ€˜!\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}