brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Jul 22. 2024

AI 5탄-3. 랭체인을 활용한 챗봇 업그레이드

생성형 AI 활용 앱 만들어줘-3/5

<7> 챗봇 업그레이드 환경

<8> 랭체인이란?

<9>  랭체인 모듈 실습 - 7-3 모델 IO

<10> 랭체인 모듈 실습 - 7-4 리트리블(Retrieval)

<11> 랭체인 모듈 실습 - 7-5 에이전트(Agent)

<12> 랭체인 모듈 실습 - 7-6 Chain

<13> 랭체인 모듈 실습 - 7-7 메모리

<14> 챗봇 업그레이드



교제는 아나콘다

여기서 실습은 코랩으로 해보자.



<7> 챗봇 업그레이드 환경


기존에 챗GPT와 그라디오를 활용하여 챗봇 제작함.

실제는 보안등 이유로 오픈 소스로 공개된 LLM을 기반으로 자체 LLM을 구축.

LLM모델에 기능을 향상하기 위해 랭체인을 사용.





<8> 랭체인이란?



1

앵무새 = 학습된 데이터를 기반으로 만든 LLM모델.

랭체인은 LLM과 외부도구(웹사이트, PDF reader, 계산기 등)를 체인으로 엮은 것처럼 결합해 주는 SDK이다.




2



<9>  랭체인 모듈 실습 - 7-3 모델 IO



# colab이용 - 랭체인 모듈을 실습해보자


1

환경

google colab

https://colab.research.google.com/?hl=ko



2

File >  새 노트북


#  OPENAI API 키 직접 입력하여 사용


!pip install --upgrade openai==1.55.3

!pip install --upgrade httpx==0.27.2

!pip install langchain_community


import os

os.environ["OPENAI_API_KEY"] = "sk-proj-fMLWHM_1ENA06iDl86IA"


from langchain.llms import OpenAI

llm = OpenAI(model="gpt-3.5-turbo-instruct")

llm.predict('파이썬을 만든 사람은?')




3

# 새 보안키 추가  - # 보안키 확인


from google.colab import userdata

userdata.get('OPENAI_API_KEY')



4

#  colab에 OPNEAI API 키 등록한 상태에서 사용법


!pip install langchain

!pip install openai 

!pip install langchain_community



# openai 라이블러리 설치

# 아래 오류 해결을 위해 openai 버전과 httpx 버전 변경함.

# TypeError: Client.__init__() got an unexpected keyword argument 'proxies' 

# 제미나이가 코드 수정함.


!pip install --upgrade openai==1.55.3

!pip install --upgrade httpx==0.27.2

!pip install langchain_community



openai_api_key = userdata.get('OPENAI_API_KEY')

from openai import OpenAI as OpenAIClient # This imports openai's OpenAI class, but rename it to OpenAIClient

from google.colab import userdata

from langchain.llms import OpenAI # This imports langchain's OpenAI class

# Pass the API key to langchain's OpenAI class:

llm = OpenAI(model="gpt-3.5-turbo-instruct", openai_api_key=openai_api_key) # add openai_api_key here

llm.predict('파인썬을 만든 사람은?')




답변

파이썬을 만든 사람은 귀도 반 로썸(Guido van Rossum)입니다.



llm.predict('서울의 인기 관 장소는?')


답변

\n서울의 인기 관광 장소는 광화문, 명동, 남산 타워, 경복궁, 인사동, 청계천, 홍대, 이태원, 강남 등이 있습니다. 또한 한강공원, 서울숲, 국립중앙박물관, 코엑스 등도 많은 관광객들이 찾는 장소입니다.



5

# 챗GPT chatmodel 연결하기  , 제미나이 수정 버전임



from langchain.chat_models import ChatOpenAI
from langchain.schema import AIMessage, HumanMessage, SystemMessage
from google.colab import userdata

# Get your API key
openai_api_key = userdata.get('OPENAI_API_KEY')

# Pass the API key to ChatOpenAI
chatgpt = ChatOpenAI(model_name="gpt-3.5-turbo", openai_api_key=openai_api_key)

messages = [
    SystemMessage(
        content="당신은 파이썬 프로그래머입니다."
    ),
    HumanMessage(
        content="파이썬에서 문자의 길이를 알려주는 명령어는?"
    ),
]

result = chatgpt(messages)
print(result.content)






6

#  프롬프트 템플릿 만들기


from langchain.prompts import PromptTemplate

llm_prompt = PromptTemplate.from_template("{goods}의 성분에 대해서 알려줘")

llm_prompt_result = llm_prompt.format_prompt(goods = "콜라")

print(llm_prompt_result)


text='콜라의 성분에 대해서 알려줘'




7

# Chat Prompt Template


from langchain.prompts import ChatPromptTemplate

from langchain.prompts import SystemMessagePromptTemplate

from langchain.prompts import HumanMessagePromptTemplate

system_message = "당신은 {language}선생님입니다.{language}로 답변해주세요"

system_prompt = SystemMessagePromptTemplate.from_template(system_message)

human_template = "{text}"

human_prompt = HumanMessagePromptTemplate.from_template(human_template)

chat_prompt = ChatPromptTemplate.from_messages([system_prompt, human_prompt])

chat_prompt.format_messages(language = "영어",text = "대한민국 수도는?")



[SystemMessage(content='당신은 영어선생님입니다.영어로 답변해주세요', additional_kwargs={}, response_metadata={}),  HumanMessage(content='대한민국 수도는?', additional_kwargs={}, response_metadata={})]



8

# OPEN AI 모델 연결하기


from langchain.prompts import PromptTemplate, ChatPromptTemplate

from langchain.llms import OpenAI

from google.colab import userdata

# Get your API key

openai_api_key = userdata.get('OPENAI_API_KEY')

# Pass the API key to langchain's OpenAI class:

llm = OpenAI(model_name="gpt-3.5-turbo-instruct", openai_api_key=openai_api_key, temperature=0)

llm_prompt = PromptTemplate.from_template("{goods}의 성분에 대해서 알려줘")

llm_prompt_result = llm_prompt.format_prompt(goods="콜라")

llm.predict_messages(llm_prompt_result.to_messages())



 콜라의 주요 성분은 물, 설탕, 이산화탄소, 카페인, 인산, 구연산, 천연향료 등이 있습니다. 이 중에서도 설탕과 카페인이 콜라의 맛과 효과를 결정하는 중요한 성분입니다. 하지만 과도한 섭취는 건강에 해로울 수 있으니 적당량을 유지하는 것이 좋습니다.', additional_kwargs={}, response_metadata={})




9

# 챗GPT Chatmodel 연결하기


from langchain.chat_models import ChatOpenAI
from langchain.schema import AIMessage, HumanMessage, SystemMessage
from google.colab import userdata

# Get your API key
openai_api_key = userdata.get('OPENAI_API_KEY')

# Pass the API key to ChatOpenAI using the openai_api_key argument
chatgpt = ChatOpenAI(model_name="gpt-3.5-turbo", openai_api_key=openai_api_key)

messages = [
    SystemMessage(
        content="당신은 파이썬 프로그래머입니다."
    ),
    HumanMessage(
        content="파이썬에서 문자의 길이를 알려주는 명령어는?"
    ),
]

result = chatgpt(messages)
print(result.content)




문자열의 길이를 알려주는 함수는 `len()`입니다. 이 함수는 문자열의 길이를 반환해줍니다. 아래는 예시입니다. ```python text = "Hello, World!" length = len(text) print(length)  # 출력 결과: 13




11

# 아웃풋 파서 , 출력에 관한 이야기


from langchain.output_parsers import CommaSeparatedListOutputParser

from langchain.prompts import PromptTemplate

from langchain.llms import OpenAI

from google.colab import userdata

openai_api_key = userdata.get('OPENAI_API_KEY')

output_parser = CommaSeparatedListOutputParser()

format_instructions = output_parser.get_format_instructions()

prompt = PromptTemplate(

    template = "{subject} 5개를 추천해줘.\n{format_instructions}",

    input_variables = ["subject"],

    partial_variables = {"format_instructions": format_instructions}

)

llm = OpenAI(temperature=0, openai_api_key=openai_api_key) # Add openai_api_key here

prompt_result = prompt.format(subject = "아이스크림")

output = llm(prompt_result)

output     



응답

\n\n바나나맛, 초콜릿맛, 딸기맛, 바닐라맛, 민트맛



변경

output_parser.parse(output)


응답

['바나나맛', '초콜릿맛', '딸기맛', '바닐라맛', '민트맛']



12


https://github.com/heypythonai/heypythonai/blob/main/Part2%20-%20%E1%84%8F%E1%85%A9%E1%84%83%E1%85%B3/%ED%97%A4%EC%9D%B4%ED%8C%8C%EC%9D%B4%EC%8D%AC%209%20%EB%9E%AD%EC%B2%B4%EC%9D%B8.ipynb





<10> 랭체인 모듈 실습 - 7-4 리트리블(Retrieval)



llm 사용시 전문성 필요부분에 질문 하면 정확도가 떨어진다.

이경우 개선 RAG

외부소스를 가져오도록 하는것 필요

랭체인에서 Data connection 모듈로 외부 데이터 활용.



1

# 문서 읽기


1)  텍스트 파일 로더


from langchain.document_loaders import TextLoader

loader = TextLoader("./hey.txt")

document = loader.load()

print(document[0].page_content)



결과

안녕하세요! 헤이마트는 신선한 과일과 다양한 물건을 판매하는 동네 마트입니다. 우리 마트는 고품질의 제품과 넓은 다양성을 자랑합니다. 우리 마트에서는 신선한 과일을 특별히 추천합니다. 매일 새로운 과일이 신선하게 도착하며, 다양한 종류와 풍부한 맛으로 고객님께 건강과 기쁨을 전해드립니다. 사과, 바나나, 포도, 딸기 등 다양한 과일을 저렴한 가격에 만나보세요. 뿐만 아니라, 헤이마트는 생활용품, 식료품, 주방용품, 세제류, 건강식품 등 다양한 물건도 판매하고 있습니다. 고객님의 생활에 필요한 다양한 제품을 한 곳에서 편리하게 구매할 수 있습니다. 또한, 친절하고 경험이 풍부한 직원들이 항상 고객님을 위해 최선을 다하며, 상담과 도움을 제공해드립니다. 헤이마트는 지역 사회와의 교류를 소중히 여기고, 지역 재료와 협력하여 신선하고 지역적인 맛을 즐길 수 있는 제품을 제공합니다.




2) CSV Loader 


from langchain.document_loaders.csv_loader import CSVLoader

csv_loader = CSVLoader(file_path = './hey_csv.csv')

documents = csv_loader.load()

documents



결과

[Document(metadata={'source': './hey_csv.csv', 'row': 0}, page_content='product_name: Apple\ncategory: fruits\nprice: 1.99'),  Document(metadata={'source': './hey_csv.csv', 'row': 1}, page_content='product_name: Banana\ncategory: fruits\nprice: 0.99'),  Document(metadata={'source': './hey_csv.csv', 'row': 2}, page_content='product_name: Milk\ncategory: dairy\nprice: 2.49'),  Document(metadata={'source': './hey_csv.csv', 'row': 3}, page_content='product_name: Bread\ncategory: bakery\nprice: 1.79'),  Document(metadata={'source': './hey_csv.csv', 'row': 



3) PDF Loaders

!pip install pyPDF


from langchain.document_loaders import PyPDFLoader

loader = PyPDFLoader("hey_pdf.pdf")

pages = loader.load_and_split()

pages


[Document(metadata={'source': 'hey_pdf.pdf', 'page': 0}, page_content='안녕하세요! 헤이마트는 신선한 과일과 다양한 물건을 판매하는 동네 마트입니다. 우리 마트는 고\n품질의 제품과 넓은 다양성을 자랑합니다. \n \n우리 마트에서는 신선한 과일을 특별히 추천합니다. 매일 새로운 과일이 신선하게 도착하며, 다양\n한 종류와 풍부한 맛으로 고객님께 건강과 기쁨을 전해드립니다. 사과, 바나나, 포도, 딸기 등 다\n양한 과일을 저렴한 가격에 만나보세요. \n \n뿐만 아니라, 헤이마트는 생활용품, 식료품, 주방용품, 세제류, 건강식품 등 다양한 물건도 판매하\n고 있습니다. 고객님의 생활에 필요한 다양한 제품을 한 곳에서 편리하게 구매할 수 있습니다. 또\n한, 친절하고 경험이 풍부한 직원들이 항상 고객님을 위해 최선을 다하며, 상담과 도움을 제공해\n드립니다. \n \n헤이마트는 지역 사회와의 교류를 소중히 여기고, 지역 재료와 협력하여 신선하고 지역적인 맛을 \n즐길 수 있는 제품을 제공합니다.')]



2

# 문서 변환

정킹, 작은 문서로 나누기, AI가 이해하기 쉽게 함.

정크 크기를 100개로 , 6개 단락으로 나누어짐



from langchain.text_splitter import RecursiveCharacterTextSplitter

from langchain.document_loaders import TextLoader

txt_loader = TextLoader("./hey.txt")

document = txt_loader.load()

document_content = document[0].page_content

text_splitter = RecursiveCharacterTextSplitter(

    chunk_size = 100,

    chunk_overlap = 0,

)

texts = text_splitter.create_documents([document_content])

print(len(texts))

print(texts)



[Document(metadata={}, page_content='안녕하세요! 헤이마트는 신선한 과일과 다양한 물건을 판매하는 동네 마트입니다. 우리 마트는 고품질의 제품과 넓은 다양성을 자랑합니다.'), Document(metadata={}, page_content='우리 




3

# 임베딩

텍스트를 벤터로 변환.

유사도 검색같은 작업을 할수 있게 해준다.


!pip install tiktoken



from google.colab import userdata

openai_api_key = userdata.get('OPENAI_API_KEY')

from langchain.embeddings import OpenAIEmbeddings

openai_embedding = OpenAIEmbeddings(openai_api_key=openai_api_key)

embeddings = openai_embedding.embed_documents(

    ["안녕하세요", "무엇을 도와드릴까요?", "어서오세요?", "도움이 필요해요"]

)

print("임베딩 수: ", len(embeddings))

print("임베딩 차원: ", len(embeddings[0]))

print("임베딩 차원: ", len(embeddings[1]))

print("embeddings[0]: ",embeddings[0])



임베딩 수:  4 임베딩 차원:  1536 임베딩 차원:  1536 embeddings[0]:  [-0.01363905893128265, -0.009446358031268955, -0.005943919478104129, -0.02294480773314062, -0.012475839748973755, 0.018202455112672995, -0.019774717717


4.

벡터 스토어 , 저장소


!pip install chromadb



from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from google.colab import userdata

# Get your API key
openai_api_key = userdata.get('OPENAI_API_KEY')

# Pass the API key to OpenAIEmbeddings
openai_embedding = OpenAIEmbeddings(openai_api_key=openai_api_key)

db = Chroma.from_texts(
    texts=['안녕', '안녕하세요', '반갑습니다.', '반가요'],
    embedding=openai_embedding
)
similar_texts = db.similarity_search("안녕")
similar_texts




# 기본적으로 유사한 5개의 결과를 제공한다.


[Document(metadata={}, page_content='안녕'),

 Document(metadata={}, page_content='안녕하세요'),

 Document(metadata={}, page_content='반가요'),

 Document(metadata={}, page_content='반갑습니다.')]




<11> 랭체인 모듈 실습 - 7-5 에이전트(Agent)


1

https://github.com/heypythonai/heypythonai/blob/main/Part2%20-%20%E1%84%8F%E1%85%A9%E1%84%83%E1%85%B3/%ED%97%A4%EC%9D%B4%ED%8C%8C%EC%9D%B4%EC%8D%AC%209%20%EB%9E%AD%EC%B2%B4%EC%9D%B8.ipynb



2



랭체인에서 제공하는 툴들

https://python.langchain.com/v0.1/docs/integrations/tools/




3

# 구글 검색 툴 -  serpapi.com api 튤 사용

메일 승인 , 전화번호 승인   2가지 모두 필요하다.

로그인

왼쪽 API Key 발급



4

File >  새 노트북


#  OPENAI API 키 직접 입력하여 사용


!pip install --upgrade openai==1.55.3

!pip install --upgrade httpx==0.27.2

!pip install langchain_community



import os

os.environ["SERPAPI_API_KEY"] = "0122487b9d62a"





5

!pip install google-search-results



import os
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI

# Option 1: Setting the API key as an environment variable (recommended)
# os.environ["OPENAI_API_KEY"] = "YOUR_ACTUAL_API_KEY" # Replace with your actual key

# Option 2: Passing the API key directly as a named parameter
chat = ChatOpenAI(temperature=0, openai_api_key="YOUR_ACTUAL_API_KEY")  # Replace with your actual key

tools = load_tools(['serpapi', 'llm-math'], llm=chat)

agent = initialize_agent(tools, llm=chat, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

agent.run('미국대통령의 나이를 10으로 나누면?')



응답


> Entering new AgentExecutor chain... I need to calculate the age of the current US president and then divide it by 10. Action: Search Action Input: "current US president age" Observation: {'type': 'organic_result', 'title': 'Joe Biden › Age ShareSend feedbackClose menu'} Thought:I found the age of the current US president, Joe Biden. Action: Calculator Action Input: 79 / 10 Observation: Answer: 7.9 Thought:I now know the final answer Final Answer: 7.9 

Finished chain. 

7.9




6

! pip install youtube_search

! pip install duckduckgo-search



from langchain.tools import YouTubeSearchTool

from langchain.chat_models import ChatOpenAI

from langchain.agents import load_tools, initialize_agent

from langchain.agents import AgentType

llm = ChatOpenAI(temperature = 0)

tools = load_tools(["ddg-search"]) + [YouTubeSearchTool()]

agent =  initialize_agent(

tools,

llm,

agent = AgentType.ZERO_SHOT_REACT_DESCRIPTION,

verbose = True)

result = agent("영화 토토로의주제곡을 찾아 유튜브 링크를 알려줘")


응답

> Entering new AgentExecutor chain... I need to search for the theme song of the movie Totoro on YouTube to find the link. Action: youtube_search Action Input: Totoro theme song,1 Observation: ['https://www.youtube.com/watch?v=RUnvkHZwDg4&pp=ygURVG90b3JvIHRoZW1lIHNvbmc%3D'] Thought:I have found the YouTube link for the theme song of the movie Totoro. Final Answer: https://www.youtube.com/watch?v=RUnvkHZwDg4&pp=ygURVG90b3JvIHRoZW1lIHNvbmc%3D > Finished chain.






<12> 랭체인 모듈 실습 - 7-6 Chain



1

다른 기능을 제공하는 모듈 등을 LLM에 연결하는 서비스가 많아.

이러한 모듈을 체인으로 연결할 수 있는 인터페이스를 제공하여 모듈을 호출



2


import langchain

import openai

from langchain.llms import OpenAI

from langchain.prompts import PromptTemplate

from langchain.chains import LLMChain

llm = OpenAI(temperature = 0.9)

prompt = PromptTemplate(input_variables = ["product"], template = "{product}를 생성하는 회사 이름을 만들어주세요.")

chain = LLMChain(llm = llm, prompt = prompt, verbose = True)

print(chain.run("컴퓨터"))



답변

> Entering new LLMChain chain... Prompt after formatting: 컴퓨터를 생성하는 회사 이름을 만들어주세요. > Finished chain. "지능처리 기술"




3


연속 답변

from langchain.llms import OpenAI

from langchain.chains import LLMChain

from langchain.prompts import PromptTemplate

from langchain.chains import SimpleSequentialChain

llm = OpenAI(temperature = .7)

template = """당신은 신문기자입니다. 제목과 같은 기사를 작성해주세요.

제목: {title}

"""

prompt_template = PromptTemplate(input_variables = ["title"], template = template)

article_chain = LLMChain(llm = llm, prompt = prompt_template)

llm = OpenAI(temperature = .7)

template = """신문기사를 짧게 줄여주세요.

신문기사:

{article}

"""

prompt_template = PromptTemplate(input_variables = ["article"], template = template)

review_chain = LLMChain(llm = llm, prompt = prompt_template)

overall_chain = SimpleSequentialChain(chains = [article_chain, review_chain], verbose = True)

review = overall_chain.run("평화로운 대한민국")



답변

> Entering new SimpleSequentialChain chain...  "대한민국, 평화의 고장으로서 더욱 발전하고 있습니다." 최근 대한민국은 평화로운 분위기 속에서 더욱 발전하고 있는 것으로 나타났습니다. 과거 전쟁으로 인해 아픔과 상처를 입은 우리나라는 이제 평화를 지키는 데 더욱 힘쓰고 있으며, 그 결과로 인해 국민들의 삶의 질이 점차 개선되고 있습니다. 지난 4월에는 남북 정상회담이 열리며 북한과의 관계가 개선되는 계기가 마련되었습니다. 이를 계기로 남북 미사일 도발이 중단되고, 남북 경제 협력이 활성화되는 등 평화를 위한 다 양한 노력이 이뤄지고 있습니다. 이러한 노력은 국민들의 미래에 대한 희망과 기대를 높여주고 있으며, 대한민국은 평화의 고장으로서 한층 더 발전할 것으로 기대됩니다. > Finished chain.






<13> 랭체인 모듈 실습 - 7-7 메모리


1


from langchain.chat_models import ChatOpenAI

from langchain.chains import ConversationChain

from langchain.memory import ConversationBufferMemory

llm = ChatOpenAI(temperature = 0.0)

memory = ConversationBufferMemory()

conversation = ConversationChain(

llm = llm,

memory = memory

)

conversation.predict(input = "안녕, 난 헤이마트 주인이야.")


답변

안녕하세요! 반가워요, 헤이마트 주인님. 저는 인공지능 비서입니다. 어떻게 도와드릴까요




2


conversation.predict(input = "내가 어디 주인이라고 했지?")


죄송해요, 그 정보는 제가 알 수 없어요. 어떤 도움이 필요하세요?



3


print(memory.buffer)


Human: 안녕, 난 헤이마트 주인이야.

AI: 안녕하세요! 반가워요, 헤이마트 주인님. 저는 인공지능 비서입니다. 어떻게 도와드릴까요?

Human: 내가 어디 주인이라고 했지?

AI: 죄송해요, 그 정보는 제가 알 수 없어요. 어떤 도움이 필요하세요?



4


memory = ConversationBufferMemory()

memory.save_context({"input": "안녕, 나는 헤이마트 주인이야."},

{"output": "헤이마트 주인님 반갑습니다."})

print(memory.buffer)



답변

Human: 안녕, 나는 헤이마트 주인이야.

AI: 헤이마트 주인님 반갑습니다.




<14> 챗봇 업그레이드



기능추가

text 업로드

pdf 업로드등



1


코드

https://github.com/heypythonai/heypythonai/blob/main/Part2%20-%20%E1%84%8F%E1%85%A9%E1%84%83%E1%85%B3/%ED%97%A4%EC%9D%B4%ED%8C%8C%EC%9D%B4%EC%8D%AC%208%20%EC%B1%97%EB%B4%87%20%EC%97%85%EA%B7%B8%EB%A0%88%EC%9D%B4%EB%93%9C.ipynb



2

다음

https://brunch.co.kr/@topasvga/3930


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari