체인은 여러 컴포넌트(프롬프트, LLM, 파서 등)를 연결하여 복잡한 작업을 수행하는 파이프라인임.
입력 → 프롬프트 → LLM → 출력 파서 → 결과
why?
2-1. LCEL 기본 문법
LangChain 1.0부터 도입된 LCEL은 파이프(|) 연산자로 컴포넌트를 연결
basic example :
# week2_01_basic_chain.py
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLM
from langchain_core.output_parsers import StrOutputParser
# LLM 초기화
llm = OllamaLLM(model="qwen3:1.7b", temperature=0.7)
# 프롬프트 템플릿
prompt = PromptTemplate(
input_variables=["product"],
template="{product}의 특징을 3가지만 간단히 설명해주세요."
)
# 출력 파서
output_parser = StrOutputParser()
# 체인 구성 (LCEL 방식)
chain = prompt | llm | output_parser
# 실행
result = chain.invoke({"product": "개발자"})
print(result)

구조 설명:
입력 dict → PromptTemplate → LLM → StrOutputParser → 문자열
2-2. 순차체인(Sequential Chain)
여러 단계를 거쳐 결과를 만드는 체인임.
# week2_02_sequential_chain.py
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLM
from langchain_core.output_parsers import StrOutputParser
llm = OllamaLLM(model="qwen3:1.7b", temperature=0.7)
# 1단계: 주제 생성
topic_prompt = PromptTemplate(
input_variables=["interest"],
template="{interest}에 관련된 블로그 주제를 1개만 제안해주세요. 주제만 출력하세요."
)
# 2단계: 개요 작성
outline_prompt = PromptTemplate(
input_variables=["topic"],
template="{topic}에 대한 블로그 글 개요를 3개 항목으로 작성해주세요."
)
# 체인 구성
chain = (
topic_prompt
| llm
| StrOutputParser()
| {"topic": lambda x: x} # 결과를 다음 프롬프트의 input으로 전달
| outline_prompt
| llm
)
# 실행
result = chain.invoke({"interest": "인공지능"})
print(result)
응답 :
(llm_env) PS C:\dev\llm> & C:/dev/llm/llm_env/Scripts/python.exe c:/dev/llm/2-2.sequencial_chain.py
### 1. **인공지능의 윤리적 한계: 과학적 탐색과 사회적 논의의 핵심 문제**
- **AI의 윤리적 한계**: 기술의 발전이 가져오는 윤리적 갈등을 분석(예: 알고리즘의 편향, 데이터의 민감성, 인간의 권리 보호). 과학적 관점에서 AI의 불확실성과 위험성을 점검.
- **사회적 논의의 중요성**: 대중의 인식 부족과 윤리적 인식의 차이가 초래할 수 있는 사회적 문제(예: AI의 대규모 사용에 대한 반발, 기술의 불균형한 확산). 과학적 연구의 사회적 맥락을 반영한 대화의 필요성.
- **과학적 토론의 한계**: 이론적 모델의 현실성과 실제 적용의 차이, AI의 윤리적 가치 평가에 대한 학계의 갈등. 과학적 탐구의 범위와 제한성에 대한 경고.
---
### 2. **인공지능의 기회: 과학적 진보와 사회적 혁명의 결합**
- **AI의 혁신적 기능**: 의료 분야(예: 진단 정확도 향상), 환경 문제 해결(예: 탄소 배출 예측), 교육 기회 확대(예: 맞춤형 학습 시스템)에 대한 과학적 기대.
- **사회적 혁명의 가능성**: AI가 인간의 역할을 재정의할 수 있는 잠재력(예: 자동화로의 전환, 인간의 창의성의 강화). 과학적 발전과 사회적 변화의 동반성을 강조.
- **공동 혁신의 필요성**: 기술 개발과 윤리적 대화의 조화를 위한 정부, 학계, 대중의 협력. AI의 사회적 기능을 확장하는 데 있어 실용적 접근의 중요성.
---
### 3. **과학적 이해와 사회적 대화의 통합: AI의 윤리적 발전 방향**
- **과학적 이해의 핵심**: AI의 기초 과학적 원리(예: 머신러닝, 네트워크 분석)를 기반으로 한 이해의 필요성. 과학적 탐구의 결과와 윤리적 적용의 차이를 반영한 분석.
- **사회적 대화의 역할**: 대중의 참여를 통한 AI 윤리의 합리적 정의(예: 공정성, 편향 최소화). 사회적 대화가 기술의 윤리적 적용에 미치는 영향과 그 예시.
- **정책과 교육의 조화**: AI 윤리의 정책 수립과 학교 교육의 조정을 통해 대중의 인식 개선. 과학적 연구와 사회적 논의의 통합을 통해 AI의 윤리적 발전의 기반 마련.
흐름:
"인공지능" → 주제 생성 → "AI의 미래" → 개요 작성 → 최종 개요
2-3. 병렬 체인 (Parallel Chain)
여러 작업을 동시에 실행하고 결과를 합침.
# week2_03_parallel_chain.py
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLM
from langchain_core.runnables import RunnableParallel
llm = OllamaLLM(model="qwen3:1.7b", temperature=0.7)
# 장점 분석 프롬프트
pros_prompt = PromptTemplate(
input_variables=["topic"],
template="{topic}의 장점 2가지를 간단히 설명해주세요."
)
# 단점 분석 프롬프트
cons_prompt = PromptTemplate(
input_variables=["topic"],
template="{topic}의 단점 2가지를 간단히 설명해주세요."
)
# 병렬 체인 구성
parallel_chain = RunnableParallel(
pros=pros_prompt | llm,
cons=cons_prompt | llm
)
# 실행
result = parallel_chain.invoke({"topic": "바이브코딩"})
print("=== 장점 ===")
print(result["pros"])
print("\n=== 단점 ===")
print(result["cons"])
응답
(llm_env) PS C:\dev\llm> & C:/dev/llm/llm_env/Scripts/python.exe c:/dev/llm/2_3.parallel_chain.py
=== 장점 ===
바이브코딩(이하 바이너)의 주요 장점은 다음과 같습니다:
1. **효율적인 저장 및 전송**
바이너는 0과 1 두 상태로만 표현되어 데이터의 크기가 작고, 저장 용량이 절약됩니다. 이로 인해 정보 전송 시 전력 소모와 처리 시간이 줄어듭니다.
2. **고정된 구조와 일관성**
0과 1의 명확한 규칙이 있어 데이터를 쉽게 해석하고 처리할 수 있으며, 다양한 기술과 호환성이 뛰어납니다.
=== 단점 ===
바이브코딩의 단점 중 두 가지는 다음과 같습니다:
1. **복잡한 인코딩 과정**
생물학적 데이터는 구조화되지 않거나 다양한 형식으로 표현될 수 있어, 디지털 시스템과 호환성을 유지하기 위한 복잡한 알고리즘을 사용해야 하므로, 시간과 자원이 많이 소요됩니다.
2. **데이터 손실 또는 오류의 위험**
생물학적 데이터는 쉽게 오염되거나 손실될 수 있어, 인코딩 과정에서 품질을 유지하는 데 어려움이 생기며, 결과적으로 신뢰성을 떨어뜨릴 수 있습니다.
구조:
┌─→ 장점 분석 → pros
입력 ──→ ┤
└─→ 단점 분석 → cons
2-4. 조건부 체인 (Conditional Chain)
입력에 따라 다른 경로로 실행
# week2_04_conditional_chain.py
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLM
from langchain_core.runnables import RunnableLambda
llm = OllamaLLM(model="qwen3:1.7b", temperature=0.7)
# 기술 질문 프롬프트
tech_prompt = PromptTemplate(
input_variables=["question"],
template="기술 전문가로서 답변: {question}"
)
# 일반 질문 프롬프트
general_prompt = PromptTemplate(
input_variables=["question"],
template="친절하게 답변: {question}"
)
# 라우팅 함수
def route_question(input_dict):
question = input_dict["question"].lower()
# 기술 관련 키워드 체크
tech_keywords = ["코드", "프로그래밍", "api", "버그", "에러"]
if any(keyword in question for keyword in tech_keywords):
return tech_prompt | llm
else:
return general_prompt | llm
# 조건부 체인
chain = RunnableLambda(route_question)
# 실행
result1 = chain.invoke({"question": "파이썬 코드 에러를 어떻게 디버깅하나요?"})
print("기술 질문 답변:")
print(result1)
print("\n" + "="*50 + "\n")
result2 = chain.invoke({"question": "오늘 서울 날씨가 좋네요."})
print("일반 질문 답변:")
print(result2)
응답 :
(llm_env) PS C:\dev\llm> & C:/dev/llm/llm_env/Scripts/python.exe c:/dev/llm/2_4.conditional_chain.py
기술 질문 답변:
파이썬 코드 디버깅은 오류를 이해하고 해결하는 데 핵심적인 역할을 합니다. 다음은 디버깅을 위한 체계적인 접근 방법과 기법입니다:
NameError, TypeError, IndexError)는 오류의 유형과 위치를 알려줍니다.print(my_list[5]) # IndexErrortraceback을 사용해 오류 발생 위치와 호출 경로를 확인합니다.import traceback
traceback.print_exc()print 사용:print("현재 값:", my_var)logging 모듈:import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug("변수 값: %s", my_var)pdb 드로퍼).pdb (Python Debugger):import pdb; pdb.set_trace()ipdb:step / next:step은 루프 내부를 실행, next는 루프 외부를 실행).int("abc") → ValueError.int(input("입력: "))으로 입력 처리.my_list[5] → IndexError 발생.len(my_list) <= 5 검사.ImportError) → import 명령어 확인.if 조건, 루프 내부).print() 또는 logging을 통해 변수 값 추적.__file__ 변수:import sys
print(sys.modules['__main__'].__file__)sys 모듈 사용:__traceback__:PYTHONPATH 등을 확인해 모듈 불러오기 문제를 해결.unittest)로 오류를 사전에 검증.def calculate_sum(a, b):
return a + b
try:
result = calculate_sum(5, "abc")
print("결과:", result)
except TypeError as e:
print("타입 오류:", e)
TypeError: unsupported operand type(s) for +: 'int' and 'str'print(type(a)) → int 확인.print(a + b) → Traceback으로 오류 위치 확인.디버깅은 오류를 이해하고 해결하는 핵심 과정입니다.
==================================================
일반 질문 답변:
안녕하세요! 오늘 서울의 날씨가 정말 좋네요 😊
고마워요! 오늘은 어울리고 싶은 날이에요.
어떤 일이든 도와드릴 수 있어요! 😊
2-5 실전 복합체엔 예제 : 이메일 자동 분류 및 답변
# week2_05_email_system.py
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLM
from langchain_core.runnables import RunnableParallel, RunnableLambda
from langchain_core.output_parsers import StrOutputParser
llm = OllamaLLM(model="qwen3:1.7b", temperature=0.7)
# 1단계: 이메일 분류
classify_prompt = PromptTemplate(
input_variables=["email"],
template="""다음 이메일을 '기술지원', '영업', '일반문의' 중 하나로 분류하세요.
분류만 출력하세요.
이메일: {email}
분류:"""
)
# 2단계: 카테고리별 답변 생성
tech_support_prompt = PromptTemplate(
input_variables=["email"],
template="기술지원팀으로서 다음 이메일에 답변하세요 (2문장):\n\n{email}"
)
sales_prompt = PromptTemplate(
input_variables=["email"],
template="영업팀으로서 다음 이메일에 답변하세요 (2문장):\n\n{email}"
)
general_prompt = PromptTemplate(
input_variables=["email"],
template="고객센터로서 다음 이메일에 답변하세요 (2문장):\n\n{email}"
)
# 분류 결과에 따라 답변 생성
def generate_response(input_dict):
category = input_dict["category"].strip().lower()
email = input_dict["email"]
if "기술" in category:
prompt = tech_support_prompt
elif "영업" in category:
prompt = sales_prompt
else:
prompt = general_prompt
chain = prompt | llm
#return chain.invoke({"email": email})
response = chain.invoke({"email": email})
# 카테고리와 답변을 함께 반환
return {
"category": category,
"response": response
}
# 전체 체인 구성
email_chain = (
{
"email": lambda x: x["email"],
"category": classify_prompt | llm | StrOutputParser()
}
| RunnableLambda(generate_response)
)
# 테스트
test_emails = [
"로그인이 안 됩니다. 비밀번호를 초기화 할 수 있나요.",
"귀사 솔루션(브릴리언트)의 가격과 할인 정책이 궁금합니다."",
"영업시간이 어떻게 되나요?"
]
for i, email in enumerate(test_emails, 1):
print(f"\n{'='*60}")
print(f"이메일 {i}: {email}")
print(f"{'='*60}")
result = email_chain.invoke({"email": email})
print(f"분류: {result['category']}")
print(f"답변:\n{result['response']}")
응답 :
(llm_env) PS C:\dev\llm> & C:/dev/llm/llm_env/Scripts/python.exe c:/dev/llm/2_5.email_system.py
============================================================
이메일 1: 로그인이 안 됩니다. 비밀번호를 초기화 할 수 있나요.
============================================================
분류: 기술지원
답변:
로그인 문제는 원인을 확인해 보시면 좋습니다. 비밀번호 초기화는 로그인 페이지에서 '비밀번호 재설정' 또는 '아이디를 이용한 패스워드 재설정' 기능을 통해 진행할 수 있습니다.
============================================================
이메일 2: 귀사 솔루션(브릴리언트)의 가격과 할인 정책이 궁금합니다.
============================================================
분류: sales
답변:
브릴리언트의 솔루션 가격은 고객님의 구매량 및 기간에 따라 달라질 수 있으며, 추가 할인 조건이나 특별한 할인 정책도 제공하고 있습니다. 문의 사항은 고객 지원팀에 연락하시면 더욱 세 부적으로 안내해 드리겠습니다.
============================================================
이메일 3: 영업시간이 어떻게 되나요?
============================================================
분류: 분류: 일반문의
답변:
고객센터 영업시간은 월~금 9시부터 17시까지 운영됩니다. 문의사항은 언제든지 연락해 주세요!
2-6. 실전 디버깅 팁 (체인 디버깅)
# week2_06_debugging.py
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLM
from langchain_core.runnables import RunnablePassthrough
from langchain_core.runnables import RunnableLambda
llm = OllamaLLM(model="qwen3:1.7b")
prompt = PromptTemplate(
input_variables=["topic"],
template="{topic}에 대해 설명해주세요."
)
# 디버깅용 함수
def print_input(x):
print(f"🔍 중간 결과: {x}")
return x
# 체인에 디버깅 포인트 추가
chain = (
prompt
| RunnableLambda(print_input) # 프롬프트 결과 확인
| llm
| RunnableLambda(print_input) # LLM 결과 확인
)
chain.invoke({"topic": "랭체인"})
응답 :
(llm_env) PS C:\dev\llm> & C:/dev/llm/llm_env/Scripts/python.exe c:/dev/llm/2_6.debug_chain.py
🔍 중간 결과: text='랭체인에 대해 설명해주세요.'
🔍 중간 결과: 랭체인은 게임 **레전드 오브 랜드(Legend of Legends)**에서 사용되는 **랭킹 시스템**의 일환으로, 플레이어가 자신의 랭킹을 점진적으로 상승시키는 과정을 의미합니다. 이 시스템은 플레이어가 게임 내에서의 성능을 기반으로 랭킹을 업데이트하고, 최고 랭킹(1000)에 도달하는 과정을 포함합니다.
### 주요 내용:
1. **랭킹 시스템**:
- 게임 내에서 플레이어의 성능(예: 스타크래프트, 레전드 오브 랜드 등)을 기준으로 랭킹을 결정합니다. 랭킹은 1에서 1000까지 점진적으로 상승합니다.
- 랭킹은 플레이어의 기술, 채팅, 스타크래프트, 그리고 게임 내에서의 성능을 종합적으로 평가합니다.
2. **랭체인(랭킹 체인)**:
- 랭킹 시스템 내에서 플레이어가 점진적으로 상승하는 경로를 의미합니다. 예를 들어, 1 → 2 → 3 → ... → 1000으로 이어지는 과정입니다.
- 랭킹 체인은 플레이어가 최고 랭킹(1000)에 도달하기 위해 필요한 단계를 포함합니다.
3. **특징**:
- 플레이어는 랭킹 체인을 통해 게임 내에서의 랭킹을 점진적으로 상승시킬 수 있습니다.
- 랭킹 체인은 게임의 전반적인 성능과 플레이어의 기술, 전략, 채팅 등을 종합적으로 반영합니다.
### 예시:
- 플레이어가 1 → 2 → 3 → ... → 1000 랭킹으로 상승하는 과정은 랭체인입니다.
- 랭체인은 게임 내에서의 성능과 전략적 능력을 반영하여, 플레이어의 성취도를 평가합니다.
### 결론:
랭체인은 게임 내에서 플레이어가 점진적으로 상승하는 랭킹 경로를 의미하며, 이는 게임의 기술, 전략, 채팅, 그리고 성능을 종합적으로 평가하는 시스템입니다. 최고 랭킹(1000)에 도달하는 과정은 랭체인의 핵심입니다.