├── .gitignore ├── .tool-versions ├── .vscode └── extensions.json ├── 01_setting ├── sample.py └── sample_complete.py ├── 02_model_io ├── chat_model_cache.py ├── chat_model_streaming.py ├── datetime_output_parser.py ├── language_models.py ├── list_output_parser.py ├── model_io_few_shot.py ├── model_io_llm.py ├── prompt.json ├── prompt.py ├── prompt_and_language_model.py ├── prompt_template_from_template_load_sample.py ├── prompt_template_from_template_save_sample.py ├── pydantic_output_parser_1.py └── pydantic_output_parser_2.py ├── 03_retrieval ├── chat_1.py ├── chat_2.py ├── chat_3.py ├── prepare_1.py ├── prepare_2.py ├── prepare_3.py ├── query_1.py ├── query_2.py ├── query_3.py ├── re_phrase_query.py ├── sample_vector.py ├── sample_wikipedia.py ├── sample_wikipedia_2.py └── wikipedia_qa_1.py ├── 04_memory ├── chat_memory_1.py ├── chat_memory_2.py ├── chat_memory_3.py ├── chat_memory_4.py ├── chat_sample_1.py ├── chat_sample_2.py ├── custom_memory_1.py ├── custom_memory_2.py └── memory_sample.py ├── 05_chain ├── conversation_chain.py ├── llmchain.py ├── request_chain.py └── sequential_chain.py ├── 06_agent ├── agent_1.py ├── agent_2.py ├── agent_3.py ├── agent_4.py └── agent_5.py ├── 07_callback ├── chainlit_callback.py └── log_callback.py ├── Readme.md ├── asset └── sample.pdf ├── poetry.lock ├── pyproject.toml └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .chainlit/ 2 | */__pycache__/ 3 | 03_retrieval/.chroma/ 4 | 03_retrieval/.data/ 5 | 03_retrieval/chainlit.md 6 | 03_retrieval/sample.pdf 7 | 03_retrieval/tmp/ 8 | 04_memory/.chainlit/ 9 | 04_memory/chainlit.md 10 | 06_agent/result.txt 11 | 06_agent/random.txt 12 | 07_callback/chainlit.md -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | python 3.10.1 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-python.vscode-pylance", 4 | "ms-python.python" 5 | ] 6 | } -------------------------------------------------------------------------------- /01_setting/sample.py: -------------------------------------------------------------------------------- 1 | import json 2 | import openai #← OpenAI에서 제공하는 Python 패키지 가져오기 3 | 4 | response = openai.ChatCompletion.create( #←OpenAI API를 호출하여 언어 모델을 호출합니다. 5 | model="gpt-3.5-turbo", #← 호출할 언어 모델의 이름 6 | messages=[ 7 | { 8 | "role": "user", 9 | "content": "iPhone8 출시일을 알려주세요" #←입력할 문장(프롬프트) 10 | }, 11 | ] 12 | ) 13 | 14 | print(json.dumps(response, indent=2, ensure_ascii=False)) 15 | -------------------------------------------------------------------------------- /01_setting/sample_complete.py: -------------------------------------------------------------------------------- 1 | import json 2 | import openai 3 | 4 | response = openai.Completion.create( #←ChatCompletion 대신 Completion을 사용 5 | engine="gpt-3.5-turbo-instruct", #←model 대신 engine을 지정하고 gpt-3.5-turbo-instruct를 지정 6 | prompt="오늘 날씨가 매우 좋고 기분이", #←prompt를 지정 7 | stop=".", #←문자가 나타나면 문장 종료 8 | max_tokens=100, #← 최대 토큰 수 9 | n=2, #← 생성할 문장 수 10 | temperature=0.5 #←다양성을 나타내는 매개변수 11 | ) 12 | 13 | print(json.dumps(response, indent=2, ensure_ascii=False)) 14 | -------------------------------------------------------------------------------- /02_model_io/chat_model_cache.py: -------------------------------------------------------------------------------- 1 | import time #← 실행 시간을 측정하기 위해 time 모듈 가져오기 2 | import langchain 3 | from langchain.cache import InMemoryCache #← InMemoryCache 가져오기 4 | from langchain.chat_models import ChatOpenAI 5 | from langchain.schema import HumanMessage 6 | 7 | langchain.llm_cache = InMemoryCache() #← llm_cache에 InMemoryCache 설정 8 | 9 | chat = ChatOpenAI() 10 | start = time.time() #← 실행 시작 시간 기록 11 | result = chat([ #← 첫 번째 실행을 수행 12 | HumanMessage(content="안녕하세요!") 13 | ]) 14 | 15 | end = time.time() #← 실행 종료 시간 기록 16 | print(result.content) 17 | print(f"실행 시간: {end - start}초") 18 | 19 | start = time.time() #← 실행 시작 시간 기록 20 | result = chat([ #← 같은 내용으로 두 번째 실행을 함으로써 캐시가 활용되어 즉시 실행 완료됨 21 | HumanMessage(content="안녕하세요!") 22 | ]) 23 | 24 | end = time.time() #← 실행 종료 시간 기록 25 | print(result.content) 26 | print(f"실행 시간: {end - start}초") 27 | -------------------------------------------------------------------------------- /02_model_io/chat_model_streaming.py: -------------------------------------------------------------------------------- 1 | from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.schema import HumanMessage 4 | 5 | chat = ChatOpenAI( 6 | streaming=True, #← streaming을 True로 설정하여 스트리밍 모드로 실행 7 | callbacks=[ 8 | StreamingStdOutCallbackHandler() #← StreamingStdOutCallbackHandler를 콜백으로 설정 9 | ] 10 | ) 11 | resp = chat([ #← 요청 보내기 12 | HumanMessage(content="맛있는 스테이크 굽는 법을 알려주세요") 13 | ]) 14 | -------------------------------------------------------------------------------- /02_model_io/datetime_output_parser.py: -------------------------------------------------------------------------------- 1 | from langchain import PromptTemplate 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.output_parsers import DatetimeOutputParser #← Output Parser인 DatetimeOutputParser를 가져오기 4 | from langchain.schema import HumanMessage 5 | 6 | output_parser = DatetimeOutputParser() #← DatetimeOutputParser를 초기화 7 | 8 | chat = ChatOpenAI(model="gpt-3.5-turbo", ) 9 | 10 | prompt = PromptTemplate.from_template("{product}의 출시일을 알려주세요") #← 출시일 물어보기 11 | 12 | result = chat( 13 | [ 14 | HumanMessage(content=prompt.format(product="iPhone8")), #← iPhone8의 출시일 물어보기 15 | HumanMessage(content=output_parser.get_format_instructions()), #← output_parser.get_format_instructions()를 실행하여 언어모델에 지시사항 추가하기 16 | ] 17 | ) 18 | 19 | output = output_parser.parse(result.content) #← 출력 결과를 분석하여 날짜 및 시간 형식으로 변환 20 | 21 | print(output) 22 | -------------------------------------------------------------------------------- /02_model_io/language_models.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI #← 모듈 가져오기 2 | from langchain.schema import HumanMessage #← 사용자의 메시지인 HumanMessage 가져오기 3 | 4 | chat = ChatOpenAI( #← 클라이언트를 만들고 chat에 저장 5 | model="gpt-3.5-turbo", #← 호출할 모델 지정 6 | ) 7 | 8 | result = chat( #← 실행하기 9 | [ 10 | HumanMessage(content="안녕하세요!"), 11 | ] 12 | ) 13 | print(result.content) 14 | -------------------------------------------------------------------------------- /02_model_io/list_output_parser.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI 2 | from langchain.output_parsers import \ 3 | CommaSeparatedListOutputParser #← Output Parser인 CommaSeparatedListOutputParser를 가져옵니다. 4 | from langchain.schema import HumanMessage 5 | 6 | output_parser = CommaSeparatedListOutputParser() #← CommaSeparatedListOutputParser 초기화 7 | 8 | chat = ChatOpenAI(model="gpt-3.5-turbo", ) 9 | 10 | result = chat( 11 | [ 12 | HumanMessage(content="애플이 개발한 대표적인 제품 3개를 알려주세요"), 13 | HumanMessage(content=output_parser.get_format_instructions()), #← output_parser.get_format_instructions()를 실행하여 언어모델에 지시사항 추가하기 14 | ] 15 | ) 16 | 17 | output = output_parser.parse(result.content) #← 출력 결과를 분석하여 목록 형식으로 변환한다. 18 | 19 | for item in output: #← 목록을 하나씩 꺼내어 출력한다. 20 | print("대표 상품 => " + item) 21 | -------------------------------------------------------------------------------- /02_model_io/model_io_few_shot.py: -------------------------------------------------------------------------------- 1 | from langchain.llms import OpenAI 2 | from langchain.prompts import FewShotPromptTemplate, PromptTemplate 3 | 4 | examples = [ 5 | { 6 | "input": "충청도의 계룡산 전라도의 내장산 강원도의 설악산은 모두 국립 공원이다", #← 입력 예 7 | "output": "충청도의 계룡산, 전라도의 내장산, 강원도의 설악산은 모두 국립 공원이다." #← 출력 예 8 | } 9 | ] 10 | 11 | prompt = PromptTemplate( #← PromptTemplate 준비 12 | input_variables=["input", "output"], #← input과 output을 입력 변수로 설정 13 | template="입력: {input}\n출력: {output}", #← 템플릿 14 | ) 15 | 16 | few_shot_prompt = FewShotPromptTemplate( #← FewShotPromptTemplate 준비 17 | examples=examples, #← 입력 예와 출력 예를 정의 18 | example_prompt=prompt, #← FewShotPromptTemplate에 PromptTemplate를 전달 19 | prefix="아래 문장부호가 빠진 입력에 문장부호를 추가하세요. 추가할 수 있는 문장부호는 ',', '.'입니다. 다른 문장부호는 추가하지 마세요.", #← 지시어 추가하기 20 | suffix="입력: {input_string}\n출력:", #← 출력 예의 입력 변수를 정의 21 | input_variables=["input_string"], #← FewShotPromptTemplate의 입력 변수를 설정 22 | ) 23 | llm = OpenAI() 24 | formatted_prompt = few_shot_prompt.format( #← FewShotPromptTemplate을 사용하여 프롬프트 작성 25 | input_string="집을 보러 가면 그 집이 내가 원하는 조건에 맞는지 살기에 편한지 망가진 곳은 없는지 확인해야 한다" 26 | ) 27 | result = llm.predict(formatted_prompt) 28 | print("formatted_prompt: ", formatted_prompt) 29 | print("result: ", result) 30 | -------------------------------------------------------------------------------- /02_model_io/model_io_llm.py: -------------------------------------------------------------------------------- 1 | from langchain.llms import OpenAI 2 | 3 | llm = OpenAI(model="gpt-3.5-turbo-instruct" #← 호출할 모델 지정 4 | ) 5 | 6 | result = llm( 7 | "맛있는 라면을", #← 언어모델에 입력되는 텍스트 8 | stop="." #← "." 가 출력된 시점에서 계속을 생성하지 않도록 9 | ) 10 | print(result) 11 | -------------------------------------------------------------------------------- /02_model_io/prompt.json: -------------------------------------------------------------------------------- 1 | { 2 | "input_variables": [ 3 | "product" 4 | ], 5 | "output_parser": null, 6 | "partial_variables": {}, 7 | "template": "{product}\ub294 \uc5b4\ub290 \ud68c\uc0ac\uc5d0\uc11c \uac1c\ubc1c\ud55c \uc81c\ud488\uc778\uac00\uc694\uff1f", 8 | "template_format": "f-string", 9 | "validate_template": true, 10 | "_type": "prompt" 11 | } -------------------------------------------------------------------------------- /02_model_io/prompt.py: -------------------------------------------------------------------------------- 1 | from langchain import PromptTemplate #← PromptTemplate 가져오기 2 | 3 | prompt = PromptTemplate( #← PromptTemplate 초기화하기 4 | template="{product}는 어느 회사에서 개발한 제품인가요?", #← {product}라는 변수를 포함하는 프롬프트 작성하기 5 | input_variables=[ 6 | "product" #← product에 입력할 변수 지정 7 | ] 8 | ) 9 | 10 | print(prompt.format(product="아이폰")) 11 | print(prompt.format(product="갤럭시")) 12 | -------------------------------------------------------------------------------- /02_model_io/prompt_and_language_model.py: -------------------------------------------------------------------------------- 1 | from langchain import PromptTemplate 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.schema import HumanMessage 4 | 5 | chat = ChatOpenAI( #← 클라이언트 생성 및 chat에 저장 6 | model="gpt-3.5-turbo", #← 호출할 모델 지정 7 | ) 8 | 9 | prompt = PromptTemplate( #← PromptTemplate을 작성 10 | template="{product}는 어느 회사에서 개발한 제품인가요?", #← {product}라는 변수를 포함하는 프롬프트 작성하기 11 | input_variables=[ 12 | "product" #← product에 입력할 변수 지정 13 | ] 14 | ) 15 | 16 | result = chat( #← 실행 17 | [ 18 | HumanMessage(content=prompt.format(product="아이폰")), 19 | ] 20 | ) 21 | print(result.content) 22 | -------------------------------------------------------------------------------- /02_model_io/prompt_template_from_template_load_sample.py: -------------------------------------------------------------------------------- 1 | from langchain.prompts import load_prompt 2 | 3 | loaded_prompt = load_prompt("prompt.json") #← JSON에서 PromptTemplate를 로드 4 | 5 | print(loaded_prompt.format(product="iPhone")) #← PromptTemplate를 사용해 문장 생성 6 | -------------------------------------------------------------------------------- /02_model_io/prompt_template_from_template_save_sample.py: -------------------------------------------------------------------------------- 1 | from langchain.prompts import PromptTemplate 2 | 3 | prompt = PromptTemplate(template="{product}는 어느 회사에서 개발한 제품인가요?", input_variables=["product"]) 4 | prompt_json = prompt.save("prompt.json") #← PromptTemplate를 JSON으로 변환 5 | -------------------------------------------------------------------------------- /02_model_io/pydantic_output_parser_1.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI 2 | from langchain.output_parsers import PydanticOutputParser 3 | from langchain.schema import HumanMessage 4 | from pydantic import BaseModel, Field, validator 5 | 6 | chat = ChatOpenAI() 7 | 8 | class Smartphone(BaseModel): #← Pydantic의 모델을 정의한다. 9 | release_date: str = Field(description="스마트폰 출시일") #← Field를 사용해 설명을 추가 10 | screen_inches: float = Field(description="스마트폰의 화면 크기(인치)") 11 | os_installed: str = Field(description="스마트폰에 설치된 OS") 12 | model_name: str = Field(description="스마트폰 모델명") 13 | 14 | @validator("screen_inches") #← validator를 사용해 값을 검증 15 | def validate_screen_inches(cls, field): #← 검증할 필드와 값을 validator의 인수로 전달 16 | if field <= 0: #← screen_inches가 0 이하인 경우 에러를 반환 17 | raise ValueError("Screen inches must be a positive number") 18 | return field 19 | 20 | parser = PydanticOutputParser(pydantic_object=Smartphone) #← PydanticOutputParser를 SmartPhone 모델로 초기화 21 | 22 | result = chat([ #← Chat models에 HumanMessage를 전달해 문장을 생성 23 | HumanMessage(content="안드로이드 스마트폰 1개를 꼽아주세요"), 24 | HumanMessage(content=parser.get_format_instructions()) 25 | ]) 26 | 27 | parsed_result = parser.parse(result.content) #← PydanticOutputParser를 사용해 문장을 파싱 28 | 29 | print(f"모델명: {parsed_result.model_name}") 30 | print(f"화면 크기: {parsed_result.screen_inches}인치") 31 | print(f"OS: {parsed_result.os_installed}") 32 | print(f"스마트폰 출시일: {parsed_result.release_date}") 33 | -------------------------------------------------------------------------------- /02_model_io/pydantic_output_parser_2.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI 2 | from langchain.output_parsers import OutputFixingParser #←OutputFixingParser를 추가 3 | from langchain.output_parsers import PydanticOutputParser 4 | from langchain.schema import HumanMessage 5 | from pydantic import BaseModel, Field, validator 6 | 7 | chat = ChatOpenAI() 8 | 9 | class Smartphone(BaseModel): 10 | release_date: str = Field(description="스마트폰 출시일") 11 | screen_inches: float = Field(description="스마트폰의 화면 크기(인치)") 12 | os_installed: str = Field(description="스마트폰에 설치된 OS") 13 | model_name: str = Field(description="스마트폰 모델명") 14 | 15 | @validator("screen_inches") 16 | def validate_screen_inches(cls, field): 17 | if field <= 0: 18 | raise ValueError("Screen inches must be a positive number") 19 | return field 20 | 21 | 22 | parser = OutputFixingParser.from_llm( #← OutputFixingParser를 사용하도록 재작성 23 | parser=PydanticOutputParser(pydantic_object=Smartphone), #← parser 설정 24 | llm=chat #← 수정에 사용할 언어 모델 설정 25 | ) 26 | 27 | result = chat([HumanMessage(content="안드로이드 스마트폰 1개를 꼽아주세요"), HumanMessage(content=parser.get_format_instructions())]) 28 | 29 | parsed_result = parser.parse(result.content) 30 | 31 | print(f"모델명: {parsed_result.model_name}") 32 | print(f"화면 크기: {parsed_result.screen_inches}인치") 33 | print(f"OS: {parsed_result.os_installed}") 34 | print(f"스마트폰 출시일: {parsed_result.release_date}") 35 | -------------------------------------------------------------------------------- /03_retrieval/chat_1.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | 3 | 4 | @cl.on_chat_start #← 채팅이 시작될 때 실행할 함수를 정의 5 | async def on_chat_start(): 6 | await cl.Message(content="준비되었습니다! 메시지를 입력하세요!").send() #← 초기에 표시할 메시지를 보냄 7 | 8 | @cl.on_message #← 메시지를 보낼 때 실행할 함수를 정의 9 | async def on_message(input_message): 10 | print("입력된 메시지: " + input_message) 11 | await cl.Message(content="안녕하세요!").send() #← 챗봇의 답변을 보냄 12 | -------------------------------------------------------------------------------- /03_retrieval/chat_2.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.embeddings import OpenAIEmbeddings 4 | from langchain.prompts import PromptTemplate 5 | from langchain.schema import HumanMessage 6 | from langchain.vectorstores import Chroma 7 | 8 | embeddings = OpenAIEmbeddings( 9 | model="text-embedding-ada-002" 10 | ) 11 | 12 | chat = ChatOpenAI(model="gpt-3.5-turbo") 13 | 14 | prompt = PromptTemplate(template="""문장을 바탕으로 질문에 답하세요. 15 | 16 | 문장: 17 | {document} 18 | 19 | 질문: {query} 20 | """, input_variables=["document", "query"]) 21 | 22 | database = Chroma( 23 | persist_directory="./.data", 24 | embedding_function=embeddings 25 | ) 26 | 27 | @cl.on_chat_start 28 | async def on_chat_start(): 29 | await cl.Message(content="준비되었습니다! 메시지를 입력하세요!").send() 30 | 31 | @cl.on_message 32 | async def on_message(input_message): 33 | print("입력된 메시지: " + input_message) 34 | documents = database.similarity_search(input_message) #← input_message로 변경 35 | 36 | documents_string = "" 37 | 38 | for document in documents: 39 | documents_string += f""" 40 | --------------------------- 41 | {document.page_content} 42 | """ 43 | 44 | result = chat([ 45 | HumanMessage(content=prompt.format(document=documents_string, 46 | query=input_message)) #← input_message로 변경 47 | ]) 48 | await cl.Message(content=result.content).send() #← 챗봇의 답변을 보냄 49 | -------------------------------------------------------------------------------- /03_retrieval/chat_3.py: -------------------------------------------------------------------------------- 1 | import os 2 | import chainlit as cl 3 | from langchain.chat_models import ChatOpenAI 4 | from langchain.document_loaders import PyMuPDFLoader 5 | from langchain.embeddings import OpenAIEmbeddings 6 | from langchain.prompts import PromptTemplate 7 | from langchain.schema import HumanMessage 8 | from langchain.text_splitter import SpacyTextSplitter 9 | from langchain.vectorstores import Chroma 10 | 11 | 12 | embeddings = OpenAIEmbeddings( 13 | model="text-embedding-ada-002" 14 | ) 15 | 16 | chat = ChatOpenAI(model="gpt-3.5-turbo") 17 | 18 | prompt = PromptTemplate(template="""문장을 기반으로 질문에 답하세요. 19 | 20 | 문장: 21 | {document} 22 | 23 | 질문: {query} 24 | """, input_variables=["document", "query"]) 25 | 26 | text_splitter = SpacyTextSplitter(chunk_size=300, pipeline="ko_core_news_sm") 27 | 28 | @cl.on_chat_start 29 | async def on_chat_start(): 30 | files = None #← 파일이 선택되어 있는지 확인하는 변수 31 | 32 | while files is None: #← 파일이 선택될 때까지 반복 33 | files = await cl.AskFileMessage( 34 | max_size_mb=20, 35 | content="PDF를 선택해 주세요", 36 | accept=["application/pdf"], 37 | raise_on_timeout=False, 38 | ).send() 39 | file = files[0] 40 | 41 | if not os.path.exists("tmp"): #← tmp 디렉터리가 존재하는지 확인 42 | os.mkdir("tmp") #← 존재하지 않으면 생성 43 | with open(f"tmp/{file.name}", "wb") as f: #← PDF 파일을 저장 44 | f.write(file.content) #← 파일 내용을 작성 45 | 46 | documents = PyMuPDFLoader(f"tmp/{file.name}").load() #← 저장한 PDF 파일을 로드 47 | splitted_documents = text_splitter.split_documents(documents) #← 문서를 분할 48 | 49 | database = Chroma( #← 데이터베이스 초기화 50 | embedding_function=embeddings, 51 | # 이번에는 persist_directory를 지정하지 않음으로써 데이터베이스 영속화를 하지 않음 52 | ) 53 | 54 | database.add_documents(splitted_documents) #← 문서를 데이터베이스에 추가 55 | 56 | cl.user_session.set( #← 데이터베이스를 세션에 저장 57 | "database", #← 세션에 저장할 이름 58 | database #← 세션에 저장할 값 59 | ) 60 | 61 | await cl.Message(content=f"`{file.name}` 로딩이 완료되었습니다. 질문을 입력하세요.").send() #← 불러오기 완료를 알림 62 | 63 | @cl.on_message 64 | async def on_message(input_message): 65 | print("입력된 메시지: " + input_message) 66 | 67 | database = cl.user_session.get("database") #← 세션에서 데이터베이스를 가져옴 68 | 69 | documents = database.similarity_search(input_message) 70 | 71 | documents_string = "" 72 | 73 | for document in documents: 74 | documents_string += f""" 75 | --------------------------- 76 | {document.page_content} 77 | """ 78 | 79 | result = chat([ 80 | HumanMessage(content=prompt.format(document=documents_string, 81 | query=input_message)) #← input_message로 변경 82 | ]) 83 | await cl.Message(content=result.content).send() 84 | -------------------------------------------------------------------------------- /03_retrieval/prepare_1.py: -------------------------------------------------------------------------------- 1 | from langchain.document_loaders import PyMuPDFLoader 2 | 3 | loader = PyMuPDFLoader("./sample.pdf") #← sample.pdf 로드 4 | documents = loader.load() 5 | 6 | print(f"문서 개수: {len(documents)}") #← 문서 개수 확인 7 | print(f"첫 번째 문서의 내용: {documents[0].page_content}") #← 첫 번째 문서의 내용을 확인 8 | print(f"첫 번째 문서의 메타데이터: {documents[0].metadata}") #← 첫 번째 문서의 메타데이터를 확인 9 | -------------------------------------------------------------------------------- /03_retrieval/prepare_2.py: -------------------------------------------------------------------------------- 1 | from langchain.document_loaders import PyMuPDFLoader 2 | from langchain.text_splitter import SpacyTextSplitter #← SpacyTextSplitter를 가져옴 3 | 4 | loader = PyMuPDFLoader("./sample.pdf") 5 | documents = loader.load() 6 | 7 | text_splitter = SpacyTextSplitter( #← SpacyTextSplitter를 초기화 8 | chunk_size=300, #← 분할할 크기를 설정 9 | pipeline="ko_core_news_sm" #← 분할에 사용할 언어 모델을 설정 10 | ) 11 | splitted_documents = text_splitter.split_documents(documents) #← 문서를 분할 12 | 13 | print(f"분할 전 문서 개수: {len(documents)}") 14 | print(f"분할 후 문서 개수: {len(splitted_documents)}") 15 | -------------------------------------------------------------------------------- /03_retrieval/prepare_3.py: -------------------------------------------------------------------------------- 1 | from langchain.document_loaders import PyMuPDFLoader 2 | from langchain.embeddings import OpenAIEmbeddings #← OpenAIEmbeddings 가져오기 3 | from langchain.text_splitter import SpacyTextSplitter 4 | from langchain.vectorstores import Chroma #← Chroma 가져오기 5 | 6 | loader = PyMuPDFLoader("./sample.pdf") 7 | documents = loader.load() 8 | 9 | text_splitter = SpacyTextSplitter( 10 | chunk_size=300, 11 | pipeline="ko_core_news_sm" 12 | ) 13 | splitted_documents = text_splitter.split_documents(documents) 14 | 15 | embeddings = OpenAIEmbeddings( #← OpenAIEmbeddings를 초기화 16 | model="text-embedding-ada-002" #← 모델명을 지정 17 | ) 18 | 19 | database = Chroma( #← Chroma를 초기화 20 | persist_directory="./.data", #← 영속화 데이터 저장 위치 지정 21 | embedding_function=embeddings #← 벡터화할 모델을 지정 22 | ) 23 | 24 | database.add_documents( #← 문서를 데이터베이스에 추가 25 | splitted_documents, #← 추가할 문서 지정 26 | ) 27 | 28 | print("데이터베이스 생성이 완료되었습니다.") #← 완료 알림 29 | -------------------------------------------------------------------------------- /03_retrieval/query_1.py: -------------------------------------------------------------------------------- 1 | from langchain.embeddings import OpenAIEmbeddings 2 | from langchain.vectorstores import Chroma 3 | 4 | embeddings = OpenAIEmbeddings( 5 | model="text-embedding-ada-002" 6 | ) 7 | 8 | database = Chroma( 9 | persist_directory="./.data", 10 | embedding_function=embeddings 11 | ) 12 | 13 | documents = database.similarity_search("비행 자동차의 최고 속도는?") #← 데이터베이스에서 유사도가 높은 문서를 가져옴 14 | print(f"문서 개수: {len(documents)}") #← 문서 개수 표시 15 | 16 | for document in documents: 17 | print(f"문서 내용: {document.page_content}") #← 문서 내용을 표시 18 | -------------------------------------------------------------------------------- /03_retrieval/query_2.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI #← ChatOpenAI 가져오기 2 | from langchain.embeddings import OpenAIEmbeddings 3 | from langchain.prompts import PromptTemplate #← PromptTemplate 가져오기 4 | from langchain.schema import HumanMessage #← HumanMessage 가져오기 5 | from langchain.vectorstores import Chroma 6 | 7 | embeddings = OpenAIEmbeddings( 8 | model="text-embedding-ada-002" 9 | ) 10 | 11 | database = Chroma( 12 | persist_directory="./.data", 13 | embedding_function=embeddings 14 | ) 15 | 16 | query = "비행 자동차의 최고 속도는?" 17 | 18 | documents = database.similarity_search(query) 19 | 20 | documents_string = "" #← 문서 내용을 저장할 변수를 초기화 21 | 22 | for document in documents: 23 | documents_string += f""" 24 | --------------------------- 25 | {document.page_content} 26 | """ #← 문서 내용을 추가 27 | 28 | prompt = PromptTemplate( #← PromptTemplate를 초기화 29 | template="""문장을 바탕으로 질문에 답하세요. 30 | 31 | 문장: 32 | {document} 33 | 34 | 질문: {query} 35 | """, 36 | input_variables=["document","query"] #← 입력 변수를 지정 37 | ) 38 | 39 | chat = ChatOpenAI( #← ChatOpenAI를 초기화 40 | model="gpt-3.5-turbo" 41 | ) 42 | 43 | result = chat([ 44 | HumanMessage(content=prompt.format(document=documents_string, query=query)) 45 | ]) 46 | 47 | print(result.content) 48 | -------------------------------------------------------------------------------- /03_retrieval/query_3.py: -------------------------------------------------------------------------------- 1 | from langchain.chains import RetrievalQA #← RetrievalQA를 가져오기 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.embeddings import OpenAIEmbeddings 4 | from langchain.vectorstores import Chroma 5 | 6 | chat = ChatOpenAI(model="gpt-3.5-turbo") 7 | 8 | embeddings = OpenAIEmbeddings( 9 | model="text-embedding-ada-002" 10 | ) 11 | 12 | database = Chroma( 13 | persist_directory="./.data", 14 | embedding_function=embeddings 15 | ) 16 | 17 | retriever = database.as_retriever() #← 데이터베이스를 Retriever로 변환 18 | 19 | qa = RetrievalQA.from_llm( #← RetrievalQA를 초기화 20 | llm=chat, #← Chat models를 지정 21 | retriever=retriever, #← Retriever를 지정 22 | return_source_documents=True #← 응답에 원본 문서를 포함할지를 지정 23 | ) 24 | 25 | result = qa("비행 자동차의 최고 속도를 알려주세요") 26 | 27 | print(result["result"]) #← 응답을 표시 28 | 29 | print(result["source_documents"]) #← 원본 문서를 표시 30 | -------------------------------------------------------------------------------- /03_retrieval/re_phrase_query.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI 2 | from langchain.retrievers import WikipediaRetriever, RePhraseQueryRetriever #← RePhraseQueryRetriever를 가져오기 3 | from langchain import LLMChain 4 | from langchain.prompts import PromptTemplate 5 | 6 | retriever = WikipediaRetriever( 7 | lang="ko", 8 | doc_content_chars_max=500 9 | ) 10 | 11 | llm_chain = LLMChain( #← LLMChain을 초기화 12 | llm = ChatOpenAI( #← ChatOpenAI를 지정 13 | temperature = 0 14 | ), 15 | prompt= PromptTemplate( #← PromptTemplate을 지정 16 | input_variables=["question"], 17 | template="""아래 질문에서 Wikipedia에서 검색할 키워드를 추출해 주세요. 18 | 질문: {question} 19 | """ 20 | )) 21 | 22 | re_phrase_query_retriever = RePhraseQueryRetriever( #← RePhraseQueryRetriever를 초기화 23 | llm_chain=llm_chain, #← LLMChain을 지정 24 | retriever=retriever, #← WikipediaRetriever를 지정 25 | ) 26 | 27 | documents = re_phrase_query_retriever.get_relevant_documents("나는 라면을 좋아합니다. 그런데 소주란 무엇인가요?") 28 | 29 | print(documents) 30 | -------------------------------------------------------------------------------- /03_retrieval/sample_vector.py: -------------------------------------------------------------------------------- 1 | from langchain.embeddings import OpenAIEmbeddings #← OpenAIEmbeddings를 가져오기 2 | from numpy import dot #← 벡터의 유사도를 계산하기 위해 dot을 가져오기 3 | from numpy.linalg import norm #← 벡터의 유사도를 계산하기 위해 norm을 가져오기 4 | 5 | embeddings = OpenAIEmbeddings( #← OpenAIEmbeddings를 초기화 6 | model="text-embedding-ada-002" 7 | ) 8 | 9 | query_vector = embeddings.embed_query("비행 자동차의 최고 속도는?") #← 질문을 벡터화 10 | 11 | print(f"벡터화된 질문: {query_vector[:5]}") #← 벡터의 일부를 표시 12 | 13 | document_1_vector = embeddings.embed_query("비행 자동차의 최고 속도는 시속 150km입니다.") #← 문서 1의 벡터를 얻음 14 | document_2_vector = embeddings.embed_query("닭고기를 적당히 양념한 후 중불로 굽다가 가끔 뒤집어 주면서 겉은 고소하고 속은 부드럽게 익힌다.") #← 문서 2의 벡터를 얻음 15 | 16 | cos_sim_1 = dot(query_vector, document_1_vector) / (norm(query_vector) * norm(document_1_vector)) #← 벡터의 유사도를 계산 17 | print(f"문서 1과 질문의 유사도: {cos_sim_1}") 18 | cos_sim_2 = dot(query_vector, document_2_vector) / (norm(query_vector) * norm(document_2_vector)) #← 벡터의 유사도를 계산 19 | print(f"문서 2와 질문의 유사도: {cos_sim_2}") 20 | -------------------------------------------------------------------------------- /03_retrieval/sample_wikipedia.py: -------------------------------------------------------------------------------- 1 | from langchain.retrievers import WikipediaRetriever 2 | 3 | retriever = WikipediaRetriever( #← WikipediaRetriever를 초기화 4 | lang="ko", #← Wikipedia의 언어를 지정 5 | ) 6 | documents = retriever.get_relevant_documents( #← Wikipedia에서 관련 문서를 가져옴 7 | "대형 언어 모델" #← 검색할 키워드를 지정 8 | ) 9 | 10 | print(f"검색 결과: {len(documents)}건") #← 검색 결과 건수를 표시 11 | 12 | for document in documents: 13 | print("---------------검색한 메타데이터---------------") 14 | print(document.metadata) #← 메타데이터를 표시 15 | print("---------------검색한 텍스트---------------") 16 | print(document.page_content[:100]) #← 텍스트의 첫 100글자를 표시 17 | -------------------------------------------------------------------------------- /03_retrieval/sample_wikipedia_2.py: -------------------------------------------------------------------------------- 1 | from langchain.retrievers import WikipediaRetriever 2 | 3 | retriever = WikipediaRetriever( 4 | lang="ko", 5 | doc_content_chars_max=100, 6 | top_k_results=1 7 | ) 8 | documents = retriever.get_relevant_documents( 9 | "나는 라면을 좋아합니다. 그런데 소주란 무엇인가요?" 10 | ) 11 | print(documents) 12 | -------------------------------------------------------------------------------- /03_retrieval/wikipedia_qa_1.py: -------------------------------------------------------------------------------- 1 | from langchain.chains import RetrievalQA 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.retrievers import WikipediaRetriever 4 | 5 | chat = ChatOpenAI() 6 | 7 | retriever = WikipediaRetriever( #← WikipediaRetriever를 초기화 8 | lang="ko", #← Wikipedia의 언어를 지정 9 | doc_content_chars_max=500, #← 검색할 텍스트의 최대 글자수를 지정 10 | top_k_results=2, #← 검색 결과 중 상위 몇 건을 가져올지 지정 11 | ) 12 | 13 | chain = RetrievalQA.from_llm( #← RetrievalQA를 초기화 14 | llm=chat, #← 사용할 Chat models를 지정 15 | retriever=retriever, #← 사용할 Retriever를 지정 16 | return_source_documents=True, #← 정보를 가져온 원본 문서를 반환 17 | ) 18 | 19 | result = chain("소주란?") #← RetrievalQA를 실행 20 | 21 | source_documents = result["source_documents"] #← 정보 출처의 문서를 가져옴 22 | 23 | print(f"검색 결과: {len(source_documents)}건") #← 검색 결과 건수를 표시 24 | for document in source_documents: 25 | print("---------------검색한 메타데이터---------------") 26 | print(document.metadata) 27 | print("---------------검색한 텍스트---------------") 28 | print(document.page_content[:100]) 29 | print("---------------응답---------------") 30 | print(result["result"]) #← 응답을 표시 31 | -------------------------------------------------------------------------------- /04_memory/chat_memory_1.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.memory import ConversationBufferMemory #← ConversationBufferMemory 가져오기 4 | from langchain.schema import HumanMessage 5 | 6 | chat = ChatOpenAI( 7 | model="gpt-3.5-turbo" 8 | ) 9 | 10 | memory = ConversationBufferMemory( #← 메모리 초기화 11 | return_messages=True 12 | ) 13 | 14 | @cl.on_chat_start 15 | async def on_chat_start(): 16 | await cl.Message(content="저는 대화의 맥락을 고려해 답변할 수 있는 채팅봇입니다. 메시지를 입력하세요.").send() 17 | 18 | @cl.on_message 19 | async def on_message(message: str): 20 | memory_message_result = memory.load_memory_variables({}) #← 메모리 내용을 로드 21 | 22 | messages = memory_message_result['history'] #← 메모리 내용에서 메시지만 얻음 23 | 24 | messages.append(HumanMessage(content=message)) #← 사용자의 메시지를 추가 25 | 26 | result = chat( #← Chat models를 사용해 언어 모델을 호출 27 | messages 28 | ) 29 | 30 | memory.save_context( #← 메모리에 메시지를 추가 31 | { 32 | "input": message, #← 사용자의 메시지를 input으로 저장 33 | }, 34 | { 35 | "output": result.content, #← AI의 메시지를 output으로 저장 36 | } 37 | ) 38 | await cl.Message(content=result.content).send() #← AI의 메시지를 송신 39 | -------------------------------------------------------------------------------- /04_memory/chat_memory_2.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | from langchain.chains import ConversationChain #← ConversationChain을 가져오기 3 | from langchain.chat_models import ChatOpenAI 4 | from langchain.memory import ConversationBufferMemory 5 | 6 | chat = ChatOpenAI( 7 | model="gpt-3.5-turbo" 8 | ) 9 | 10 | memory = ConversationBufferMemory( 11 | return_messages=True 12 | ) 13 | 14 | chain = ConversationChain( #← ConversationChain을 초기화 15 | memory=memory, 16 | llm=chat, 17 | ) 18 | 19 | @cl.on_chat_start 20 | async def on_chat_start(): 21 | await cl.Message(content="저는 대화의 맥락을 고려해 답변할 수 있는 채팅봇입니다. 메시지를 입력하세요.").send() 22 | 23 | @cl.on_message 24 | async def on_message(message: str): 25 | 26 | result = chain( #← ConversationChain을 사용해 언어 모델을 호출 27 | message #← 사용자 메시지를 인수로 지정 28 | ) 29 | 30 | await cl.Message(content=result["response"]).send() 31 | -------------------------------------------------------------------------------- /04_memory/chat_memory_3.py: -------------------------------------------------------------------------------- 1 | import os #← 환경변수를 얻기 위해 os를 가져오기 2 | import chainlit as cl 3 | from langchain.chains import ConversationChain 4 | from langchain.chat_models import ChatOpenAI 5 | from langchain.memory import RedisChatMessageHistory #← RedisChatMessageHistory를 추가 6 | from langchain.memory import ConversationBufferMemory 7 | 8 | chat = ChatOpenAI( 9 | model="gpt-3.5-turbo" 10 | ) 11 | 12 | history = RedisChatMessageHistory( #← RedisChatMessageHistory를 초기화 13 | session_id="chat_history", 14 | url=os.environ.get("REDIS_URL"), #← 환경변수에서 Redis의 URL을 가져오기 15 | ) 16 | 17 | memory = ConversationBufferMemory( 18 | return_messages=True, 19 | chat_memory=history, #← 채팅 기록을 지정 20 | ) 21 | 22 | chain = ConversationChain( 23 | memory=memory, 24 | llm=chat, 25 | ) 26 | 27 | @cl.on_chat_start 28 | async def on_chat_start(): 29 | await cl.Message(content="저는 대화의 맥락을 고려해 답변할 수 있는 채팅봇입니다. 메시지를 입력하세요.").send() 30 | 31 | @cl.on_message 32 | async def on_message(message: str): 33 | 34 | result = chain(message) 35 | 36 | await cl.Message(content=result["response"]).send() 37 | -------------------------------------------------------------------------------- /04_memory/chat_memory_4.py: -------------------------------------------------------------------------------- 1 | import os 2 | import chainlit as cl 3 | from langchain.chains import ConversationChain 4 | from langchain.chat_models import ChatOpenAI 5 | from langchain.memory import ConversationBufferMemory, RedisChatMessageHistory 6 | from langchain.schema import HumanMessage 7 | 8 | chat = ChatOpenAI( 9 | model="gpt-3.5-turbo" 10 | ) 11 | 12 | @cl.on_chat_start 13 | async def on_chat_start(): 14 | thread_id = None 15 | while not thread_id: #← 스레드 ID가 입력될 때까지 반복 16 | res = await cl.AskUserMessage(content="저는 대화의 맥락을 고려해 답변할 수 있는 채팅봇입니다. 스레드 ID를 입력하세요.", timeout=600).send() #← AskUserMessage를 사용해 스레드 ID 입력 17 | if res: 18 | thread_id = res['content'] 19 | 20 | history = RedisChatMessageHistory( #← 새로 채팅이 시작될 때마다 초기화하도록 on_chat_start로 이동 21 | session_id=thread_id, #← 스레드 ID를 세션 ID로 지정 22 | url=os.environ.get("REDIS_URL"), 23 | ) 24 | 25 | memory = ConversationBufferMemory( #← 새로 채팅이 시작될 때마다 초기화하도록 on_chat_start로 이동 26 | return_messages=True, 27 | chat_memory=history, 28 | ) 29 | 30 | chain = ConversationChain( #← 새로 채팅이 시작될 때마다 초기화하도록 on_chat_start로 이동 31 | memory=memory, 32 | llm=chat, 33 | ) 34 | 35 | memory_message_result = chain.memory.load_memory_variables({}) #← 메모리 내용 가져오기 36 | 37 | messages = memory_message_result['history'] 38 | 39 | for message in messages: 40 | if isinstance(message, HumanMessage): #← 사용자가 보낸 메시지인지 판단 41 | await cl.Message( #← 사용자 메시지이면 authorUser를 지정해 송신 42 | author="User", 43 | content=f"{message.content}", 44 | ).send() 45 | else: 46 | await cl.Message( #← AI의 메시지이면 ChatBot을 지정해 송신 47 | author="ChatBot", 48 | content=f"{message.content}", 49 | ).send() 50 | cl.user_session.set("chain", chain) #← 기록을 세션에 저장 51 | 52 | @cl.on_message 53 | async def on_message(message: str): 54 | chain = cl.user_session.get("chain") #← 세션에서 기록을 가져오기 55 | 56 | result = chain(message) 57 | 58 | await cl.Message(content=result["response"]).send() 59 | -------------------------------------------------------------------------------- /04_memory/chat_sample_1.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI 2 | from langchain.schema import HumanMessage 3 | 4 | chat = ChatOpenAI( 5 | model="gpt-3.5-turbo", 6 | ) 7 | 8 | result = chat( 9 | [ 10 | HumanMessage(content="계란찜을 만드는 재료를 알려주세요"), 11 | ] 12 | ) 13 | print(result.content) 14 | -------------------------------------------------------------------------------- /04_memory/chat_sample_2.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI 2 | from langchain.schema import ( 3 | HumanMessage, 4 | AIMessage 5 | ) 6 | 7 | chat = ChatOpenAI( 8 | model="gpt-3.5-turbo", 9 | ) 10 | 11 | result = chat([ 12 | HumanMessage(content="계란찜을 만드는 재료를 알려주세요"), 13 | AIMessage( #← 이 언어모델에 AIMessage로 응답 추가 14 | content="""계란찜을 만드는 재료는 다음과 같습니다: 15 | 16 | - 계란: 3개 17 | - 물: 1/2컵 18 | - 다진 양파: 1/4컵 19 | - 다진 당근: 1/4컵 20 | - 다진 대파: 1/4컵 21 | - 소금: 약간 22 | - 후추: 약간 23 | - 참기름: 약간 (선택 사항) 24 | 25 | 위의 재료로 계란찜을 만들 수 있습니다. 하지만 재료 비율이나 추가할 수 있는 다른 재료는 개인의 취향에 따라 다를 수 있습니다."""), 26 | HumanMessage(content="위의 답변을 영어로 번역하세요")#← 메시지를 추가해 번역시킴 27 | ]) 28 | print(result.content) 29 | -------------------------------------------------------------------------------- /04_memory/custom_memory_1.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | from langchain.chains import ConversationChain 3 | from langchain.chat_models import ChatOpenAI 4 | from langchain.memory import ConversationBufferWindowMemory # ConversationBufferWindowMemory 가져오기 5 | 6 | chat = ChatOpenAI( 7 | model="gpt-3.5-turbo" 8 | ) 9 | 10 | memory = ConversationBufferWindowMemory( 11 | return_messages=True, 12 | k=3 # 3번 주고받은 메시지를 기억 13 | ) 14 | 15 | chain = ConversationChain( 16 | memory=memory, 17 | llm=chat, 18 | ) 19 | 20 | @cl.on_chat_start 21 | async def on_chat_start(): 22 | await cl.Message(content="저는 대화의 맥락을 고려해 답변할 수 있는 채팅봇입니다. 메시지를 입력하세요.").send() 23 | 24 | @cl.on_message 25 | async def on_message(message: str): 26 | messages = chain.memory.load_memory_variables({})["history"] # 저장된 메시지 가져오기 27 | 28 | print(f"저장된 메시지 개수: {len(messages)}" # 저장된 메시지 개수를 표시 29 | ) 30 | 31 | for saved_message in messages: # 저장된 메시지를 1개씩 불러옴 32 | print(saved_message.content # 저장된 메시지를 표시 33 | ) 34 | 35 | result = chain(message) 36 | 37 | await cl.Message(content=result["response"]).send() 38 | -------------------------------------------------------------------------------- /04_memory/custom_memory_2.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | from langchain.chains import ConversationChain 3 | from langchain.chat_models import ChatOpenAI 4 | from langchain.memory import ConversationSummaryMemory 5 | from langchain.memory import ConversationSummaryMemory 6 | from langchain.chains import ConversationChain 7 | from langchain.memory import ConversationSummaryMemory 8 | from langchain.chains import ConversationChain 9 | 10 | chat = ChatOpenAI( 11 | model="gpt-3.5-turbo" 12 | ) 13 | 14 | memory = ConversationSummaryMemory( #← ConversationSummaryMemory를 사용하도록 변경 15 | llm=chat, #← Chat models를 지정 16 | return_messages=True, 17 | ) 18 | 19 | chain = ConversationChain( 20 | memory=memory, 21 | llm=chat, 22 | ) 23 | 24 | @cl.on_chat_start 25 | async def on_chat_start(): 26 | await cl.Message(content="저는 대화의 맥락을 고려해 답변할 수 있는 채팅봇입니다. 메시지를 입력하세요.").send() 27 | 28 | @cl.on_message 29 | async def on_message(message: str): 30 | messages = chain.memory.load_memory_variables({})["history"] # 저장된 메시지 가져오기 31 | 32 | print(f"저장된 메시지 개수: {len(messages)}" # 저장된 메시지 개수를 표시 33 | ) 34 | 35 | for saved_message in messages: # 저장된 메시지를 1개씩 불러옴 36 | print(saved_message.content # 저장된 메시지를 표시 37 | ) 38 | 39 | result = chain(message) 40 | 41 | await cl.Message(content=result["response"]).send() 42 | -------------------------------------------------------------------------------- /04_memory/memory_sample.py: -------------------------------------------------------------------------------- 1 | from langchain.memory import ConversationBufferMemory 2 | memory = ConversationBufferMemory( #← 메모리 초기화 3 | return_messages=True, 4 | ) 5 | memory.save_context( #← 메모리에 메시지를 추가 6 | { 7 | "input": "안녕하세요!" 8 | }, 9 | { 10 | "output": "안녕하세요! 잘 지내고 계신가요? 궁금한 점이 있으면 알려 주세요. 어떻게 도와드릴까요?" 11 | } 12 | ) 13 | memory.save_context( #← 메모리에 메시지를 추가 14 | { 15 | "input": "오늘 날씨가 좋네요" 16 | }, 17 | { 18 | "output": "저는 AI이기 때문에 실제 날씨를 느낄 수는 없지만, 날씨가 좋은 날은 외출이나 활동을 즐기기에 좋은 날입니다!" 19 | } 20 | ) 21 | 22 | print( 23 | memory.load_memory_variables({}) #← 메모리 내용을 확인 24 | ) 25 | -------------------------------------------------------------------------------- /05_chain/conversation_chain.py: -------------------------------------------------------------------------------- 1 | from langchain.chains import ConversationChain 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.memory import ConversationBufferMemory 4 | 5 | chat = ChatOpenAI() 6 | 7 | memory = ConversationBufferMemory(return_messages=True) 8 | 9 | chain = ConversationChain( #← ConversationChain을 초기화 10 | memory=memory, #← Memory 모듈을 지정 11 | llm=chat, #← 언어 모델을 지정 12 | ) 13 | -------------------------------------------------------------------------------- /05_chain/llmchain.py: -------------------------------------------------------------------------------- 1 | from langchain import LLMChain, PromptTemplate #← LLMChain 가져오기 2 | from langchain.chat_models import ChatOpenAI 3 | 4 | chat = ChatOpenAI( 5 | model="gpt-3.5-turbo", 6 | ) 7 | 8 | prompt = PromptTemplate( 9 | template="{product}는 어느 회사에서 개발한 제품인가요?", 10 | input_variables=[ 11 | "product" 12 | ] 13 | ) 14 | 15 | chain = LLMChain( #← LLMChain을 생성 16 | llm=chat, 17 | prompt=prompt, 18 | ) 19 | 20 | result = chain.predict(product="iPhone") #← LLMChain을 실행 21 | 22 | print(result) 23 | -------------------------------------------------------------------------------- /05_chain/request_chain.py: -------------------------------------------------------------------------------- 1 | from langchain.chains import LLMChain, LLMRequestsChain 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.prompts import PromptTemplate 4 | 5 | chat = ChatOpenAI() 6 | 7 | prompt = PromptTemplate( #← PromptTemplate을 초기화 8 | input_variables=["query", 9 | "requests_result"], 10 | template="""아래 문장을 바탕으로 질문에 답해 주세요. 11 | 문장: {requests_result} 12 | 질문: {query}""", 13 | ) 14 | 15 | llm_chain = LLMChain( 16 | llm=chat, 17 | prompt=prompt, 18 | verbose=True, 19 | ) 20 | 21 | chain = LLMRequestsChain( #← LLMRequestsChain을 초기화 22 | llm_chain=llm_chain, #← llm_chain에 LLMChain을 지정 23 | ) 24 | 25 | print(chain({ 26 | "query": "도쿄의 날씨를 알려주세요", 27 | "url": "https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json", 28 | })) 29 | -------------------------------------------------------------------------------- /05_chain/sequential_chain.py: -------------------------------------------------------------------------------- 1 | from langchain.chains import LLMChain, SimpleSequentialChain 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.prompts import PromptTemplate 4 | 5 | chat = ChatOpenAI(model="gpt-3.5-turbo") 6 | 7 | write_article_chain = LLMChain( #← 기사를 쓰는 LLMChain 만들기 8 | llm=chat, 9 | prompt=PromptTemplate( 10 | template="{input}에 관한 기사를 써주세요.", 11 | input_variables=["input"], 12 | ), 13 | ) 14 | 15 | translate_chain = LLMChain( #← 번역하는 LLMChain을 생성 16 | llm=chat, 17 | prompt=PromptTemplate( 18 | template="다음 문장을 영어로 번역해 주세요.\n{input}", 19 | input_variables=["input"], 20 | ), 21 | ) 22 | 23 | sequential_chain = SimpleSequentialChain( #← SimpleSequentialChain을 생성 24 | chains=[ #← 실행할 Chain을 지정 25 | write_article_chain, 26 | translate_chain, 27 | ] 28 | ) 29 | 30 | result = sequential_chain.run("일렉트릭 기타 선택 방법") 31 | 32 | print(result) 33 | -------------------------------------------------------------------------------- /06_agent/agent_1.py: -------------------------------------------------------------------------------- 1 | from langchain.agents import AgentType, initialize_agent, load_tools 2 | from langchain.chat_models import ChatOpenAI 3 | 4 | chat = ChatOpenAI( 5 | temperature=0, #← temperature를 0으로 설정해 출력의 다양성을 억제 6 | model="gpt-3.5-turbo" 7 | ) 8 | 9 | tools = load_tools( #← LangChain에 준비된 Tool을 로드 10 | [ 11 | "requests", #← 특정 URL의 결과를 얻는 Tool인 requests를 로드 12 | ] 13 | ) 14 | 15 | agent = initialize_agent( #← Agent를 초기화 16 | tools=tools, #← Agent가 사용할 수 있는 Tool의 배열을 설정 17 | llm=chat, #← Agent가 사용할 언어 모델을 지정 18 | agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, #←ReAct 방식으로 작동하게 설정 19 | verbose=True #← 실행 중 로그를 표시 20 | ) 21 | 22 | result = agent.run("""아래 URL에 접속해 도쿄의 날시를 검색해 한국어로 답하세요. 23 | https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json 24 | """) 25 | 26 | print(f"실행 결과: {result}") 27 | -------------------------------------------------------------------------------- /06_agent/agent_2.py: -------------------------------------------------------------------------------- 1 | from langchain.agents import AgentType, initialize_agent, load_tools #←load_tools 가져오기를 추가 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.tools.file_management import WriteFileTool #←파일 쓰기를 할 수 있는 Tool을 가져오기 4 | 5 | chat = ChatOpenAI( 6 | temperature=0, 7 | model="gpt-3.5-turbo" 8 | ) 9 | 10 | tools = load_tools( 11 | [ 12 | "requests_get", 13 | "serpapi" #←serpapi를 추가 14 | ], 15 | llm=chat 16 | ) 17 | 18 | tools.append(WriteFileTool( #←파일 쓰기를 할 수 있는 Tool을 추가 19 | root_dir="./" 20 | )) 21 | 22 | agent = initialize_agent( 23 | tools, 24 | chat, 25 | agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, #←Agent 유형을 변경 26 | verbose=True 27 | ) 28 | 29 | result = agent.run("경주시의 특산물을 검색해 result.txt 파일에 한국어로 저장하세요.") #←실행 결과를 파일에 저장하도록 지시 30 | 31 | print(f"실행 결과: {result}") 32 | -------------------------------------------------------------------------------- /06_agent/agent_3.py: -------------------------------------------------------------------------------- 1 | import random #←임의의 숫자를 생성하기 위해 필요한 모듈을 가져오기 2 | from langchain.agents import AgentType, Tool, initialize_agent #←Tool을 가져오기 3 | from langchain.chat_models import ChatOpenAI 4 | from langchain.tools import WriteFileTool 5 | 6 | chat = ChatOpenAI( 7 | temperature=0, 8 | model="gpt-3.5-turbo" 9 | ) 10 | 11 | tools = [] #← 다른 도구는 필요 없으므로 일단 삭제 12 | 13 | tools.append(WriteFileTool( 14 | root_dir="./" 15 | )) 16 | 17 | def min_limit_random_number(min_number): #←최솟값을 지정할 수 있는 임의의 숫자를 생성하는 함수 18 | return random.randint(int(min_number), 100000) 19 | 20 | 21 | tools.append( #←도구를 추가 22 | Tool( 23 | name="Random", #←도구 이름 24 | description="특정 최솟값 이상의 임의의 숫자를 생성할 수 있습니다.", #←도구 설명 25 | func=min_limit_random_number #←도구가 실행될 때 호출되는 함수 26 | ) 27 | ) 28 | 29 | agent = initialize_agent( 30 | tools, 31 | chat, 32 | agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, 33 | verbose=True 34 | ) 35 | 36 | result = agent.run("10 이상의 난수를 생성해 random.txt 파일에 저장하세요.") 37 | 38 | print(f"실행 결과: {result}") 39 | -------------------------------------------------------------------------------- /06_agent/agent_4.py: -------------------------------------------------------------------------------- 1 | from langchain.agents import AgentType, Tool, initialize_agent 2 | from langchain.agents.agent_toolkits import create_retriever_tool #← create_retriever_tool을 가져오기 3 | from langchain.chat_models import ChatOpenAI 4 | from langchain.retrievers import WikipediaRetriever #←WikipediaRetriever를 가져오기 5 | from langchain.tools import WriteFileTool 6 | 7 | chat = ChatOpenAI( 8 | temperature=0, 9 | model="gpt-3.5-turbo" 10 | ) 11 | 12 | tools = [] 13 | 14 | tools.append(WriteFileTool( 15 | root_dir="./" 16 | )) 17 | 18 | retriever = WikipediaRetriever( #←WikipediaRetriever를 초기화 19 | lang="ko", #←언어를 한국어로 설정 20 | doc_content_chars_max=500, #←글의 최대 글자 수를 500자로 설정 21 | top_k_results=1 #←검색 결과 중 상위 1건을 가져옴 22 | ) 23 | 24 | tools.append( 25 | create_retriever_tool( #←Retrievers를 사용하는 Tool을 생성 26 | name="WikipediaRetriever", #←Tool 이름 27 | description="받은 단어에 대한 Wikipedia 기사를 검색할 수 있다", #←Tool 설명 28 | retriever=retriever, #←Retrievers를 지정 29 | ) 30 | ) 31 | 32 | agent = initialize_agent( 33 | tools, 34 | chat, 35 | agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, 36 | verbose=True 37 | ) 38 | 39 | result = agent.run("스카치 위스키에 대해 Wikipedia에서 찾아보고 그 개요를 한국어로 result.txt 파일에 저장하세요.") 40 | 41 | print(f"실행 결과: {result}") 42 | -------------------------------------------------------------------------------- /06_agent/agent_5.py: -------------------------------------------------------------------------------- 1 | from langchain.agents import AgentType, initialize_agent 2 | from langchain.agents.agent_toolkits import create_retriever_tool 3 | from langchain.chat_models import ChatOpenAI 4 | from langchain.memory import ConversationBufferMemory #←ConversationBufferMemory 가져오기 5 | from langchain.retrievers import WikipediaRetriever 6 | 7 | chat = ChatOpenAI( 8 | temperature=0, 9 | model="gpt-3.5-turbo" 10 | ) 11 | 12 | tools = [] 13 | 14 | # WriteFileTool을 제거 15 | 16 | retriever = WikipediaRetriever( 17 | lang="ko", 18 | doc_content_chars_max=500, 19 | top_k_results=1 20 | ) 21 | 22 | tools.append( 23 | create_retriever_tool( #←Retrievers를 사용하는 Tool을 생성 24 | name="WikipediaRetriever", #←Tool 이름 25 | description="받은 단어에 대한 Wikipedia 기사를 검색할 수 있다", #←Tool 설명 26 | retriever=retriever, #←Retrievers를 지정 27 | ) 28 | ) 29 | 30 | memory = ConversationBufferMemory( #←ConversationBufferMemory를 초기화 31 | memory_key="chat_history", #←메모리 키를 설정 32 | return_messages=True #←메시지를 반환하도록 설정 33 | ) 34 | 35 | agent = initialize_agent( 36 | tools, 37 | chat, 38 | agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, #←Agent의 유형을 대화형으로 변경 39 | memory=memory, #←Memory를 지정 40 | verbose=True 41 | ) 42 | 43 | result = agent.run("스카치 위스키에 대해 Wikipedia에서 찾아보고 그 개요를 한국어로 개요를 정리하세요.") #←Wikipedia에서 찾아보라고 지시 44 | print(f"1차 실행 결과: {result}") #←실행 결과를 표시 45 | result_2 = agent.run("이전 지시를 다시 한번 실행하세요.") #←이전 지시를 다시 실행하도록 지시 46 | print(f"2차 실행 결과: {result_2}") #←실행 결과를 표시 47 | -------------------------------------------------------------------------------- /07_callback/chainlit_callback.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | from langchain.agents import AgentType, initialize_agent, load_tools 3 | from langchain.chat_models import ChatOpenAI 4 | 5 | chat = ChatOpenAI( 6 | temperature=0, 7 | model="gpt-3.5-turbo" 8 | ) 9 | 10 | tools = load_tools( 11 | [ 12 | "serpapi", 13 | ] 14 | ) 15 | 16 | agent = initialize_agent(tools=tools, llm=chat, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True) 17 | 18 | @cl.on_chat_start 19 | async def on_chat_start(): 20 | await cl.Message(content="Agent 초기화 완료").send() 21 | 22 | @cl.on_message 23 | async def on_message(input_message): 24 | result = agent.run( #← Agent를 실행 25 | input_message, #← 입력 메시지 26 | callbacks=[ #← 콜백을 지정 27 | cl.LangchainCallbackHandler() #← chainlit에 준비된 Callbacks를 지정 28 | ] 29 | ) 30 | await cl.Message(content=result).send() 31 | -------------------------------------------------------------------------------- /07_callback/log_callback.py: -------------------------------------------------------------------------------- 1 | from langchain.callbacks.base import BaseCallbackHandler #← BaseCallbackHandler 가져오기 2 | from langchain.chat_models import ChatOpenAI 3 | from langchain.schema import HumanMessage 4 | 5 | 6 | class LogCallbackHandler(BaseCallbackHandler): #← Callback을 생성 7 | 8 | def on_chat_model_start(self, serialized, messages, **kwargs): #← Chat models 실행 시작 시 호출되는 처리를 정의 9 | print("Chat models 실행 시작....") 10 | print(f"입력: {messages}") 11 | 12 | def on_chain_start(self, serialized, inputs, **kwargs): #← Chain 실행 시작 시 호출되는 처리를 정의 13 | print("Chain 실행 시작....") 14 | print(f"입력: {inputs}") 15 | 16 | chat = ChatOpenAI( 17 | model="gpt-3.5-turbo", 18 | callbacks=[ #← Chat models 초기화 시 Callback을 지정 19 | LogCallbackHandler() #← 생성한 LogCallbackHandler를 지정 20 | ] 21 | ) 22 | 23 | result = chat([ 24 | HumanMessage(content="안녕하세요!"), 25 | ]) 26 | 27 | print(result.content) 28 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 《랭체인 완벽 입문》의 실습 코드 저장소입니다. 2 | 3 | 4 | ## 이 책을 실습하기 위한 라이브러리 설치 방법 5 | 6 | 이 책의 예제 일부는 최신 버전의 라이브러리를 설치할 경우 제대로 작동하지 않는 문제가 발생합니다. 7 | 다음 명령을 실행해 원고 작성 시점의 버전을 설치하면 정상적으로 작동합니다. 8 | 9 | ``` 10 | python3 -m pip install -r requirements.txt 11 | ``` 12 | 13 | 자세한 방법은 책의 1.4절 '실습 준비'를 참고합니다. 14 | -------------------------------------------------------------------------------- /asset/sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wikibook/langchain/d2d9101531698f1c2f52aae013fb01a57d4a69a3/asset/sample.pdf -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "langchain-book" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["harukaxq "] 6 | readme = "README.md" 7 | packages = [{include = "langchain_book"}] 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.10" 11 | openai = "^0.27.8" 12 | pypdf = "^3.11.1" 13 | pymupdf = "^1.22.5" 14 | spacy = "^3.5.4" 15 | python-dotenv = "^1.0.0" 16 | redis = "^4.6.0" 17 | pinecone-client = "^2.2.2" 18 | chainlit = "^0.5.1" 19 | google-search-results = "^2.4.2" 20 | chromadb = "^0.3.26" 21 | bs4 = "^0.0.1" 22 | youtube-transcript-api = "^0.6.1" 23 | pytube = "^15.0.0" 24 | wikipedia = "^1.4.0" 25 | pylint = "^2.17.5" 26 | black = "^23.7.0" 27 | autopep8 = "^2.0.2" 28 | steamship = "^2.17.22" 29 | ipython = "^8.14.0" 30 | lark = "^1.1.7" 31 | matplotlib = "^3.7.2" 32 | arxiv = "^1.4.8" 33 | playwright = "^1.36.0" 34 | lxml = "^4.9.3" 35 | langchain = "^0.0.261" 36 | unstructured = "^0.9.2" 37 | libmagic = "^1.0" 38 | rich = "^13.5.2" 39 | rank-bm25 = "^0.2.2" 40 | faiss-cpu = "^1.7.4" 41 | gitpython = "^3.1.32" 42 | isort = "^5.12.0" 43 | yapf = "^0.40.1" 44 | ruff = "^0.0.285" 45 | 46 | [build-system] 47 | requires = ["poetry-core"] 48 | build-backend = "poetry.core.masonry.api" 49 | 50 | [tool.isort] 51 | line_length = 120 52 | 53 | --------------------------------------------------------------------------------