Posts LangChain 기초 튜토리얼 파트1
Post
Cancel

LangChain 기초 튜토리얼 파트1

해당 쿡북은 langchain-tutorials-LangChain Cookbook Part 1 - Fundamentals를 한글로 번역한 것이며 LangChain Conceptual Documentation을 기반으로 작성 되었습니다.

목표: ELI5예제와 코드를 통해 LangChain의 구성 요소와 사용 사례에 대한 기본적인 이해를 제공합니다. 사용 사례는 2부에서 확인할 수 있습니다.

링크:

1. LangChain 이란?

LangChain은 언어 모델(LLM) 기반의 애플리케이션을 개발하기 위한 프레임워크입니다.

요약: LangChain은 AI 모델과 작업 및 구축하는 복잡한 부분을 간단하게 만들어줍니다. 이를 위해 다음 두 가지 방법을 사용합니다:

  1. 통합 - 파일, 애플리케이션, API 데이터와 같은 외부 데이터를 LLM에 가져올 수 있습니다.
  2. 에이전시 - LLM을 통해 다음에 어떤 조치를 취할지 결정하는 데 도움을 줍니다.

2. 왜 LangChain인가?

  1. 구성 요소 - LangChain은 언어 모델과 함께 작업하기 위해 필요한 추상화와 구성 요소를 쉽게 교체할 수 있게 해줍니다.
  2. 사용자 정의 체인 - LangChain은 ‘체인’ - 연속된 일련의 동작 - 을 사용하고 사용자 정의하는 데 필요한 지원을 제공합니다.
  3. 속도 🚢 - 빠른 업데이트로 최신 LLM 기능을 계속해서 사용할 수 있습니다.
  4. 커뮤니티 👥 - 디스코드와 커뮤니티 지원, 모임, 해커톤 등이 활발합니다.

LLM은 간단할 수 있지만(텍스트 입력, 텍스트 출력) 더 복잡한 애플리케이션을 개발하면 LangChain이 도와주는 문제점에 부딪힐 것입니다. 참고: 이 쿡북은 LangChain의 모든 측면을 다루지 않습니다. 내용은 가능한 빠르게 설계 하는것으로 선별되었습니다. 자세한 내용은 LangChain 개념 문서를 참조하세요.

1
2
# OpenAI API Key - 유출되지 않게 조심해야함
openai_api_key='YOUR OPENAI API KEY'

LangChain 구성 요소

3. 스키마 - LLM과 작업할 때의 기본 구성 요소

1) 텍스트

LLM과 상호 작용하는 자연어 방식LangChain

1
2
# 간단한 문자열로 시작
my_text = "금요일 다음은 뭐지?"

2) 채팅 메세지

텍스트와 비슷하지만 메시지 유형(시스템, 인간, AI)으로 지정됩니다.

  • 시스템(SystemMessage) - AI에게 수행할 작업을 알려주는 유용한 배경 컨텍스트
  • 사람(HumanMessage) - 사용자를 나타내기 위한 메시지
  • AI(AIMessage) - AI가 응답한 내용을 보여주는 메시지

자세한 내용은 OpenAI의 문서를 참조하세요.

1
2
3
4
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage, AIMessage

chat = ChatOpenAI(temperature=.7, openai_api_key=openai_api_key)
1
2
3
4
5
6
chat(
    [
        SystemMessage(content="당신은 짧은 문장 하나로 사용자가 무엇을 먹을지 알아내는 데 도움을 주는 AI 봇입니다."),
        HumanMessage(content="나는 토마토를 좋아해요. 나는 무엇을 먹을까요?")
    ]
)
1
AIMessage(content='당신은 토마토를 좋아하는군요! 그렇다면 토마토를 사용한 요리를 먹어보는 것은 어떨까요? 예를 들어, 토마토 샐러드, 토마토 스파게티, 토마토 스프 등을 고려해볼 수 있습니다. 토마토가 포함된 다양한 요리를 살펴보고, 당신이 먹고 싶은 것을 선택해보세요!', additional_kwargs={}, example=False)
  • AI의 응답으로 더 많은 채팅을 전달할 수도 있습니다.
1
2
3
4
5
6
7
8
9
10
11
chat(
    [   # 배경 컨텍스트
        SystemMessage(content="당신은 짧은 문장 하나로 사용자가 여행할 곳을 알아내는 데 도움을 주는 AI 봇입니다."),
        # 사람 질문 메세지
        HumanMessage(content="나는 해변을 좋아하는데 어디로 가는게 좋을까요?"),
        # AI 응답 메세지
        AIMessage(content="프랑스의 니스가 좋을것 같군요"),
        # 사람 질문 메세지
        HumanMessage(content="거기에 가면 무엇을 하면 좋을까요?")
    ]
)
1
AIMessage(content='니스에 가면 해변에서 일광욕을 즐기거나 해변에서 수영을 즐길 수 있습니다. 또한, 프로마나드 데잉슈트(프랑스어로 해변 산책로)를 따라 산책하거나 자전거를 타며 해안 경치를 감상하는 것도 좋은 활동입니다. 또한, 니스의 역사적인 지역인 오래된 마을인 비에유를 방문하여 현지 문화와 건축을 즐길 수도 있습니다.', additional_kwargs={}, example=False)

3) 문서 (Documents)

  • 텍스트와 메타데이터(해당 텍스트에 대한 추가 정보)를 보유하는 개체
  • page_content : 문서에 대한 설명
  • metadata : 해당 문서에 대한 추가 정보들
1
from langchain.schema import Document
1
2
3
4
5
6
Document(page_content="이것은 나의 문서입니다. 다른 곳에서 수집한 글들로 가득해요",
         metadata={
             'my_document_id' : 234234,
             'my_document_source' : "LangChain 문서",
             'my_document_create_time' : 1680013019
         })
1
Document(page_content='이것은 나의 문서입니다. 다른 곳에서 수집한 글들로 가득해요', metadata={'my_document_id': 234234, 'my_document_source': 'LangChain 문서', 'my_document_create_time': 1680013019})

4. 모델 - AI 두뇌의 인터페이스

1) 언어 모델

텍스트 입력 ➡️ 텍스트 출력을 하는 모델!

기본으로 설정된 모델에서 gpt-3.5-turbo로 모델을 바꾼 것을 확인해보세요. 더 많은 모델은 여기에서 확인하세요.

1
2
3
from langchain.llms import OpenAI

llm = OpenAI(model_name="gpt-3.5-turbo", openai_api_key=openai_api_key)
1
llm("너에 대해서 자세히 설명해줄래")
1
'저는 가상의 AI 개체인 OpenAI Assistant입니다. 사람들의 다양한 질문에 대답하기 위해 프로그래밍 및 인공지능 기술을 사용합니다. 즉, 인간과의 대화를 모방하고 사용자로부터 질문을 받아들이며 그에 따라 최대한 정확하고 유용한 답변을 제공합니다. 사용자가 공식적이고 정확한 정보를 필요로 할 때, 개인적인 상담이나 정보를 요청할 때, 창의적인 문제를 물어볼 때 등 다양한 목적으로 사용될 수 있습니다. 또한, 저는 계속해서 학습을 통해 지식을 갱신하고 발전하는 AI입니다.'

2) 채팅 모델

메시지를 입력 받아 메시지 출력을 반환하는 모델.

1
2
3
4
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage, AIMessage

chat = ChatOpenAI(temperature=1, openai_api_key=openai_api_key)
1
2
3
4
5
6
7
chat(
    [   # 배경 컨텍스트
        SystemMessage(content="너는 사용자가 무엇을 말하든 농담을 해서 도움이 되지 않는 AI 봇입니다."),
        # 사람 메세지
        HumanMessage(content="부산에 가고 싶은데 어떻게 해야 하나요?")
    ]
)
1
AIMessage(content='비행기로 가면 될까요? 아니면 헬리콥터를 타고 가면 좋을 것 같아요. 물론 저도 걷는 것을 추천해요. 그런데 실제로 가보셨으면 좋겠어요, 저는 여행한 적이 없어요!', additional_kwargs={}, example=False)

3) 텍스트 임베딩 모델 (Text embedding model)

텍스트를 벡터로 변환합니다(텍스트의 의미적-Semantic ‘의미’를 가진 일련의 숫자). 주로 텍스트들을 비교할 때 사용됩니다.

참고: ‘의미적(Semantic)’은 ‘언어나 논리에서의 의미와 관련된’을 의미합니다.###

1
2
3
from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
1
text = "안녕!? 해변에 갈 시간이야!!"
1
2
3
text_embedding = embeddings.embed_query(text)
print (f"임베딩 길이: {len(text_embedding)}")
print (f"임베딩 샘플: {text_embedding[:5]}...")
1
2
임베딩 길이: 1536
임베딩 샘플: [0.011675495166686155, -0.0308764886668093, -0.006576743692478846, -0.01785208352692096, -0.028191576851779605]...

5. 프롬프트 (Prompt)- 모델에게 지시를 주기 위해 일반적으로 사용되는 텍스트

1) 프롬프트

모델에 전달할 기본적인 내용

1
2
3
4
5
6
7
8
9
10
11
12
from langchain.llms import OpenAI

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

# 세개의 큰 따옴표를 사용하는것을 읽고 쓰기 쉽기 때문에 선호합니다. 
prompt = """
오늘은 월요일, 내일은 수요일

이 내용에는 어떤 논리적 문제가 있나요?
"""

llm(prompt)
1
'이 내용에는 논리적 문제가 있습니다. 문장에 언급된 두 날짜가 정확하지 않고 일치하지 않기 때문입니다. 요일의 연속성을 유지하기 위해 내일이 화요일이어야 합니다.'

2) 프롬프트 템플릿 (Prompt Template)

사용자 입력처럼 정적인 텍스트가 아닌 정보나 고정된 템플릿 문자열의 조합을 기반으로 프롬프트를 생성하는 객체입니다.

파이썬의 f-string과 비슷합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from langchain.llms import OpenAI
from langchain import PromptTemplate

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

# "{location}"에 주의하세요, 이것은 나중에 다른 값으로 대체됩니다.
template = """
나는 정말 {location}에 여행 가고 싶어. 어떻게 하면 갈 수 있을까??

짧은 한 문장으로 대답하세요.
"""

prompt = PromptTemplate(
    input_variables=["location"],
    template=template,
)

final_prompt = prompt.format(location="프랑스")

print (f"최종 프롬프트: {final_prompt}")
print ("-----------")
print (f"LLM 결과물: {llm(final_prompt)}")
1
2
3
4
5
6
7
최종 프롬프트: 
나는 정말 프랑스에 여행 가고 싶어. 어떻게 하면 갈 수 있을까??

짧은 한 문장으로 대답하세요.

-----------
LLM 결과물: 비행기 티켓을 예약하세요.

3) 예제 선택기 (example selector)

컨텍스트 정보를 동적으로 프롬프트에 넣을 수 있게 해주는 일련의 예제 중에서 쉽게 선택할 수 있는 방법입니다. 작업이 미묘하거나 큰 예제 목록을 가지고 있을 때 자주 사용됩니다.

다양한 예제 선택기의 유형을 여기에서 확인하세요.

예제가 중요한 이유(프롬프트 엔지니어링)에 대한 개요를 원하시면 이 비디오를 확인하세요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.llms import OpenAI

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

example_prompt = PromptTemplate(
    input_variables=["input", "output"],
    template="샘플 입력: {input}\n샘플 출력: {output}",
)

# 입출력 예시
examples = [
    {"input": "선원", "output": "배"},
    {"input": "파일럿", "output": "비행기"},
    {"input": "운전수", "output": "자동차"},
    {"input": "나무", "output": "땅"},
    {"input": "새", "output": "둥지"},
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# SemanticSimilarityExampleSelector는 의미론적 의미로 입력과 유사한 예시를 선택합니다.
example_selector = SemanticSimilarityExampleSelector.from_examples(
    # 선택할 수 있는 예시의 목록입니다.
    examples, 
    
   # 의미론적 유사성을 측정하기 위해 사용되는 임베딩을 생성하는 데 사용되는 임베딩 클래스입니다.
    OpenAIEmbeddings(openai_api_key=openai_api_key), 
    
    # 이것은 임베딩을 저장하고 유사성 검색을 수행하는 데 사용되는 VectorStore 클래스입니다.
    FAISS, 
    
    # 생성할 예시의 수입니다.
    k=2
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
similar_prompt = FewShotPromptTemplate(
    # 예제를 선택하는 데 도움이 될 객체
    example_selector=example_selector,
    
    # 프롬프트
    example_prompt=example_prompt,
    
    # 프롬프트의 상단과 하단에 추가될 맞춤 설정
    prefix="아이템이 보통 어디에서 발견되는지 알려주세요.",
    suffix="Input: {noun}\nOutput:",
    
    # 프롬프트가 받을 입력 내용
    input_variables=["noun"],
)
1
2
3
4
# 명사 입력!
my_noun = "학생"

print(similar_prompt.format(noun=my_noun))
1
2
3
4
5
6
7
8
9
10
아이템이 보통 어디에서 발견되는지 알려주세요.

샘플 입력: 나무
샘플 출력: 땅

샘플 입력: 새
샘플 출력: 둥지

Input: 학생
Output:
1
llm(similar_prompt.format(noun=my_noun))
1
'학교'

4) 출력 파서(Output Parsers)

모델의 출력을 형식화하는 유용한 방법입니다. 주로 구조화된 출력에 사용됩니다.

두 가지 주요 개념:

A. 형식 지시문 (Format Instructions) - 원하는 결과를 기반으로 LLM에게 응답의 형식을 어떻게 할지 알려주는 자동 생성된 프롬프트

B. 파서 (Parser) - 모델의 텍스트 출력을 원하는 구조(보통 json)로 추출하는 방법

1
2
3
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain.llms import OpenAI
1
llm = OpenAI(model_name="gpt-3.5-turbo", openai_api_key=openai_api_key)
1
2
3
4
5
6
7
8
# 응답을 어떻게 구조화하길 원하는지에 대한 가벼운 기본 프롬프트 템플릿입니다.
response_schemas = [
    ResponseSchema(name="bad_string", description="이것은 잘못 포맷된 사용자 입력 문자열입니다."),
    ResponseSchema(name="good_string", description="이것은 당신의 응답, 재구성된 응답입니다.")
]

# 출력을 어떻게 파싱하길 원하는지.
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
1
2
3
# 출력 파서 프롬프로 템플릿 확인
format_instructions = output_parser.get_format_instructions()
print (format_instructions)
1
2
3
4
5
6
7
8
The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
	"bad_string": string  // 이것은 잘못 포맷된 사용자 입력 문자열입니다.
	"good_string": string  // 이것은 당신의 응답, 재구성된 응답입니다.
}
```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template = """
사용자로부터 잘못 작성된 문자열을 받게 될 것입니다.
다시 작성하고 모든 단어의 철자가 올바른지 확인하세요.

{format_instructions}

% 사용자 입력:
{user_input}

% 응답:
"""

prompt = PromptTemplate(
    input_variables=["user_input"],
    partial_variables={"format_instructions": format_instructions},
    template=template
)

promptValue = prompt.format(user_input="한극에 오신것을 환영합니다.")

print(promptValue)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
사용자로부터 잘못 작성된 문자열을 받게 될 것입니다.
다시 작성하고 모든 단어의 철자가 올바른지 확인하세요.

The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
	"bad_string": string  // 이것은 잘못 포맷된 사용자 입력 문자열입니다.
	"good_string": string  // 이것은 당신의 응답, 재구성된 응답입니다.
}
```

% 사용자 입력:
한극에 오신것을 환영합니다.

% 응답:
1
2
llm_output = llm(promptValue)
llm_output
1
'```json\n{\n\t"bad_string": "한극에 오신것을 환영합니다.",\n\t"good_string": "한국에 오신 것을 환영합니다."\n}\n```'
1
output_parser.parse(llm_output)
1
{'bad_string': '한극에 오신것을 환영합니다.', 'good_string': '한국에 오신 것을 환영합니다.'}

6. 색인(Index) - LLM이 처리할 수 있도록 문서 구조화하기

1) 문서 로더(Document Loaders)

다른 소스에서 데이터를 가져오는 쉬운 방법들입니다. OpenAI 플러그인 특히 검색 플러그인과 공유 기능을 가지고 있습니다.

여기에 문서 로더의 큰 목록을 확인하세요. Llama Index에도 많은 정보가 있습니다.

1
from langchain.document_loaders import HNLoader
1
loader = HNLoader("https://news.ycombinator.com/item?id=34422627")
1
data = loader.load()
1
2
print (f"{len(data)}개의 댓글")
print (f"샘플:\n\n{''.join([x.page_content[:150] for x in data[:2]])}")
1
2
3
4
5
6
7
8
9
10
76개의 댓글
샘플:

Ozzie_osman 7 months ago  
             | next [–] 

LangChain is awesome. For people not sure what it's doing, large language models (LLMs) are very Ozzie_osman 7 months ago  
             | parent | next [–] 

Also, another library to check out is GPT Index (https://github.com/jerryjliu/gpt_index)

2) 텍스트 분할기(Text Splitters)

대부분의 경우 문서가 LLM에게 너무 길다고 느껴질 수 있습니다(예컨대 책 같은 경우). 이럴 때 텍스트를 여러 부분으로 나눠야 합니다. 이때 텍스트 분할기가 도움이 됩니다.

텍스트를 여러 조각으로 나누는 여러 가지 방법이 있습니다. 어떤 것이 가장 적합한지 알아보기 위해 다양한 방법을 실험해보세요.

1
from langchain.text_splitter import RecursiveCharacterTextSplitter
1
2
3
4
5
import requests
url = "https://raw.githubusercontent.com/hmkim312/datas/main/Langchain/worked.txt"
response = requests.get(url)
pg_work = response.text
print (f"{len([pg_work])}개의 문서")
1
1개의 문서
1
2
3
4
5
6
7
text_splitter = RecursiveCharacterTextSplitter(
    # 보여주기 위해 작은 크기로 설정합니다.
    chunk_size = 150,
    chunk_overlap  = 20,
)

texts = text_splitter.create_documents([pg_work])
1
print (f"{len(texts)}개의 문서")
1
614개의 문서
1
2
3
print ("미리보기:")
print (texts[0].page_content, "\n")
print (texts[1].page_content)
1
2
3
4
5
6
미리보기:
February 2021Before college the two main things I worked on, outside of school,
were writing and programming. I didn't write essays. I wrote what 

beginning writers were supposed to write then, and probably still
are: short stories. My stories were awful. They had hardly any plot,

3) 검색기 (Retrievers)

문서를 언어 모델과 쉽게 결합하는 방법으로 검색기에는 여러 종류가 있으며, 가장 널리 지원되는 것은 VectoreStoreRetriever입니다.

1
2
3
4
5
6
7
8
9
import requests

url = "https://raw.githubusercontent.com/hmkim312/datas/main/Langchain/disc.txt"
response = requests.get(url)

# 파일을 저장하기
file_name = "disc.txt"
with open(file_name, 'w', encoding="utf-8") as f:
    f.write(response.text)
1
2
3
4
5
6
7
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings

loader = TextLoader(file_name)
documents = loader.load()
1
2
3
4
5
6
7
8
9
10
11
# 분할기 준비
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)

# 문서 분할
texts = text_splitter.split_documents(documents)

# 임베딩 준비
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)

# 텍스트 임베딩
db = FAISS.from_documents(texts, embeddings)
1
2
# 검색기를 초기화하세요. 단지 1개의 문서만 반환하도록 요청하세요.
retriever = db.as_retriever()
1
retriever
1
VectorStoreRetriever(tags=['FAISS'], metadata=None, vectorstore=<langchain.vectorstores.faiss.FAISS object at 0x7f2c31bf5b70>, search_type='similarity', search_kwargs={})
1
docs = retriever.get_relevant_documents("저자는 어떤 종류의 것들을 만들고 싶었나요?")
1
print("\n\n".join([x.page_content[:200] for x in docs[:2]]))
1
2
3
4
5
6
7
8
9
10
11
January 2017Because biographies of famous scientists tend to 
edit out their mistakes, we underestimate the 
degree of risk they were willing to take.
And because anything a famous scientist did that


seemed roughly equally promising. No one knew yet
what the payoff would be for inventing what we
now call physics; if they had, more people would 
have been working on it. And alchemy and theology
wer

4) VectorStores

벡터를 저장하기 위한 데이터베이스입니다. 가장 인기 있는 것들은 PineconeWeaviate입니다. OpenAI의 검색기 문서에서 더 많은 예시를 확인할 수 있습니다. ChromaFAISS는 로컬에서 쉽게 작업할 수 있습니다.

개념적으로, 임베딩(벡터)을 위한 열과 메타데이터를 위한 열이 있는 테이블로 생각하십시오.

예시

임베딩(Embedding)메타데이터(Metadata)
[-0.00015641732898075134, -0.003165106289088726, …]{‘date’ : ‘1/2/23}
[-0.00035465431654651654, 1.4654131651654516546, …]{‘date’ : ‘1/3/23}
1
2
3
4
5
6
7
8
9
import requests

url = "https://github.com/hmkim312/datas/blob/main/Langchain/worked.txt"
response = requests.get(url)

# 파일을 저장하기
file_name = "worked.txt"
with open(file_name, 'w', encoding="utf-8") as f:
    f.write(response.text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings

loader = TextLoader(file_name)
documents = loader.load()

# 분할기 준비
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)

# 텍스트 분할
texts = text_splitter.split_documents(documents)

# 임베딩 준비
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
1
print (f"{len(texts)}개의 문서")
1
98개의 문서
1
embedding_list = embeddings.embed_documents([text.page_content for text in texts])
1
2
print (f"{len(embedding_list)}개의 임베딩")
print (f"샘플: {embedding_list[0][:3]}...")
1
2
98개의 임베딩
샘플: [-0.01545365036202117, 0.012095730552875413, 0.0013115743425161806]...

벡터스토어는 임베딩을 저장하고 쉽게 검색할 수 있게 만듭니다.

7. 메모리

LLM에 정보를 기억하게 도와줍니다.

메모리는 약간 모호한 용어입니다. 과거에 대화한 정보를 간단하게 기억하는 것에서부터 더 복잡한 정보 검색까지 다양할 수 있습니다.

여기서는 채팅 메시지 사용 사례를 중심으로 설명하겠습니다. 이것은 채팅 봇에 사용됩니다.

많은 종류의 메모리가 있습니다. 문서를 탐색하여 당신의 사용 사례에 어느 것이 가장 적합한지 확인해 보세요.

1) 채팅 메세지 기록

1
2
3
4
5
6
7
8
9
10
from langchain.memory import ChatMessageHistory
from langchain.chat_models import ChatOpenAI

chat = ChatOpenAI(temperature=0, openai_api_key=openai_api_key)

history = ChatMessageHistory()

history.add_ai_message("안녕!")

history.add_user_message("한국의 수도는 어디야?")
1
history.messages
1
2
[AIMessage(content='안녕!', additional_kwargs={}, example=False),
 HumanMessage(content='한국의 수도는 어디야?', additional_kwargs={}, example=False)]
1
2
ai_response = chat(history.messages)
ai_response
1
AIMessage(content='한국의 수도는 서울이야.', additional_kwargs={}, example=False)
1
2
history.add_ai_message(ai_response.content)
history.messages
1
2
3
[AIMessage(content='안녕!', additional_kwargs={}, example=False),
 HumanMessage(content='한국의 수도는 어디야?', additional_kwargs={}, example=False),
 AIMessage(content='한국의 수도는 서울이야.', additional_kwargs={}, example=False)]

8. 체인(Chains)

다양한 LLM 호출과 자동으로 수행되는 동작을 결합합니다.

예: 요약 #1, 요약 #2, 요약 #3 > 최종 요약

다양한 요약 체인 유형에 대한 설명을 위한 이 비디오를 확인해보세요.

체인의 많은 응용 프로그램들이 있으므로, 당신의 사용 사례에 가장 적합한 것을 찾아보세요.

우리는 그 중 두 가지를 다룰 것입니다:

1). 단순 순차 체인 (Simple Sequential Chains)

LLM의 출력을 다른 것의 입력으로 사용할 수 있는 간단한 체인입니다. 작업을 나누는 데 유용하며(그리고 LLM을 집중시키는 데 도움이 됩니다)

1
2
3
4
5
6
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chains import SimpleSequentialChain

llm = OpenAI(temperature=1, openai_api_key=openai_api_key, max_tokens=1048)
1
2
3
4
5
6
7
8
9
10
template = """당신은 사용자가 제안하는 지역의 전통적인 요리를 제안합니다..
% 사용자 위치
{user_location}

% 응답:
"""
prompt_template = PromptTemplate(input_variables=["user_location"], template=template)

# 지역
location_chain = LLMChain(llm=llm, prompt=prompt_template)
1
2
3
4
5
6
7
8
9
10
template = """음식을 주면 집에서 어떻게 만드는지 간단하고 쉬운 레시피를 제공하세요.
% 음식
{user_meal}

% 응답:
"""
prompt_template = PromptTemplate(input_variables=["user_meal"], template=template)

# 음식
meal_chain = LLMChain(llm=llm, prompt=prompt_template)
1
overall_chain = SimpleSequentialChain(chains=[location_chain, meal_chain], verbose=True)
1
review = overall_chain.run("rome")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
> Entering new SimpleSequentialChain chain...
로마의 전통적인 요리로는 피자가 대표적으로 있습니다. 로마의 피자는 "로마 피자"라고도 불리며, 토마토피클, 모짜렐라 치즈, 허브, 오일, 로메인 양념 그리고 블랙 올리브가 주로 사용됩니다. 또한 "감튀까르보나라"(Gnocchi alla Romana)라고 불리는 주방 재료로 감자와 같은 식료품을 사용하여 만든 요리도 유명합니다. 또한 "그라탕"(Carbonara)과 "카레라 비냐"(Cacio e Pepe)도 로마의 특색 있는 요리입니다.
로마의 피자를 만드는 방법

필요한 재료: 
- 크기 작은 피자 도우 
- 토마토피클
- 베이컨 알갱이
- 모짜렐라 치즈
- 허브
- 올리브
- 오일
- 로메인 양념
- 미리 까기한 블랙 올리브

만드는 방법:

1. 먼저 피자 도우를 불리고 다양한 재료를 준비합니다.

2. 다이어트 오일로 납작하게 바텀을 돌려 오일을 뿌려주고 토마토 피클을 뿌립니다.

3. 다양한 재료를 배열해 줍니다. 먼저 베이컨 알갱이이며 그 다음에 모짜렐라 치즈, 허브, 올리브, 로메인 양념을 올려줍니다.

4. 마지막으로 블랙 올리브를 상단에 가볍게 뿌려 줍니다.

5. 그리고 구운다고 따로 설정해 놓은 오븐에 넣어 충분히 구워 내줍니다. 

6. 열대 모든 재료가 상호 작용하여 맛있게 구워지면 로마 피자가 만들어집니다.

> Finished chain.

2) 요약 체인 (Summarization Chain)

긴 여러 문서를 쉽게 훑어볼 수 있고 요약을 얻을 수 있습니다. 맵-리듀스 외의 다른 체인 유형에 대해서는 이 비디오를 확인해보세요.

1
2
3
4
5
6
7
8
9
import requests

url = "https://raw.githubusercontent.com/hmkim312/datas/main/Langchain/disc_ko.txt"
response = requests.get(url)

# 파일을 저장하기
file_name = "disc_ko.txt"
with open(file_name, 'w', encoding="utf-8") as f:
    f.write(response.text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from langchain.chains.summarize import load_summarize_chain
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

loader = TextLoader('disc_ko.txt')
documents = loader.load()

# 분할기 준비
text_splitter = RecursiveCharacterTextSplitter(chunk_size=700, chunk_overlap=50)

# 분할
texts = text_splitter.split_documents(documents)

chain = load_summarize_chain(llm, chain_type="map_reduce", verbose=True)
chain.run(texts)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
> Entering new MapReduceDocumentsChain chain...


> Entering new LLMChain chain...
Prompt after formatting:
Write a concise summary of the following:


"**인공지능과 인간의 희망적 동반**

우리 시대는 인공지능(AI)과 인간이 함께 발전하며 서로 보완적인 관계를 형성하는 시대로 불린다. 과거에는 기술적 발전이 사람의 일자리를 위협하는 것으로만 여겨졌다. 그러나 지금은 AI가 인간의 삶의 질을 향상시키는 데 기여하며, 우리의 일상생활에서 많은 도움을 주고 있다. 

무엇보다, AI는 우리가 접근하기 어려웠던 많은 지식과 정보를 우리 손안에 가져다준다. 의료, 교육, 연구 등 다양한 분야에서 AI는 맞춤화된 정보와 솔루션을 제공하며, 이를 통해 사람들은 더 나은 결정을 내리고 효율적인 생활을 이끌어 낸다. 우리의 지능과 AI의 능력이 융합됨으로써, 인류는 전례 없는 혁신적인 발견과 변화의 시대를 맞이하게 된다.

더불어, 인공지능은 인간의 창조력과 감성, 그리고 경험을 강조하게 만든다. AI가 단순 반복적인 업무나 데이터 분석 등의 작업을 담당함으로써, 인간은 더 깊이 있는 창조적인 활동에 몰두할 수 있게 되었다. 이런 관계 속에서 인간과 기술은 더욱 가까워지며, 그 결과로 더 풍요로운 미래를 상상하게 된다."


CONCISE SUMMARY:

> Finished chain.


> Entering new LLMChain chain...
Prompt after formatting:
Write a concise summary of the following:


" 우리 시대는 인공지능과 인간이 서로 보완하며 함께 발전하는 관계로 발전하고 있으며, AI가 인간들의 일상 생활을 향상시키고 다양한 분야의 영역에서 맞춤화된 정보와 솔루션을 제공하고 있다. AI는 또한 창조적인 활동을 증진시키며, 전례 없는 혁신적 변화로 희망적인 미래를 열고 있다."


CONCISE SUMMARY:

> Finished chain.

> Finished chain.





' 인공지능과 인간이 서로 보완하며 함께 발전하는 관계로 발전하고 있는 우리 시대에서 AI는 인간들의 생활을 개선하고 맞춤화된 정보와 솔루션을 제공하며, 창조적인 활동을 보장하고 있으며, 혁신적 변화로 희망적인 미래를 열고 있다.'

9. 에이전트 🤖🤖

공식 LangChain 문서에서는 에이전트를 완벽하게 설명하고 있습니다:

어떤 응용 프로그램은 LLMs/다른 도구에 대한 사전에 정해진 연쇄 호출만을 필요로 하지 않을 수 있으며, 사용자의 입력에 따라 알 수 없는 연쇄가 될 수 있습니다. 이러한 유형의 연쇄에서는 여러 도구에 액세스할 수 있는 “에이전트”가 있습니다. 사용자의 입력에 따라 에이전트는 이러한 도구 중 어떤 것을 호출할지 결정할 수 있습니다.

기본적으로 LLM을 텍스트 출력뿐만 아니라 의사 결정을 위해 사용합니다.

Sam Altman은 LLM이 좋은 ‘추론 엔진‘이라고 강조합니다. 에이전트는 이를 활용합니다.

1) 에이전트

의사 결정을 주도하는 언어 모델입니다.

더 구체적으로, 에이전트는 입력을 받아들이고 행동 입력과 함께 취할 행동에 대한 응답을 반환합니다. 다양한 유형의 에이전트들 (다른 사용 사례에 더 적합한)을 여기에서 볼 수 있습니다.

2) 도구

에이전트의 ‘능력’입니다. 이것은 LLMs (그리고 에이전트)가 쉽게 상호 작용할 수 있게 하는 함수 위의 추상화입니다. 예: 구글 검색.

이 영역은 OpenAI 플러그인과 공통점을 공유합니다.

3) 툴킷

당신의 에이전트가 선택할 수 있는 도구 그룹입니다.

이제 모든 것을 함께 가져와 봅시다:

1
2
3
4
5
6
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.llms import OpenAI
import json

llm = OpenAI(temperature=0, openai_api_key=openai_api_key)
1
2
# SerpApi는 "Search Engine Results Page API"의 약어로, 검색 엔진 결과 페이지에 대한 데이터를 추출하기 위한 서비스나 도구입니다
serpapi_api_key="YOUR SERPAPI API KEY"
1
toolkit = load_tools(["serpapi"], llm=llm, serpapi_api_key=serpapi_api_key)
1
agent = initialize_agent(toolkit, llm, agent="zero-shot-react-description", verbose=True, return_intermediate_steps=True)
1
response = agent({"input":"creep은 누구의 노래인가요?"})
1
2
3
4
5
6
7
8
9
> Entering new AgentExecutor chain...
 노래를 찾아보는 것이 좋을 것 같다.
Action: Search
Action Input: "creep" song
Observation: "Creep" is the debut single by the English rock band Radiohead, released on 21 September 1992. It appeared on their debut studio album, Pablo Honey (1993).
Thought: 라디오헤드의 노래라는 것을 알았다.
Final Answer: "Creep"은 라디오헤드의 노래입니다.

> Finished chain.
1
print(response["intermediate_steps"])
1
[(AgentAction(tool='Search', tool_input='creep" song', log=' 노래를 찾아보는 것이 좋을 것 같다.\nAction: Search\nAction Input: "creep" song'), '"Creep" is the debut single by the English rock band Radiohead, released on 21 September 1992. It appeared on their debut studio album, Pablo Honey (1993).')]
1
2
# 하입보이가 웨이크원 노래라는걸 보면, 성능은 그닥인걸로..
response = agent({"input":"하입보이는 누구의 노래인가요?"})
1
2
3
4
5
6
7
8
9
> Entering new AgentExecutor chain...
 I should try to find out who sings this song.
Action: Search
Action Input: 하입보이 노래
Observation: 보이즈플래닛 K그룹 웨이크원 팀의 무대에서 하입보이의 하이라이트 안무가 있다. 발매후 6개월 10일이 지난 2023년 2월 12일, 인기가요에 1위 후보로 ...
Thought: It looks like the song is by Wakeon, a K-pop group.
Final Answer: 하입보이는 보이즈플래닛 K그룹 웨이크원 팀의 노래입니다.

> Finished chain.
1
print(response["intermediate_steps"])
1
[(AgentAction(tool='Search', tool_input='하입보이 노래', log=' I should try to find out who sings this song.\nAction: Search\nAction Input: 하입보이 노래'), '보이즈플래닛 K그룹 웨이크원 팀의 무대에서 하입보이의 하이라이트 안무가 있다. 발매후 6개월 10일이 지난 2023년 2월 12일, 인기가요에 1위 후보로 ...')]
This post is licensed under CC BY 4.0 by the author.

뽐뿌 특가 데이터 분석 하기

PCA, t-SNE, LDA으로 알아보는 차원 축소