RAG, MMR, 임베딩 심화
This commit is contained in:
+557
-15
@@ -23,34 +23,40 @@
|
||||
"id": "ceaff2f6",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2026-05-27T08:50:09.993923078Z",
|
||||
"start_time": "2026-05-27T08:50:09.983490192Z"
|
||||
"end_time": "2026-05-28T01:43:20.987484992Z",
|
||||
"start_time": "2026-05-28T01:43:20.978670755Z"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"import selectors\n",
|
||||
"\n",
|
||||
"import langchain_core\n",
|
||||
"#라이브러리 로드\n",
|
||||
"\n",
|
||||
"from langchain_ollama import ChatOllama\n",
|
||||
"from langchain_ibm import ChatWatsonx\n",
|
||||
"from langchain_core.prompts import PromptTemplate, ChatPromptTemplate\n",
|
||||
"from langchain_core.prompts import PromptTemplate, ChatPromptTemplate, MessagesPlaceholder\n",
|
||||
"from langchain_core.output_parsers import StrOutputParser, JsonOutputParser, PydanticOutputParser\n",
|
||||
"from langchain_core.runnables import RunnablePassthrough, RunnableParallel, RunnableLambda\n",
|
||||
"from langchain_core.messages import HumanMessage, SystemMessage, AIMessage\n",
|
||||
"from langchain_core.chat_history import InMemoryChatMessageHistory, BaseChatMessageHistory\n",
|
||||
"from langchain_core.runnables.history import RunnableWithMessageHistory\n",
|
||||
"from prompt_toolkit.history import InMemoryHistory\n",
|
||||
"from pydantic import BaseModel, Field\n",
|
||||
"from typing import Literal\n",
|
||||
"from dotenv import load_dotenv\n",
|
||||
"import os"
|
||||
],
|
||||
"outputs": [],
|
||||
"execution_count": 56
|
||||
"execution_count": 39
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"id": "2e83941f",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2026-05-27T08:50:11.888281707Z",
|
||||
"start_time": "2026-05-27T08:50:11.876005807Z"
|
||||
"end_time": "2026-05-28T01:01:25.315262434Z",
|
||||
"start_time": "2026-05-28T01:01:25.303683341Z"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
@@ -59,18 +65,19 @@
|
||||
"\n",
|
||||
"apikey = os.getenv(\"WATSONX_API_KEY\")\n",
|
||||
"project_id = os.getenv(\"WATSONX_PROJECT_ID\")\n",
|
||||
"watsonx_ai_url = os.getenv(\"WATSONX_URL\")\n"
|
||||
"watsonx_ai_url = os.getenv(\"WATSONX_URL\")\n",
|
||||
"hf_token = os.getenv(\"HF_TOKEN\")\n"
|
||||
],
|
||||
"outputs": [],
|
||||
"execution_count": 57
|
||||
"execution_count": 26
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"id": "7c0a9354",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2026-05-27T08:50:16.189743767Z",
|
||||
"start_time": "2026-05-27T08:50:13.584144045Z"
|
||||
"end_time": "2026-05-28T01:01:29.753326236Z",
|
||||
"start_time": "2026-05-28T01:01:26.671654629Z"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
@@ -87,7 +94,7 @@
|
||||
"gemma_llm = ChatOllama(model=\"gemma4:e2b\")"
|
||||
],
|
||||
"outputs": [],
|
||||
"execution_count": 58
|
||||
"execution_count": 27
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -1965,11 +1972,546 @@
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
" - InMemoryChatMessageHistory\n",
|
||||
" - 메모리에 대화 저장 후 대화 기록 관리\n"
|
||||
],
|
||||
"id": "84cc5b7e61f2a23d"
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2026-05-28T00:54:22.590632509Z",
|
||||
"start_time": "2026-05-28T00:52:55.700793745Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"execution_count": null,
|
||||
"source": "",
|
||||
"id": "fb66178274d6381"
|
||||
"source": [
|
||||
"history = InMemoryChatMessageHistory()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def chat(user_input):\n",
|
||||
" history.add_user_message(user_input)\n",
|
||||
" response = gemma_llm.invoke(history.messages) # 전체 대화 이력 같이 보냄\n",
|
||||
" history.add_ai_message(response.content)\n",
|
||||
" return response.content\n",
|
||||
"\n",
|
||||
"print(chat(\"파이썬이란?\"))\n",
|
||||
"print(chat(\"방금 말한 내용의 장점 3가지는?\"))\n",
|
||||
"print(chat(\"그 중 첫번째 장점에 대한 예시 코드 작성해줘\"))\n",
|
||||
"print(chat(\"두 번째 장점에 대한 예시 코드 작성해줘\"))\n",
|
||||
"\n",
|
||||
"for m in history.messages:\n",
|
||||
" print(f\"{m.content[:40]}...\")"
|
||||
],
|
||||
"id": "fb66178274d6381",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"파이썬(Python)은 오늘날 가장 인기 있고 널리 사용되는 프로그래밍 언어 중 하나입니다.\n",
|
||||
"\n",
|
||||
"쉽게 말해, **사람이 읽고 쓰기 쉬운 문법**을 사용하여 컴퓨터에게 원하는 작업을 지시할 수 있게 해주는 **고급(High-level) 프로그래밍 언어**입니다.\n",
|
||||
"\n",
|
||||
"파이썬이 왜 그렇게 유명하고 많은 분야에서 사용되는지, 그리고 어떤 특징을 가지고 있는지 자세히 설명해 드리겠습니다.\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"## 1. 파이썬의 핵심 특징\n",
|
||||
"\n",
|
||||
"### 1. 쉬운 문법 (Readability)\n",
|
||||
"파이썬의 가장 큰 장점은 문법이 매우 간결하고 영어와 유사해서 초보자도 비교적 쉽게 배울 수 있다는 점입니다. 복잡한 명령어를 적는 대신, 자연어처럼 코드를 작성할 수 있어 코드의 이해와 유지보수가 매우 쉽습니다.\n",
|
||||
"\n",
|
||||
"### 2. 인터프리터 방식 (Interpreted Language)\n",
|
||||
"파이썬은 코드를 한 줄씩 읽어서 즉시 실행하는 **인터프리터(Interpreter)** 방식으로 작동합니다. 이는 개발자가 코드를 컴파일(Compile)하는 복잡한 과정을 거치지 않고도 빠르게 결과를 확인하고 테스트할 수 있게 해줍니다.\n",
|
||||
"\n",
|
||||
"### 3. 방대한 라이브러리 및 생태계 (Vast Ecosystem)\n",
|
||||
"파이썬의 가장 강력한 힘은 방대하고 활발한 **라이브러리(Library)**와 **프레임워크(Framework)** 생태계에 있습니다. 이미 수많은 개발자들이 만들어 놓은 모듈(라이브러리)을 가져와서 복잡한 기능을 아주 쉽게 구현할 수 있습니다. (예: NumPy, Pandas, Django, TensorFlow 등)\n",
|
||||
"\n",
|
||||
"### 4. 다목적성 (Versatility)\n",
|
||||
"파이썬은 특정 분야에 국한되지 않고, 데이터 분석, 웹 개발, 인공지능, 자동화 등 거의 모든 종류의 프로그래밍 작업에 사용될 수 있습니다.\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"## 2. 파이썬은 어디에 사용되나요? (주요 활용 분야)\n",
|
||||
"\n",
|
||||
"파이썬의 높은 범용성 덕분에 현재 가장 활발하게 사용되는 분야는 다음과 같습니다.\n",
|
||||
"\n",
|
||||
"### 1. 데이터 과학 및 분석 (Data Science & Analytics)\n",
|
||||
"* **활용:** 대량의 데이터를 처리, 분석하고 패턴을 찾는 데 압도적으로 많이 사용됩니다.\n",
|
||||
"* **주요 라이브러리:** **Pandas** (데이터 조작), **NumPy** (수치 계산), **Matplotlib** (시각화).\n",
|
||||
"\n",
|
||||
"### 2. 인공지능 (AI) 및 머신러닝 (Machine Learning)\n",
|
||||
"* **활용:** 인공지능 모델을 개발하고 훈련하는 데 핵심적인 언어입니다.\n",
|
||||
"* **주요 라이브러리:** **TensorFlow**, **PyTorch**, **Scikit-learn**.\n",
|
||||
"\n",
|
||||
"### 3. 웹 개발 (Web Development)\n",
|
||||
"* **활용:** 웹사이트의 백엔드(서버 로직) 개발에 사용됩니다.\n",
|
||||
"* **주요 프레임워크:** **Django**, **Flask**.\n",
|
||||
"\n",
|
||||
"### 4. 자동화 및 스크립팅 (Automation & Scripting)\n",
|
||||
"* **활용:** 반복적이거나 지루한 시스템 관리 작업을 자동화하는 데 매우 효율적입니다.\n",
|
||||
"* **예시:** 파일 정리, 이메일 자동 발송, 웹 크롤링(정보 수집).\n",
|
||||
"\n",
|
||||
"### 5. 소프트웨어 테스트 및 QA\n",
|
||||
"* **활용:** 소프트웨어의 오류를 찾고 테스트하는 자동화 스크립트를 작성하는 데 사용됩니다.\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"## 💡 요약 정리\n",
|
||||
"\n",
|
||||
"| 구분 | 내용 | 비고 |\n",
|
||||
"| :--- | :--- | :--- |\n",
|
||||
"| **정의** | 사람이 읽기 쉬운 문법을 사용하는 고급 프로그래밍 언어 | |\n",
|
||||
"| **특징** | 문법이 간결하고, 라이브러리가 풍부하며, 다목적성이 높음 | |\n",
|
||||
"| **주요 강점** | 배우기 쉽고, 코드를 빠르게 작성할 수 있음 | |\n",
|
||||
"| **주요 분야** | 데이터 과학, AI/머신러닝, 웹 개발, 시스템 자동화 | |\n",
|
||||
"\n",
|
||||
"**결론적으로,** 만약 프로그래밍을 처음 시작하거나, 데이터 분석, AI 등 미래 기술 분야에 관심이 있다면 **파이썬은 가장 먼저 배워야 할 강력한 언어**라고 할 수 있습니다.\n",
|
||||
"방금 설명드린 내용을 바탕으로 파이썬의 가장 핵심적이고 강력한 장점 3가지를 정리해 드리겠습니다.\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"### 🥇 장점 1: 배우기 매우 쉽고 직관적이다 (쉬운 문법)\n",
|
||||
"\n",
|
||||
"파이썬의 가장 큰 장점은 **코드를 읽고 쓰는 것이 매우 쉽다**는 점입니다.\n",
|
||||
"\n",
|
||||
"* **설명:** 다른 언어들에 비해 문법이 간결하고 영어와 유사하여, 프로그래밍을 처음 시작하는 사람도 비교적 적은 시간 투자로 코드를 이해하고 작성할 수 있습니다.\n",
|
||||
"* **효과:** 코딩에 대한 진입 장벽이 낮아 초보자가 빠르게 성취감을 느끼고 실제 문제 해결에 집중할 수 있습니다.\n",
|
||||
"\n",
|
||||
"### 🥈 장점 2: 방대하고 강력한 생태계 (풍부한 라이브러리)\n",
|
||||
"\n",
|
||||
"파이썬은 혼자 모든 것을 다 할 필요가 없습니다. 이미 수많은 사람들이 만들어 놓은 강력한 도구들(라이브러리, 프레임워크)이 존재합니다.\n",
|
||||
"\n",
|
||||
"* **설명:** 데이터 분석, 인공지능, 웹 개발 등 특정 분야에서 필요로 하는 수많은 기능을 이미 잘 만들어진 모듈(라이브러리) 형태로 제공합니다.\n",
|
||||
"* **효과:** 개발자가 기본적인 기능 구현에 시간을 낭비하지 않고, **이미 검증된 강력한 도구들을 가져와서** 복잡하고 전문적인 작업(예: AI 모델 훈련, 대규모 데이터 분석)을 훨씬 빠르고 효율적으로 구현할 수 있게 해줍니다.\n",
|
||||
"\n",
|
||||
"### 🥉 장점 3: 뛰어난 범용성 (다목적성)\n",
|
||||
"\n",
|
||||
"파이썬은 특정 분야에 갇혀 있지 않고, 거의 모든 종류의 프로그래밍 작업에 활용될 수 있습니다.\n",
|
||||
"\n",
|
||||
"* **설명:** 웹사이트를 만들거나, 데이터를 분석하거나, 자동화 스크립트를 작성하거나, 인공지능 모델을 만들고, 게임을 만드는 등 원하는 거의 모든 분야에 적용이 가능합니다.\n",
|
||||
"* **효과:** 하나의 언어만 배우면 여러 분야를 커버할 수 있어, 개발 분야를 바꾸거나 새로운 프로젝트를 시도할 때 유연하게 대처할 수 있는 큰 이점이 있습니다.\n",
|
||||
"네, 첫 번째 장점인 **\"배우기 쉽고 직관적인 문법\"**을 보여주는 예시 코드를 작성해 드리겠습니다.\n",
|
||||
"\n",
|
||||
"이 코드는 파이썬의 가장 기본적인 개념(변수 할당, 출력)만으로도 하나의 작업을 수행하는 예시입니다.\n",
|
||||
"\n",
|
||||
"### 📝 예시 코드: 간단한 인사말 출력 및 계산\n",
|
||||
"\n",
|
||||
"이 코드는 사용자의 이름을 입력받아 환영 메시지를 출력하고, 나이를 5살 더한 나이를 계산하는 아주 간단한 작업을 수행합니다.\n",
|
||||
"\n",
|
||||
"```python\n",
|
||||
"# 1. 사용자에게 이름 입력받기 (input 함수 사용)\n",
|
||||
"name = input(\"당신의 이름은 무엇인가요? \")\n",
|
||||
"\n",
|
||||
"# 2. 사용자에게 나이 입력받기 (input을 받고 숫자로 변환)\n",
|
||||
"age_str = input(\"당신의 나이는 몇 살인가요? \")\n",
|
||||
"age = int(age_str) # 문자열을 숫자로 변환\n",
|
||||
"\n",
|
||||
"# 3. 계산 결과 만들기\n",
|
||||
"new_age = age + 5\n",
|
||||
"\n",
|
||||
"# 4. 결과 출력하기 (print 함수 사용)\n",
|
||||
"print(\"안녕하세요, \" + name + \"님!\")\n",
|
||||
"print(\"당신은 \" + str(new_age) + \"살이고, 5살을 더하면 \" + str(new_age + 5) + \"살이 됩니다.\")\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"### ✨ 이 코드가 첫 번째 장점을 보여주는 이유\n",
|
||||
"\n",
|
||||
"1. **직관적인 명령:** 코드가 마치 우리가 일상에서 사용하는 영어 문장처럼 읽히기 때문에, 프로그래밍 경험이 없어도 코드의 흐름을 쉽게 파악할 수 있습니다. (예: `print(...)`는 '화면에 이것을 보여줘'라는 뜻으로 매우 직관적입니다.)\n",
|
||||
"2. **간결한 문법:** 복잡한 기호나 괄호 사용이 최소화되어 있어, 코드가 길어지더라도 논리적인 흐름을 따라가기 쉽습니다.\n",
|
||||
"3. **쉬운 흐름:** 코드가 위에서 아래로 순서대로 실행되므로, 어떤 명령이 언제 실행되는지 예측하기가 매우 쉽습니다.\n",
|
||||
"\n",
|
||||
"**💡 핵심:** 파이썬 코드는 \"무엇을 하라\"고 명령하는 방식이 아니라, **\"이렇게 하라\"**는 자연스러운 문장으로 지시하는 방식에 가깝기 때문에, 초보자가 코딩의 논리 자체에 집중할 수 있도록 돕습니다.\n",
|
||||
"두 번째 장점인 **\"방대하고 강력한 생태계 (풍부한 라이브러리)\"**를 보여주는 예시 코드를 작성해 드리겠습니다.\n",
|
||||
"\n",
|
||||
"이 예시에서는 데이터 분석에서 가장 강력한 라이브러리 중 하나인 **Pandas**를 사용하여, 복잡한 데이터 처리 작업을 단 몇 줄의 코드로 해결하는 모습을 보여줍니다.\n",
|
||||
"\n",
|
||||
"### 🛠️ 예시 코드: Pandas를 이용한 간단한 데이터 분석\n",
|
||||
"\n",
|
||||
"이 코드는 실제로 데이터를 읽어와서 평균을 계산하고, 단순히 명령 한 줄로 데이터를 처리하는 과정을 보여줍니다.\n",
|
||||
"\n",
|
||||
"**(참고: 이 코드를 실행하려면 컴퓨터에 `pandas` 라이브러리가 설치되어 있어야 합니다. `pip install pandas` 명령으로 설치할 수 있습니다.)**\n",
|
||||
"\n",
|
||||
"```python\n",
|
||||
"# 1. 필요한 라이브러리 불러오기 (외부 도구 사용)\n",
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"# 2. 데이터 준비 (실제로는 파일에서 불러오지만, 예시를 위해 직접 데이터를 만듭니다.)\n",
|
||||
"data = {\n",
|
||||
" '제품': ['사과', '바나나', '오렌지', '포도', '수박'],\n",
|
||||
" '판매량': [150, 200, 120, 350, 180],\n",
|
||||
" '가격': [1000, 800, 1200, 1500, 2000]\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# 3. 데이터프레임(DataFrame) 생성 (Pandas 라이브러리 사용)\n",
|
||||
"df = pd.DataFrame(data)\n",
|
||||
"\n",
|
||||
"print(\"--- 원본 데이터 테이블 ---\")\n",
|
||||
"print(df)\n",
|
||||
"print(\"\\n\" + \"=\"*30 + \"\\n\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# 4. 강력한 라이브러리 기능을 사용한 데이터 분석 (복잡한 로직 대신 함수 호출)\n",
|
||||
"# '판매량' 열의 평균을 계산\n",
|
||||
"average_sales = df['판매량'].mean()\n",
|
||||
"\n",
|
||||
"# '가격' 열의 총합을 계산\n",
|
||||
"total_price = df['가격'].sum()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# 5. 결과 출력\n",
|
||||
"print(f\"🚀 계산 결과:\")\n",
|
||||
"print(f\"모든 제품의 평균 판매량: {average_sales:.2f} 개\")\n",
|
||||
"print(f\"모든 제품의 총 판매 가격: {total_price:,} 원\")\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"### 💡 이 코드가 두 번째 장점을 보여주는 이유\n",
|
||||
"\n",
|
||||
"1. **단순한 명령으로 복잡한 작업 수행:**\n",
|
||||
" * 만약 Pandas 라이브러리가 없었다면, 우리는 위에서 만든 데이터(`df`)를 반복문(Loop)을 사용하여 하나씩 꺼내서, 판매량을 더하고, 가격을 나누고, 평균을 구하는 **복잡한 수백 줄의 코드**를 작성해야 했을 것입니다.\n",
|
||||
" * 하지만 Pandas라는 **도구(라이브러리)**를 사용함으로써, 우리는 단지 `df['판매량'].mean()`이라는 **단 한 줄의 명령**만으로 원하는 결과를 얻어냈습니다.\n",
|
||||
"\n",
|
||||
"2. **시간 절약 및 효율성:**\n",
|
||||
" * 라이브러리는 이미 수많은 전문가들이 테스트하고 만든 최적화된 코드를 담고 있습니다. 개발자는 이러한 기본 코드를 다시 만들 필요 없이, **필요한 기능만 가져와서** 자신의 목적에 맞게 조합하기만 하면 됩니다.\n",
|
||||
"\n",
|
||||
"**핵심:** 파이썬은 기본적으로 강력한 '도구 상자'이며, 우리는 이 도구 상자에 이미 만들어진 수많은 전문가의 지혜(라이브러리)를 쉽게 빌려와서, 남들이 하기 어려운 전문적인 작업까지 손쉽게 처리할 수 있게 해줍니다.\n",
|
||||
"파이썬이란?...\n",
|
||||
"파이썬(Python)은 오늘날 가장 인기 있고 널리 사용되는 프로그래밍 ...\n",
|
||||
"방금 말한 내용의 장점 3가지는?...\n",
|
||||
"방금 설명드린 내용을 바탕으로 파이썬의 가장 핵심적이고 강력한 장점 3가...\n",
|
||||
"그 중 첫번째 장점에 대한 예시 코드 작성해줘...\n",
|
||||
"네, 첫 번째 장점인 **\"배우기 쉽고 직관적인 문법\"**을 보여주는 예...\n",
|
||||
"두 번째 장점에 대한 예시 코드 작성해줘...\n",
|
||||
"두 번째 장점인 **\"방대하고 강력한 생태계 (풍부한 라이브러리)\"**를...\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 22
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2026-05-28T01:44:33.443082277Z",
|
||||
"start_time": "2026-05-28T01:44:16.764525701Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# 여러 사람과 대화하는 부분 저장 => 세선별로 저장\n",
|
||||
"\n",
|
||||
"# 세션별 이력 저장\n",
|
||||
"store = {}\n",
|
||||
"\n",
|
||||
"def get_sesstion_history(session_id):\n",
|
||||
" if session_id not in store:\n",
|
||||
" store[session_id] = InMemoryChatMessageHistory()\n",
|
||||
" return store[session_id]\n",
|
||||
"\n",
|
||||
"# 프롬프트 생성\n",
|
||||
"prompt = ChatPromptTemplate.from_messages([\n",
|
||||
" (\"system\", \"당신은 {role}입니다., 한국어로 답변하세요.\"),\n",
|
||||
" MessagesPlaceholder(variable_name=\"history\"), # 대화이력 삽입될 위치임\n",
|
||||
" (\"human\", \"{input}\")\n",
|
||||
" # (\"human\", \"{input}\\n {history}\\n\")\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"# LLM 생성\n",
|
||||
"# 체인 생성\n",
|
||||
"chain = prompt | gemma_llm | StrOutputParser()\n",
|
||||
"\n",
|
||||
"# 1. sesstion_id 이력 조회\n",
|
||||
"# 2. history 키에 이력 삽입 -> prompt -> llm 실행 -> 대화 나눈 이력을 history 추가\n",
|
||||
"\n",
|
||||
"with_history = RunnableWithMessageHistory(chain, get_sesstion_history, input_messages_key=\"input\", history_messages_key=\"history\")\n",
|
||||
"\n",
|
||||
"# 세션 생성\n",
|
||||
"cfg_a = {\"configurable\":{\"session_id\":\"user_alice\"}}\n",
|
||||
"cfg_b = {\"configurable\":{\"session_id\":\"user_bob\"}}\n",
|
||||
"\n",
|
||||
"# Alice 대화\n",
|
||||
"res1 = with_history.invoke({\"role\":\"파이썬 튜더\", \"input\":\"안녕\"}, config=cfg_a)\n",
|
||||
"res2 = with_history.invoke({\"role\":\"파이썬 튜더\", \"input\":\"내 이름은 Alice야\"}, config=cfg_a)\n",
|
||||
"res5 = with_history.invoke({\"role\":\"파이썬 튜더\", \"input\":\"내 이름은 기억해?\"}, config=cfg_a)\n",
|
||||
"\n",
|
||||
"# Bob 대화\n",
|
||||
"res3 = with_history.invoke({\"role\":\"파이썬 튜더\", \"input\":\"안녕\"}, config=cfg_b)\n",
|
||||
"res4 = with_history.invoke({\"role\":\"파이썬 튜더\", \"input\":\"내 이름은 Bob야\"}, config=cfg_b)\n",
|
||||
"\n",
|
||||
"print(\"alice \", res2)\n",
|
||||
"print(\"bob \", res5)\n",
|
||||
"\n",
|
||||
"# # 세션 생성\n",
|
||||
"# def create_session():\n",
|
||||
"# sesstion_id = uuid.uuid4().hex\n",
|
||||
"# return sesstion_id\n",
|
||||
"#\n",
|
||||
"# # 세션별 이력 조회\n",
|
||||
"# def get_sesstion_history(sesstion_id):\n",
|
||||
"# if sesstion_id not in store:\n",
|
||||
"# store[sesstion_id] = InMemoryChatMessageHistory()\n",
|
||||
"# return store[sesstion_id]\n"
|
||||
],
|
||||
"id": "a2ade04f6a51a29",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/home/cooney/Source/.venv/lib/python3.12/site-packages/IPython/core/interactiveshell.py:3748: LangChainDeprecationWarning: RunnableWithMessageHistory is deprecated. Use LangGraph's built-in persistence instead.\n",
|
||||
" exec(code_obj, self.user_global_ns, self.user_ns)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"alice Alice님, 만나서 반갑습니다! 😊\n",
|
||||
"\n",
|
||||
"앞으로 파이썬 학습에 있어서 궁금한 점이나 도움이 필요한 부분이 있다면 언제든지 저에게 질문해주세요. 제가 알고 있는 모든 것을 동원해서 최대한 자세하고 친절하게 도와드리겠습니다!\n",
|
||||
"\n",
|
||||
"이제 파이썬으로 무엇을 해보고 싶으신가요? 예를 들어, 기본적인 문법부터 시작해 볼까요?\n",
|
||||
"bob 네, 기억하고 있습니다! 😊\n",
|
||||
"\n",
|
||||
"당신이 **Alice**라는 이름을 알려주셨기 때문에, 지금 이 대화에서는 Alice님이시라는 것을 기억하고 있습니다.\n",
|
||||
"\n",
|
||||
"저는 대화의 맥락(context)을 기억하여 이전 내용을 바탕으로 더 자연스럽게 소통하려고 노력합니다.\n",
|
||||
"\n",
|
||||
"이제 Alice님과 함께 파이썬 공부를 계속할 준비가 되었습니다! 다음 질문이나 학습하고 싶은 주제가 있으신가요?\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 41
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"- 대화가 길어지면 이력 전체를 LLM에 넘기는 경우 ContextWindowExceededError 발생 = 즉 Context Window를 초과\n",
|
||||
"- memory에 어떤 정보를 얼마나 보존할 지 결정\n",
|
||||
"- 전략\n",
|
||||
" - 최근 K 턴만 유지\n",
|
||||
" - 오래된 대화 요약\n",
|
||||
" - 요약 + 최근대화\n"
|
||||
],
|
||||
"id": "c83d8f23c50214c"
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2026-05-28T01:55:05.424326080Z",
|
||||
"start_time": "2026-05-28T01:54:33.248920182Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# 세션별 이력 저장\n",
|
||||
"store = {}\n",
|
||||
"\n",
|
||||
"def get_sesstion_history(session_id):\n",
|
||||
" if session_id not in store:\n",
|
||||
" store[session_id] = InMemoryChatMessageHistory()\n",
|
||||
" return store[session_id]\n",
|
||||
"\n",
|
||||
" # 최근 몇 개만 유지\n",
|
||||
" history = store[session_id]\n",
|
||||
"\n",
|
||||
" if len(history.messages) > 8:\n",
|
||||
" history.messages[:] = history.messages[-8:]\n",
|
||||
"\n",
|
||||
" return history\n",
|
||||
"\n",
|
||||
"with_history = RunnableWithMessageHistory(chain, get_sesstion_history, input_messages_key=\"input\", history_messages_key=\"history\")\n",
|
||||
"\n",
|
||||
"for i in range(10):\n",
|
||||
" with_history.invoke({\"role\":\"파이썬 튜터\", \"input\":f\"{i}번째 질문\"}, config=cfg_a)\n",
|
||||
"\n",
|
||||
"history = get_sesstion_history(\"user_alice\")\n",
|
||||
"\n",
|
||||
"for msg in history.messages:\n",
|
||||
" print(msg)\n",
|
||||
"\n",
|
||||
"print(len(history.messages))"
|
||||
],
|
||||
"id": "4464efadb9ea0fc7",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"content='0번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='안녕하세요! 파이썬 튜터입니다. 😊\\n\\n**첫 번째 질문을 해주세요!** 어떤 것에 대해 궁금하신가요? 프로그래밍, 특정 개념, 코드 작성, 문제 해결 등 무엇이든 좋습니다. 편하게 질문해 주세요!' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='1번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='네, 준비되었습니다! 😊\\n\\n**첫 번째 질문을 말씀해 주세요!** 제가 아는 범위 내에서 최대한 자세하고 명확하게 답변해 드리겠습니다.' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='2번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='네, 이제 **두 번째 질문**을 해 주시면 됩니다! 😊\\n\\n어떤 주제가 궁금하신가요? 코딩, 라이브러리 사용법, 특정 개념 설명 등 무엇이든 좋습니다.\\n\\n**준비되셨다면, 편하게 질문해 주세요!** 기다리고 있겠습니다. ✨' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='3번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='세 번째 질문을 기다리고 있겠습니다! 😊\\n\\n이제 **세 번째 질문**을 해주시면 됩니다. 어떤 것에 대해 알고 싶으신가요?\\n\\n궁금한 점을 구체적으로 말씀해 주시면, 제가 파이썬 지식을 활용하여 친절하게 설명해 드릴게요! 편하게 질문해 주세요. ✨' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='4번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='네, **네 번째 질문**을 기다리고 있겠습니다! 😊\\n\\n지금까지 질문해주신 내용을 종합해 볼 때, 파이썬과 관련된 질문이 많을 것 같습니다.\\n\\n**마음 편하게 네 번째 질문을 해 주세요!** 제가 최선을 다해 답변해 드리겠습니다. 😊' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='5번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='네, 이제 **다섯 번째 질문**을 기다리고 있겠습니다! 😊\\n\\n어떤 내용이 궁금하신가요?\\n\\n언제든지 편하게 질문해 주세요. 파이썬에 관한 것이든, 다른 것이든 제가 아는 선에서 최선을 다해 답변해 드리겠습니다! ✨' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='6번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='네, **여섯 번째 질문**을 기다리고 있겠습니다! 😊\\n\\n이제 궁금한 것을 질문해 주시면 됩니다. 😊\\n\\n**질문해 주세요!** 기다리고 있겠습니다. 😄' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='7번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='네, **일곱 번째 질문**을 기다리고 있겠습니다! 😊\\n\\n궁금한 점이 있으시면 언제든지 질문해 주세요.\\n\\n**편하게 질문해 주세요!** 제가 아는 모든 것을 동원해서 명쾌하게 답변해 드리겠습니다. 😊' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='8번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='네, 이제 **여덟 번째 질문**을 기다리고 있겠습니다! 😊\\n\\n마지막 질문까지 모두 드려주셔서 감사합니다. 이제 **실제로 궁금한 내용을 질문해 주세요!**\\n\\n어떤 것이든 좋습니다. 파이썬에 관한 것이든, 알고 싶은 프로그래밍 개념이든, 어떤 것이든 좋습니다.\\n\\n**질문해 주세요!** 제가 자세히 설명해 드리겠습니다. 😊' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"content='9번째 질문' additional_kwargs={} response_metadata={}\n",
|
||||
"content='네, **아홉 번째 질문**을 기다리고 있겠습니다! 😊\\n\\n이제 모든 질문 요청을 마쳤으니, **정말로 알고 싶은 질문**을 던져주시면 됩니다!\\n\\n파이썬에 대해 궁금한 점, 특정 코드에 대한 설명, 개념 이해 등 무엇이든 좋습니다.\\n\\n**주저하지 마시고 지금 바로 질문해 주세요!** 제가 최고의 답변을 드리기 위해 준비하고 있겠습니다. ✨' additional_kwargs={} response_metadata={} tool_calls=[] invalid_tool_calls=[]\n",
|
||||
"20\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 44
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2026-05-28T03:05:41.353949975Z",
|
||||
"start_time": "2026-05-28T03:02:10.585619509Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# 오래된 대화 요약\n",
|
||||
"\n",
|
||||
"# history 요약\n",
|
||||
"summary_prompt = ChatPromptTemplate.from_messages([\n",
|
||||
" (\"system\", \"다음 대화 내용을 핵심만 3문장 이내로 한국어로 요약하세요.\"),\n",
|
||||
" (\"human\", \"{converstaion}\"),\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"summary_chain = summary_prompt | gemma_llm | StrOutputParser()\n",
|
||||
"\n",
|
||||
"# 요약 기능이 포함된 클래스\n",
|
||||
"class SummarizedChatHistory(InMemoryChatMessageHistory):\n",
|
||||
" \"\"\"대화가 max_turns 초과 시 오래된 메시지 요약하기\"\"\"\n",
|
||||
" max_turns:int = Field(default=6)\n",
|
||||
" summary:str = Field(default=\"\")\n",
|
||||
"\n",
|
||||
"def _maybe_summarize(self):\n",
|
||||
" if len(self.add_message) > self.max_turns * 2:\n",
|
||||
" # 오래된 내용 찾기\n",
|
||||
" cutoff = len(self.messages)\n",
|
||||
" old_megs = self.message[:cutoff]\n",
|
||||
" new_msgs = self.message[cutoff:]\n",
|
||||
"\n",
|
||||
" # 요약할 텍스트 구성\n",
|
||||
" conv_text = \"\\n\".join(f\"{'사용자' if isinstance(m, HumanMessage) else 'AI'}:{m.content}\" for m in old_megs)\n",
|
||||
"\n",
|
||||
" # 기존 요약이 있으면 함께 포함\n",
|
||||
" if self.summary:\n",
|
||||
" conv_text = f\"[이전 요약]\\n{self.summary}\\n\\n[새 대화]\\n{conv_text}\"\n",
|
||||
"\n",
|
||||
" # 요약 실행\n",
|
||||
" self.summary = summary_chain.invoke({'converstation':conv_text})\n",
|
||||
"\n",
|
||||
" # 오래된 메시지 제거 후 요약본 SystemMessage 로 앞에 삽입\n",
|
||||
" self.messages.clear()\n",
|
||||
" self.messages.append(SystemMessage(content=f\"[이전 대화 요약]\\n{self.summary}\"))\n",
|
||||
" self.messages.extend(new_msgs)\n",
|
||||
"\n",
|
||||
"def add_message(self, message):\n",
|
||||
" super().add_message(message)\n",
|
||||
" self._maybe_summarize()\n",
|
||||
"\n",
|
||||
"store = {}\n",
|
||||
"\n",
|
||||
"def get_sesstion_history(session_id) -> SummarizedChatHistory:\n",
|
||||
" if session_id not in store:\n",
|
||||
" store[session_id] = SummarizedChatHistory(max_turns=6)\n",
|
||||
"\n",
|
||||
" return store[session_id]\n",
|
||||
"\n",
|
||||
"# 프롬프트 생성\n",
|
||||
"prompt = ChatPromptTemplate.from_messages([\n",
|
||||
" (\"system\", \"친절한 ai 어시스턴트입니다., 한국어로 답변하세요.\"),\n",
|
||||
" MessagesPlaceholder(variable_name=\"history\"), # 대화이력 삽입될 위치임\n",
|
||||
" (\"human\", \"{input}\")\n",
|
||||
" # (\"human\", \"{input}\\n {history}\\n\")\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"# LLM 생성\n",
|
||||
"# 체인 생성\n",
|
||||
"chain = prompt | gemma_llm | StrOutputParser()\n",
|
||||
"\n",
|
||||
"with_history = RunnableWithMessageHistory(chain, get_sesstion_history, input_messages_key=\"input\", history_messages_key=\"history\")\n",
|
||||
"\n",
|
||||
"# 세션 생성\n",
|
||||
"cfg_a = {\"configurable\":{\"session_id\":\"user_alice\"}}\n",
|
||||
"\n",
|
||||
"# 임의 대화 생성\n",
|
||||
"question = [\n",
|
||||
" \"파이썬이란?\",\n",
|
||||
" \"방금 설명한 파이썬의 장점은?\",\n",
|
||||
" \"단점은?\",\n",
|
||||
" \"어떤 분야에 많이 쓰여?\",\n",
|
||||
" \"입문자에게 추천하는 학습 순서는?\",\n",
|
||||
" \"좋은 파이썬 책 추천해줘?\",\n",
|
||||
" \"무료로 배울 수 있는 사이트는?\",\n",
|
||||
" \"이전에 내가 뭘 물어봤는지 기억해?\",\\\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"for i, q in enumerate(question, 1):\n",
|
||||
" resonse = with_history.invoke({\"input\":q}, config=cfg_a)\n",
|
||||
" print(f\"\\n{i}턴 Q: {q}\")\n",
|
||||
" print(f\"\\n A: {resonse[:60]}....\")\n",
|
||||
"\n",
|
||||
" # 요약 여부 확인\n",
|
||||
" history = get_sesstion_history(\"user_alice\")\n",
|
||||
" if history.summary:\n",
|
||||
" print(f\"\\n 요약 처리! 현재 메시지 수 {len(history.messages)}\")\n",
|
||||
" print(f\"\\n 요약 내용 {history.summary[:200]}....\")"
|
||||
],
|
||||
"id": "eefbcb9dd8c9af32",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"1턴 Q: 파이썬이란?\n",
|
||||
"\n",
|
||||
" A: 파이썬(Python)은 오늘날 가장 인기 있고 널리 사용되는 **프로그래밍 언어** 중 하나입니다.\n",
|
||||
"\n",
|
||||
"쉽게 ....\n",
|
||||
"\n",
|
||||
"2턴 Q: 방금 설명한 파이썬의 장점은?\n",
|
||||
"\n",
|
||||
" A: 방금 설명드린 내용을 바탕으로 파이썬이 가진 **핵심적인 장점**들을 정리해 드리겠습니다. 이 장점들 때문에....\n",
|
||||
"\n",
|
||||
"3턴 Q: 단점은?\n",
|
||||
"\n",
|
||||
" A: 파이썬은 그 장점들이 매우 강력한 만큼, 모든 프로그래밍 언어와 마찬가지로 **단점**도 존재합니다. 단점은....\n",
|
||||
"\n",
|
||||
"4턴 Q: 어떤 분야에 많이 쓰여?\n",
|
||||
"\n",
|
||||
" A: 파이썬은 그 **뛰어난 범용성** 덕분에 현재 IT 업계에서 **가장 활발하게 사용되는 분야** 중 하나입니....\n",
|
||||
"\n",
|
||||
"5턴 Q: 입문자에게 추천하는 학습 순서는?\n",
|
||||
"\n",
|
||||
" A: 파이썬을 처음 배우시는 분이라면, **기초 문법을 탄탄하게 다진 후, 관심 있는 분야로 확장해 나가는 순서*....\n",
|
||||
"\n",
|
||||
"6턴 Q: 좋은 파이썬 책 추천해줘?\n",
|
||||
"\n",
|
||||
" A: 파이썬 학습을 시작하는 분들을 위한 책은 정말 많습니다. 어떤 책이 '가장 좋다'고 단정하기보다는, **학습....\n",
|
||||
"\n",
|
||||
"7턴 Q: 무료로 배울 수 있는 사이트는?\n",
|
||||
"\n",
|
||||
" A: 파이썬을 무료로 배울 수 있는 훌륭한 온라인 플랫폼과 자료들이 정말 많습니다! 어떤 학습 스타일(인터랙티브 ....\n",
|
||||
"\n",
|
||||
"8턴 Q: 이전에 내가 뭘 물어봤는지 기억해?\n",
|
||||
"\n",
|
||||
" A: 네, 저는 **이전 대화의 맥락(Context)**을 기억하고 있습니다.\n",
|
||||
"\n",
|
||||
"지금까지의 대화 내용을 바탕으로,....\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 52
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
Reference in New Issue
Block a user