Ⅰ. 오전 수업
A. 1교시
1. 지난 시간 복습
2. request 활용하기
3. response 활용하기
B. 2교시
1. response 활용하기 (cont.)
2. 파일 활용
C. 3교시
1. form 태그로 데이터 주고받기
Ⅱ. 오후 수업
A. 4교시
1. 지난 시간 복습
2. 메모리를 가진 챗봇 구현
B. 5교시
1. ConversationChain 클래스가 더 이상 권장되지 않는 문제
2. RunnableWithMessageHistory
C. 6교시
1. RAG (Retrieval - Argumented Generation)
2. PDF를 학습한 나만의 챗봇 만들기
Ⅲ. CAREER UP
A. 현직자 특강
Ⅳ. 하루 돌아보기
| blocking(동기) | non-blocking(비동기) |
|---|---|
| 설계가 매우 간단하고 직관적 | 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업 가능 |
| 결과가 주어질 때까지 대기 → 시간 효율 좋지 않음 | 동기보다 코드 짜기 복잡함 |
require로 불러와야 함const {result} = require("./0_더하기모듈");const http = require("http");module.exports = {result};
cd .\1_노드기초\node .\2_req.jsipconfig 입력
:3000 포트 붙이기 → 터미널 확인
let ip = req_ip.getClientIp(req);로 ip 정보를 가져올 수 있음

localhost:3000 입력
서버 수정할 때는 항상 서버를 먼저 끄자! → CTRL + C

.writeHead();res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});<!DOCTYPE html><meta charset="UTF-8">.end();

사실 위에서 쓴 기법들은 실제로는 잘 사용하지 않아요~
const fs = require("fs").promises;/*
실습 목표: 미리 제작해 둔 HTML 파일을 사용자에게 보내주는 실습
* 정적 페이지를 활용한다 → 사용자마다 모두 똑같은 화면을 볼 때
* 모듈: fs모듈(filesystem) → 파일을 넘길 때 활용하는 모듈(내장모듈)
* 키 포인트: 사용자에게 응답을 담당하는 변수는 res → html 파일을 넘겨준다.
실습 핵심: node는 기본적으로 비동기로 코드를 처리 → 작업이 오래 걸리지 않는 업무를 먼저 처리
* 주의점: 오래 걸리는 코드의 결과를 활용하는 코드는 오류가 발생
* 해결책: 개발자가 임의로 코드의 순서를 지정한다.
* async/await → await를 만나면 해당 코드가 끝날 때까지 밑의 코드를 실행하지 않는다.
*/
const http = require("http");
const fs = require("fs").promises;
http.createServer(async (req,res)=>{
let html = await fs.readFile("./return.html");
res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"});
res.write(html);
res.end();
}).listen(3000);
node:_http_outgoing:950
throw new ERR_INVALID_ARG_TYPE(
^
TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Promise
at write_ (node:_http_outgoing:950:11)
at ServerResponse.write (node:_http_outgoing:905:15)
at Server.<anonymous> (C:\Users\내 PC\Desktop\Node\1_node_basic\4_file.js:13:9)
at Server.emit (node:events:519:28)
at parserOnIncoming (node:_http_server:1168:12)
at HTTPParser.parserOnHeadersComplete (node:_http_common:117:17) {
code: 'ERR_INVALID_ARG_TYPE'
}
Node.js v22.19.0
res.write(html);에서 왜 오류가 날까?



const http = require("http");
const fs = require("fs").promises;
http.createServer(async (req,res)=>{
let html = await fs.readFile("./return.html");
res.write(html);
res.end();
}).listen(3000);
express 프레임워크 쓰면 알아서 처리해 주니까 너무 많이 신경쓰진 말고 개념 정도만 기억하세요~


const http = require("http");
// url 데이터를 객체 형태로 변환하는 모듈 → GET 방식과 세트
const url = require("url");
http.createServer((req,res)=>{
console.log(req.url); // req.url → "/?id=isuhyeon&pw=1234" 문자열 형태 → 객체로 변환 필요
// get 방식은 데이터를 url에 보낸다 → req.url
// 문제점: 넘어온 데이터가 string(문자열) → 특정 값에 접근이 불가능
// 해결책: 따로 따로 접근할 수 있게 문자열을 객체로 변환
let data = url.parse(req.url,true).query; // string을 객체 형태로 변환
console.log(data);
}).listen(3000);


// 미션: 콘솔창에 '안녕하세요. 당신의 id는 000입니다.'
// 미션: 콘솔창에 '당신의 pw는 000입니다.'
// 힌트: 객체 데이터 → .key
console.log(`안녕하세요. 당신의 id는 ${data.id}입니다.`);
console.log(`당신의 pw는 ${data.pw}입니다.`);
.invoke()만 하면 흐르듯 출력되는 스트리밍을 진행할 수 있음lim.stream()을 반복문에 넣어 토큰 단위로 출력 # 구글 마운트 및 경로 설정
%cd /content/drive/MyDrive/Colab Notebooks/LangChain
# api key 설정
import os
with open("./key/.openai_api_key",'r') as f:
api_key = f.read().strip()
os.environ["OPENAI_API_KEY"] = api_key
!pip install -qU openai langchain-openai langchain langchain_community
!pip install -qU tiktoken pypdf chromadb faiss-cpu
!pip install -qU langchain-teddynote
!pip install -qU huggingface_hub langchain_huggingface
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, FewShotPromptTemplate, PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler # 스트리밍 → 모델 생성 시 포함
# 모델 생성
llm = ChatOpenAI(
model = "gpt-4o-mini"
, temperature=0
, max_tokens=100
, streaming=True
, callbacks=[StreamingStdOutCallbackHandler()]
)
# 간단한 챗봇 구성하기
while True:
q = input("입력: ")
if q == "exit":
print("채팅 종료")
break
# 모델 응답
llm.invoke(q)
print() # 개행용 print
입력: 안녕, 점심 메뉴를 추천해 줄래?
안녕하세요! 점심 메뉴로 몇 가지 추천해드릴게요.
1. **비빔밥** - 다양한 채소와 고기를 넣고 고추장과 함께 비벼 먹는 건강한 한 끼.
2. **김치찌개** - 뜨끈한 김치찌개에 밥을 곁들여 먹으면 든든하고 맛있어요.
3. **샐러드 볼** - 신선한 채
입력: 첫 번째 메뉴로 유명한 광주 맛집 소개해 줘
광주에는 다양한 맛집이 있지만, 특히 첫 번째 메뉴로 유명한 곳 몇 군데를 소개해드릴게요.
1. **광주식당** - 이곳은 전통적인 광주식 한정식으로 유명합니다. 신선한 재료로 만든 다양한 반찬과 함께 제공되는 메인 요리가 특징입니다.
2. **무등산막걸리** - 이곳은 막걸리와 함께 즐길 수 있는 전통 안
입력: 네가 아까 이야기한 내용에서 두 번째 메뉴가 뭐였지?
죄송하지만, 제가 이전에 이야기한 내용을 기억할 수는 없습니다. 어떤 메뉴에 대해 이야기하고 싶으신지 구체적으로 말씀해 주시면, 그에 대한 정보를 제공해 드리겠습니다.
입력: 아까 점심 메뉴 추천해 준 거 기억나니?
죄송하지만, 이전 대화 내용을 기억할 수는 없습니다. 하지만 점심 메뉴 추천이 필요하시면 기꺼이 도와드리겠습니다! 어떤 종류의 음식을 원하시나요?
입력: exit
채팅 종료
→ 메모리가 없는 상태라 이전 대화 내용을 기억하지 못함
from langchain.chains import ConversationChain # 대화형 체인을 구성하기 위한 클래스
from langchain.memory import ConversationBufferMemory # 대화 기록을 저장하는 클래스
# 1. 메모리 객체 생성
memory = ConversationBufferMemory()
# 2. 체인 구성: 대화형 모델과 메모리를 결합
conversation = ConversationChain(llm=llm, memory=memory)
# 챗봇 실행
while True:
q = input("입력 :")
if q == "exit":
print("채팅 종료")
break
# 모델 응답
conversation.invoke(q)
print() # 개행용
입력 :안녕, 오늘 점심 메뉴 추천해 줄 수 있니?
안녕! 물론이지! 점심 메뉴로는 여러 가지가 좋을 것 같은데, 어떤 종류의 음식을 좋아해? 예를 들어, 한식, 중식, 일식, 양식 중에서 선호하는 게 있어? 아니면 특별히 먹고 싶은 재료가 있으면 알려줘! 그에 맞춰 추천해 줄게.
입력 :난 양식이 좋아. 그중에서도 스페인 요리를 좋아해.
스페인 요리를 좋아하신다니 멋지네요! 스페인 요리 중에서는 파에야가 정말 유명하죠. 해산물이나 닭고기, 채소를 넣고 쌀과 함께 조리하는 요리인데, 풍미가 가득하고 한 끼 식사로 아주 만족스러워요. 또, 타파스도 추천해 드리고 싶어요. 다양한 작은 요리들을 여러 가지 맛볼 수 있어서 친구
입력 :광주에 파에야 파는 곳이 있을까?
광주에 파에야를 파는 곳이 몇 군데 있어요! 예를 들어, "스페인 레스토랑" 같은 곳에서는 정통 스페인식 파에야를 맛볼 수 있습니다. 해산물 파에야나 닭고기 파에야 등 다양한 옵션이 있을 거예요. 또, "타파스 바" 같은 곳에서도 파에야와 함께 다양한 타파스를 즐길 수 있어서 좋습니다. 구체적인
입력 :두 번째로 추천해 준 메뉴가 뭐얐지?
두 번째로 추천해 드린 메뉴는 타파스였어요! 타파스는 스페인에서 유래된 다양한 작은 요리들을 말하는데, 여러 가지 맛을 한 번에 즐길 수 있어서 정말 좋습니다. 예를 들어, 감자 브라바스, 올리브, 하몽, 그리고 다양한 해산물 요리들이 포함될 수 있어요. 친구들과 함께 나눠 먹기에도 아주 좋은 메뉴랍니다!
입력 :exit
채팅 종료
→ 이전 대화 내용을 잘 기억함
# 메모리 확인
print(memory.buffer)
Human: 안녕, 오늘 점심 메뉴 추천해 줄 수 있니?
AI: 안녕! 물론이지! 점심 메뉴로는 여러 가지가 좋을 것 같은데, 어떤 종류의 음식을 좋아해? 예를 들어, 한식, 중식, 일식, 양식 중에서 선호하는 게 있어? 아니면 특별히 먹고 싶은 재료가 있으면 알려줘! 그에 맞춰 추천해 줄게.
Human: 난 양식이 좋아. 그중에서도 스페인 요리를 좋아해
AI: 스페인 요리를 좋아하신다니 멋지네요! 스페인 요리 중에서는 파에야가 정말 유명하죠. 해산물이나 닭고기, 채소를 넣고 쌀과 함께 조리하는 요리인데, 풍미가 가득하고 한 끼 식사로 아주 만족스러워요. 또, 타파스도 추천해 드리고 싶어요. 다양한 작은 요리들을 여러 가지 맛볼 수 있어서 친구
Human: 광주에 파에야 파는 곳이 있을까?
AI: 광주에 파에야를 파는 곳이 몇 군데 있어요! 예를 들어, "스페인 레스토랑" 같은 곳에서는 정통 스페인식 파에야를 맛볼 수 있습니다. 해산물 파에야나 닭고기 파에야 등 다양한 옵션이 있을 거예요. 또, "타파스 바" 같은 곳에서도 파에야와 함께 다양한 타파스를 즐길 수 있어서 좋습니다. 구체적인
Human: 두 번째로 추천해 준 메뉴가 뭐얐지?
AI: 두 번째로 추천해 드린 메뉴는 타파스였어요! 타파스는 스페인에서 유래된 다양한 작은 요리들을 말하는데, 여러 가지 맛을 한 번에 즐길 수 있어서 정말 좋습니다. 예를 들어, 감자 브라바스, 올리브, 하몽, 그리고 다양한 해산물 요리들이 포함될 수 있어요. 친구들과 함께 나눠 먹기에도 아주 좋은 메뉴랍니다!
ConversationBufferWindowMemory()from langchain.memory import ConversationBufferWindowMemory # 저장할 대화의 개수 설정
# 메모리 객체 생성 (최근 2개 대화만 저장)
memory_2 = ConversationBufferWindowMemory(k=2)
# 직접 이전 대화 내용을 적립할 수도 있음 → save_context
memory_2.save_context({"input": "너는 누구니"},
{"output": "저는 홍길동입니다"})
memory_2.save_context({"input": "나이는"},
{"output": "25세입니다"})
memory_2.save_context({"input": "직업은"},
{"output": "의적입니다"})
memory_2.save_context({"input": "집은 어디지"},
{"output": "전라남도 장성입니다"})
print(memory_2.buffer)
Human: 직업은
AI: 의적입니다
Human: 집은 어디지
AI: 전라남도 장성입니다
# 1. 메모리 객체 생성
memory = ConversationBufferWindowMemory(k=2)
# 2. 체인 구성: 대화형 모델과 메모리를 결합
conversation = ConversationChain(llm=llm, memory=memory)
# 챗봇 실행
while True:
q = input("입력 :")
if q == "exit":
print("채팅 종료")
break
# 모델 응답
conversation.invoke(q)
print() # 개행용
입력 :안녕, 꽥꽥 하고 우는 하얀 동물이 뭐지?
안녕! 꽥꽥 하고 우는 하얀 동물은 바로 오리야. 오리는 물가에서 자주 발견되며, 꽥꽥 소리를 내는 것이 특징이야. 하얀 오리는 특히 농장에서 많이 볼 수 있고, 때로는 애완동물로도 기르기도 해. 오리는 물속에서 헤엄치는 것을 좋아하고, 주로 곤충이나 식물의 씨앗을 먹
입력 :방금 전에 어떤 동물 이야길 했더라?
방금 전에 오리에 대해 이야기했어. 오리는 꽥꽥 소리를 내는 하얀 동물로, 주로 물가에서 발견되고 농장에서 많이 볼 수 있어. 물속에서 헤엄치는 것을 좋아하고, 곤충이나 식물의 씨앗을 먹는다고 했지. 더 궁금한 점이 있으면 언제든지 물어봐!
입력 :남극에 살고 있는 동물에 대해 알고 있어?
네, 남극에는 다양한 동물들이 살고 있어! 가장 잘 알려진 동물 중 하나는 펭귄이야. 특히 황제펭귄은 남극에서 가장 큰 펭귄 종류로, 약 1.2미터까지 자랄 수 있어. 이들은 극한의 추위에서도 살아남기 위해 서로 몸을 맞대고 체온을 유지하는 행동을 해.
또한, 남극에는 바다표
입력 :북극에도 동물이 살고 있어?
네, 북극에도 다양한 동물들이 살고 있어! 북극의 대표적인 동물 중 하나는 북극곰이야. 북극곰은 두꺼운 털과 지방층 덕분에 극한의 추위에서도 잘 견딜 수 있어. 이들은 주로 바다 얼음 위에서 사냥을 하며, 물개와 같은 해양 포유류를 주로 먹어.
또한, 북극에는 순록
입력 :북극곰은 뭘 먹을까?
북극곰은 주로 해양 포유류를 먹어. 그들의 주요 먹이는 물개, 특히 고래와 물개가 있는 지역에서 사냥하는 경우가 많아. 북극곰은 얼음 위에서 물개가 숨을 쉬기 위해 올라오는 구멍을 기다리며 사냥을 하기도 해. 이 외에도, 때때로 조류나 죽은 고래와 같은 다른 먹이도 섭취할 수
입력 :네가 첫 번째로 소개한 남극 동물 이름이 뭐였지?
죄송하지만, 제가 남극 동물에 대해 언급한 적은 없어요. 북극에 대한 이야기만 했었죠. 남극에는 펭귄, 바다코끼리, 그리고 다양한 해양 생물들이 살고 있어요. 궁금한 점이 있으면 언제든지 물어보세요!
입력 :exit
채팅 종료
→ 마지막 대화로부터 세 번째에 위치한 대화(남극 동물)를 기억하지 못함
ConversationChain 클래스가 더 이상 권장되지 않는 문제
- LangChain 0.2.7 버전부터 사용 중지(deprecated)로, 향후 1.0 버전에서 삭제될 예정
- 아래 Memory 클래스도 마찬가지
| Memory Type | 설명 |
|---|---|
| ConversationBufferMemory | 이전 대화 내용을 그대로 저장하는 메모리 |
| ConversationBufferWindowMemory | 윈도우 크기 k를 지정하면 최근 k개의 대화만 기억하고, 그 이전 대화는 삭제됨 |
| ConversationTokenBufferMemory | 최근 대화 히스토리를 버퍼에 저장하며, 대화 개수가 아닌 토큰 길이를 기준으로 대화내용 플러시 시기를 설정함 |
| ConversationSummaryMemory | 이전 대화 내용을 그대로 기억하지 않고 요약해서 저장함. 긴 대화에서 토큰 사용량을 줄이는 데 유용 |
| ConversationSummaryBufferMemory | ConversationSummaryMemory의 확장판 이전 대화를 요약해 저장하면서 최근 대화는 최대 토큰 범위 내에서 유지하도록 하며, 최대 토큰 길이를 지정할 수 있음 토큰을 줄여 API 활용 시 비용을 최소화하는 효율적인 메모리 |
| VectorStoreRetrieverMemory | 대화 내역을 벡터 저장소에 저장하고, 입력을 기반으로 과거 대화 중 가장 관련성 높은 부분을 검색함 |
~langchain_core.runnables.history.RunnableWithMessageHistory instead./tmp/ipython-input-2383733555.py:5: LangChainDeprecationWarning: The class
ConversationChainwas deprecated in LangChain 0.2.7 and will be removed in 1.0. Use :class:~langchain_core.runnables.history.RunnableWithMessageHistoryinstead.
conversation = ConversationChain(llm=llm, memory=memory)
→ RunnableWithMessageHistory 사용해 보기
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.chat_history import InMemoryChatMessageHistory
# 기본 컴포넌트 설정
prompt = ChatPromptTemplate.from_messages([
("system", "당신은 천문학 전문가입니다. 사용자와 친근한 대화를 나누며 천문학 질문에 답변해주세요."),
MessagesPlaceholder(variable_name="history"),
("human", "{question}")
])
chain = prompt | llm
# 메모리 저장소 구성
store = {}
def get_session_history(session_id: str) -> InMemoryChatMessageHistory:
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
# 메모리 기능을 가진 체인 생성
chain_with_history = RunnableWithMessageHistory(
chain, # 기본 체인 (prompt | llm)
get_session_history, # 세션 히스토리를 가져오는 함수
input_messages_key="question", # 사용자 입력 키
history_messages_key="history", # 대화 기록 키
)
# 대화 흐름 분석
config = {"configurable": {"session_id": "astronomy_chat_1"}}
# 첫 번째 대화
response1 = chain_with_history.invoke(
{"question": "안녕하세요, 저는 지구과학을 공부하는 학생입니다."},
config=config
)
# 두 번째 대화 - 컨텍스트 유지
response2 = chain_with_history.invoke(
{"question": "태양계에서 가장 큰 행성은 무엇인가요?"},
config=config
)
# 세 번째 대화 - 참조 관계 이해
response3 = chain_with_history.invoke(
{"question": "그 행성의 위성은 몇 개나 되나요?"},
config=config
)
웹 개념의 '쿠키 세션'을 차용해 사용자마다 이전 기록을 저장하는 아이디(세션 아이디)를 부여하고 DB에 저장
기억한 질문에 대해 메모리를 따로 꾸려서(방을 사용자마다 각각 만듦) 사용자 로그인 시 이전 대화 내용을 기억할 수 있도록 만듦
# 라이브러리 불러오기
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.output_parsers import StrOutputParser
# 1. 모델 생성
llm_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 2. 메시지 리스트 생성 → 과거 기록 관리
messages = [
("system","너는 신뢰 가능한 AI 조수다.")
, MessagesPlaceholder(variable_name="history") # 과거 대화 기록이 들어갈 자리
, ("human", "{input}")
]
# 3. 메시지 기반 템플릿 객체 생성
prompt = ChatPromptTemplate.from_messages(messages)
# 4. 체인 구성
chain = prompt | llm_model | StrOutputParser()
# 5. 세션 기록 저장을 위한 딕셔너리
# {key: value} → {session_id: ChatMessageHistory}
store = {}
# 6. 세션을 관리하는 함수 정의
# 대화 기록을 저장하고 관리하는 담당: ChatMessageHistory
def get_session_history (session_ids: str): # type hinting
if session_ids not in store: # 만약 store에 세션 id가 없다면 새로운 히스토리 메시지를 생성
store[session_ids] = ChatMessageHistory()
return store[session_ids] # 이미 존재하는 세션 → 딕셔너리에서 히스토리 메시지를 반환
# 7. 체인과 세션을 관리하는 함수를 연결
# RunnableWithMessageHistory
with_message_history = RunnableWithMessageHistory(
chain # llm 체인
, get_session_history # 대화 기록 관리 함수
, input_messages_key="input" # 입력 받는 값 → 2번에서 이미 등장함
, history_messages_key="history" # 메시지에서 정의한 history → 2번에서 이미 등장함
)
# 8. 무한 루프를 통한 채팅 진행
# 챗봇 실행
while True:
q = input("입력: ")
if q == "exit":
print("채팅 종료")
break
# 모델 응답
res = with_message_history.invoke(
{"input": q}
, config = {"configurable":{"session_id":"x-test1234"}} # 세션 아이디를 전달하여 해당 대화 기록을 불러오거나 새로 생성
)
print(res)
print()
입력: 안녕하세요, 남극에 사는 동물에 대해 알려주시겠어요?
안녕하세요! 남극은 극한의 환경이지만, 그곳에도 다양한 동물들이 살고 있습니다. 남극의 동물들은 극한의 추위와 얼음으로 덮인 환경에 적응하여 생존하고 있습니다. 주요 동물들을 소개해 드릴게요.
1. **펭귄**: 남극에서 가장 잘 알려진 동물 중 하나입니다. 특히 황제펭귄과 아델리펭귄이 유명합니다. 펭귄은 수영을 잘하며, 바다에서 물고기를 잡아 먹습니다. 그들은 육지에서 번식하며, 알을 낳고 새끼를 기릅니다.
2. **물개**: 남극에는 여러 종류의 물개가 서식합니다. 대표적으로 남극물개, 웨델물개, 그리고 얼음물개가 있습니다. 이들은 바다에서 먹이를 찾고, 얼음 위에서 휴식을 취합니다.
3. **고래**: 남극 주변의 바다에는 여러 종류의 고래가 서식합니다. 대표적으로 남극흰수염고래, 혹등고래, 그리고 범고래가 있습니다. 이들은 주로 크릴과 같은 해양 생물을 먹고 삽니다.
4. **남극 크릴**: 남극의 해양 생태계에서 중요한 역할을 하는 작은 갑각류입니다. 많은 해양 동물들이 크릴을 주요 먹이로 삼습니다.
5. **남극 새**: 남극 대륙 자체에는 새가 많지 않지만, 주변의 섬들에는 다양한 새들이 서식합니다. 예를 들어, 남극갈매기와 남극제비갈매기가 있습니다.
6. **바다표범**: 남극의 바다에는 여러 종류의 바다표범이 서식합니다. 이들은 얼음 위에서 휴식을 취하고, 바다에서 물고기를 잡아 먹습니다.
남극의 동물들은 극한의 환경에서 생존하기 위해 특별한 적응을 가지고 있으며, 그들의 생태계는 매우 독특합니다. 더 궁금한 점이 있으면 언제든지 질문해 주세요!
입력: 북극에는 어떤 동물이 사나요?
북극 지역은 극한의 환경이지만, 다양한 동물들이 이곳에서 생존하고 있습니다. 북극의 동물들은 극한의 추위와 얼음으로 덮인 환경에 적응하여 살아가고 있습니다. 주요 동물들을 소개해 드릴게요.
1. **북극곰**: 북극의 상징적인 동물로, 주로 얼음 위에서 사냥을 하며 물개와 같은 해양 포유류를 주로 먹습니다. 북극곰은 두꺼운 지방층과 털로 덮여 있어 극한의 추위에서도 잘 견딥니다.
2. **바다표범**: 북극 지역에는 여러 종류의 바다표범이 서식합니다. 대표적으로 링세일표범, 하프물범, 그리고 그린란드표범이 있습니다. 이들은 얼음 위에서 휴식을 취하고, 바다에서 물고기를 잡아 먹습니다.
3. **북극여우**: 북극여우는 두꺼운 털로 덮여 있어 추위에 잘 견디며, 주로 작은 설치류, 새, 그리고 과일 등을 먹습니다. 여름철에는 털 색이 갈색으로 변해 환경에 잘 녹아듭니다.
4. **순록**: 북극 지역의 타이가와 툰드라에서 서식하는 동물로, 주로 식물과 이끼를 먹습니다. 순록은 이동성이 강해 계절에 따라 이동합니다.
5. **북극토끼**: 북극토끼는 두꺼운 털로 덮여 있으며, 주로 풀과 이끼를 먹습니다. 겨울철에는 흰색 털로 변해 눈과 잘 어우러집니다.
6. **고래**: 북극 해역에는 여러 종류의 고래가 서식합니다. 대표적으로 벨루가고래, 혹등고래, 그리고 북극고래가 있습니다. 이들은 주로 물고기와 크릴을 먹습니다.
7. **해양 조류**: 북극 지역에는 다양한 해양 조류가 서식합니다. 대표적으로 북극갈매기, 알카, 그리고 북극제비갈매기가 있습니다.
북극의 동물들은 극한의 환경에서 생존하기 위해 특별한 적응을 가지고 있으며, 그들의 생태계는 매우 독특합니다. 더 궁금한 점이 있으면 언제든지 질문해 주세요!
입력: 북극에 여우는 안 사나요?
북극에는 **북극여우**(Arctic fox)가 서식합니다. 북극여우는 북극 지역의 대표적인 동물 중 하나로, 극한의 추위에 잘 적응해 있습니다. 이들은 두꺼운 털로 덮여 있어 체온을 유지할 수 있으며, 겨울철에는 털 색이 흰색으로 변해 눈과 잘 어우러집니다. 여름철에는 갈색이나 회색으로 변해 주변 환경에 잘 녹아듭니다.
북극여우는 주로 작은 설치류, 새, 그리고 과일 등을 먹으며, 때때로 사냥한 먹이를 저장해 두기도 합니다. 이들은 매우 적응력이 뛰어나고, 북극의 혹독한 환경에서도 생존할 수 있는 능력을 가지고 있습니다.
따라서 북극에는 여우가 살고 있으며, 북극여우는 그 지역의 생태계에서 중요한 역할을 하고 있습니다. 더 궁금한 점이 있으면 언제든지 질문해 주세요!
입력: 남극에 사는 동물 알려주셨을 때 세 번째로 이야기해주신 동물 이름이 뭐였을까요?
남극에 사는 동물에 대해 이야기할 때 세 번째로 언급한 동물은 **고래**입니다. 남극 주변의 바다에는 여러 종류의 고래가 서식하며, 대표적으로 남극흰수염고래, 혹등고래, 그리고 범고래가 있습니다. 이들은 주로 크릴과 같은 해양 생물을 먹고 삽니다. 더 궁금한 점이 있으면 언제든지 질문해 주세요!
입력: exit
채팅 종료
추가: history 변수
history 변수는 대화의 맥락(과거 메시지 기록)을 저장하고, 프롬프트에 동적으로 삽입하는 역할을 합니다. 이 history가 실제로 어디에서 데이터가 할당되고 전달되는지 이해하기 위해 각 흐름을 단계별로 설명합니다.
- history의 흐름 요약
- MessagesPlaceholder(variable_name="history")
- 프롬프트에 history라는 이름으로 과거 대화 메시지가 들어갈 자리를 지정
- 하지만, 이 시점에서는 내용을 채우지 않음
- RunnableWithMessageHistory
- chain에 세션별로 history 값을 실제로 전달하는 객체
- get_session_history
- session_id별로 각각의 ChatMessageHistory 인스턴스를 반환하는 함수
- ChatMessageHistory
- 해당 세션의 실제 과거 메시지(=history)를 저장하는 객체
- invoke 시점:
- RunnableWithMessageHistory가 invoke될 때, 내부적으로 get_session_history 함수로부터 해당 세션의 ChatMessageHistory 객체를 받아 그 안에 저장된 history를 “history” 변수로 프롬프트(template)에 넘김
- 코드 라인별 핵심 연결
- MessagesPlaceholder(variable_name="history")
- 프롬프트 템플릿에서 'history'라는 자리표시자로 삽입됨
- RunnableWithMessageHistory
- 세션별로 history(=대화기록)를 동적으로 꺼내서 history 자리표시자 자리에 끼워 넣음
- 이때 get_session_history 함수를 통해 history 데이터를 얻음
- invoke 호출
- config에 session_id 값을 주면, 이 값으로 store 딕셔너리에서 ChatMessageHistory 객체를 가져오고, 이 객체가 가진 메시지들이 history로 전달됨
- chain에게 프롬프트를 전달할 때, 'input'은 사용자의 새 질문, 'history'는 get_session_history에서 가져온 메시지 배열로 전달
- 실제 동작 그림
- 사용자가 입력(q)을 하면,
- with_message_history.invoke 호출 → config의 session_id로 적절한 ChatMessageHistory 객체를 꺼냄
- 이 ChatMessageHistory의 메시지 리스트가 'history'라는 이름으로 프롬프트에 삽입됨
- history가 MessagesPlaceholder(variable_name="history") 위치에 들어감
- 프롬프트와 함께 llm에 전달되어 응답이 생성됨
- 새로 받은 질문/응답 쌍은 해당 history에 덧붙여짐
- 핵심 요약
- history는 ChatMessageHistory 객체 안에 저장되어 있고,
- get_session_history 함수 및 RunnableWithMessageHistory가 프롬프트에 넣어주는 역할을 함
- 프롬프트 템플릿의 history 부분 → 실제 리스트가 런타임에서 대입되는 자리(placeholder)
- 즉, history 값은 사용자 입력마다 session_id를 바탕으로 get_session_history에서 ChatMessageHistory 객체를 받아, 그 안에 저장된 메시지들을 프롬프트의 history 자리에 동적으로 넣어주기 때문에, 코드상 명확하게 값을 세팅하는 부분이 직접적으로 보이진 않지만, 내부 함수 호출의 결과로 전달되고 있음!
# 구글 마운트 및 경로 설정(파일 위치 변경)
%cd /content/drive/MyDrive/Colab Notebooks/LangChain
# api key 설정
import os
with open("./key/.openai_api_key",'r') as f:
api_key = f.read().strip()
os.environ["OPENAI_API_KEY"] = api_key
!pip install -qU openai langchain-openai langchain langchain_community
!pip install -qU tiktoken pypdf chromadb faiss-cpu
!pip install -qU langchain-teddynote
!pip install -qU huggingface_hub langchain_huggingface
# pdf 파일 불러오는 라이브러리
from langchain.document_loaders import PyPDFLoader
loader = PyPDFLoader("./data/미래 필수 역량.pdf")
document = loader.load()
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
separator="\n\n" # 둔단 단위
, chunk_size = 500
, chunk_overlap = 50
, length_function = len
)
chunks = text_splitter.split_documents(document)
# 분리 결과 확인
for idx, text in enumerate(chunks):
print(f"*****결과{idx+1}***** \n {text}")
*****결과1*****
page_content='홈• 인공지능• 일문일답 | AI 혁명 속 승자가 되는 법··· AWS 교육 임원이 말하는 미래 필수 역량
By Lucas Mearian
Senior Reporter
일문일답 | AI 혁명 속 승자가 되는 법···AWS 교육 임원이 말하는 미래 필수 역량
인터뷰
2025.03.03 • 11분
교육 산업 생성형 AI IT 직업
AWS 교육 및 수료증 프로그램에 대한 수요가 급증하고 있다. 일부 과정은 수강생이 전년 대비 9
배까지 증가했다. 아마존웹서비스(AWS)의 교육·인증 제품 및 서비스 디렉터 제니 트라우트먼은
이러한 수요 증가는 최근 급변하는 기술 역량에 대한 시장의 요구를 반영한다고 설명한다.
CREDIT: JENNY TROUTMAN / JENNY TROUTMAN'S LINKEIN' metadata={'producer': 'Skia/PDF m133', 'creator': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36', 'creationdate': '2025-03-05T04:57:45+00:00', 'title': '일문일답 | AI 혁명 속 승자가 되는 법··· AWS 교육 임원이 말하는 미래 필수 역량 | CIO', 'moddate': '2025-03-05T04:57:45+00:00', 'source': './data/미래 필수 역량.pdf', 'total_pages': 6, 'page': 0, 'page_label': '1'}
*****결과2*****
page_content='AI와 기술 역량이 빠르게 변화하면서 취업이나 커리어 발전을 위해 필요한 역량도 몇 년 전과 비교해 크게
달라졌다. 특히 직무 능력 외에 의사소통, 문제 해결, 협업, 리더십 능력 등으로 대표되는 ‘소프트 스킬’의
중요성이 그 어느 때보다 커지고 있다고 AWS의 교육·수료(training and certification) 제품 및 서비스
디렉터 제니 트라우트먼이 밝혔다.
(이하 생략)
# 청크의 수 출력
print(f"분리된 청크의 수: {len(chunks)}")
분리된 청크의 수: 6
GPT는 "언어 모델" → '지능'이 아님!
사람들이 입력한 걸 잘 붙여서 말을 만드는 것뿐
예: GPT가 알려주는 코드는 스택오버플로우 같은 곳에 사람들이 쓴 코드를 가져온 것
레시피 같은 것도 다른 사람들이 쓴 글을 가져와 쓰는 것
인공지능의 '지능(AGI)'에 대한 담론 읽어보기
책 "The AI con"에서는 인공'지능'이라는 말이 마케팅 용어라고 꼬집음 → AI가 스스로 생각할 수 있는 힘이 있는 것처럼 현혹
cf. Chain-of-Thought(CoT) 같은 방법을 사용한 AI의 추론(reasoning)을 따라가는 방법과 지능 헷갈리지 않기
기본 개념


