본문 바로가기
  • 시 쓰는 개발자
1일 1개념정리 (24년 8월~)/AI

1일1개 (39) - LangChain

by poetDeveloper 2024. 9. 21.
반응형

1일 1개념정리 24.08.09.금 ~ 

 

큰 결정에 큰 동기가 따르지 않을 때도 있다. 하지만 큰 결심이 따라야 이뤄낼 수 있다.

무조건 무조건 1일 1개의 개념 정리하기 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!


#39. LangChain

랭체인이란 무엇인고 ... 예전에 잠깐 언급했었다.

https://100won-developer.tistory.com/entry/1%EC%9D%BC1%EA%B0%9C-9-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81

 

1일1개 (9) - 프롬프트 엔지니어링

1일 1개념정리 24.08.09.금 ~  큰 결정에 큰 동기가 따르지 않을 때도 있다. 하지만 큰 결심이 따라야 이뤄낼 수 있다.무조건 무조건 1일 1개의 개념 정리하기 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!#9. 프롬프트 엔

100won-developer.tistory.com

프롬프트 엔지니어링을 할 때 사용하는 기법정도로 소개했는데, 좀 더 깊게 프로젝트에서 사용해야하는 상황이라 공부할겸 정리해보겠다.

 

LangChain

랭체인은 NLP 개발시 LLM을 쉽게 활용할 수 있게 하는 프레임워크이다. gpt3, gpt4 이런 LLM을 사용할 때 함께 활용된다. 랭체인의 주요 목적은 한마디로 사용자 요구에 따라 맞춤형으로 활용될 수 있도록 설계된 워크플로우를 제공하는 것이다. AI 기반 챗봇, 어시스턴트를 만들거나 자동화 처리, 그리고 문서 요약 및 질의응답 등에 이용될 수 있다.

 

주요 구성 요소

랭체인의 구성 요소는 보통 체인, 에이전트, 메모리, 프롬프트 템플릿 등으로 나뉜다.

 

1. Chain : 체인은 여러 자연어 처리 작업들을 연결하는 파이프라인이다. 예를 들어 입력받은 텍스트를 처리하고 결과를 다른 시스템에 전달하는 과정을 체인화할 수 있다. 여기엔 단일 체인과 멀티스텝 체인이 있다.

  • 단일 체인 : 하나의 프롬프트나 질문을 모델에 전달하고, 그 결과를 반환하는 단순한 체인이다.
  • 멀티 스텝 체인 : 여러 단계의 작업이 포함된 복잡한 워크플로우에 사용된다. 예를 들어 텍스트를 먼저 분석하고 요약하고, 이 요약을 다시 다른 곳에 사용하는 등의 방식이다.
from langchain.chains import SimpleChain, SequentialChain

# 단일 체인
chain = SimpleChain(llm, prompt="What's the capital of France?")
result = chain.run("France")

# 멀티 스텝 체인
seq_chain = SequentialChain(chains=[step1, step2, step3])
result = seq_chain.run(input_data)

 

2. Agent : 에이전트는 다양한 툴과 상호작용하면서 사용자의 요청에 따라 적절한 동작을 수행하는 시스템인데, 단순히 프롬프트를 처리하는 것을 넘어서, 외부 API와 통신하거나, 파일 시스템, DB 등에 접근하여 필요한 데이터를 얻는다.

# 도구와 에이전트 설정
tools = [search_tool, calculator_tool]
agent = initialize_agent(tools)

# 에이전트를 통해 도구 사용
agent.run("What is the population of Tokyo?")

 

3. Memory : 메모리는 대화의 문맥을 기억하는 기능을 제공한다. 사실 챗봇같은 곳에선 이게 정말 중요하다. 메모리를 사용하면 사용자의 이전 입력을 기억하고, 이를 바탕으로 일관성 있는 대화를 유지할 수 있다.

  • 단기 메모리 : 특정 세션 동안만 정보를 유지하고, 세션이 끝나면 정보가 사라진다.
  • 장기 메모리 : 여러 세션에 걸쳐 정보를 유지하여, 사용자가 이전에 했던 질문이나 대화를 기억할 수 있다.
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
memory.save_context({"input": "What is the capital of Japan?"}, {"output": "Tokyo"})

# 대화 중간에 기억을 불러와서 사용할 수 있음
print(memory.load_context())

 

4. Prompt Template : 프롬프트 템플릿은 프롬프트 엔지니어링을 쉽게 할 수 있도록 도와주는 도구이다. 사용자 입력을 바탕으로 동적으로 프롬프트를 생성하는 데 사용된다. 특정 구조나 패턴을 가진 프롬프트를 미리 정의하고, 필요한 변수에 따라 프롬프트를 유연하게 생성할 수 있다.

from langchain.prompts import PromptTemplate

template = "Translate the following text to {language}: {text}"
prompt = PromptTemplate(input_variables=["language", "text"], template=template)

# 템플릿에 동적 값 채워넣기
formatted_prompt = prompt.format(language="Spanish", text="Hello, how are you?")
print(formatted_prompt)

앞서 3번 메모리를 설명할 때, ConversationBufferMemory에 기억 정보를 저장한다고 말했다. 구체적으로 어떻게 저장될까 ?? 사실 내 제일 큰 관심사는 3번 메모리와 4번 템플릿이다. 이 두개에 대해 자세히 알아보자.

 

ConversationBufferMemory

1. 저장되는 데이터의 형태 : ConversationBufferMemory는 입출력 쌍을 딕셔너리로 저장한다. 즉 사용자가 질문한 내용과 그에 대한 AI의 응답을 순서대로 기록하는 방식이다. 각 대화는 {"input": 사용자 입력, "output": AI 응답} 형식으로 딕셔너리로 저장된다.

 

2. 버퍼 : ConversationBufferMemory에서는 대화가 진행될수록 새 대화가 버퍼에 쌓이는 형태로(데이터가 순차적으로 저장되는 형태) 관리된다. 즉 모든 대화가 누적되어 저장되며, 나중에 이 메모리를 불러오면 대화의 흐름 전체를 그대로 확인할 수 있다.

 

3. 저장 & 로드 방식

  • save_context : 사용자의 입력과 AI의 답변을 저장하고, 이는 내부적으로는 딕셔너리로 관리된다.
  • load_context : 지금까지 저장된 "모든 대화 기록"이 list 형태로 반환된다. 그니까, list 형식으로 반환되지만 각 element들은 딕셔너리형태의 대화라고 생각하면 된다.
from langchain.memory import ConversationBufferMemory

# 메모리 생성
memory = ConversationBufferMemory()

# 대화 저장: 사용자가 "What is the capital of Japan?"라고 질문하고, 모델이 "Tokyo"라고 답변
memory.save_context({"input": "What is the capital of Japan?"}, {"output": "Tokyo"})

# 저장된 대화 불러오기
print(memory.load_context())



# 실제 저장된 데이터 예시 (딕셔너리 형태)
[
  {"input": "What is the capital of Japan?", "output": "Tokyo"},
  {"input": "What is the population of Tokyo?", "output": "Around 14 million"},
  ....
]

 

Prompt Template

프롬프트 템플릿은 프롬프트 엔지니어링을 효율적으로 수행하기 위한 도구이다. 특정 구조를 미리 정의하고 필요한 변수만 동적으로 삽입하여 프롬프트를 생성하는 방법이다. 즉, 다양한 입력이 들어와도 일정한 형식으로 답변할 수 있다. 사용법 예시를 보자.

 

먼저 템플릿을 정의하고, 이를 바탕으로 값을 넣어 프롬프트를 생성한다.

from langchain.prompts import PromptTemplate

# 템플릿 정의
template = "Translate the following text to {language}: {text}"

# PromptTemplate 객체 생성
prompt = PromptTemplate(input_variables=["language", "text"], template=template)

# 템플릿에 값을 넣어 완전한 프롬프트 생성
formatted_prompt = prompt.format(language="Spanish", text="Hello, how are you?")
print(formatted_prompt)

 

더 복잡한 경우 어떻게 할까 ??

from langchain.prompts import PromptTemplate

# 복잡한 템플릿
template = """
You are a {role}. # ex) teacher
Your task is to help the user with {task}.
Please provide a detailed response based on the following context: {context}.
"""

# 템플릿 인스턴스 생성
prompt = PromptTemplate(input_variables=["role", "task", "context"], template=template)

# 변수 입력
formatted_prompt = prompt.format(role="customer service agent", task="resolving an issue",
				context="The user has a problem with their internet connection.")

print(formatted_prompt)

 

이를 통해 일관성, 재사용성, 최적화가 가능하며, 복잡한 자연어 작업에도 쉽게 적용할 수 있다.

반응형