LangChain์ LM(Large Language)์ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ฃผ๋ Framework์ ๋๋ค.
LangChain Basic์์๋ LangChain์ ๊ฐ ๊ตฌ์ฑ๋ณ Sample ์ฝ๋๋ฅผ ์ค๋ช ํฉ๋๋ค.
Falcon FM์ผ๋ก ๋ง๋ SageMaker Endpoint์ LangChain์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช ํฉ๋๋ค. SageMaker JumpStart๋ก Falcon FM ์ค์นํ๊ธฐ์์ ์ป์ SageMaker Endpoint(์: jumpstart-dft-hf-llm-falcon-7b-instruct-bf16)๋ฅผ ์ด์ฉํฉ๋๋ค.
Falcon์ ์ ๋ ฅ๊ณผ ์ถ๋ ฅ์ ์ฐธ์กฐํ์ฌ ์๋์ ๊ฐ์ด ContentHandler์ transform_input, transform_output์ ๋ฑ๋กํฉ๋๋ค.
from langchain import PromptTemplate, SagemakerEndpoint
from langchain.llms.sagemaker_endpoint import LLMContentHandler
class ContentHandler(LLMContentHandler):
content_type = "application/json"
accepts = "application/json"
def transform_input(self, prompt: str, model_kwargs: dict) -> bytes:
input_str = json.dumps({'inputs': prompt, 'parameters': model_kwargs})
return input_str.encode('utf-8')
def transform_output(self, output: bytes) -> str:
response_json = json.loads(output.read().decode("utf-8"))
return response_json[0]["generated_text"]์๋์ ๊ฐ์ด endpoint_name, aws_region, parameters, content_handler์ ์ด์ฉํ์ฌ Sagemaker Endpoint์ ๋ํ llm์ ๋ฑ๋กํฉ๋๋ค.
endpoint_name = 'jumpstart-dft-hf-llm-falcon-7b-instruct-bf16'
aws_region = boto3.Session().region_name
parameters = {
"max_new_tokens": 300
}
content_handler = ContentHandler()
llm = SagemakerEndpoint(
endpoint_name = endpoint_name,
region_name = aws_region,
model_kwargs = parameters,
content_handler = content_handler
)llm์ ๋์์ ์๋์ ๊ฐ์ด ํ์ธํ ์ ์์ต๋๋ค.
llm("Tell me a joke")์ด๋์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ต๋๋ค.
I once told a joke to a friend, but it didn't work. He just looked
Web loader - langchain์ ์ด์ฉํ์ฌ web page๋ฅผ loading ํ ์ ์์ต๋๋ค.
from langchain.document_loaders import WebBaseLoader
from langchain.indexes import VectorstoreIndexCreator
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
index = VectorstoreIndexCreator().from_loaders([loader])์๋์ ๊ฐ์ด template๋ฅผ ์ ์ํ์ LLMChain์ ์ ์ํ run์ ์ํํ ์ ์์ต๋๋ค. ์ธ๋ถ ๋ด์ฉ์ langchain-sagemaker-endpoint-Q&A.ipynb์ ์ฐธ์กฐํฉ๋๋ค.
from langchain import PromptTemplate, LLMChain
template = "Tell me a {adjective} joke about {content}."
prompt = PromptTemplate.from_template(template)
llm_chain = LLMChain(prompt=prompt, llm=llm)
outputText = llm_chain.run(adjective="funny", content="chickens")
print(outputText)์ด๋์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ต๋๋ค.
Why did the chicken cross the playground? To get to the other slide!
langchain.chains.question_answering์ ์ด์ฉํ์ฌ Document์ ๋ํ Question/Answering์ ์ํํฉ๋๋ค. ์ธ๋ถ ๋ด์ฉ์ langchain-sagemaker-endpoint-Q&A.ipynb์ ์ฐธ์กฐํฉ๋๋ค.
prompt์ template์ ์ ์ํฉ๋๋ค.
template = """Use the following pieces of context to answer the question at the end.
{context}
Question: {question}
Answer:"""
prompt = PromptTemplate(
template=template, input_variables=["context", "question"]
)langchain.docstore.document์ ์ด์ฉํ์ฌ Document๋ฅผ ์์ฑํฉ๋๋ค.
from langchain.docstore.document import Document
example_doc_1 = """
Peter and Elizabeth took a taxi to attend the night party in the city. While in the party, Elizabeth collapsed and was rushed to the hospital.
Since she was diagnosed with a brain injury, the doctor told Peter to stay besides her until she gets well.
Therefore, Peter stayed with her at the hospital for 3 days without leaving.
"""
docs = [
Document(
page_content=example_doc_1,
)
]์ด์ Question/Answering์ ์ํํฉ๋๋ค.
from langchain.chains.question_answering import load_qa_chain
question = "How long was Elizabeth hospitalized?"
chain = load_qa_chain(prompt=prompt, llm=llm)
output = chain({"input_documents": docs, "question": question}, return_only_outputs=True)
print(output)์ด๋์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ต๋๋ค.
{'output_text': ' 3 days'}
langchain-sagemaker-endpoint-pdf-summary.ipynb์์๋ Falcon FM ๊ธฐ๋ฐ์ SageMaker Endpoint๋ก PDF Summery๋ฅผ ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช ํ๊ณ ์์ต๋๋ค.
๋จผ์ PyPDF2๋ฅผ ์ด์ฉํ์ฌ S3์ ์ ์ฅ๋์ด ์๋ PDF ํ์ผ์ ์ฝ์ด์ Text๋ฅผ ์ถ์ถํฉ๋๋ค.
import PyPDF2
from io import BytesIO
sess = sagemaker.Session()
s3_bucket = sess.default_bucket()
s3_prefix = 'docs'
s3_file_name = '2016-3series.pdf' # S3์ ํ์ผ๋ช
s3r = boto3.resource("s3")
doc = s3r.Object(s3_bucket, s3_prefix+'/'+s3_file_name)
contents = doc.get()['Body'].read()
reader = PyPDF2.PdfReader(BytesIO(contents))
raw_text = []
for page in reader.pages:
raw_text.append(page.extract_text())
contents = '\n'.join(raw_text)
new_contents = str(contents).replace("\n"," ")๋ฌธ์์ ํฌ๊ธฐ๊ฐ ํฌ๋ฏ๋ก RecursiveCharacterTextSplitter๋ฅผ ์ด์ฉํด chunk ๋จ์๋ก ๋ถ๋ฆฌํ๊ณ Document์ ์ ์ฅํฉ๋๋ค. ์ดํ load_summarize_chain๋ฅผ ์ด์ฉํด ์์ฝํฉ๋๋ค.
from langchain.text_splitter import CharacterTextSplitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=0)
texts = text_splitter.split_text(new_contents)
from langchain.docstore.document import Document
docs = [
Document(
page_content=t
) for t in texts[:3]
]
from langchain.chains.summarize import load_summarize_chain
from langchain.prompts import PromptTemplate
prompt_template = """Write a concise summary of the following:
{text}
CONCISE SUMMARY """
PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])
chain = load_summarize_chain(llm, chain_type="stuff", prompt=PROMPT)
summary = chain.run(docs)- stuff puts all the chunks into one prompt. Thus, this would hit the maximum limit of tokens.
- map_reduce summarizes each chunk, combines the summary, and summarizes the combined summary. If the combined summary is too large, it would raise error.
- refine summarizes the first chunk, and then summarizes the second chunk with the first summary. The same process repeats until all chunks are summarized.
from langchain import Bedrock
from langchain.embeddings import BedrockEmbeddings
llm = Bedrock()
print(llm("explain GenAI"))AWS Kendra Langchain Extensions
LangChain - Modules - Language models - LLMs - Integration - SageMakerEndpoint