From 6f001e5914ddeb78930bf2a1530a3257b05f2eb8 Mon Sep 17 00:00:00 2001 From: seunghan96 Date: Mon, 13 Jan 2025 11:49:40 +0900 Subject: [PATCH] ab --- _posts/2024-12-17-(paper)TimeMixer2.md | 10 +- _posts/CoT.md | 133 ++ "_posts/LLM_\353\201\235.md" | 253 ++++ _posts/Langchain_ch1.md | 1125 +++++++++++++++++ _posts/Langchain_ch2.md | 550 ++++++++ ...0\353\207\275\354\245\254\353\246\254.pdf" | Bin 0 -> 91145 bytes 6 files changed, 2064 insertions(+), 7 deletions(-) create mode 100644 _posts/CoT.md create mode 100644 "_posts/LLM_\353\201\235.md" create mode 100644 _posts/Langchain_ch1.md create mode 100644 _posts/Langchain_ch2.md create mode 100644 "_posts/\354\225\210\353\207\275\354\245\254\353\246\254.pdf" diff --git a/_posts/2024-12-17-(paper)TimeMixer2.md b/_posts/2024-12-17-(paper)TimeMixer2.md index b5bc1c0b3309..3f148939c328 100644 --- a/_posts/2024-12-17-(paper)TimeMixer2.md +++ b/_posts/2024-12-17-(paper)TimeMixer2.md @@ -279,8 +279,6 @@ Key point = Multi-scale + Multi-periodic - (2) With convolution operations with a stride of 2 - $$\mathrm{x}_m=\operatorname{Conv}\left(\mathrm{x}_{m-1}, \text { stride }=2\right), \quad m \in\{1, \cdots, M\} $$ -
- (3) Result: **multi-scale set** $$X_{\text {init }}=\left\{\mathrm{x}_0, \cdots, \mathrm{x}_M\right\}$$, - where $$\mathrm{x}_m \in \mathbb{R}^{\frac{\pi}{2} m \mathrm{~J}} \times C$$. @@ -458,7 +456,7 @@ $$\mathbf{A},\left\{f_1, \cdots, f_K\right\},\left\{p_1, \cdots, p_K\right\}=\op Each 1 D time series $$\mathrm{x}_m^l$$ is then reshaped into $$K 2 \mathrm{D}$$ images as: -v +
@@ -486,13 +484,11 @@ Conventional methods (Wu et al., 2021; Wang et al., 2024) ***Multi-resolution time images*** -- Each image $$\mathbf{z}_m^{(l, k)} \in \mathbb{R}^{p_k \times f_{m . k} \times d_{\text {model }}}$$ encodes a specific scale and period, +- Each image $$\mathbf{z}_m^{(l, k)} \in \mathbb{R}^{p_k \times f_{m . k} \times d_{\text {model }}}$$ encodes a specific scale and period $$\rightarrow$$ Enabling finer disentanglement of seasonality and trend -- How? Apply **2D convolution** to these images - - $$\rightarrow$$ Capture long-range patterns and enhance temporal dependency extraction. +- Apply **2D conv** to these images - Details diff --git a/_posts/CoT.md b/_posts/CoT.md new file mode 100644 index 000000000000..f29f1cd9e213 --- /dev/null +++ b/_posts/CoT.md @@ -0,0 +1,133 @@ +Chain-of-Thought Prompting (ACL, 2024) + +Proposal + +1. Active Prompt + - 아이디어: ***Task별로 가장 적합한*** CoT 예시를 선정 + - 기준: uncertainty score +2. Chain-of-knowledge + - 아이디어: 모델이 ***이해하기 쉽게*** 정보를 전달 + +
+ +(1) Manual CoT + +- Pros & Cons + - pros) 정확함 + - cons) requires human label + +
+ +(2) Zero-shot CoT: "Let's think step by step" + +- Pros & Cons + - pros) w/o human label + - cons) too simple + +- Pipeline + - Step 1) reasoning extraction + - LLM에 "Let's think step by step"를 넣어줌으로써 나온 추론 과정 ( = reasoning path ) 생성 + - Step 2) answer extraction + - 앞서 생성한 reasoning path를 함께 넣어줌 + - 요약) 입력 prompt: (1) question + (2) let's think step by step + (3) reasoning path + +
+ +(3) Auto CoT = (1) + (2) + +- (1)처럼 성능을 어느 정도 보장하면서도 +- (2)처럼 자동으로 생성되도록! + +
+ +### Auto CoT + +Step 1) 모든 질문들을 K개의 cluster로 나눔 + +Step 2) 클러스터 별 1개씩 질문 선정 ( = 총 K개의 질문) + +Step 3) K개의 질문에 대해 (Zero-shot CoT로) Reasoning path 생성 + +Step 4) 최종 prompt: (1) + (2) + (3) + +- (1) question +- (2) let's think step by step +- (3) K개의 질문에 대한 + - (3-1) question + - (3-2) let's think step by step + - (3-3) reasoning path + +$\rightarrow$ Few-shot CoT가 가능해짐! + +
+ +### Complex-CoT + +어떤 추론 과정 (reasoning path)가 좋을까? + +$\rightarrow$ 기본 아이디어: ***복잡한*** 추론 과정을 우선시하자! + +- ( 복잡하다 = 추론 step이 많다 = # steps ) + +
+ +Procedure + +- Step 1) 동일한 질문에 대해 N개의 reasoning path를 생성 (with Zero-shot CoT) + +- Step 2) Step 수(=complexity)로 sorting & step이 많은 **Top K개**의 reasoning path를 선택 + +- Step 3) 이 K개 중, 다수결 (Majority)로써 answer를 판단 +- Step 4) 이를 선택한 최종 reasoning path를 선정 + +
+ +### Self-Consistency + +목적: **가장 일관성 있는 답**을 도출하자! + +Procedure + +- Step 1) 동일한 질문에 대해 N개의 reasoning path를 생성 (with Zero-shot CoT) +- Step 2) 여러 답들 중, 가장 일관성 있는 ( = majority )를 최종 답으로 선정 + +요약: **"하나의 경로"**를 통해 나온 답이 아닌, **"여러 경로"**를 통해 나온 여러 답을 종합하여 선택! + +
+ +### Proposal 1) Active Prompt + +- 기존의 한계점: "Task에 대한 고려 없이" 샘플을 선택함 + + $\rightarrow$ 최선의 샘플이라는 보장 X + +- 아이디어: ***Task 별 최적의 샘플을 찾자!*** + + ( = 태스크마다 가장 중요하고 유용한 샘플을 선택하자! ) + + ( = 샘플에 대한 ***"모델 예측의 불확실성이 가장 높은"*** 샘플을 찾자! ) + +- Procedure + + - Step 1) Uncertainty estimation + - K번 답변을 생성 후, 이들을 기반으로 metric 계산 + - Uncertainty metric: (1) disagreement & (2) entropy + - Step 2) Selection + - Uncertainty 기준으로 sorting & Top N개 선정 + - Step 3) Annotation + - Top N개에 대해 annotation을 인간이 달기 + - Step 4) Inference + +
+ +### Proposal 2) Chain-of-knowledge + +- 기존의 한계점: Textual reasoning chain을 바탕으로 태스크 수행 + + $\rightarrow$ Hallucination 문제 + +- 아이디어: Triple의 구조로 추론을 수행 & 결과 검증을 하자 + + ( = 추론 결과에 대한 "신뢰성 점수" 계산 후, 이를 개선시키도록! ) + +https://www.youtube.com/watch?v=OTP52AURAok&t=58s (18분부터 이어서보기) diff --git "a/_posts/LLM_\353\201\235.md" "b/_posts/LLM_\353\201\235.md" new file mode 100644 index 000000000000..57c9c5ca0c7f --- /dev/null +++ "b/_posts/LLM_\353\201\235.md" @@ -0,0 +1,253 @@ + + +# EP01. #RAG의 동작 과정 쉽게 이해하기 + +### (1) LLM vs. RAG + +- LLM : 외부 정보 참고 X + +- LLM **+ RAG**: 외부 정보 참고 O + - 외부 정보 = 참고 정보 (context) + +
+ +## (2) Chunking + +참고 정보 예시: pdf 문서 + +***통째로*** LLM의 입력에 넣어줄 경우의 문제점: + +- (1) Too costly +- (2) Lost in the middle + + + +해결책: **Chunking** + +- Chunk 예시: 1개의 단락 (1000 token) +- 주로 overlap (O) + + + +### (3) Pre-processing 단계 요약 + +- Step 1) Document load +- Step 2) Text split +- Step 3) Embedding +- Step 4) Store => Vector DB + + + +# EP02. #RAG의 동작 과정 쉽게 이해하기 (실행 단계) + +Runtime 단계 + +( 참고: 현재 Vector DB는 이미 준비 된 상태) + + + +### (1) 유사도 검색 ( = Similarity search ) + +- User가 질문 시, retriever (=검색기)가 질문과의 연관도 (유사도) 계산 +- 관련된 단락을 Vector DB에서 (Top K개) 뽑아낸 뒤, prompt에 넣어줌 + +- 결국, LLM의 입력에는 (1) + (2)가 함께 들어가게 됨 + - (1) User의 질문 + - (2) [Prompt] RAG를 통해 찾아온 정보 (Top K개의 chucnk) + +
+ +### (2) Retriever (검색기)의 필요성 + +- (1) 정확한 정보 제공 + - 질문과 가장 유사도(관련성) 높은 정보를 검색함 +- (2) 응답 시간 단축 + - 효율적인 검색 알고리즘을 통해 관련있는 정보를 빠르게 검색 + - User experience에 매우 중요 +- (3) 최적화 + - 필요하한 정보만을 추출 ( 불필요 데이터 처리 줄임 ) + +
+ +### (3) 동작 방식 + +- Step 1) 질문의 벡터화 +- Step 2) 벡터 유사도 계산 & 비교 +- Step 3) Top K 문서 선정 +- Step 4) Prompt로 전달 + +
+ +### (4) Retriever (검색기)의 종류 + +**a) Sparse retriever** + +- User의 질문을 **discrete (keyword) vector**로 변환 +- How? e.g., TF-IDF, BM25 (전통적인 방법들) +- 장/단점 + - 장점) 간단함/단어의 유무만을 가지고 판단 + - 단점) 의미적 연관성 고려 X + +
+ +**b) Dense retriever** + +- User의 질문을 **continuous vector**로 변환 +- How? DL models +- 장/단점: Sparse retriever와 반대 + +
+ +# EP03. PDF 문서 기반 QA (RAG 구축하기) + +# Procedure + +- Step 1) Load document +- Step 2) Split (to chunks) +- Step 3) Embedding +- Step 4) VectorStore +- Step 5) Retrieval +- Step 6) Prompt +- Step 7) LLM +- Step 8) Output + +
+ +### Environment Setting + +```python +# 1-1) Load API key +from dotenv import load_dotenv +load_dotenv() + +# 1-2) LangSmith (for tracking) +!pip install -qU langchain-teddynote +from langchain_teddynote import logging + +# 1-3) Project Name +project_nm = "CH12-RAG" +logging.langsmith(project_nm) + +# 1-4) Langchain packages +from langchain_text_splitters import RecursiveCharacterTextSplitter +from langchain_community.document_loaders import PyMuPDFLoader +from langchain_community.vectorstores import FAISS +from langchain_core.output_parsers import StrOutputParser +from langchain_core.runnables import RunnablePassthrough +from langchain_core.prompts import PromptTemplate +from langchain_openai import ChatOpenAI, OpenAIEmbeddings +``` + +
+ +### Step 1) Load document + +```python +import os +PATH = 'data' +fn = 'SPRI_AI_Brief_2023년12월호_F.pdf' +loader = PyMuPDFLoader(os.path.join(PATH,fn)) +docs = loader.load() + +print(f"# pages: {len(docs)}") +print(docs[10].page_content) # contents of 10th page +print(docs[10].__dict__) # meta data +``` + +
+ +### Step 2) Split (to chunks) + +```python +text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50) +split_documents = text_splitter.split_documents(docs) + +print(f"# chunks: {len(split_documents)}") +print(split_documents[7].page_content) # content of 7th chunck +``` + +
+ +### Step 3) Embedding + +```python +embeddings = OpenAIEmbeddings() # OpenAI +``` + +
+ +### Step 4) VectorStore + +```python +# Create Vector DB (e.g, FAISS) +vectorstore = FAISS.from_documents(documents=split_documents, embedding=embeddings) + +# ex) Find chunks from DB with high similarity +example_keyword = "구글" +for doc in vectorstore.similarity_search(example_keyword): + print(doc.page_content) +``` + +
+ +### Step 5) Retrieval + +```python +# Retreiver to search for chunks +retriever = vectorstore.as_retriever() + +# Ex) Find the closests chunks +example_query = "삼성전자가 자체 개발한 AI 의 이름은?" +retriever.invoke(example_query) +``` + +
+ +### Step 6) Prompt + +```python +# Create prompt +# Requirements: context & question +prompt = PromptTemplate.from_template( + """You are an assistant for question-answering tasks. +Use the following pieces of retrieved context to answer the question. +If you don't know the answer, just say that you don't know. +Answer in Korean. + +#Context: +{context} + +#Question: +{question} + +#Answer:""" +) +``` + +
+ +### Step 7) LLM + +```python +# GPT-4o +llm = ChatOpenAI(model_name="gpt-4o", temperature=0) +``` + +
+ +### Step 8) Output + +```python +chain = ( + {"context": retriever, "question": RunnablePassthrough()} + | prompt + | llm + | StrOutputParser() +) + +response = chain.invoke(example_query) +print(response) +``` + + + diff --git a/_posts/Langchain_ch1.md b/_posts/Langchain_ch1.md new file mode 100644 index 000000000000..5df8d77d19f7 --- /dev/null +++ b/_posts/Langchain_ch1.md @@ -0,0 +1,1125 @@ +# Langchain + +## (0) Intro + +### a) Langchain이란 + +- 개념: **LLM을 활용**해 다양한 애플리케이션을 개발할 수 있는 framework + +- 두 가지 기능: + - (1) **문맥 인식** + - (2) **추론** + +- 활용 예시: RAG 어플리케이션 제작, 구조화된 데이터 분석, 챗봇 개발 + +
+ +### b) 설치 + +```bash +# v1) standard +pip install -r https://raw.githubusercontent.com/teddylee777/langchain-kr/main/requirements.txt + +# v2) mini +pip install -r https://raw.githubusercontent.com/teddylee777/langchain-kr/main/requirements-mini.txt +``` + +
+ +### c) 구성 + +- **[LangChain 라이브러리](https://python.langchain.com/v0.2/docs/introduction/)**: + - **Python 및 JavaScript 라이브러리** +- **[LangChain 템플릿](https://templates.langchain.com/)**: + - 다양한 작업을 위한 쉽게 배포할 수 있는 **참조 아키텍처 모음** +- **[LangServe](https://github.com/langchain-ai/langserve)**: + - **REST API**로 배포하기 위한 라이브러리 +- **[LangSmith](https://smith.langchain.com/)**: + - (LLM-agnostic) 구축된 chain 을 **디버그, 테스트, 평가, 모니터링** +- **[LangGraph](https://python.langchain.com/docs/langgraph)**: + - LLM을 사용한 상태유지가 가능한 다중 액터 애플리케이션을 구축하기 위한 라이브러리 + +
+ +### d) 개발 용이성 + +1. **컴포넌트의 조립 및 통합** + +- 모듈식으로 설계되어서 사용하기 편리 + +2. **즉시 사용 가능한 "체인"** + +- 체인 = 컴포넌트의 내장 조합 +- 개발 과정 간소화 가능 + +
+ +### e) 주요 모듈 + +1. **모델 I/O** + +- 프롬프트 관리 및 최적화 + +2. **검색** + +- RAG 통해 외부에서 데이터 가져오기 + +3. **에이전트** + +- LLM이 어떠한 조치를 취할지 결정 & 실행 & 관찰 & 반복 + +
+ +## (1) 설치하기 + +https://wikidocs.net/257836 + +https://www.youtube.com/watch?v=mVu6Wj8Z7C0 + + + +## (2) OpenAPI 키 발급 및 테스트 + +https://wikidocs.net/233342 + + + +## (3) LangSmith 추적 설정 + +LangSmith: **LLM 애플리케이션 개발, 모니터링 및 테스트** 를 위한 플랫폼 + +
+ +### a) LangSmith의 추적 기능 + +**When useful?** + +- 예상치 못한 결과 디버깅 +- agent가 looping되는 경우 +- chain이 예상보다 느린 경우 +- agent가 각 단계에서 사용한 token 수 파악 + + + +**Details** + +- (1) **"project" 단위**로 추적 가능 + - ( e.g., 실행 카운트, error 발생률, token 사용량 등 ) +- (2) 프로젝트 click시, (해당 프로젝트 내에서 실행했던) **"모든 run 확인 가능"** +- (3) 검색 결과, **"LLM의 input/output"**등을 전부 상세히 기록 + +
+ +### b) LangSmith 추적 사용하기 + +- Step 1) **LangSmith API key 발급** + - https://smith.langchain.com/ 회원가입 + - Setting - Personal - Create API Key + - (주의: Key 보관 잘 하기) +- Step2) **`.env` 파일에 API Key & Project 정보 입력** + - `LANGCHAIN_TRACING_V2`: **true** = 추적 허용 + - `LANGCHAIN_ENDPOINT`: `https://api.smith.langchain.com` : 그대로 두기 + - `LANGCHAIN_API_KEY`: **{API_KEY}** + - `LANGCHAIN_PROJECT`: **프로젝트 명** + +
+ +### c) 추적 활성화하기 + +매우 간단! 환경 변수만 설정하면 됨. + +```python +# 앞서 설정한 .env 불러오기 +from dotenv import load_dotenv +load_dotenv() +``` + +
+ +( 만약, 프로젝트 명/추적 여부 변경 원하면, **직접 jupyter notebook에서도 변경 가능** ) + +```python +import os + +os.environ["LANGCHAIN_TRACING_V2"] = "true" +os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com" +os.environ["LANGCHAIN_PROJECT"] = "LangChain 프로젝트명" +os.environ["LANGCHAIN_API_KEY"] = "LangChain API KEY 입력" +``` + +
+ +### c) Langchain의 편리한 사용 + +`langchain-teddynote` 패키지 ( 출처: https://wikidocs.net/250954 ) + +```bash +pip install langchain-teddynote +``` + +```python +from langchain_teddynote import logging + +# Tracing On/Off +logging.langsmith("LangChain 프로젝트명") # On +logging.langsmith("LangChain 프로젝트명", set_enable=False) # Off +``` + +
+ +## (4) OpenAI의 API 사용 (GPT-4o 멀티모달) + +### a) Environment setting + +```python +from dotenv import load_dotenv +load_dotenv() + +from langchain_teddynote import logging +logging.langsmith("CH01-Basic") +``` + +
+ +### b) ChatOpenAI + +**ChatOpenAI** = OpenAPI의 LLM + +- `temperature`: sharpness 조절 + - Smaller = 더 집중 (다양성 low) + - Higher = 덜 집중 (다양성 high) +- `max_tokens`: 최대 토큰 수 +- `model_name`: 사용할 모델 지정 + - e.g., `gpt-3.5-turbo` - `gpt-4-turbo` - `gpt-4o` + - 참조: https://platform.openai.com/docs/models + +
+ +```python +from langchain_openai import ChatOpenAI + +# LLM +llm = ChatOpenAI( + temperature=0.1, + model_name="gpt-4o", +) + +# Question +question = "대한민국의 수도는 어디인가요?" +response = llm.invoke(question) +``` + +
+ +### c) 답변의 형식 (AI Message) + +```python +print(response) # All +print(response.content) # Answer +print(response.response_metadata) # Metadata +``` + +
+ +### d) LogProb 활성화 + +**Log probability of tokens** + +( = LLM이 각 토큰을 예측할 확률 ) + +```python +llm_with_logprob = ChatOpenAI( + temperature=0.1, + max_tokens=2048, + model_name="gpt-3.5-turbo", +).bind(logprobs=True) +``` + +
+ +```python +question = "대한민국의 수도는 어디인가요?" + +response = llm_with_logprob.invoke(question) +print(response.response_metadata) # Metadata (X), Log probability (O) +``` + +
+ +### e) 스트리밍 출력 (실시간) + +```python +answer = llm.stream("대한민국의 아름다운 관광지 10곳과 주소를 알려주세요!") + +# Option 1) +for token in answer: + print(token.content, end="", flush=True) +``` + +
+ +(혹은, `langchain_teddynote` 패키지 활용할 경우) + +```python +from langchain_teddynote.messages import stream_response + +# Option 2) +stream_response(answer) +``` + +
+ +### f) Multimodal model + +(e.g., text, image, audio, video ... ) + +Note) `gpt-4o`, `gpt-4-turbo`: 이미지 인식 기능 O + +```python +from langchain_teddynote.models import MultiModal +from langchain_teddynote.messages import stream_response + +llm = ChatOpenAI( + temperature=0.1, + max_tokens=2048, + model_name="gpt-4o", # Multimodal model +) + +multimodal_llm = MultiModal(llm) +``` + +
+ +step 1) 이미지 주소 + +```python +IMAGE_URL = "https://t3.ftcdn.net/jpg/03/77/33/96/360_F_377339633_Rtv9I77sSmSNcev8bEcnVxTHrXB4nRJ5.jpg" +``` + +
+ +step 2) 이미지에 대한 해석 + +```python +answer = multimodal_llm.stream(IMAGE_URL) + +stream_response(answer) +``` + +
+ +### g) Sytem, User 프롬프트 수정 + +- System prompt: LLM에게 요구하는 **"가치관/정체성"** + +- User prompt: LLM에게 던지는 **""구체적인 요구 사항** + +```python +system_prompt = """ +당신은 표(재무제표) 를 해석하는 금융 AI 어시스턴트 입니다. +당신의 임무는 주어진 테이블 형식의 재무제표를 바탕으로 흥미로운 사실을 정리하여 친절하게 답변하는 것입니다. +""" + +user_prompt = """ +당신에게 주어진 표는 회사의 재무제표 입니다. 흥미로운 사실을 정리하여 답변하세요. +""" + + +multimodal_llm_with_prompt = MultiModal( + llm, + system_prompt=system_prompt, + user_prompt=user_prompt +) + +``` + +
+ +이후는 동일 + +```python +IMAGE_PATH = "https://storage.googleapis.com/static.fastcampus.co.kr/prod/uploads/202212/080345-661/kwon-01.png" + +answer = multimodal_llm_with_prompt.stream(IMAGE_PATH) + +stream_response(answer) +``` + +
+ +## (5) LangChain Expression Language (LCEL) + +LCEL 3줄 요약 + +- LangChain에서 ***복잡한 데이터 흐름과 작업***을 ***직관적으로 표현***하기 위해 도입된 언어 +- ***데이터의 변환, 필터링, 조건부 실행*** 등을 간결하게 작성할 수 있는 문법을 제공 +- 주로 ***프롬프트 템플릿***을 생성하거나, ***체인을 연결***할 때 효율성을 높이는 데 사용 + +
+ +이번 Section의 task: + +- "Prompt - Model - Output parser"를 연결하는 chain 생성할 것 + +
+ +기본적인 세팅 + +```python +from dotenv import load_dotenv +load_dotenv() + +from langchain_teddynote import logging +logging.langsmith("CH01-Basic") +``` + +
+ +### a) Prompt 템플릿 + +`PromptTemplate` + +- 목적: **"프롬프트 문자열"**을 만들기 + - with 사용자의 입력 변수 +- Arguments + - `template`: 템플릿 문자열 ( 중괄호 `{}`: 변수 ) + - `input_variables`: 변수의 이름을 정의하는 리스트 + +
+ +Example + +```python +from langchain_teddynote.messages import stream_response +from langchain_core.prompts import PromptTemplate + +# template 정의 +template = "{country}의 수도는 어디인가요?" + +# PromptTemplate 객체 생성 +prompt_template = PromptTemplate.from_template(template) +prompt_template +``` + +``` +PromptTemplate(input_variables=['country'], template='{country}의 수도는 어디인가요?') +``` + +
+ +Prompt 생성하기 + +```python +# prompt 생성 +prompt1 = prompt_template.format(country="대한민국") +prompt2 = prompt_template.format(country="미국") +print(prompt1) +print(prompt2) +``` + +``` +'대한민국의 수도는 어디인가요?' +'미국의 수도는 어디인가요?' +``` + +
+ +### b) Chain 생성 + +with **LCEL (LangChain Expression Language)** + +- (1) Prompt $$\rightarrow$$ (2) LLM (model) $$\rightarrow$$ (3) Output Parser + +
+ +**`|` 기호**: unix 파이프 연산자 ( 서로 다른 구성 요소를 연결 ) + +```python +chain = prompt | model | output_parser +``` + +
+ +Example + +```python +# (1) Prompt +prompt = PromptTemplate.from_template("{topic} 에 대해 쉽게 설명해주세요.") + +# (2) Model +model = ChatOpenAI() + +# Chain = (1) | (2) | xxx +chain = prompt | model +``` + +
+ +### c) `invoke()` , `stream()` + +입력값 형식: **python dictionary** + +```python +input = {"topic": "인공지능 모델의 학습 원리"} +``` + + + +(1) **chain의 invoke 메소드 ** + +````python +chain.invoke(input) +```` + +``` +AIMessage(content='인공지능 모델의 학습 원리는 데이터를 이용하여 패턴을 학습하는 것입니다. 모델은 입력 데이터를 받아들이고 내부적으로 가중치를 조정하여 원하는 결과를 출력합니다. 학습 과정에서 모델은 입력 데이터와 정답 데이터를 이용하여 오차를 계산하고 이 오차를 최소화하는 방향으로 가중치를 업데이트합니다. 이렇게 반복적으로 학습을 진행하면 모델은 입력 데이터로부터 패턴을 학습하여 정확한 결과를 예측하게 됩니다. 이러한 학습 원리를 통해 인공지능 모델은 데이터를 이용하여 스스로 학습하고 문제를 해결할 수 있습니다.', response_metadata={'token_usage': {'completion_tokens': 214, 'prompt_tokens': 33, 'total_tokens': 247}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-7f8a08f4-51ba-4d14-b9d2-2e092be3e7aa-0', usage_metadata={'input_tokens': 33, 'output_tokens': 214, 'total_tokens': 247}) +``` + +
+ +(2) **chain의 stream 메소드** (for 출력) + +```python +answer = chain.stream(input) +stream_response(answer) +``` + +``` +인공지능 모델의 학습 원리는 데이터를 입력으로 받아서 패턴을 학습하고 이를 기반으로 예측이나 분류를 수행하는 과정입니다. + +학습 과정은 크게 입력층, 은닉층, 출력층으로 구성된 인공신경망을 사용합니다. 입력층에서 데이터를 받아 은닉층을 거쳐 출력층으로 결과를 출력하는 구조입니다. + +이때, 모델은 주어진 데이터를 통해 가중치를 조정하고 오차를 최소화하는 방향으로 학습을 진행합니다. 이를 위해 주어진 데이터에 대해 예측을 수행하고 실제 값과 비교하여 오차를 계산한 후, 이 오차를 줄이기 위해 가중치를 업데이트합니다. + +이러한 반복적인 과정을 통해 모델은 데이터 간의 패턴을 학습하고 새로운 데이터에 대해 정확한 예측을 수행할 수 있게 됩니다. 이렇게 학습된 모델은 새로운 데이터에 대해 일반화된 예측을 할 수 있습니다. +``` + +
+ +**`invoke ()` vs. `stream()`** + +- Invoke + + - **작동 방식**: 주어진 입력에 대해 **"한 번에" 응답을 생성** + + - **결과**: 호출이 완료되면 최종 응답이 반환. 동기적 처리 방식으로, 호출이 끝날 때까지 대기. + + - **사용 사례**: 결과가 빠르게 나오는 경우, 스트리밍 응답이 필요하지 않은 상황 + +- Stream + + - **작동 방식**: 주어진 입력에 대해 **"스트리밍" 방식으로 응답을 생성** + + ( 응답이 생성되는 동안 데이터가 **실시간**으로 전달 ) + + - **결과**: + + - Step 1) `chain.stream(input)`: 스트리밍 응답 객체(`answer`)를 반환 + + - Step 2) `stream_response(answer)`: 스트리밍 데이터를 하나씩 출력 + + - **사용 사례**: 긴 텍스트 생성, 사용자 대화, 또는 결과를 **실시간으로 출력해야** 하는 상황에 적합 + +
+ +### d) Output Parser + +( chain의 세번째 구성 요소 ) + +```python +from langchain_core.output_parsers import StrOutputParser + +# (3) Output Parser +output_parser = StrOutputParser() + +# Chain = (1) | (2) | (3) +chain = prompt | model | output_parser +``` + +
+ +출력값 형식이 어떻게 달라지는지 확인! + +```python +# option 1) invoke +chain.invoke(input) + +# option 2) stream +answer = chain.stream(input) +stream_response(answer) +``` + +``` +인공지능 모델의 학습 원리는 데이터를 이용해서 패턴을 학습하는 과정입니다. 먼저 모델은 입력 데이터를 받아서 처리하고, 이때 입력 데이터와 정답 데이터를 비교하여 오차를 계산합니다. 이 오차를 최소화하기 위해 모델은 가중치와 편향을 조정하면서 점차적으로 정확한 패턴을 학습해나갑니다. 이런 과정을 반복하여 모델이 데이터에 대해 정확한 예측을 할 수 있도록 학습시키는 것이 인공지능 모델의 핵심 원리입니다. +``` + +
+ +### e) Template 변경하여 적용 + +```python +template = """ +당신은 영어를 가르치는 10년차 영어 선생님입니다. 상황에 [FORMAT]에 영어 회화를 작성해 주세요. + +상황: +{question} + +FORMAT: +- 영어 회화: +- 한글 해석: +""" + +# (1) Prompt +prompt = PromptTemplate.from_template(template) + +# (2) Model +model = ChatOpenAI(model_name="gpt-4-turbo") + +# (3) Parser +output_parser = StrOutputParser() +``` + +
+ +```python +# Chain = (1)+(2)+(3) +chain = prompt | model | output_parser +``` + +
+ +```python +answer = chain.stream({"question": + "저는 식당에 가서 음식을 주문하고 싶어요"}) + +stream_response(answer) +``` + +``` +영어 회화: +- Hello, could I see the menu, please? +- I'd like to order the grilled salmon and a side of mashed potatoes. +- Could I have a glass of water as well? +- Thank you! + +한글 해석: +- 안녕하세요, 메뉴판 좀 볼 수 있을까요? +- 구운 연어와 매시드 포테이토를 주문하고 싶어요. +- 물 한 잔도 주실 수 있나요? +- 감사합니다! +``` + +
+ +## (6) LCEL 인터페이스 + +[`Runnable`](https://api.python.langchain.com/en/stable/runnables/langchain_core.runnables.base.Runnable.html#langchain_core.runnables.base.Runnable) 프로토콜 + +- **사용자 정의 체인**을 가능한 쉽게 만들 수 있도록! 대부분의 컴포넌트에 구현되어 있음 +- 표준 인터페이스 + + - (a) [`stream`](https://wikidocs.net/233345#stream): 응답의 **청크**를 스트리밍합니다. + + - (b) [`invoke`](https://wikidocs.net/233345#invoke): **입력**에 대해 체인을 호출 + + - (c) [`batch`](https://wikidocs.net/233345#batch): **입력 목록**에 대해 체인을 호출 +- 비동기 메소드: 앞에 `a`가 붙음 + + - [`astream`](https://wikidocs.net/233345#async-stream), [`ainvoke`](https://wikidocs.net/233345#async-invoke), [`abatch`](https://wikidocs.net/233345#async-batch) + - (d) [`astream_log`](https://wikidocs.net/233345#async-stream-intermediate-steps): (최종 응답뿐만 아니라) 중간 단계를 스트리밍 + +
+ +**Sync** vs. **Async** + +- Sync: 작업이 **"순서대로" 실행** + - 하나의 작업이 끝날 때까지 기다렸다가, 그 다음 작업을 시작 +- Async: 작업이 **"동시"에 실행** + - 한 작업이 끝날 때까지 기다리지 않고, 다른 작업을 진행 + +
+ +```python +from dotenv import load_dotenv +load_dotenv() + +from langchain_teddynote import logging +logging.langsmith("CH01-Basic") + +from langchain_openai import ChatOpenAI +from langchain_core.prompts import PromptTemplate +from langchain_core.output_parsers import StrOutputParser +``` + +
+ +Chain 생성 + +```python +# (1) Prompt +prompt = PromptTemplate.from_template("{topic} 에 대하여 3문장으로 설명해줘.") + +# (2) Model +model = ChatOpenAI() + +# Chain = (1)+(2)+(3) +chain = prompt | model | StrOutputParser() +``` + +
+ +아래의 섹션에서는, 다양한 method들에 대해서 알아볼 것! + +- stream +- invoke +- batch +- astream (async stream) +- ainvoke (async invoke) +- abatch (async batch) + +
+ +### a) stream + +데이터 스트림을 생성 + +( 이 스트림을 반복하여 각 데이터의 내용을 즉시 출력 ) + +```python +for token in chain.stream({"topic": "멀티모달"}): + print(token, end="", flush=True) +``` + +- `end=""`: 줄바꿈 X +- `flush=True`: 출력 buffer 비우기 + +``` +멀티모달은 여러 가지 다른 형태의 커뮤니케이션 수단을 통해 정보를 전달하고 상호작용하는 기술을 의미합니다. 예를 들어 음성, 텍스트, 이미지, 동영상 등 다양한 매체를 활용하여 사용자와 상호작용할 수 있습니다. 멀티모달 기술은 사용자 경험을 향상시키고 정보 전달의 효율성을 높이는데 도움을 줄 수 있습니다. +``` + +
+ +### b) invoke + +해당 주제에 대한 처리를 **한번에** 수행 + +``` +'ChatGPT는 OpenAI에서 개발한 대화형 인공지능 모델로, 다양한 주제에 대한 대화를 자연스럽게 이어나갈 수 있습니다. 사용자들은 ChatGPT를 통해 질문에 답변을 받거나 대화를 이어가며 새로운 정보를 습득할 수 있습니다. 또한 ChatGPT는 사용자의 입력을 학습하여 점차적으로 더욱 유창하고 자연스러운 대화를 제공합니다.' +``` + +
+ +### c) batch (단위 실행) + +**여러 개**의 딕셔너리를 포함하는 리스트를 인자로 받음 (일괄 처리) + +```python +chain.batch([{"topic": "ChatGPT"}, + {"topic": "Instagram"}]) +``` + +``` +['ChatGPT는 인공지능 챗봇으로 자연어 처리 기술을 사용하여 대화를 수행합니다. 사용자들과 자연스럽게 상호작용하며 다양한 주제에 대해 대화할 수 있습니다. ChatGPT는 정보 제공, 질문 응답, 상담 및 엔터테인먼트 등 다양한 용도로 활용될 수 있습니다.', 'Instagram은 사진과 동영상을 공유하고 다른 사람들과 소통하는 소셜 미디어 플랫폼이다. 해시태그를 통해 관심사나 주제별로 사진을 검색하고 팔로워들과 소통할 수 있다. 인기 있는 인플루언서나 브랜드가 활발하게 활동하는 플랫폼으로 세계적으로 인기가 높다.'] +``` + +
+ +argument) `max_concurrency` + +- 동시 요청 수 (처리할 수 있는 최대 작업 수)를 설정 + + - **시스템이 한 번에 병렬로 처리할 수 있는 요청의 수** + + ( 순차적으로 처리되는 것이 아니라 동시에 실행되어 작업 속도를 향상시키는 데 활용 ) + +```python +chain.batch( + [ + {"topic": "ChatGPT"}, + {"topic": "Instagram"}, + {"topic": "멀티모달"}, + {"topic": "프로그래밍"}, + {"topic": "머신러닝"}, + ], + config={"max_concurrency": 3}, +) +``` + +
+ +### d) async stream + +응답을 비동기적으로 처리 + +- 비동기 for 루프(`async for`)를 사용 +- 스트림에서 메시지를 순차적으로 받아옴 + +```python +async for token in chain.astream({"topic": "YouTube"}): + print(token, end="", flush=True) +``` + +
+ +### e) async invoke + +`await` : 비동기로 처리되는 프로세스가 완료될 때까지 기다림 + +```python +my_process = chain.ainvoke({"topic": "NVDA"}) +await my_process +``` + +
+ +### f) async batch + +비동기적으로 일련의 작업을 일괄 처리합니다. + +```python +my_abatch_process = chain.abatch( + [{"topic": "YouTube"}, + {"topic": "Instagram"}, + {"topic": "Facebook"}] +) + +await my_abatch_process +``` + +
+ +### g) Parallel + +LCEL가 병렬 요청을 지원하는 방법? + +$$\rightarrow$$ with `RunnableParallel` + +
+ +Example: + +- Step 1) 주어진 `country`에 대한 **수도** 와 **면적** 을 구하는 두 개의 체인(`chain1`, `chain2`) 생성 +- Step 2) `RunnableParallel` 클래스를 사용하여 이 두 체인을 `capital`와 `area`이라는 키로 결합 + +
+ +```python +from langchain_core.runnables import RunnableParallel + +template1 = PromptTemplate.from_template("{country} 의 수도는 어디야?") +template2 = PromptTemplate.from_template("{country} 의 면적은 얼마야?") + +chain1 = (template1 | model | StrOutputParser()) +chain2 = (template2 | model | StrOutputParser()) + +combined = RunnableParallel(capital=chain1, area=chain2) +``` + +
+ +```python +# chain1.invoke({"country": "대한민국"}) +# chain2.invoke({"country": "대한민국"}) +combined.invoke({"country": "대한민국"}) +``` + +``` +{'capital': '대한민국의 수도는 서울입니다.', 'area': '대한민국의 면적은 약 100,363.4 제곱 킬로미터 입니다.'} +``` + +
+ +(batch) 병렬 처리도 가능! + +```python +# chain1.batch([{"country": "대한민국"}, {"country": "미국"}]) +# chain2.batch([{"country": "대한민국"}, {"country": "미국"}]) +combined.batch([{"country": "대한민국"}, {"country": "미국"}]) +``` + +
+ +## (7) Runnable + +(이전과 동일한 세팅) + +```python +# 환경 변수 설정 +from dotenv import load_dotenv +load_dotenv() + +# LangSmith 추적 +from langchain_teddynote import logging +logging.langsmith("CH01-Basic") +``` + +
+ +데이터를 효과적으로 전달하는 방법 + +- (1) `RunnablePassthrough` + - 입력을 변경하지 않거나 추가 키를 더하여 전달 +- (2) `RunnablePassthrough()` + - 단순히 입력을 받아 그대로 전달 +- (3) `RunnablePassthrough.assign()` + - assign 함수에 전달할 추가적인 인수를 받음 + +
+ +### a) RunnablePassthrough + +```python +from langchain_core.prompts import PromptTemplate +from langchain_openai import ChatOpenAI + + +# (1) Prompt +prompt = PromptTemplate.from_template("{num} 의 10배는?") + +# (2) model +llm = ChatOpenAI(temperature=0) + +# chain = (1) + (2) +chain = prompt | llm +``` + +
+ +Note: `invoke()`의 입력은 **dictionary** 형식이어야 했음 + +```python +chain.invoke({"num": 5}) +``` + +
+ +(updated version) 변수가 1개일 경우에는 dictionary일 필요 X + +- 어차피 입력 변수가 뭔지 알 수 있으니까 + +```python +chain.invoke(5) +``` + +
+ +`RunnablePassthrough` + +- `runnable` 객체임 $$\rightarrow$$ `invoke()` 메소드 통해 실행 가능 + +```python +from langchain_core.runnables import RunnablePassthrough +RunnablePassthrough().invoke({"num": 10}) +``` + +``` +{'num': 10} +``` + +
+ +```python +# (Before) chain = (1) prompt + (2) model +# (After) chain = RunnablePassthrough + (1) prompt + (2) model +runnable_chain = {"num": RunnablePassthrough()} | prompt | ChatOpenAI() + +runnable_chain.invoke(10) +``` + +``` +AIMessage(content='100입니다.', response_metadata={'token_usage': {'completion_tokens': 3, 'prompt_tokens': 16, 'total_tokens': 19}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-66270ca2-4d62-4c71-859b-de6318f29909-0', usage_metadata={'input_tokens': 16, 'output_tokens': 3, 'total_tokens': 19}) +``` + +
+ +`RunnablePassthrough.assign()` + +```python +# v1: RunnablePassthrough +RunnablePassthrough().invoke({"num": 1}) +# 출력: {'num': 1} + +#---------------------------------------------# +# v2: RunnablePassthrough.assign() +(RunnablePassthrough.assign(new_num=lambda x: x["num"] * 3)).invoke({"num": 1}) +# 출력: {'num': 1, 'new_num': 3} +``` + +
+ +### b) `RunnableParallel` + +목적: **여러 Runnable 인스턴스를 병렬로 실행** + +```python +from langchain_core.runnables import RunnableParallel + +runnable = RunnableParallel( + passed=RunnablePassthrough(),# 입력 그대로 전달 + extra=RunnablePassthrough.assign(mult=lambda x: x["num"] * 3), + modified=lambda x: x["num"] + 1, +) +``` + +
+ +출력 결과 예시 + +```python +runnable.invoke({"num": 1}) +``` + +``` +{'passed': {'num': 1}, 'extra': {'num': 1, 'mult': 3}, 'modified': 2} +``` + +
+ +Chain에도 적용 가능 + +```python +chain1 = ( + {"country": RunnablePassthrough()} + | PromptTemplate.from_template("{country} 의 수도는?") + | ChatOpenAI() +) + +chain2 = ( + {"country": RunnablePassthrough()} + | PromptTemplate.from_template("{country} 의 면적은?") + | ChatOpenAI() +) +``` + +```python +combined_chain = RunnableParallel(capital=chain1, + area=chain2) +combined_chain.invoke("대한민국") +``` + +``` +{'capital': AIMessage(content='서울입니다.', response_metadata={'token_usage': {'completion_tokens': 5, 'prompt_tokens': 19, 'total_tokens': 24}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-d9324c24-9670-4430-97d6-1272f5dbe0f2-0', usage_metadata={'input_tokens': 19, 'output_tokens': 5, 'total_tokens': 24}), +#---------------------------------------------------# +'area': AIMessage(content='대한민국의 총 면적은 약 100,363 km²입니다.', response_metadata={'token_usage': {'completion_tokens': 24, 'prompt_tokens': 20, 'total_tokens': 44}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-f27442a3-fc9c-4d08-9fdf-189c1b4585c8-0', usage_metadata={'input_tokens': 20, 'output_tokens': 24, 'total_tokens': 44})} +``` + +
+ +### c) `RunnableLambda` + +**사용자 정의 함수** 이용 가능 + +```python +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import PromptTemplate +from langchain_openai import ChatOpenAI +from langchain_core.runnables import RunnableLambda, RunnablePassthrough +from datetime import datetime +``` + +
+ +ex) 사용자 정의 함수: 오늘 날짜 반환 + +```python +def get_today(a): + return datetime.today().strftime("%b-%d") +``` + +
+ +(Runnable을 포함하여) chain 생성하기 + +```python +# (1) prompt +prompt = PromptTemplate.from_template( + "{today} 가 생일인 유명인 {n} 명을 나열하세요. 생년월일을 표기해 주세요." +) + +# (2) model +llm = ChatOpenAI(temperature=0, model_name="gpt-4o") + +# (3) parser +# output_parser = StrOutputParser() +``` + +```python +# chain = Runnable + (1) + (2) + (3) +chain = ( + {"today": RunnableLambda(get_today), "n": RunnablePassthrough()} + | prompt + | llm + | StrOutputParser() +) +``` + +
+ +출력 예시 + +```python +print(chain.invoke(3)) +``` + +``` +다음은 6월 19일이 생일인 몇몇 유명인들입니다: + +1. 폴 도노반 (Paul Dano) - 1984년 6월 19일 +2. 디렉 노박 조코비치 (Novak Djokovic) - 1987년 6월 19일 +3. 필리페 쿠티뉴 (Philippe Coutinho) - 1992년 6월 19일 + +이들은 각각 배우, 테니스 선수, 축구 선수로서 다양한 분야에서 활동하고 있습니다. +``` + +
+ +특정 딕셔너리의 key값에 해당하는 value 추출 + +```python +from operator import itemgetter + +def get_length(text): + return len(text) + +def _multiple_get_length(text1, text2): + return len(text1) * len(text2) + +def multiple_get_length(_dict): + return _multiple_get_length(_dict["text1"], + _dict["text2"]) +``` + +
+ +```python +# (1) prompt +prompt = ChatPromptTemplate.from_template("{a} + {b} 는 무엇인가요?") + +# (2) model +model = ChatOpenAI() + +# chain = Runnable + (1) + (2) +chain = ( + {"a": itemgetter("word1") | RunnableLambda(get_length), +"b": {"text1": itemgetter("word1"), "text2": itemgetter("word2")} | RunnableLambda(multiple_get_length), + } + | prompt + | model +) + +chain.invoke({"word1": "hello", "word2": "world"}) +``` + +작동원리 + +- `"a": itemgetter("word1") | RunnableLambda(get_length)`: + - step 1-1) "word1"의 key값을 가지는 value인 "hello"를 반환 + - step 1-2) "hello"의 길이를 계산하여 "5"를 반환 + - 결론: `a` 변수에 5값이 할당 +- `"b": {"text1": itemgetter("word1"), "text2": itemgetter("word2")} | RunnableLambda(multiple_get_length)` + - Dictionary 완성하기 + - step 2) `text1` 변수에 "word1"의 key값을 가지는 value인 "hello"를 할당 + - step 3) `text2` 변수에 "word2"의 key값을 가지는 value인 "world"를 할당 + - 결론: `{text1:"hello", text2:"world"}` + - `b` 변수에 25이 할당됨 (5x5=25) +- 5 + 25 = 30 diff --git a/_posts/Langchain_ch2.md b/_posts/Langchain_ch2.md new file mode 100644 index 000000000000..c000beef98a3 --- /dev/null +++ b/_posts/Langchain_ch2.md @@ -0,0 +1,550 @@ +# 2. Prompt + +## (0) Intro + +Prompt = LLM에 던지는 질문/명령 + +원하는 답변을 얻기 위해 필수적인 단계! + +
+ +### a) 프롬프트의 필요성 + +- (1) **문맥(Context) 설정**: LLM이 특정 문맥 하에서 작동하도록 설정 +- (2) **정보 통합**: 여러 문서에서 검색된 정보는 서로 다른 관점이나 내용을 포함. 이러한 내용을 전부 담도록 +- (3) **응답 품질 향상**: 프롬프트에 따라 응답 품질이 크게 영향 받음 + +
+ +### b) RAG 프롬프트 구조 + +- (1) 지시 사항 (Instruction) +- (2) 질문 (사용자 입력 질문) +- (3) 문맥 (검색된 정보) + +```yaml +# (1) 지시 사항 +당신은 질문-답변(Question-Answer) Task 를 수행한는 AI 어시스턴트 입니다. +검색된 문맥(context)를 사용하여 질문(question)에 답하세요. +만약, 문맥(context) 으로부터 답을 찾을 수 없다면 '모른다' 고 말하세요. +한국어로 대답하세요. + +# (2) 질문 +#Question: +{이곳에 사용자가 입력한 질문이 삽입됩니다} + +# (3) 문맥 +#Context: +{이곳에 검색된 정보가 삽입됩니다} +``` + +
+ +## (1) 프롬프트 + +### a) `PromptTemplate` + +기본적인 설정 + +```python +from dotenv import load_dotenv +from langchain_teddynote import logging +from langchain_openai import ChatOpenAI + +load_dotenv() + +logging.langsmith("CH02-Prompt") +llm = ChatOpenAI() +``` + +
+ +**방법 1) `from_template()` 사용 (O)** + +```python +from langchain_core.prompts import PromptTemplate + +template = "{country}의 수도는 어디인가요?" +prompt = PromptTemplate.from_template(template) +``` + +
+ +```python +prompt_ex1 = prompt.format(country="대한민국") +prompt_ex1 +``` + +``` +'대한민국의 수도는 어디인가요?' +``` + +
+ +```python +chain = prompt | llm +output_ex1 = chain.invoke("대한민국").content +print(output_ex1) +``` + +``` +'대한민국의 수도는 서울입니다.' +``` + +
+ +**방법 2) `from_template()` 사용 (X)** + +- (객체 생성과 동시에) 프롬프트 생성 +- default 입력값은 `input_variables`에 넣은 변수이다! + +```python +template = "{country}의 수도는 어디인가요?" + +prompt = PromptTemplate( + template=template, + input_variables=["country"], +) +``` + +
+ +```python +prompt_ex2 = prompt.format(country="대한민국") +prompt_ex2 +``` + +``` +'대한민국의 수도는 어디인가요?' +``` + +
+ +**심화** : 2개의 입력 변수 + +```python +template = "{country1}과 {country2}의 수도는 각각 어디인가요?" + +prompt = PromptTemplate( + template=template, + input_variables=["country1"], + partial_variables={ + "country2": "미국" + }, +) +``` + +
+ +```python +prompt_ex3 = prompt.format(country1="대한민국") +prompt_ex3 +``` + +``` +'대한민국과 미국의 수도는 각각 어디인가요?' +``` + +
+ +```python +prompt2 = prompt.partial(country2="캐나다") +prompt_ex4 = prompt2.format(country1="대한민국") +prompt_ex4 +``` + +``` +'대한민국과 캐나다의 수도는 각각 어디인가요?' +``` + +
+ +```python +chain = prompt_partial | llm +output_ex2a = chain.invoke("대한민국").content +output_ex2b = chain.invoke({"country1": "대한민국", "country2": "호주"}).content + +print(output_ex2a) +print(output_ex2b) +``` + +``` +'대한민국의 수도는 서울이며, 캐나다의 수도는 오타와입니다.' +'대한민국의 수도는 서울이고 호주의 수도는 캔버라입니다.' +``` + +
+ +### b) `partial_variables` + +- 목적: 함수를 **부분적으로 사용** + + - When? **항상 공통된 방식으로 가져오고 싶은 변수** 가 있는 경우 + + ( e.g., 날짜나 시간 ) + +
+ +현재 날짜가 항상 표시되기를 원하는 프롬프트 + +```python +from datetime import datetime + +def get_today(): + return datetime.now().strftime("%B %d") +``` + +```python +# (1) prompt +prompt = PromptTemplate( + template="오늘의 날짜는 {today} 입니다. 오늘이 생일인 유명인 {n}명을 나열해 주세요. 생년월일을 표기해주세요.", + input_variables=["n"], + partial_variables={ + "today": get_today + }, +) + +# (2) model +llm = ChatOpenAI() + +# chain = (1) + (2) +chain = prompt | llm +``` + +
+ +(Default: 오늘의 날짜를 불러와서 응답 생성) + +```python +print(chain.invoke(3).content) +``` + +``` +1. Nicole Kidman - 1967년 6월 20일 +2. John Goodman - 1952년 6월 20일 +3. Lionel Richie - 1949년 6월 20일 +``` + +
+ +지정해서도 가능! + +```python +print(chain.invoke({"today": "Jan 02", "n": 3}).content) +``` + +``` +1. Kate Bosworth - 1983년 1월 2일 +2. Tia Carrere - 1967년 1월 2일 +3. Christy Turlington - 1969년 1월 2일 +``` + +
+ +### c) 파일로부터 template 읽어오기 + +```python +from langchain_core.prompts import load_prompt + +prompt = load_prompt("prompts/fruit_color.yaml") +prompt +``` + +``` +PromptTemplate(input_variables=['fruit'], template='{fruit}의 색깔이 뭐야?') +``` + +
+ +```python +prompt_ex1 = prompt.format(fruit="사과") +print(prompt_ex1) +``` + +``` +'사과의 색깔이 뭐야?' +``` + +
+ +### d) `ChatPromptTemplate` + +- 목적: **"대화 목록"** 을 프롬프트로 주입하고자 할 때 +- 형식: **튜플 (tuple)** + - (`role`, `message`) 로 구성하여 리스트로 생성 +- 세부 사항 + - `"system"`: 시스템 설정 메시지 + - `"human"` : 사용자 입력 메시지 + - `"ai"`: AI 의 답변 메시지 + +
+ +Ex 1) `from_template()` + +```python +from langchain_core.prompts import ChatPromptTemplate + +chat_prompt = ChatPromptTemplate.from_template("{country}의 수도는 어디인가요?") + +prompt_ex1 = chat_prompt.format(country="대한민국") +prompt_ex1 +``` + +``` +'Human: 대한민국의 수도는 어디인가요?' +``` + +
+ +Ex 1) `from_messages()` + +```python +chat_template = ChatPromptTemplate.from_messages( + [ + ("system", "당신은 친절한 AI 어시스턴트입니다. 당신의 이름은 {name} 입니다."), + ("human", "반가워요!"), + ("ai", "안녕하세요! 무엇을 도와드릴까요?"), + ("human", "{user_input}"), + ] +) + +messages = chat_template.format_messages( + name="테디", user_input="당신의 이름은 무엇입니까?" +) +messages +``` + +``` +[SystemMessage(content='당신은 친절한 AI 어시스턴트입니다. 당신의 이름은 테디 입니다.'), HumanMessage(content='반가워요!'), AIMessage(content='안녕하세요! 무엇을 도와드릴까요?'), HumanMessage(content='당신의 이름은 무엇입니까?')] +``` + +
+ +```python +output_ex1 = llm.invoke(messages).content +print(output_ex1) +``` + +``` +'제 이름은 테디입니다. 필요한 도움이 있으면 언제든지 말씀해주세요!' +``` + +
+ +Chain 생성 + +```python +chain = chat_template | llm +output_ex2 = chain.invoke({"name": "Teddy", + "user_input": "당신의 이름은 무엇입니까?"}).content +print(output_ex2) +``` + +``` +'제 이름은 Teddy입니다. 어떻게 도와드릴까요?' +``` + +
+ +### e) `MessagePlaceholder` + +- 목적: 렌더링할 **메시지를 완전히 제어**하기 위해 +- When? **메시지 프롬프트 템플릿에 어떤 역할을 사용해야 할지 확실하지 않거나 서식 지정 중에 메시지 목록을 삽입하려는 경우** + +```python +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder + +chat_prompt = ChatPromptTemplate.from_messages( + [ + ("system","당신은 요약 전문 AI 어시스턴트입니다. 당신의 임무는 주요 키워드로 대화를 요약하는 것입니다."), + + + MessagesPlaceholder(variable_name="conversation"), + + + ("human", "지금까지의 대화를 {word_count} 단어로 요약합니다."), + ] +) +``` + +
+ +위와 같이 작성 할 경우, `conversation` 대화목록을 **나중에/원할 때** 추가 가능! + +```python +formatted_chat_prompt = chat_prompt.format( + word_count=5, + conversation=[ + ("human", "안녕하세요! 저는 오늘 새로 입사한 테디 입니다. 만나서 반갑습니다."), + ("ai", "반가워요! 앞으로 잘 부탁 드립니다."), + ], +) + +print(formatted_chat_prompt) +``` + +``` +System: 당신은 요약 전문 AI 어시스턴트입니다. 당신의 임무는 주요 키워드로 대화를 요약하는 것입니다. +Human: 안녕하세요! 저는 오늘 새로 입사한 테디 입니다. 만나서 반갑습니다. +AI: 반가워요! 앞으로 잘 부탁 드립니다. +Human: 지금까지의 대화를 5 단어로 요약합니다. +``` + +
+ +Chain 생성 + +```python +chain = chat_prompt | llm | StrOutputParser() + + +chain.invoke( + { + "word_count": 5, + "conversation": [ + ("human","안녕하세요! 저는 오늘 새로 입사한 테디 입니다. 만나서 반갑습니다."), + ("ai", "반가워요! 앞으로 잘 부탁 드립니다."), + ], + } +) +``` + +``` +# 5 단어로 대화가 요약된 것을 확인할 수 있음! +'새로운 입사자 테디 만남.' +``` + +
+ +## (2) Few-shot Prompt ( `FewShotPromptTemplate` ) + +기본 설정 + +```python +from dotenv import load_dotenv +from langchain_teddynote import logging +from langchain_openai import ChatOpenAI +from langchain_teddynote.messages import stream_response + +load_dotenv() + +logging.langsmith("CH02-Prompt") + +llm = ChatOpenAI( + temperature=0, + model_name="gpt-4-turbo", +) +``` + +
+ +```python +question = "대한민국의 수도는 뭐야?" +answer = llm.stream(question) +stream_response(answer) +``` + +``` +대한민국의 수도는 서울입니다. +``` + +
+ +간단한 example + +```python +from langchain_core.prompts.few_shot import FewShotPromptTemplate +from langchain_core.prompts import PromptTemplate +from langchain_core.output_parsers import StrOutputParser + +fewshot_ex = examples = [ + {"input": "고양이", "output": "Cat"}, + {"input": "강아지", "output": "Dog"} +] + +template_ex = "Input: {input}\nOutput: {output}" +example_prompt = FewShotPromptTemplate.from_examples( + examples=fewshot_ex, + example_prompt_template=template_ex, + input_variables=["input"], + suffix="Input: {input}\nOutput:", +) +``` + +
+ +Few-shot 예시들과 함께 출력된 것을 확인할 수 있다. + +```python +final_prompt = example_prompt.format(input="토끼") +print(final_prompt) +``` + +``` +Input: 고양이 +Output: Cat + +Input: 강아지 +Output: Dog + +Input: 토끼 +Output: +``` + +
+ +## (3) LangChain Hub + +### a) Hub로부터 Prompt 받아오기 + +Prompt를 **LangChain Hub**에서도 받아올 수 있음 + +다양한 방법 + +- (1) 프롬프트 repo의 아이디 값을 가져오기 +- (2) commit id 를 붙여서 특정 버전에 대한 프롬프트를 받아오기 + +```python +from langchain import hub + +prompt = hub.pull("rlm/rag-prompt") +print(prompt) +``` + +``` +input_variables=['context', 'question'] metadata={'lc_hub_owner': 'rlm', 'lc_hub_repo': 'rag-prompt', 'lc_hub_commit_hash': '50442af133e61576e74536c6556cefe1fac147cad032f4377b60c436e6cdcb6e'} messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['context', 'question'], template="You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.\nQuestion: {question} \nContext: {context} \nAnswer:"))] +``` + +
+ +```python +prompt = hub.pull("rlm/rag-prompt:50442af1") +prompt +``` + +``` +ChatPromptTemplate(input_variables=['context', 'question'], metadata={'lc_hub_owner': 'rlm', 'lc_hub_repo': 'rag-prompt', 'lc_hub_commit_hash': '50442af133e61576e74536c6556cefe1fac147cad032f4377b60c436e6cdcb6e'}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['context', 'question'], template="You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.\nQuestion: {question} \nContext: {context} \nAnswer:"))]) +``` + +
+ +### Hub에 프롬프트 등록하기 + +```python +from langchain.prompts import ChatPromptTemplate + +prompt = ChatPromptTemplate.from_template( + "주어진 내용을 바탕으로 다음 문장을 요약하세요. 답변은 반드시 한글로 작성하세요\n\nCONTEXT: {context}\n\nSUMMARY:" +) + +hub.push("teddynote/simple-summary-korean", prompt) + +# 잘 불러와지는지 검토 +# pulled_prompt = hub.pull("teddynote/simple-summary-korean") +``` + +
+ + + diff --git "a/_posts/\354\225\210\353\207\275\354\245\254\353\246\254.pdf" "b/_posts/\354\225\210\353\207\275\354\245\254\353\246\254.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..ca1f31fbc186a493f990549bc684b6bbaced54ee GIT binary patch literal 91145 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 DB2r=H literal 0 HcmV?d00001