사용자 또는 시스템에서 제공하는 입력 값이다. 프롬프트는 특정 작업을 수행하도록 지시하거나 정보를 요청하는 형태로 제공된다. LLM은 이 프롬프트를 기반으로 텍스트를 생성하거나 분석한다.
프롬프트를 효과적으로 사용하는 것이 생성형 인공지능의 능력을 최대치로 발휘시키는 열쇠이다.
,,, 등등 다양한 방식이 존재한다. 모델에게 역할을 부여하는 역할기반 프롬프트 ( Role-based-Prompt )도 자주 보인다.
LLM(대규모 언어 모델)은 대량의 텍스트 데이터를 분석하여 다음 단어 또는 문장을 예측한다.
수억 개 이상의 파라미터를 가지고 있으며, 방대한 텍스트 데이터로 사전 학습을 진행한다.
이러한 대규모 모델은 텍스트 생성, 번역, 감정 분석, 질문 응답, 텍스트 요약 등 다양한 자연어 처리 작업을 수행한다.
- 사전 학습 ( Pre-training ) : 대규모 텍스트 데이터로 모델을 사전 학습. 언어의 구조와 문법, 단어 간의 관계를 파악한다.
- 파인 튜닝 ( Fine-tuning ) : 사전 학습된 모델을 특정 작업에 맞게 가중치를 조정하는 단계.
"프롬프트 생성 => LLM 처리 => 응답 반환"의 세 단계로 나눌 수 있다. 각 단계는 LLM이 자연어를 이해하고 사용자에게 적절한 응답을 생성하는 데 중요한 역할을 한다. 생성된 응답은 애플리케이션으로 반환되며, 직접접인 답변, 텍스트, 요약된 정보, CSV,, 등 다양한 형태를 취할 수 있다.
사용자가 문자열을 입력하면 프롬프트 템플릿이 이를 기반으로 프롬프트를 자동으로 완성하고, LLM을 호출해 텍스트 출력을 반환하는 방식이다.
LLM 기반 애플리케이션을 개발할 때, 한 번의 LLM 호출로 결과를 낼 수도 있지만, 보다 정교한 LLM 애플리케이션의 경우, LLM의 출력을 다음 LLM의 입력으로 넣어서 답변을 낼 수도 있고, 입력 프롬프트에 알맞은 프롬프트나 LLM을 선택하게 할 수 있다.
!pip install -q langchain langchain-openai tiktoken
Langchain : 다양한 LLM을 연동하고 체인을 구성할 수 있는 프레임워크.
OpenAI : GPT와 같은 OpenAI의 언어 모델과 상호작용하기 위한 라이브러리.
Tiktoken : 토큰화 및 텍스트 처리에 사용되는 라이브러리.
https://openai.com/index/openai-api/
API Key( GPT )는 여기서 발급받으면 된다.
import os
os.environ["OPENAI_API_KEY"] = "your-openai-api-key-here"
기본 체인은 사용자가 입력한 텍스트를 LLM으로 전달하고, LLM이 이를 처리하여 응답을 반환하는 방식으로 동작한다.
다양한 자연어 처리 작업을 수행할 수 있다.
from langchain_openai import ChatOpenAI
# model
llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
# chain 실행
result = llm.invoke("지구의 자전 주기는?")
invoke 메서드는 지정된 프롬프트를 LLM에 전달하여 즉시 응답을 반환하는 함수이다.
호출할 때마다 LLM을 실행해 결과를 생성하며, LLM의 특성에 따라 동일한 프롬프트라도 응답이 조금씩 달라질 수 있다.
result.content # 텍스트만 추출
API 호출 시 결과를 result에 저장해서 따로 불러오지 않으면, 호출할 때마다 과금이 발생한다. LLM은 확률 기반으로 응답을 생성하기 때문에, 실행할 때마다 문장의 구조가 미세하게 달라진다.
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_template("You are an expert in astronomy. Answer the question. : {input}")
prompt
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
# chain 연결 (LCEL)
chain = prompt | llm
# chain 호출
chain.invoke({"input": "지구의 자전 주기는?"})
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# prompt + model + output parser
prompt = ChatPromptTemplate.from_template("You are an expert in astronomy. Answer the question. : {input}") # "너는 천문학의 전문가야"라는 프름프트 템플릿 / 시스템 메시지 (2)
llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
output_parser = StrOutputParser() # 텍스트만 가져오겠다. (3)
# LCEL chaining
chain = prompt | llm | output_parser # 출력 순서
# chain 호출
chain.invoke({"input": "지구의 자전 주기는?"}) # 사용자의 인풋을 받겠다. (1)
여러 개의 체인을 연결하거나 복합적으로 작용하는 것은 멀티 체인 ( Multi Chain ) 구조를 통해서 이루어진다.
예제에서는 2개의 체인 (chain1, chain2)를 정의하고 연결하는 과정이다.
prompt1 = ChatPromptTemplate.from_template("translates {korean_word} to English.") # 한국어 단어를 입력 받을 수 있는 단어를 문자열 포멧팅을 사용해서 지정 => 영어로 번역하라는 프름포트 작성
prompt2 = ChatPromptTemplate.from_template(
"explain {english_word} using oxford dictionary to me in Korean."
)
llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
chain1 = prompt1 | llm | StrOutputParser()
chain1.invoke({"korean_word":"맛집"})
chain2 = (
{"english_word": chain1}
| prompt2
| llm
| StrOutputParser() # 문자열 (strings)을 출력해주는 Parser
)
chain2.invoke({"korean_word":"맛집"}) # invoke 실행 => "korean_word"에 맛집 전달 => chain1 맛집 영어 출력 "english_word"에 전달 => prompt2의 "english_word"에 전달 => LLM에 전달 => llm => StrOutputParser() 문자열 출력
첫 번째 체인(chain 1)은 한국어 단어를 영어로 번역한다. 두 번째 체인(chain 2)은 번역된 단어를 english_word라는 변수에 저장해서 입력으로 제공하고, 영어 단어의 뜻을 한국어로 설명하는 작업을 수행한다.
from langchain_core.prompts import PromptTemplate
# 'name'과 'age'라는 두 개의 변수를 사용하는 프롬프트 템플릿을 정의
template_text = "안녕하세요, 제 이름은 {name}이고, 나이는 {age}살입니다." # 문자열 포멧팅을 사용해서 두 개의 입력 변수 설정
# PromptTemplate 인스턴스를 생성
prompt_template = PromptTemplate.from_template(template_text) # 생성된 문자열을 PromptTemplate에 전달
# 템플릿에 값을 채워서 프롬프트를 완성
filled_prompt = prompt_template.format(name="이승훈", age=26)
filled_prompt
# 문자열 템플릿 결합 (PromptTemplate + PromptTemplate + 문자열) / str이기 때문에 +가 사용 가능하다.
combined_prompt = (
prompt_template
+ PromptTemplate.from_template("\n\n그만하고 싶어요 집에 갈래요.")
+ "\n\n{language}로 번역해주세요."
)
combined_prompt
combined_prompt.format(name="이승훈", age=26, language="중국어") # 각각의 매게변수에 값을 입력
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
chain = combined_prompt | llm | StrOutputParser()
chain.invoke({"age":26, "language":"중국어", "name":"이승훈"})
프롬프트는 사용자와 언어 모델 간의 대화에서 질문이나 요청의 형태로 제시되는 입력문이다. 만약 잘 작동하는 프롬프트를 발견했다면, 이를 재사용하거나 기본 템플릿으로 활용하는 것이 좋다.
예시에서는
만 사용하지만
다양한 유형이 존재한다.
# 2-튜플 형태의 메시지 목록으로 프롬프트 생성 (type, content)
from langchain_core.prompts import ChatPromptTemplate
chat_prompt = ChatPromptTemplate.from_messages([
("system", "이 시스템은 천문학 질문에 답변할 수 있습니다."),
("user", "{user_input}"),
])
messages = chat_prompt.format_messages(user_input="태양계에서 가장 큰 행성은 무엇인가요?")
messages
chain = chat_prompt | llm | StrOutputParser()
chain.invoke({"user_input": "태양계에서 가장 큰 행성은 무엇인가요?"})
# MessagePromptTemplate 활용
from langchain_core.prompts import SystemMessagePromptTemplate, HumanMessagePromptTemplate # 역활에 따라서 Prompt Template을 사용할 수 있다.
chat_prompt = ChatPromptTemplate.from_messages(
[
SystemMessagePromptTemplate.from_template("이 시스템은 천문학 질문에 답변할 수 있습니다."),
HumanMessagePromptTemplate.from_template("{user_input}"),
]
)
messages = chat_prompt.format_messages(user_input="태양계에서 가장 큰 행성은 무엇인가요?")
messages
chain = chat_prompt | llm | StrOutputParser() # 템플릿은 재사용성, 사용의 유연성 때문에 사용하는 것이다. chain을 구성해서 simple하게 구현 하였다.
chain.invoke({"user_input": "태양계에서 가장 큰 행성은 무엇인가요?"})
템플릿은 재사용성, 사용의 유연성을 위해서 사용한다는 점을 항상 기억하며 공부하자.
랭체인 문서에 따르면 LLM과 Chat Model 클래스는 각각 다른 형태의 입력과 출력을 다루는 언어 모델을 나타낸다.
각기 다른 특성과 용도를 가지고 있어서 요구사항에 맞게 선택하여 사용해야 한다.
from langchain_openai import OpenAI
llm = OpenAI()
llm.invoke("제주도의 대표적인 관광지 3군데를 추천해주세요.")
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
chat = ChatOpenAI()
chat_prompt = ChatPromptTemplate.from_messages([ # 메시지의 리스트를 구성
("system", "이 시스템은 여행 전문가입니다."), # 시스템 메시지
("user", "{user_input}"), # 유저 메시지로 구별 해서 튜플 형태로 조합하고 리스트 형태로 배열을 만들어서 => from_messages에 전달한다
])
chain = chat_prompt | chat
chain.invoke({"user_input": "안녕하세요? 제주도의 대표적인 관광지 3군데를 추천해주세요."})
Chat Model은 대화형 상황에 최적화된 모델이기 때문에 친근한 출력값을 확인할 수 있다.
https://sundg0162.tistory.com/19
01. LLM 모델이란?
개요저번 글인 생성형 AI 소개에 이어 써보겠습니다.LLM 모델이 기억하는 원리나 각종 파라미터 등에 대해 적어볼겁니다. 상당히 흥미로운 주제이지만 논문 쓰는 것 같고 막 그럽니다. LLM이
sundg0162.tistory.com
쉽게 풀어주셨네요.
from langchain_openai import ChatOpenAI
# 모델 파라미터 설정
params = {
"temperature": 0.7, # 생성된 텍스트의 다양성 조정
"max_tokens": 100, # 생성할 최대 토큰 수
"frequency_penalty": 0.5, # 이미 등장한 단어의 재등장 확률
"presence_penalty": 0.5, # 새로운 단어의 도입을 장려
"stop": ["\n"] # 정지 시퀀스 설정
}
# 모델 인스턴스를 생성할 때 설정
model = ChatOpenAI(model="gpt-3.5-turbo-0125", **params)
# 모델 호출
question = "태양계에서 가장 큰 행성은 무엇인가요?"
response = model.invoke(input=question)
# 전체 응답 출력
print(response)
# 모델 파라미터 설정
params = {
"temperature": 0.7, # 생성된 텍스트의 다양성 조정
"max_tokens": 10, # 생성할 최대 토큰 수
}
# 모델 인스턴스를 호출할 때 전달
response = model.invoke(input=question, **params)
# 문자열 출력
print(response.content)
- bind 메서드를 사용하여 체인에 새로운 파라미터를 추가하여 연결 가능
- 다양한 상황에 맞게 모델의 동작을 제어
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "이 시스템은 천문학 질문에 답변할 수 있습니다."),
("user", "{user_input}"),
])
model = ChatOpenAI(model="gpt-3.5-turbo-0125", max_tokens=100)
messages = prompt.format_messages(user_input="태양계에서 가장 큰 행성은 무엇인가요?")
before_answer = model.invoke(messages)
# # binding 이전 출력
print(before_answer)
# 모델 호출 시 추가적인 인수를 전달하기 위해 bind 메서드 사용 (응답의 최대 길이를 10 토큰으로 제한)
chain = prompt | model.bind(max_tokens=10)
after_answer = chain.invoke({"user_input": "태양계에서 가장 큰 행성은 무엇인가요?"})
# binding 이후 출력
print(after_answer)
논문: https://arxiv.org/abs/2005.11401
Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks
Large pre-trained language models have been shown to store factual knowledge in their parameters, and achieve state-of-the-art results when fine-tuned on downstream NLP tasks. However, their ability to access and precisely manipulate knowledge is still lim
arxiv.org
!pip install -q langchain langchain-openai langchain_community tiktoken chromadb
import os
os.environ["OPENAI_API_KEY"] = "your-openai-api-key-here"
Load Data - Text Split - Indexing - Retrieval(검색) - Generation(생성)
# Data Loader - 웹페이지 데이터 가져오기
from langchain_community.document_loaders import WebBaseLoader
# 위키피디아 정책과 지침
url = 'https://ko.wikipedia.org/wiki/%EC%9C%84%ED%82%A4%EB%B0%B1%EA%B3%BC:%EC%A0%95%EC%B1%85%EA%B3%BC_%EC%A7%80%EC%B9%A8'
loader = WebBaseLoader(url)
# 웹페이지 텍스트 -> Documents
docs = loader.load()
print(len(docs))
print(len(docs[0].page_content))
print(docs[0].page_content[5000:6000])
# Text Split (Documents -> small chunks: Documents)
from langchain.text_splitter import RecursiveCharacterTextSplitter # 쉼표 기준으로 짤라주기 때문에 문장이 매끄럽게 잘린다.
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) # RecursiveCharacterTextSplitter 텍스트를 작게 나누어 주는 클래스 함수
splits = text_splitter.split_documents(docs) # split_documents 리스트에 들어있는 documents 객체를 청크 단위로 작게 나누어 준다.
print(len(splits))
print(splits[10])
# page_content 속성
splits[10].page_content
# metadata 속성
splits[10].metadata
# Indexing (Texts -> Embedding -> Store)
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
vectorstore = Chroma.from_documents(documents=splits,
embedding=OpenAIEmbeddings())
docs = vectorstore.similarity_search("격하 과정에 대해서 설명해주세요.") # 격하 과정과 가장 연관이 있는 청크를 가져와서 보여준다.
print(len(docs))
print(docs[0].page_content)
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# Prompt
template = '''Answer the question based only on the following context:
{context}
Question: {question}
'''
prompt = ChatPromptTemplate.from_template(template)
# LLM
model = ChatOpenAI(model='gpt-3.5-turbo-0125', temperature=0) # temperature=0 답변의 일관성을 위해서 낮추는 경우도 있다.
# Rretriever
retriever = vectorstore.as_retriever() # 임베딩 된 벡터들 사이에서 검색해오도록 설정
# Combine Documents
def format_docs(docs):
return '\n\n'.join(doc.page_content for doc in docs)
# RAG Chain 연결
rag_chain = (
{'context': retriever | format_docs, 'question': RunnablePassthrough()} # RunnablePassthrough()} 사용자의 입력이 question에 전달되도록 구현
| prompt
| model
| StrOutputParser()
)
# Chain 실행
rag_chain.invoke("격하 과정에 대해서 설명해주세요.")
큰 가다는 잡았는데,, 이제 시작이네요 파이팅
참고 자료
Langchain을 이용한 LLM 애플리케이션 개발 #13 - Chain을 이용한 워크 플로우 구현 #1
Chain을 이용한, LLM 워크 플로우 구현 #1 조대협 (http://bcho.tistory.com) LLM 기반 애플리케이션을 개발할때, 한번의 LLM 호출로 결과를 낼 수 도 있지만, 복잡한 LLM 애플리케이션의 경우, LLM의 출력을 다
bcho.tistory.com
출처
https://wikidocs.net/book/14473
랭체인(LangChain) 입문부터 응용까지
**랭체인(LangChain) 입문부터 응용까지** 이책은 거대언어모델(LLM)을 활용하여 애플리케이션과 파이프라인을 신속하게 구축할 때 주로 활용되는 랭체인(LangCha…
wikidocs.net
[ 논문 리뷰 ] Transformer - Attention Is All You Need(2017) [ 1 ] (21) | 2024.10.09 |
---|---|
딥 러닝 " RNN (Recurrent Neural Network) " (15) | 2024.10.08 |
Deep Learning 공부하기 ( 2 ) (1) | 2024.09.19 |
Deep Learning 공부하기 ( 1 ) (7) | 2024.09.19 |
한국 경제신문 with toss bank - 중간 프로젝트_( 3 ) (5) | 2024.09.08 |