LLM(Large Language Model)의 멀티턴(Multi-turn) 방법론은 사용자가 챗봇이나 AI 모델과 여러 차례의 대화를 통해 원하는 답변이나 정보를 얻는 과정을 말합니다. 멀티턴 방법론을 구현할 때는 주로 다음의 요소와 기법이 중요하게 사용됩니다.
단순히 질문과 답변이 한 번에 끝나는(Single-turn) 것이 아니라, 여러 번 주고받으며 맥락(Context)을 유지하고 이전 대화 내용을 기억하여 더 적합하고 정확한 응답을 제공하는 방식입니다.
예시:
- 사용자: "내일 날씨 어때?"
- 챗봇: "내일 서울은 맑고 기온은 약 22도입니다."
- 사용자: "그럼 모레는?"
- 챗봇: (이전 대화 문맥 유지) "모레 서울은 흐리고 비가 올 확률이 높습니다."
LangChain, LlamaIndex 같은 프레임워크를 활용하여 쉽게 구축할 수 있습니다.벡터DB 및 임베딩(Embedding) 기술과 결합하여 효과적인 멀티턴 응답을 구현할 수 있습니다.명확한 컨텍스트 범위 설정:
맥락이 너무 길어지면 정확한 컨텍스트를 유지하기 어렵기 때문에 중요한 부분을 우선적으로 관리합니다.
효율적인 메모리 관리:
모든 정보를 메모리에 보관하지 말고, 중요한 정보만 압축하여 저장하거나 요약 기법을 적용합니다.
사용자 발화 해석의 유연성:
사용자가 이전의 맥락을 생략하거나 암시적으로 표현할 수 있으므로, 추론(Inference) 능력을 키워야 합니다.
"어제 주문한 물건 언제 도착하나요?"주문번호(#12345), 어제 주문한 "무선 이어폰"사용자 질문 → 배송 상태 조회(intent)
상품정보(slot) = "무선 이어폰", 주문번호(slot) = #12345"어제 주문하신 무선 이어폰(#12345)은 오늘 오후 5시에 배송 예정입니다."| 방법론 및 기술 | 설명 | 예시 도구 |
|---|---|---|
| Dialogue State Tracking | 사용자 발화에서 의도와 요구사항 파악 및 관리 | Rasa, Dialogflow |
| Prompt Engineering | 문맥을 프롬프트로 제공하여 멀티턴 생성 | GPT API, LangChain |
| Memory 메커니즘 | 대화 내용을 메모리에 저장하고 관리 | LangChain, Pinecone |
| Fine-tuning/RLHF | 맞춤형 데이터로 모델을 추가 학습하여 성능 향상 | Hugging Face, OpenAI API |
| Retrieval-Augmented Generation | 외부 정보 검색 후 응답 생성 | LlamaIndex, 벡터DB |
위의 방법론을 종합적으로 활용하면 자연스럽고 정확한 멀티턴 대화를 구현할 수 있습니다. 추가적으로 궁금한 사항이 있으면 알려주세요!
| 항목 | 주요 기술 및 방법 |
|---|---|
| 의도 분석 멀티턴 | Intent Classification, Dialogue State Tracking, Rasa, DialogFlow 등 대화 관리 기술 |
| LLM 단계 Fallback 멀티턴 | Session Memory 유지, Prompt Engineering, Dialogue Manager로 Fallback 조건 설정 |
위의 통합 구조를 통해 사용자의 질문 의도를 정확히 파악하고, 데이터 부족 시에도 자연스럽고 체계적으로 사용자와 대화를 이어갈 수 있습니다.
LangChain에서 멀티턴 대화를 구성하는 방식은 "문맥을 기억하면서 LLM과 연속적으로 대화하는 구조"로 설계됩니다.
아래에 전체 구성 원리와 예시, 그리고 문환님에게 맞는 실제 흐름을 설명해드릴게요.
| 요소 | 설명 |
|---|---|
| LLM | GPT-4, Claude 등과 연결되는 대화 엔진 |
| Memory | 이전 대화를 저장하고 이어서 사용할 수 있게 함 |
| Chain | 대화 흐름을 구성하는 처리 로직 (ex. ConversationChain, RouterChain) |
| PromptTemplate | 어떤 방식으로 LLM에게 질문할지 구성하는 틀 |
[사용자 질문] → “암보험 뭐가 좋아요?”
↓
[LangChain: ConversationChain + Memory]
→ LLM: “보험 나이와 성별을 알려주시면 비교해드릴게요.”
↓
[사용자 응답] → “30세 남자요”
↓
LangChain은 이전 문맥(‘암보험’ 문의)을 기억한 채,
→ DB RAG 또는 문서 RAG로 흐름 전환 가능
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory
# LLM 초기화
llm = ChatOpenAI(temperature=0)
# 메모리 생성 (대화 히스토리 저장용)
memory = ConversationBufferMemory()
# 멀티턴 대화용 체인 구성
conversation = ConversationChain(
llm=llm,
memory=memory,
verbose=True
)
# 사용자 대화 시뮬레이션
print(conversation.predict(input="암보험 추천해줘"))
print(conversation.predict(input="30세 남자입니다"))
print(conversation.predict(input="40세면 어떻게 돼요?"))
| 사용자 입력 | LLM이 인식하는 전체 문맥 |
|---|---|
| “40세면요?” | “암보험 추천” → “30세 남자입니다” → “40세면요?” |
즉, 대화 전체 흐름을 기억하며 맥락을 유지합니다.
| 질문 흐름 | 처리 방식 |
|---|---|
| “암보험 괜찮은 거 있어요?” | → ConversationChain으로 첫 intent 이해 |
| “30세 남자예요” | → memory에서 이전 발화 기억, DB RAG 실행 |
| “40세 기준은요?” | → context 유지하며 재질의 |
| “보장 항목은요?” | → 문서 RAG 전환 후, 결과 제공 |
| 전략 | 설명 |
|---|---|
ConversationBufferMemory | 간단한 멀티턴이면 이거면 충분 |
ConversationSummaryMemory | 대화 길어지면 요약 방식 메모리 추천 |
RouterChain + PromptTemplate | 질문 분석 후 알맞은 응답 흐름 분기 |
이제 LangChain만으로도 대화 흐름 유지 + 조건 부족 시 멀티턴 + RAG 연동까지 한 번에 처리할 수 있어요.
좋습니다, 문환님이 지금까지 주신 정보와 구성 내용을 모두 기반으로 보면,
LangChain 단독보다는 Rasa + LangChain을 연동한 하이브리드 방식이 가장 적합합니다.
두 종류의 질문을 처리해야 함:
멀티턴 흐름 필수:
유형별 시나리오가 정해져 있음
[사용자 질문]
↓
[Rasa]
├─ Intent 분석 (약관? 비교?)
├─ 슬롯 채우기 (나이/성별 등)
├─ 멀티턴 흐름 설계 (Rule 기반)
└─ Custom Action → LangChain 호출
↓
[LangChain]
├─ 문서 RAG (약관 설명)
├─ SQL RAG (보험료 비교)
└─ LLM fallback (조건 모호할 때 유도 질문)
최종 응답 → Rasa 통해 사용자 전달
| 기능 | Rasa | LangChain | 적용 이유 |
|---|---|---|---|
| Intent 분류 | O | △ (LLM 기반) | 문환님은 명확한 분류 기준을 갖고 있음 (약관 vs 비교) |
| 멀티턴 흐름 설계 | O (Stories, Rules) | △ (Memory) | 슬롯 채우기와 되묻기 처리를 안정적으로 수행 가능 |
| RAG 처리 | X | O (Vector/SQL) | LangChain에서 문서/DB 기반 질의 처리가 유연함 |
| 모호한 질문 처리 | △ (fallback rule) | O (LLM Prompt) | LLM이 follow-up 질문을 자연스럽게 생성 가능 |
| 시각화, 요약 | X | O | 결과 정리/요약 능력은 LLM이 강점 |
1. 사용자: 암보험 괜찮은 거 있어요?
→ [Rasa] → 보험 비교 Intent 분류됨 → 슬롯 부족 → 멀티턴
2. 사용자: 30세 남자예요
→ [슬롯 채움] → Custom Action → LangChain SQLChain 호출
3. LangChain: 보험료 비교 → 정리 후 응답 → Rasa가 사용자에게 출력
물론 가능합니다. 단,
➤ 더 유연하지만, 더 많은 설정/제어가 필요합니다.
문환님의 시스템처럼 약관 + 비교설계 + 멀티턴 + 시나리오 기반 흐름이 필요한 경우:
✅ “Rasa로 흐름 제어 + LangChain으로 검색·요약 처리”가 가장 안정적이고 확장성 있는 구조입니다.
좋습니다, 문환님이 제시한 데이터를 바탕으로 Rasa와 LangChain을 함께 사용하는 실제 예시 코드와 예상 출력 결과를 정리해드릴게요.
"암보험 괜찮은 거 있어요?"
ask_recommendation으로 intent 분류insu_age, sex가 비어 있으므로 다음 질문:보험 나이와 성별을 알려주시면 조건에 맞는 암보험 상품을 비교해드릴게요.
30세 남자입니다.
insu_age=30, sex=male 슬롯이 채워짐# actions/actions.py (Rasa 측)
class ActionFetchComparison(Action):
def name(self) -> Text:
return "action_fetch_comparison"
def run(self, dispatcher, tracker, domain):
age = tracker.get_slot("insu_age")
sex = tracker.get_slot("sex")
# LangChain API 서버로 요청
import requests
response = requests.post("http://localhost:8000/query", json={
"type": "db",
"age": age,
"sex": sex,
"intent": "compare_insurance"
})
answer = response.json()["answer"]
dispatcher.utter_message(text=answer)
return []
# main.py (LangChain API 서버)
from fastapi import FastAPI, Request
from langchain.llms import OpenAI
from langchain.chains import SQLDatabaseChain
from langchain.sql_database import SQLDatabase
app = FastAPI()
llm = OpenAI(temperature=0)
db = SQLDatabase.from_uri("mysql+pymysql://user:pwd@localhost/insurance")
chain = SQLDatabaseChain(llm=llm, database=db, verbose=True)
@app.post("/query")
async def query_handler(request: Request):
body = await request.json()
if body["type"] == "db":
prompt = f"""
30세 남성 기준으로 암보험 상품을 비교해줘.
보험료(premium_amount)를 기준으로 낮은 순으로 정리하고,
보험사명과 상품명도 함께 보여줘.
"""
response = chain.run(prompt)
return {"answer": response}
30세 남성 기준으로 추천되는 암보험 상품은 다음과 같습니다:
1. 삼성생명 - 스마트암케어: 월 28,000원
2. 한화손해 - 안심암보험: 월 31,000원
3. DB생명 - 뉴프라임암: 월 33,000원
모든 상품은 기본 암진단 특약을 포함하며, 특약 추가 시 금액이 달라질 수 있습니다.
그중에 갑상선암도 보장되나요?
→ LangChain의 Memory에서 이전 대화를 기억하고 문서 RAG로 전환:
conversation.predict(input="그중에 갑상선암도 보장되나요?")
삼성생명의 스마트암케어 상품은 일반암 진단시 보장되며, 갑상선암의 경우 경계성 종양으로 분류되어 일부 상품에서 제외될 수 있습니다. 약관을 확인하시겠어요?
| 구성 | 역할 | 장점 |
|---|---|---|
| Rasa | 멀티턴 흐름 제어, 슬롯 채우기 | 대화 흐름을 안정적으로 관리 |
| LangChain | DB 검색, 문서 요약, LLM 생성 | 유연한 응답 생성 및 자연어 요약 |
| FastAPI | Rasa ↔ LangChain 연결 | 구조적이고 유연한 통신 |
필정확히 이해하셨어요!
Rasa는 import ~ from rasa 같은 파이썬 코드 기반의 프레임워크가 아니라, YAML 설정 중심의 대화 설계 시스템이에요.
| 방식 | 설명 |
|---|---|
| ✅ YAML 파일 작성 | nlu.yml, domain.yml, stories.yml, rules.yml 등으로 대화 흐름, 의도, 응답, 슬롯을 정의 |
✅ actions.py만 파이썬 코드 | 외부 시스템 호출(LangChain, DB 등)이 필요할 때 actions.py에 파이썬 코드 작성 |
❌ 일반적인 Python 패키지처럼 import rasa 하고 사용하는 방식은 아님 | 대신 rasa run, rasa train, rasa shell 등 CLI 명령어로 작동함 |
# 이런 식으로 직접 사용하는 건 아님 ❌
from rasa import RasaModel ← 이런 코드 X
대신:
# 이런 식으로 터미널에서 실행해요 ✅
rasa train # 학습
rasa run # 서버 실행
rasa run actions # 파이썬 액션 서버 실행
rasa shell # 터미널에서 테스트 대화
nlu.yml: 질문 유형(Intent)과 예시 문장 작성domain.yml: 슬롯(Slot), 응답 템플릿 설정stories.yml 또는 rules.yml: 대화 흐름 설정actions.py: 필요한 외부 요청 코드 작성rasa train → 모델 학습rasa run + rasa run actions → 실행해서 챗봇 운영네, 가능합니다. 정확히 말하자면, LangChain으로도 Rasa를 대체하여 멀티턴(Multi-turn) 시스템을 구현할 수 있습니다. 다만, 두 가지 기술은 구현 방식과 강점이 서로 다릅니다. 아래에서 LangChain과 Rasa의 차이점과 장단점을 명확히 비교하여 설명드리겠습니다.
🔹 ① LangChain으로 멀티턴 시스템 구현
LangChain은 본래 LLM을 중심으로 다양한 도구(VectorDB, DB, API 등)를 연결하여 복잡한 워크플로우 및 멀티턴 질의응답 시스템을 구축하기 위한 Python 기반 프레임워크입니다.
LangChain의 주요기능
LangChain의 장점
LangChain의 단점
LangChain이 사용자의 암보험 사례에 좋은 이유
🔹 ② Rasa로 멀티턴 시스템 구현
Rasa는 Intent(의도) 분석과 대화 상태(Dialogue Management)를 중심으로 설계된 오픈소스 챗봇 프레임워크입니다.
Rasa의 주요기능
Rasa의 장점
Rasa의 단점
Rasa가 사용자의 암보험 사례에 좋은 이유
🔹 LangChain vs Rasa 비교표
| 기능 | LangChain | Rasa |
|---|---|---|
| 의도(Intent) 분석 | 🔸 직접 구현 필요 | ✅ 기본제공 |
| 멀티턴 대화 관리 | ✅ LLM 중심, 자연스러움 | ✅ 명확한 Flow 관리 |
| Prompt Engineering | ✅ 매우 뛰어남 | 🔸 제한적 |
| GUI 지원 여부 | ❌ 없음 | ✅ Rasa X 제공 |
| 구축 난이도 | 🔸 중간~상급 (개발 중심) | 🔸 중급 (데이터 관리 필요) |
| 데이터 및 배포 방식 | ✅ 자유로운 연결 | ✅ 자체 관리, 온프레미스 |
| 추천 사용자 | LLM 활용, 빠른 프로토타입, 유연한 구조 원함 | 명확한 Flow, GUI 관리, 데이터 자체 관리 필요함 |
🔹 사용자의 암보험 멀티턴 시스템에 추천하는 방향
사용자가 추구하는 VectorDB, MySQL RAG 및 LLM 중심의 자연스러운 추가 질문과 fallback 구조를 원하면 LangChain 추천
명확한 의도 분류, 보험상담의 정형화된 멀티턴 대화 흐름 관리, GUI기반 관리가 더 중요하면 Rasa 추천
실제 최근 LLM 기반의 멀티턴 및 RAG기반 질의응답 시스템 구축 시에는 LangChain의 활용이 높은 편이며,
기존의 Intent 및 시나리오 기반의 챗봇은 Rasa 활용도가 높습니다.
사용자의 환경(개발 리소스, 자체 데이터 관리 중요도 등)에 맞춰 기술을 선택하시면 가장 좋은 결과를 얻으실 수 있습니다.
🔹 결론 (LangChain이 Rasa 대체 가능?)
결과적으로 사용자의 암보험 시스템에는 LangChain이 충분히 Rasa를 대체 가능하며,
구체적인 의도(Intent) 분류와 세션 메모리 유지 등은 LangChain의 ConversationMemory 기능과 Prompt 설계를 통해 구현 가능합니다.
🔖 LangChain 학습 추천 자료
이러한 자료로 학습하면 LangChain을 사용해 Rasa를 충분히 대체하여 더욱 효율적이고 자연스러운 멀티턴 시스템 구축이 가능합니다.
좋은 질문이에요, 문환님!
“슬롯 기반 멀티턴이 강력한데, 그럼 LLM은 Rasa보다 성능이 낮은가요?”
→ 이건 상황에 따라 답이 달라지는 질문이에요.
아래에 비교 중심으로 설명드릴게요:
LLM이 Rasa보다 “기능이 부족”한 게 아니라,
“슬롯 기반 멀티턴”처럼 정형화된 흐름에는 Rasa가 더 강력하다는 뜻이에요!
| 항목 | 설명 |
|---|---|
| 슬롯 기반 | 챗봇이 필요한 정보를 하나씩 요청하며 대화 진행 |
| 장점 | 필요한 조건이 명확할 때 안정적으로 흐름 제어 |
| 예시 | “예약하려면 날짜, 시간, 인원수 주세요” → 누락된 항목 자동으로 질문 |
| 항목 | 설명 |
|---|---|
| LLM 멀티턴 | 문맥(Memory)을 기반으로 대화를 이어감 |
| 장점 | 유연하고 자연스러운 대화 흐름에 강함 |
| 단점 | “30세 남자인데 암보험 추천해줘” → 따로따로 주면 기억 실패할 수도 있음 (= 슬롯 기반처럼 보장되지 않음) |
| 사용자 발화 | Rasa 슬롯 기반 | LLM |
|---|---|---|
| “암보험 추천해줘” | → 나이, 성별 물어봄 | → “추천해줄게, 어떤 나이?” 질문 가능 |
| “30세 남자야” (다음 발화) | → 슬롯 채움, 정확히 이어짐 | → 문맥 기억 실패 가능 (짧은 모델이나 context 누락 시) |
| 상황 | Rasa (슬롯 기반) | LLM (Memory 기반) |
|---|---|---|
| 정형 데이터 수집 (예약, 견적, 설계 등) | ✅ 매우 강함 | △ 유연하지만 불안정 가능성 |
| 자연어 질의/응답 (약관 요약, 문서 설명 등) | ✖ 안됨 | ✅ 매우 강함 |
| 모호한 대화 흐름 처리 | △ 조건 필요 | ✅ 유도 질문 가능 |
보험 설계처럼 “나이, 성별” 등 조건이 명확하게 필요한 구조에서는
👉 Rasa가 슬롯 기반으로 흐름을 안정적으로 잡아주고,
👉 LangChain의 LLM이 답변을 자연스럽게 생성해주는 구조가 가장 효율적이에요.
문환님, 아주 좋은 질문이에요!
Rasa와 LangChain이 함께 동작할 때, "LangChain의 LLM은 어디서 실제 답변을 생성하느냐"에 대한 구체적인 흐름을 알려드릴게요.
LangChain의 LLM은 Rasa가 API로 요청을 보낸 “LangChain 서버”에서 응답을 생성해요.
즉, Rasa는 질문을 분석하고 정보를 모은 뒤,
LangChain 쪽에 “이제 답 좀 만들어줘”라고 요청하는 거예요.
LLM(GPT-4, Claude 등)은 LangChain 쪽에서 응답을 생성하고,
그 결과를 다시 Rasa가 받아서 사용자에게 전달합니다.
사용자 → Rasa 챗봇
↓
Rasa: 의도 분석 + 슬롯 수집
↓
Rasa Custom Action → LangChain 서버 호출 (예: /query)
↓
LangChain 내부:
- LLM에 프롬프트 구성
- SQL 또는 문서 검색 결과 포함
- GPT가 자연어 응답 생성
↓
LangChain → 응답 텍스트 반환
↓
Rasa → 사용자에게 전달
actions.pyresponse = requests.post("http://localhost:8000/query", json={
"type": "db",
"age": 30,
"sex": "male",
"intent": "compare_insurance"
})
# LLM이 만든 텍스트 응답
answer = response.json()["answer"]
dispatcher.utter_message(text=answer)
main.py)@app.post("/query")
async def query_handler(request: Request):
body = await request.json()
if body["type"] == "db":
# 프롬프트 구성
prompt = f"{body['age']}세 {body['sex']} 기준 암보험 상품을 추천해줘."
# LLM이 응답 생성
result = sql_chain.run(prompt)
return {"answer": result}
필요하시면 이 흐름을 도식 + 전체 연결 코드 예제로 Canvas에 정리해드릴게요.
넣어드릴까요? 😊