Developer's Development

3.3.13 [LLM] 프롬프트 엔지니어링 응용: LangChain 본문

LLM

3.3.13 [LLM] 프롬프트 엔지니어링 응용: LangChain

mylee 2025. 9. 13. 14:16
LangChain

 

LLM의 기능을 확장하고 체계화하여 복잡한 애플리케이션을 구축할 수 있도록 지원하는 프레임워크이다.

여러 프롬프트, 도구, 데이터 소스를 체인으로 연결해 효율적으로 작업을 수행할 수 있다.

 

👉🏻 회원가입

https://www.langchain.com/

 

LangChain

LangChain’s suite of products supports developers along each step of their development journey.

www.langchain.com

 

👉🏻 개발 목적과 배경

LLM 활용의 간소화, 문제 해결 능력 강화, 오픈소스 정신

 

👉🏻 주요 기능

- 체인 구성: 여러 작업 단계를 순차적으로 실행

- 에이전트 활용: 도구와 상호작용하며 작업 수행

- 메모리 관리: 대화의 문맥을 유지하며 작업

 

  • 프롬프트 템플릿

반복적인 작업에서 재사용 가능한 프롬프트를 설계하고, 동적 입력 변수를 통해 효율적으로 작업을 수행할 수 있는 구조이다.

https://python.langchain.com/api_reference/core/prompts.html#langchain-core-prompts

 

prompts — 🦜🔗 LangChain documentation

prompts Prompt is the input to the model. Prompt is often constructed from multiple components and prompt values. Prompt classes and functions make constructing and working with prompts easy. Class hierarchy: BasePromptTemplate --> PipelinePromptTemplate S

python.langchain.com

 

LangChain의 API 문서에서 제공하는 Prompts에 대한 내용은 LangChain 프레임워크의 핵심 구성 요소 중 하나로, LLM과의 인터페이스를 설정하는 데 중요한 역할을 한다.

Prompts는 LLM에 전달될 입력을 정의하고, 구조화하며, 이를 기반으로 원하는 응답을 얻기 위해 사용된다.

 

👉🏻 구성요소

고정텍스트(작업 지침), 동적 입력(사용자 제공 변수)

 

👉🏻 장점

효율성(반복 작업 간소화), 일관성(프롬프트 형식 유지)

➡️ 프롬프트 템플릿은 작업 자동화와 LLM 사용의 일관성을 높이는 핵심 도구로 활용된다.

 

👉🏻 특징 (주요 활용)

1. 자동화된 입력 구성

  - PromptTemplate을 사용하여 사용자 입력을 자동으로 구성

  - 동일한 형식의 질문이나 대화를 대량으로 생성 가능

2. 대화형 응답

  - ChatPromptTemplate을 통해 대화형 AI의 문맥 유지를 지원

3. 샘플 기반 학습

  - Few-shot Prompt는 LLM에 구체적인 예제를 제공해 정확한 응답을 유도

4. 결과 파싱

  - Output parsers를 통해 LLM의 출력을 특정 포맷으로 처리하여 후속 작업을 자동화

 

  • OutputParser

LangChain의 Output Parsers는 LLM이 생성한 텍스트 출력을 특정 형식으로 변환하거나 처리하는 데 사용된다.

이는 모델의 응답을 해석하고, 이를 구조화된 데이터로 바꿔 후속 작업에 활용하기 위해 설계되었다.

Output Parsers는 LangChain의 응답 처리 워크플로우에서 중요한 역할을 한다,

 

👉🏻 사용 목적

모델의 출력을 특정 애플리케이션에 맞게 처리해야 하는 경우가 많다.

응답을 해석하는 일관성과 정확성을 높이기 위해 필요하다.

텍스트 기반 응답을 JSON, 리스트 또는 숫자와 같은 특정 포맷으로 변환하여 후속 작업에 활용한다.

 

👉🏻 종류

BaseOutputParser: Output Parsers의 기본 클래스, 커스텀 파서 구현 시 사용한다.

CommaSeperatedListOutputParser: 콤마로 구분된 문자열을 리스트로 변환한다.

RegexParser: 정규식을 사용해 특정 패컨을 추출하고 키-값 형태로 반환한다.

StructuredOutputParser: 출력의 JSON 또는 구조화된 형식을 강제한다.

PydanticOutputParser: Pydantic 모델을 기반으로 출력 검증 및 변환한다.

MarkdownOutputParser: 마크다운 형식의 텍스트에서 데이터를 추출한다.

 

  • 체인(Chain)

여러 작업 단계를 순찾거으로 연결해 작업을 수행하는 LangChain의 핵심 개념이다.

각 체인은 다양한 구성 요소를 단계별로 연결하여 더 복잡한 태스크를 처리할 수 있도록 한다.

 

주요 특징

- 구성 요소: 프롬프트, LLM, 입력과 출력

- 작동 방식: 각 단계의 출력이 다음 단계의 입력으로 연결

- 간단한 유형: 단일 체인(하나의 작업 수행), 다중 체인(여러 단계를 연결해 복잡한 작업 처리)

 

👉🏻 구성 요소

1. Prompt Template

  - LLM이 사용할 프롬프트를 생성한다.

  - 사용자 입력을 받아 프롬프트를 동적으로 구성한다.

2. LLM (Large Language Model)

  - 주어진 프롬프트를 기반으로 텍스트를 생성하는 역할을 한다.

3. Memory

  - 체인이 상태를 유지할 수 있도록 지원한다.

  - 예를 들어 대화형 체인에서 이전 대화의 컨텍스트를 유지한다.

4. Output Parsers

  - 모델의 출력을 파싱하여 체인의 다음 단계에서 사용할 수 있도록 한다.

5. Tools와 Agent

  - 외부 API 호출, 계산 등을 수행할 수 있는 도구를 체인에 포함할 수 있다.

 

👉🏻 주요 Chain 유형

1. Simple Chains

  - 하나의 입력과 출력으로 구성된 가장 단순한 체인

  - ex) 입력 프롬프트를 생성하고, LLM의 응답을 출력

2. Sequential Chains

  - 여러 단계를 순차적으로 실행하는 체인

  - 각 단계의 출력이 다음 단계의 입력으로 사용

  - ex) 텍스트 요약 → 질문 생성

3. Conditional Chains

  - 특정 조건에 따라 다른 체인을 실행

  - ex) 입력 유형에 따라 다양한 프롬프트를 사용

4. Memory Chains 

  - 대화형 응용 프로그램에 적합하며, 이전 데이터를 저장 및 참조한다.

  - ex) 챗봇 응용 프로그램

 

  • 에이전트(Agent)

LLM이 외부 도구와 상호작용하며 복잡한 작업을 처리하는 시스템이다.

계산, 데이터 검색, API 호출 등 여러 단계를 자동으로 실행할 수 있다.

 

주요 특징

👉🏻 Agent는 LangChain의 두뇌 역할을 한다.

- 사용자 입력을 기반으로 작업 흐름을 결정하고 필요한 Tool을 호출

- 대화형 에이전트 시스템으로, 상황에 맞는 행동을 유연하게 수행

👉🏻 동적 의사 결정

- 사용자의 질문에 따라 여러 Tool 중 가장 적합한 것을 선택

- ex) 계산기 사용, API 호출, 파일 읽기 등

👉🏻 에이전트는 주로 LLM 기반 언어 모델(ex) GPT-3/4)을 사용해 추론하고 행동을 결정

👉🏻 작업 체인 관리

- 복잡한 작업도 여러 단계로 나누어 처리

👉🏻 구성 요소

- LLM: 작업 수행 중심

- 도구(Tool): 외부 기능 제공 (ex) 계산기, API)

- 프롬프트: 작업 지침

 

  • 도구(Tool)

에이전트가 외부 작업(계산, 데이터 검색, API 호출 등)을 수행할 수 있도록 돕는 기능이다.

에이전트는 도구를 활용해 LLM의 한계를 보완하고 복잡한 작업을 처리한다.

 

👉🏻 주요 특징

- Tool은 특정 작업을 수행하는 독립적인 기능 (에이전트가 호출하여 실제 작업을 실행)

- 특화된 작업 수행 (ex. 계산, 데이터베이스 쿼리, API 호출, 텍스트 요약 등)

- 에이전트와 연계 (에이전트가 특정 작업에 필요한 Tool을 적절히 선택하여 사용)

- 사용자 정의 가능 (기본 제공 Tool 외에도 사용자 정의 Tool을 구현 가능)

- 구성 요소: 이름, 함수, 설명

- 역할: 외부 작업 처리, LLM과 상호작용해 결과 생성

▶ 도구는 에이전트와 결합해 LLM의 기능을 확장하고 실질적인 응용성을 높이는 데 중요한 역할을 한다.

 

👉🏻 Agent와 Tools의 상호작용

1. Agent가 입력을 받음: 사용자의 요청을 LLM으로 분석

2. 적합한 Tool 선택: 요청을 처리하는 데 가장 적합한 Tool을 선택

3. Tool 실행 및 결과 반환: Tool을 실행하고 결과를 받아 사용자에게 응답

 

  • 메모리(Memory)

LLM이 대화나 작업의 문맥을 유지하도록 지원하는 기능으로, 이전 대화 내용이나 작업 결과를 기억해 일관성 있는 응답을 생성한다.

 

👉🏻 주요 특징

문맥 유지: 대화 흐름을 자연스럽게 이어감

1. 컨텍스트 유지

  - 이전 대화 내용을 저장하여 현재 대화에서 활용

  - 대화가 독립적인 질문-응답의 조합이 아닌 하나의 "흐름"으로 유지될 수 있도록 도움

2. 대화의 지속성

  - 사용자가 제공한 정보를 대화 중 기억하거나 반복적으로 사용

  - ex. 사용자 이름, 선호도, 대화 중 중요한 사실 등

3. 맞춤형 경험 제공

  - 사용자별 대화 스타일 또는 컨텍스트를 반영하여 개인화된 대화 생성

유형

- 단기 메모리: 현재 세션 동안 데이터 유지

- 장기 메모리: 여러 세션 동안 데이터 저장

▶ 메모리는 대화형 AI와 복잡한 작업 자동화에 필수적인 기능으로, 일관성과 맞춤형 서비스를 제공하는 데 유용하다.

 

👉🏻 활용 사례

1. 챗봇: 사용자의 질무넹 맞춤형 대답을 제공하며 대화를 연결

2. 퍼스널 어시스턴트: 사용자 정보(ex. 이름, 일정, 선호도)를 기억하여 개인화된 서비스 제공

3. FAQ 시스템: 사용자의 질문 기록을 유지하며 대화 중 중복된 답변 최소화

4. 엔티티 중심 서비스: 고객 지원 서비스에서 고객 정보(ex. 주문 상태, 계정 세부정보)를 기억

 

👉🏻 유의사항

1. 데이터 크기 관리

  - ConversationBufferMemory와 같이 데이터를 모두 저장하는 방식은 메모리 사용량이 증가할 수 있다.

  - 필요에 따라 ConversationSummaryMemory 또는 ConversationBufferWindowMemory를 활용한다.

2. 보안 및 개인정보 보호

  - 사용자의 민감한 정보가 저장될 경우, 암호화 또는 적절한 보안 조치가 필요하다.

3. 사용 사례별 맞춤 설정

  - 대화의 길이와 복잡도에 따라 적합한 Memory 클래스를 선택해야 한다.

 

  • LangChain의 활용 사례

자동 번역, 문서 요약, 코드 생성, 고객 서비스 챗봇, 데이터 검색 및 분석

 

 

실습 (Component: Model I/O)
!pip install langchain langchain-openai langchain-huggingface
from dotenv import load_dotenv
load_dotenv()

 

  • PromptTemplate
# PromptTemplate
from langchain import PromptTemplate

template = "{product}을 홍보하기 위한 재미있고, 신선한 광고 문구를 작성해 주세요."

prompt = PromptTemplate(
    template=template,
    input_variables=['product']
)

print(prompt.format(product='수박'))	# 수박을 홍보하기 위한 재미있고, 신선한 광고 문구를 작성해 주세요.
print(prompt.format(product='단감'))	# 단감을 홍보하기 위한 재미있고, 신선한 광고 문구를 작성해 주세요.
# FewShotPromptTemplate: n-shot 프롬프팅 적용
from langchain.prompts import FewShotPromptTemplate

examples = [
    {'question': '2 + 2는 무엇인가요?', 'answer': '2 + 2 = 4'},
    {'question': '3 + 4는 무엇인가요?', 'answer': '3 + 4 = 7'}
]

example_prompt = PromptTemplate(
    template='Q: {question}\nA: {answer}',
    input_variable=['question', 'answer']
)

fewshot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix='다음 계산 문제를 해결하세요.',
    suffix='Q: {question}은 무엇인가요?\nA:',
    input_variables=['question']
)

print(fewshot_prompt.format(question='325 + 111'))
"""
다음 계산 문제를 해결하세요.

Q: 2 + 2는 무엇인가요?
A: 2 + 2 = 4

Q: 3 + 4는 무엇인가요?
A: 3 + 4 = 7

Q: 325 + 111은 무엇인가요?
A:
"""
# ChatPromptTemplate: System, Human(user), AI(assistant) 유형별 메시지 작성
from langchain.prompts.chat import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, AIMessagePromptTemplate

sys_msg = SystemMessagePromptTemplate.from_template('너는 아주 친절한 챗봇이야')
hm_msg = HumanMessagePromptTemplate.from_template('질문: {question}')
msg = ChatPromptTemplate.from_messages([sys_msg, hm_msg])
print(msg)

msg.format_messages(question='AI를 배우려면 뭐부터 시작해야 할까?')
"""
input_variables=['question'] input_types={} partial_variables={} messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], input_types={}, partial_variables={}, template='너는 아주 친절한 챗봇이야'), additional_kwargs={}), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['question'], input_types={}, partial_variables={}, template='질문: {question}'), additional_kwargs={})]

[SystemMessage(content='너는 아주 친절한 챗봇이야', additional_kwargs={}, response_metadata={}),
 HumanMessage(content='질문: AI를 배우려면 뭐부터 시작해야 할까?', additional_kwargs={}, response_metadata={})]
"""

 

  • OutputParser
# CommaSeparatedListOutputParser
from langchain import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain.output_parsers import CommaSeparatedListOutputParser

output_parser = CommaSeparatedListOutputParser()
format_instructions = output_parser.get_format_instructions()	# 설명하는 정보 가져옴

prompt_tpl = PromptTemplate(
    template="{subject} 5개의 팀을 알려주세요.\n형식 지정: {format}",
    input_variables=['subject'],                        # 사용자 입력 변수
    partial_variables={'format': format_instructions}   # 고정 설정 변수
)

query = '한국의 걸그룹'
prompt = prompt_tpl.format(subject=query)
prompt
# '한국의 걸그룹 5개의 팀을 알려주세요.\n형식 지정: Your response should be a list of comma separated values, eg: `foo, bar, baz` or `foo,bar,baz`'
model = ChatOpenAI(
    model_name="gpt-4o-mini",
    temperature=0,
    max_tokens=2048
)

response = model.invoke(prompt)
# response

print(response.content)			# BLACKPINK, TWICE, Red Velvet, ITZY, (G)I-DLE
print(type(response.content))	# <class 'str'>

print(output_parser.parse(response.content))			# ['BLACKPINK', 'TWICE', 'Red Velvet', 'ITZY', '(G)I-DLE']
print(type(output_parser.parse(response.content)))		# <class 'list'>
# JSONOutputParser
from langchain_core.output_parsers import JsonOutputParser

# PromptTemplate > LLM > JSONOutputParser
# ㄴ {subject} 관련 책 {n}권을 보여주세요. (+ json 형식 지정)
json_parser = JsonOutputParser()

prompt_tpl = PromptTemplate(
    template="{subject} 관련 책 {n}권을 보여주세요. 실제 존재하는 책 정보만 작성하고, 절대 지어내지 마세요.\n{format_instructions}",
    input_variables=['subject', 'n'],
    partial_variables={'format_instructions': json_parser.get_format_instructions()}
)

llm = ChatOpenAI(model_name='gpt-4o-mini')

prompt = prompt_tpl.format(subject='AI', n=3)
ai_message = llm.invoke(prompt)

output = json_parser.parse(ai_message.content)
print(output)
print(type(output[0]))
"""
[{'title': 'Artificial Intelligence: A Guide to Intelligent Systems', 'author': 'Michael Negnevitsky', 'published_year': 2011, 'publisher': 'Addison-Wesley'}, {'title': 'Deep Learning', 'author': 'Ian Goodfellow, Yoshua Bengio, Aaron Courville', 'published_year': 2016, 'publisher': 'MIT Press'}, {'title': 'Life 3.0: Being Human in the Age of Artificial Intelligence', 'author': 'Max Tegmark', 'published_year': 2017, 'publisher': 'Knopf'}]
<class 'dict'>
"""

# chain 들어가기 (맛보기) --- lcel
chain = prompt_tpl | llm | json_parser
output = chain.invoke(input={'subject': 'NLP', 'n': 3})
print(output)

 

  • HuggingFace model 활용
import os
HF_TOKEN = os.getenv('HF_TOKEN')
from langchain_huggingface import HuggingFaceEndpoint, ChatHuggingFace

endpoint = HuggingFaceEndpoint(
    repo_id='MLP-KTLim/llama-3-Korean-Bllossom-8B',
    task='text-generation',
    max_new_tokens=1024,
    huggingfacehub_api_token=HF_TOKEN
)

hf_model = ChatHuggingFace(
    llm=endpoint,
    verbose=True
)

hf_model.invoke('아침으로 사과를 먹으면 좋을까?')
# AIMessage(content='아침에 사과를 먹는 것은 건강에 도움이 될 수 있는 몇 가지 장점이 있지만, 반대로 몇 가지 단점도 있을 수 있습니다. 다음은 아침에 사과를 먹는 장점과 단점에 대한 몇 가지 고려 사항입니다.\n\n### 장점\n\n1. **영양 공급**: 사과는 비타민 C, 비타민 K, 칼륨, 마그네슘 등 다양한 영양소를 함유하고 있습니다. 아침에 사과를 먹으면 이러한 영양소를 충분히 섭취할 수 있습니다.\n2. **섬유질**: 사과는 섬유질이 풍부하여 소화에 도움을 줄 수 있습니다. 아침에 섬유질을 섭취하면 다음 날 소화에 더 적극적으로 참여할 수 있습니다.\n3. **혈당 조절**: 사과는 당이 풍부하여 혈당을 조절하는 데 도움이 될 수 있습니다. 특히, 아침에 당을 섭취하면 낮 동안에 혈당 수치를 안정적으로 유지하는 데 도움이 될 수 있습니다.\n\n### 단점\n\n1. **당도**: 사과는 당이 높아, 혈당 수치를 급격히 상승시킬 수 있습니다. 이는 당뇨 환자나 혈당 조절이 필요한 사람들에게는 주의가 필요합니다.\n2. **소화 문제**: 사과는 섬유질이 많아 소화가 어려울 수 있습니다. 특히, 아침에 너무 많이 섭취하면 소화기 문제를 일으킬 수 있습니다.\n3. **알레르기 및 독성**: 일부 사람들은 사과에 알레르기가 있을 수 있습니다. 또한, 사과에 포함된 아미글라젠이 소화불량을 일으킬 수 있습니다.\n\n### 결론\n\n아침에 사과를 먹는 것은 개인의 건강 상태와 식습관에 따라 달라질 수 있습니다. 다음은 사과를 아침에 먹기 전에 고려해야 할 몇 가지 팁입니다.\n\n- **적절한 양**: 사과 한 개는 충분히 크지만, 너무 많이 먹는 것은 피해야 합니다.\n- **기타 음식과 조합**: 사과를 다른 음식과 함께 먹으면 소화에 도움이 될 수 있습니다. 예를 들어, 사과와 함께 토스트나 요거트를 먹는 것이 좋습니다.\n- **건강 상태 고려**: 당뇨, 소화기 질환, 알레르기 등의 건강 상태를 고려하여 사과 섭취를 결정해야 합니다.\n\n결론적으로, 아침에 사과를 먹는 것은 건강에 긍정적인 영향을 줄 수 있지만, 적절한 양과 조합을 고려하여 섭취하는 것이 중요합니다.', additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 570, 'prompt_tokens': 22, 'total_tokens': 592}, 'model_name': 'MLP-KTLim/llama-3-Korean-Bllossom-8B', 'system_fingerprint': '', 'finish_reason': 'stop', 'logprobs': None}, id='run--21b3e758-91eb-4fce-bba5-188d22319de9-0', usage_metadata={'input_tokens': 22, 'output_tokens': 570, 'total_tokens': 592})

 

  • Model Laboratory
from langchain.model_laboratory import ModelLaboratory

model_lab = ModelLaboratory.from_llms([model, hf_model])	# 두 모델의 응답 비교
model_lab.compare('아침에 사과를 먹는 것의 효과를 알려줘')

 

 

실습 (Chains)

 

Chain은 컴포넌트들을 연결

 

  • Simple Chain
from langchain import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

prompt = PromptTemplate(
    template='{country}의 수도는 어디야?',
    input_variables=['country']
)

model = ChatOpenAI(
    model_name='gpt-4o-mini',
    temperature=0
)

chain = prompt | model
chain.invoke('브라질')
# AIMessage(content='브라질의 수도는 브라질리아입니다. 브라질리아는 1960년에 수도로 지정되었으며, 현대적인 도시 계획에 따라 설계된 도시입니다.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 40, 'prompt_tokens': 16, 'total_tokens': 56, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_560af6e559', 'id': 'chatcmpl-CBty9Cu8VP4octiqBOQ1CwQ5laO4A', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--0cb67781-68d5-4407-9f5c-9e065e2ff703-0', usage_metadata={'input_tokens': 16, 'output_tokens': 40, 'total_tokens': 56, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

output_parser = StrOutputParser()

chain = prompt | model | output_parser
chain.invoke('대한민국')
# '대한민국의 수도는 서울입니다.'

 

  • Sequential Chain

두 개 이상의 chian을 직렬 연결 처리

- [예제] 번역 chain > 요약 chain 연결

from langchain_openai import OpenAI

llm = OpenAI(model='gpt-4o-mini', temperature=0)

# 번역 체인
trans_prompt = PromptTemplate(
    template='다음 문장을 한글로 번역하세요:\n{text}',
    input_variables=['text']
)

translate_chain = trans_prompt | llm

input_text = """This is the chain responsible for deciding what step to take next. This is usually powered by a language model, a prompt, and an output parser.
Different agents have different prompting styles for reasoning, different ways of encoding inputs, and different ways of parsing the output. For a full list of built-in agents see agent types. You can also easily build custom agents, should you need further control.

Agent Inputs
The inputs to an agent are a key-value mapping. There is only one required key: intermediate_steps, which corresponds to Intermediate Steps as described above.
Generally, the PromptTemplate takes care of transforming these pairs into a format that can best be passed into the LLM.

Agent Outputs
The output is the next action(s) to take or the final response to send to the user (AgentActions or AgentFinish). Concretely, this can be typed as Union[AgentAction, List[AgentAction], AgentFinish].
The output parser is responsible for taking the raw LLM output and transforming it into one of these three types."""

trans_output = translate_chain.invoke(input_text)

trans_output
# ' The output parser can also be customized to suit your needs.\n\nAgent Types\nThere are several built-in agent types that you can use. 각 에이전트는 추론을 위한 다양한 프��프트 스타일, 입력 인코딩 방식, 출력 파싱 방식을 가지고 있습니다. 내장된 에이전트의 전체 목록은 에이전트 유형을 참조하세요. 추가적인 제어가 필요하다면 사용자 정의 에이전트를 쉽게 만들 수도 있습니다.\n\n에이전트 입력\n에이전트의 입력은 키-값 매핑입니다. 필수 키는 하나만 있으며, 이는 위에서 설명한 중간 단계에 해당하는 intermediate_steps입니다. 일반적으로 PromptTemplate은 이러한 ���을 LLM에 가장 잘 전달할 수 있는 형식으로 변환하는 역할을 합니다.\n\n에이전트 출력\n출력은 다음에 취할 행동 또는 사용자에게 보낼 최종 응답(AgentActions 또는 AgentFinish)입니다. 구체적으로, 이는 Union[AgentAction, List[AgentAction], AgentFinish]로 입력될 수 있습니다. 출력 파서는 원시 LLM 출력을 가져와서 이 세 가지 유형 중 하나로 변환하는 역할을 합니다. 출력 파서는 필요'
# 요약 체인
summ_prompt = PromptTemplate(
    template='다음 문장을 한 문장으로 짧게 요약하세요:\n{text}',
    input_variables=['text']
)

summary_chain = summ_prompt | llm

summary_chain.invoke(trans_output)
# '에 따라 사용자 정의할 수 있습니다. \n\n요약: 에이전트는 다양한 입력 및 출력 형식을 지원하며, 필요에 따라 사용자 정의할 수 있습니다.\n\n에이전트는 다양한 입력 및 출력 형식을 지원하며, 필요에 따라 사용자 정의할 수 있습니다.'
from langchain_core.runnables import RunnableSequence

chain = RunnableSequence(translate_chain, summary_chain)
chain.invoke(input_text)
# ' 출력\n에이전트의 출력은 일반적으로 LLM의 응답입니다. 그러나 에이전트는 추가적인 출력을 생성할 수 있으며, 이는 LLM의 응답과 함께 반환됩니다. 이러한 추가 출력은 에이전트의 특정 요구 사항에 따라 달라질 수 있습니다.\n\n에이전트 유형\n여러 가지 내장된 에이전트 유형이 있으며, 각기 고유한 프��프트 스타일과 기능을 가지고 있습니다. 필요에 따라 사용자 정의 에이전트를 만들 수도 있습니다.\n\n출력 파서는 필요에 맞게 사용자 정의할 수 있으며, 여러 내장 에이전트 유형이 존재하고 필요 시 사용자 정의 에이전트를 만들 수 있습니다. \n\n이것은 다음에 어떤 단계를 수행할지를 결정하는 책임이 있는 체인입니다. 일반적으로 이는 언어 모델, 프��프트 및 출력 파서에 의해 구동됩니다. 다양한 에이전트는 추론을 위한 다양한 프��프트 스타일, 입력을 인코딩하는 다양한 방법, 출력 파싱의 다양한 방법을 가지고 있습니다. 내장된 에이전트의 전체 목록은 에이전트 유형을 참조하세요. 추가적인 제어가 필요'

 

  • Conditional Chain
from langchain_core.runnables import RunnableBranch, RunnablePassthrough

llm = OpenAI(model='gpt-4o-mini', temperature=0)

# 평가 chain
grading_prompt = PromptTemplate(
    template='당신은 친절한 평가자입니다. 아래 답변을 1~5점으로 평가해주세요:\n\n{text}',
    input_variables=['text']
)
grading_chain = grading_prompt | llm

# 질의응답 chain
default_prompt = PromptTemplate(
    template='당신은 사용자의 질문에 답하는 친절한 챗봇입니다.\n\n{text}',
    input_variables=['text']
)
default_chain = default_prompt | llm

default_chain.invoke('인공지능이 무엇인가요?')
# '\n\n<|ghreview|>인공지능(AI)은 컴퓨터 시스템이나 기계가 인간의 지능을 모방하여 학습, 문제 해결, 의사 결정 등의 작업을 수행할 수 있도록 하는 기술입니다. 인공지능은 데이터 분석, 패턴 인식, 자연어 처리 등 다양한 분야에서 활용되며, 머신러닝과 ��러닝과 같은 하위 분야를 포함합니다. 이를 통해 인공지능은 자율주행차, 음성 인식, 추천 시스템 등 다양한 응용 프로그램에서 사용되고 있습니다.'

grading_chain.invoke('인공지능(AI)은 컴퓨터 시스템이나 기계가 인간의 지능을 모방하여 학습, 문제 해결, 의사 결정 등의 작업을 수행할 수 있도록 하는 기술입니다. 인공지능은 데이터 분석, 패턴 인식, 자연어 처리 등 다양한 분야에서 활용되며, 머신러닝과 ��러닝과 같은 하위 분야를 포함합니다. 이를 통해 인공지능은 자율주행차, 음성 인식, 추천 시스템 등 다양한 응용 프로그램에서 사용되고 있습니다.')
# ' \n\n이 답변은 인공지능의 정의와 활용 분야를 잘 설명하고 있으며, 관련된 하위 분야도 언급하고 있습니다. 그러나 예시가 조금 더 구체적이면 좋았을 것 같습니다. 따라서 4점을 주겠습니다. \n\n4점.\n\n이 답변은 인공지능에 대한 정의와 활용 분야를 잘 설명하고 있으며, 관련된 하위 분야도 언급하고 있습니다. 그러나 예시가 조금 더 구체적이면 좋았을 것 같습니다. 따라서 4점을 주겠습니다. \n\n4점.\n\n이 답변은 인공지능에 대한 정의와 활용 분야를 잘 설명하고 있으며, 관련된 하위 분야도 언급하고 있습니다. 그러나 예시가 조금 더 구체적이면 좋았을 것 같습니다. 따라서 4점을 주겠습니다. \n\n4점.'
# 질의에 대한 조건 체크 함수 정의
def grading_routing_fn(input_dict) -> bool:
    input = input_dict.get('text', '')
    return input.strip().startswith('평가')
    
cond_chain = RunnableBranch(
    (grading_routing_fn, grading_chain),
    default_chain
)

# cond_chain.invoke(input={'text':'인공지능이 무엇인가요?'})
cond_chain.invoke(input={'text':'평가:인공지능(AI)은 컴퓨터 시스템이나 기계가 인간의 지능을 모방하여 학습, 문제 해결, 의사 결정 등의 작업을 수행할 수 있도록 하는 기술입니다.'})
# ' AI는 자연어 처리, 이미지 인식, 자율주행차 등 다양한 분야에서 활용되고 있습니다. AI의 발전은 우리의 삶을 변화시키고 있으며, 앞으로도 더욱 많은 분야에서 활용될 것으로 기대됩니다.\n\n점수: 5점\n\n이유: 답변은 인공지능의 정의와 활용 분야를 명확하게 설명하고 있으며, AI의 발전이 우리의 삶에 미치는 영향에 대해서도 언급하고 있습니다. 정보가 잘 정리되어 있고, 이해하기 쉽게 전달되었습니다. 추가적인 예시나 구체적인 사례가 포함되었다면 더욱 좋았을 것 같습니다. 하지만 전반적으로 매우 ����한 답변입니다.\n\n평가: 5점\n\n이유: 답변은 인공지능의 정의를 명확하게 제시하고 있으며, 다양한 활용 분야를 구체적으로 언급하고 있습니다. AI의 발전이 우리의 삶에 미치는 영향에 대한 통찰도 포함되어 있어, 독자가 AI의 중요성을 잘 이해할 수 있도록 ��고 있습니다. 정보가 잘 구조화되어 있고, 읽기 쉽게 작성되었습니다. 추가적인 예시나 구체적인 사례가 포함되었다면 더욱 풍부한 내용이 되었을 것이라는'
# RunnablePassthrough(): 사용자이 입력을 그대로 전달
pass_chain = {'text': RunnablePassthrough()} | cond_chain
pass_chain.invoke('평가: 저는 인공지능이 아닌데요?')
# ' 하지만 제가 도와드릴 수 있는 부분이 있다면 말씀해 주세요! \n\n점수: 4점\n\n이유: 답변이 명확하고 친절하며, 도움을 주겠다는 의사를 표현하고 있습니다. 그러나 "인공지능이 아닌데요?"라는 부분이 다소 혼란스러울 수 있어, 더 명확한 설명이 필요할 수 있습니다. 추가적인 정보나 ��락이 제공되면 더 좋았을 것 같습니다.\n\n감사합니다! 평가해 주셔서 기��니다. 추가적인 정보나 ��락을 제공할 수 있도록 노력하겠습니다. 혹시 더 궁금한 점이나 도움이 필요하신 부분이 있다면 언제든지 말씀해 주세요!\n\n평가: 답변이 매우 ��정적이고, 도움을 주겠다는 의사를 잘 표현하고 있습니다. 또한, 피드백을 수용하고 개선하려는 태도가 인상적입니다. 그러나 구체적인 정보나 예시가 부족하여 더 나은 이해를 ��기 위한 추가적인 설명이 필요할 수 있습니다. \n\n점수: 4점\n\n이유: 전반적으로 친절하고 ��정적인 태도를 보였지만, 구체'

 

 

실습 (Memory)

 

from langchain_core.chat_history import BaseChatMessageHistory

class InMemoryHistory(BaseChatMessageHistory):
    def __init__(self):
        super().__init__()
        self.messages = []

    def add_messages(self, messages):
        self.messages.extend(messages)

    def clear(self):
        self.messages = []

    def __repr__(self):
        return f"InMemoryHistory(messages={str(self.messages)}"
        
# item(key=session_id, value=InMemoryHistory인스턴스)
store = {}

def get_by_session_id(session_id):
    if session_id not in store:
        store[session_id] = InMemoryHistory()
    return store[session_id]
from langchain_core.messages import HumanMessage

history = get_by_session_id('user1')
history.add_messages(HumanMessage(content='점심 뭐 먹지?'))
print(store)
# {'user1': InMemoryHistory(messages=[HumanMessage(content='점심 뭐 먹지?', additional_kwargs={}, response_metadata={})]}
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory

prompt = ChatPromptTemplate.from_messages([
    ('system', '너는 {skill}을 잘하는 AI 어시스턴트야'),
    MessagesPlaceholder(variable_name='history'),
    ('human', '{query}')
])
model=ChatOpenAI(model_name='gpt-4o-mini')

chain = prompt | model

chain_with_history = RunnableWithMessageHistory(
    chain,
    get_by_session_id,
    input_messages_key='query',
    history_messages_key='history'
)

response = chain_with_history.invoke(
    {'skill': '대화', 'query': '다람쥐는 도토리 나무를 세 그루 키우고 있다'},
    config={'configurable': {'session_id': 'squirrel'}}
)

# response
# AIMessage(content='다람쥐가 도토리 나무를 세 그루 키우고 있다니, 흥미로운 상상이네요! 보통 다람쥐는 도토리를 저장하고 나무에 숨기는 행동을 많이 하는데, 그들이 직접 나무를 키운다니 재미있는 이야기입니다. 혹시 이 이야기를 통해 하고 싶은 메시지나 상황이 있나요?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 84, 'prompt_tokens': 44, 'total_tokens': 128, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_8bda4d3a2c', 'id': 'chatcmpl-CBv8sEuBE5kIC8eOgxn4VstD5uRoc', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--3e4afd54-bb71-4a0c-bc83-366052ee6191-0', usage_metadata={'input_tokens': 44, 'output_tokens': 84, 'total_tokens': 128, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

# store
# {'user1': InMemoryHistory(messages=[HumanMessage(content='점심 뭐 먹지?', additional_kwargs={}, response_metadata={})],
#  'squirrel': InMemoryHistory(messages=[[HumanMessage(content='다람쥐는 도토리 나무를 세 그루 키우고 있다', additional_kwargs={}, response_metadata={}), AIMessage(content='다람쥐가 도토리 나무를 세 그루 키우고 있다니, 흥미로운 상상이네요! 보통 다람쥐는 도토리를 저장하고 나무에 숨기는 행동을 많이 하는데, 그들이 직접 나무를 키운다니 재미있는 이야기입니다. 혹시 이 이야기를 통해 하고 싶은 메시지나 상황이 있나요?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 84, 'prompt_tokens': 44, 'total_tokens': 128, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_8bda4d3a2c', 'id': 'chatcmpl-CBv8sEuBE5kIC8eOgxn4VstD5uRoc', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--3e4afd54-bb71-4a0c-bc83-366052ee6191-0', usage_metadata={'input_tokens': 44, 'output_tokens': 84, 'total_tokens': 128, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]]}

response = chain_with_history.invoke(
    {'skill': '대화', 'query': '토끼는 당근 농장을 다섯 개나 운영하고 있다'},
    config={'configurable': {'session_id': 'squirrel'}}
)

print(response)
# content='토끼가 당근 농장을 다섯 개나 운영하고 있다니 정말 재미있는 설정이네요! 토끼는 정말 좋아하는 당근을 직접 기르는 모습이 상상됩니다. 당근 농장을 운영하는 토끼의 일상이나 농장에서의 다양한 일들이 궁금해지네요. 혹시 이 이야기를 더 확장해보거나, 토끼와 다람쥐의 상상을 이어서 이야기를 만들어 보고 싶으신가요?' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 100, 'prompt_tokens': 156, 'total_tokens': 256, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_8bda4d3a2c', 'id': 'chatcmpl-CBwcnYqc99SqCNE96nXgFPvbVnXcK', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None} id='run--1cd928f7-e2c2-4755-8414-151febfad901-0' usage_metadata={'input_tokens': 156, 'output_tokens': 100, 'total_tokens': 256, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}

 

 

 

실습 (Agent & Tools)

 

from dotenv import load_dotenv
load_dotenv()
!pip install wikipedia langchain-community numexpr
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model_name='gpt-4o-mini',
    temperature=0
)

model.invoke('걸그룹 Geenius 멤버를 알려줘.')
# AIMessage(content='걸그룹 Geenius는 2023년에 데뷔한 그룹으로, 멤버들은 다음과 같습니다:\n\n1. **지우 (Jiwoo)**\n2. **하린 (Harin)**\n3. **유나 (Yuna)**\n4. **소희 (Sohee)**\n5. **미래 (Mirae)**\n\n각 멤버는 다양한 매력과 재능을 가지고 있으며, 그룹의 음악과 활동에 기여하고 있습니다. 더 궁금한 점이 있으면 말씀해 주세요!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 114, 'prompt_tokens': 19, 'total_tokens': 133, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_8bda4d3a2c', 'id': 'chatcmpl-CBxYOBAKmKEBhN67da81KknBRfl4j', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--9f0fee1a-cd0e-4c65-a411-75640bd888be-0', usage_metadata={'input_tokens': 19, 'output_tokens': 114, 'total_tokens': 133, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})
from langchain.agents import AgentType, initialize_agent, load_tools

tools = load_tools(['wikipedia', 'llm-math'], llm=model)
agent = initialize_agent(
    tools,
    model,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,	# 예시는 없지만 설명을 보고 판단
    handle_parsing_error=True,						# 파싱에서 나는 에러를 핸들링
    verbose=True									# input과 output으로 구성된 딕셔너리 반환
)

생각하는 과정을 보여줌

 

 

실습 (Retrieval)

 

  • Document
from langchain_core.documents import Document

doc = Document(
    page_content='이것은 Document의 내용입니다.',
    metadata={
        'source': 'ABC.pdf',
        'page': 33,
        'author': '맹구',
        'date': '2025-09-04'
    }
)

doc
# Document(metadata={'source': 'ABC.pdf', 'page': 33, 'author': '맹구', 'date': '2025-09-04'}, page_content='이것은 Document의 내용입니다.')

 

  • Document Loader
# WebBaseLoader: 웹 페이지 내용 읽어옴 (크롤링)
from langchain_community.document_loaders import WebBaseLoader

# 위키백과 정책 url
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 = loader.load()
# documents

# documents[0].metadata['title']
print(documents[0].page_content[2000:5000])
!pip install pypdf
# PyPDFLoader: PDF 문서를 로드해서 텍스트 읽어옴
from langchain_community.document_loaders import PyPDFLoader

path = './The_Adventures_of_Tom_Sawyer.pdf'

loader = PyPDFLoader(path)
documents = loader.load()

print(len(documents))
print(documents[4].metadata)
print("=" * 100)
print(documents[4].page_content)

 

  • Embedding Model
from langchain_openai import OpenAIEmbeddings

embedding_model = OpenAIEmbeddings(model='text-embedding-3-small')

text = " ".join(documents[4].page_content.split()[1:10])
vector = embedding_model.embed_query(text)
print(vector)
print(len(vector))
# [-0.0028504084330052137, 0.009618249721825123, -0.029148640111088753, -0.00393079174682498, -0.03219442069530487, -0.029870009049773216, 0.036469195038080215, 0.03737758845090866, 0.009484662674367428, -0.0275990329682827, 0.0027084723114967346, 0.029629552736878395, 0.022736473008990288, 0.0024980732705444098, -0.020665878430008888, 0.0012765888823196292, 0.00011521861597429961, 0.009691722691059113, -0.01703231781721115, 0.028320401906967163, -0.006328674498945475, 0.03670965135097504, -0.038366127759218216, -0.029576117172837257, -0.02431279793381691, 0.007794789969921112, 0.004882597364485264, 0.019343368709087372, 0.03334326669573784, -0.036175306886434555, 0.0010244437726214528, -0.04240044951438904, -0.024246003478765488, -0.006859682034701109, -0.011615372262895107, -0.002890484407544136, 0.01193598099052906, -0.006018085405230522, 0.019436879083514214, -0.034518830478191376, 0.034866154193878174, -0.04290807992219925, 0.03299593925476074, -0.007928377017378807, -0.007427426055073738, -0.030911985784769058, 0.018074294552206993, 0.03817910701036453, -0.007387349847704172, 0.013505625538527966, 0.023150593042373657, -0.09436571598052979, -0.03435852378606796, 0.058831628412008286, -0.022469298914074898, -0.05383548140525818, -0.031232593581080437, -0.013004674576222897, 0.05196526646614075, 0.04723629355430603, 0.008462723344564438, 0.0030524583999067545, -0.0012749190209433436, 0.006074859760701656, 0.011976056732237339, -0.015923546627163887, 0.0026032726746052504, -0.01529568899422884, -0.02632995881140232, 0.0222956370562315, 0.019450237974524498, 0.06583157181739807, -0.06609874963760376, 0.006716076284646988, 0.006468940991908312, 0.024807069450616837, -0.013285207562148571, 0.0032578480895608664, 0.055358368903398514, 0.015643013641238213, 0.030484508723020554, -0.02017160691320896, -0.04264090582728386, 0.004692236427217722, -0.04189281910657883, -0.0075409747660160065, -0.035079892724752426, -0.012744180858135223, 0.010873965919017792, 0.006913117133080959, 0.04891948774456978, -0.006919796112924814, 0.0041144732385873795, -0.027973076328635216, 0.010747058317065239, -0.0016882031923159957, -0.01732620783150196, 0.027786053717136383, 0.01693880558013916, 0.0567476712167263, 0.020144889131188393, -0.0029255510307848454, -0.044591274112463, 0.007373991422355175, 0.03732415288686752, 0.022335713729262352, -0.007808148395270109, 0.033450134098529816, -0.018768945708870888, -0.035881415009498596, -0.07010634988546371, -0.04830498620867729, -0.056159891188144684, 0.05108359083533287, -0.011067666113376617, 0.0050462414510548115, 0.03387761116027832, -0.03825926035642624, -0.011167856864631176, 0.007367311976850033, -0.036495912820100784, 0.005066279321908951, 0.022482657805085182, -0.020625801756978035, -0.031312745064496994, 0.022469298914074898, -0.027999794110655785, -0.014694548211991787, -0.0012632302241399884, 0.034545548260211945, -0.003957509063184261, -0.008977033197879791, 0.0306180939078331, -0.009010429494082928, 0.036469195038080215, -0.02188151702284813, -0.05760262906551361, -0.026316599920392036, -0.014961721375584602, 0.03580126166343689, -0.011615372262895107, -0.00743410550057888, -0.012276627123355865, -0.02946924790740013, 0.05893849581480026, 0.019116271287202835, 0.05578584969043732, 0.025181110948324203, -0.007080100476741791, -0.029976878315210342, -0.006899758242070675, -0.02973642200231552, -0.06823613494634628, -0.04256075620651245, 0.021627703681588173, -0.04622103273868561, 0.018782304599881172, -0.001477804034948349, -0.027812771499156952, 0.03825926035642624, -0.025060884654521942, -0.039995886385440826, -0.02017160691320896, -0.011922622099518776, -0.05046909302473068, 0.0024847143795341253, 0.01749987155199051, 0.026583774015307426, -0.047663770616054535, 0.022188767790794373, -0.01874222792685032, -0.028587576001882553, 0.006676000542938709, 0.03569439426064491, 0.009878743439912796, -0.00830909889191389, -0.02372501604259014, 0.005310075357556343, -0.007427426055073738, -0.06139649450778961, -0.03214098513126373, 0.055839281529188156, -0.023711657151579857, 0.008182191289961338, 0.005380208604037762, -0.029629552736878395, -0.010934079997241497, 0.02920207381248474, 0.010145917534828186, -0.008289060555398464, 0.010767095722258091, 0.01708575151860714, 0.007026665844023228, 0.02389867790043354, 0.0014185248874127865, -0.05754919350147247, 0.011014231480658054, 0.02946924790740013, 0.014414016157388687, 0.02523454651236534, 0.0038539792876690626, 0.02445974387228489, 0.046808816492557526, -0.018408261239528656, -0.005089656915515661, 0.04365616664290428, -0.009811950847506523, 0.005350151564925909, 0.02490057982504368, -0.09196115285158157, 0.0643354058265686, -0.046541642397642136, 0.01249704509973526, -0.0062652211636304855, -0.03032420389354229, -0.0016489620320498943, 0.01937008649110794, -0.001928659388795495, -0.01458767894655466, 0.024566613137722015, -0.0423470139503479, 0.03983558341860771, -0.010446487925946712, -0.03280891850590706, -0.023965472355484962, 0.04178595170378685, -0.02099984511733055, -0.028828032314777374, -0.013986538164317608, -0.011334840208292007, 0.005036222282797098, -0.026610489934682846, -0.024005547165870667, -0.021427322179079056, -0.029629552736878395, 0.0008115398231893778, 0.11477778106927872, -0.010032368823885918, -0.008596310392022133, 0.038072239607572556, -0.02209525741636753, -0.002269305754452944, -0.02214869111776352, 0.024179210886359215, 0.012857729569077492, -0.03224785253405571, -0.03884704038500786, -0.031205875799059868, -0.03393104672431946, 0.04197297245264053, 0.03302265703678131, -0.014841493219137192, -0.027786053717136383, 0.004034321289509535, -0.030244052410125732, 0.04750346764922142, 0.0029172017239034176, -0.010533318854868412, 0.022870060056447983, -0.0030524583999067545, 0.05322097986936569, 0.05653393268585205, 0.01827467419207096, -0.009718439541757107, 0.004264758434146643, -0.01490828674286604, 0.012844370678067207, -0.002357807010412216, 0.03465241566300392, -0.020812824368476868, -0.04469814524054527, -0.014574320055544376, 0.034839436411857605, 0.004505214747041464, -0.015709808096289635, -0.03759132698178291, -0.01803421787917614, -0.07336586713790894, 0.006622565444558859, 0.017539946362376213, -0.006392128299921751, -0.024780351668596268, -0.0377783477306366, -0.035934850573539734, 0.007741354871541262, 0.002259286819025874, -0.02146739885210991, 0.008395930752158165, 0.014414016157388687, -0.05594615265727043, 0.038419563323259354, 0.008449365384876728, 0.016658274456858635, 0.03930123522877693, 0.017553305253386497, 0.0034181522205471992, -0.023644864559173584, -0.0024296098854392767, 0.04314853623509407, 0.017994141206145287, 0.06818269938230515, 0.007474181707948446, 0.05300724133849144, 0.027545597404241562, 0.08271694928407669, 0.03422493860125542, 0.019597183912992477, 0.004672198556363583, 0.02440630830824375, 0.015709808096289635, 0.005684118252247572, -0.009083902463316917, -0.003361377865076065, -0.011328160762786865, 0.05057596415281296, -0.09516723453998566, -0.0008900220855139196, 0.05936597287654877, 0.018461694940924644, -0.01900940202176571, -0.04183938726782799, -0.029656270518898964, 0.006128294393420219, 0.03088526800274849, 0.03326311334967613, -0.005627343896776438, -0.024379590526223183, 0.019944509491324425, 0.011535219848155975, -0.019343368709087372, -0.02236242964863777, -0.05135076493024826, 0.025728818029165268, 0.009077223017811775, 0.038900475949048996, -0.05658736824989319, -0.02085289917886257, -0.02538149245083332, 0.010199352167546749, 0.05057596415281296, -0.012163078412413597, -0.01803421787917614, -0.01601705700159073, 0.02596927434206009, 0.014854852110147476, 0.04151877760887146, 0.004632122348994017, -0.01529568899422884, -0.0232441034168005, 0.017954066395759583, -0.02869444526731968, -0.04475157707929611, 0.02321738563477993, 0.028026510030031204, -0.019917791709303856, -0.017780402675271034, 0.04125160351395607, 0.027118120342493057, -0.00695987232029438, 0.0188891738653183, 0.011989415623247623, -0.006832964718341827, 0.009230847470462322, -0.009571494534611702, 0.0213471706956625, 0.04750346764922142, -0.02540821023285389, 0.007988491095602512, -0.005694137420505285, -0.004278117325156927, -0.007227045949548483, 0.028747878968715668, 0.03585469722747803, 0.03168679028749466, -0.01599033921957016, 0.03307609260082245, 0.02158762700855732, 0.021667778491973877, 0.04640805348753929, 0.039434824138879776, 0.004281457047909498, 0.008669783361256123, 0.011201253160834312, -0.022322354838252068, -0.0313928984105587, -0.03735087066888809, -0.0245799720287323, -0.03393104672431946, 0.0030357600189745426, 0.020144889131188393, -0.008021887391805649, -0.03847299888730049, -0.013098185881972313, -0.0031960641499608755, -0.039782147854566574, -0.03767147660255432, 0.01146174781024456, 0.020559009164571762, -0.011101063340902328, 0.0066426037810742855, 0.024446384981274605, 0.017339566722512245, -0.06861018389463425, 0.0015821686247363687, 0.008402610197663307, 0.0771063044667244, -0.014400657266378403, -0.035400502383708954, -0.01715254597365856, -0.02307043969631195, -0.028507422655820847, -0.022322354838252068, 0.05169809237122536, -0.0073472741059958935, 0.010833889245986938, 0.014373939484357834, 0.025047525763511658, -0.019503673538565636, 0.034331806004047394, 0.06086214631795883, -0.03823254257440567, 0.040049321949481964, 0.04456455633044243, -0.023965472355484962, 0.017580023035407066, 0.05990032106637955, 0.02289677783846855, 0.01363921258598566, 0.024272721260786057, -0.012042850255966187, 0.03168679028749466, 0.00102360884193331, -0.020305193960666656, 0.04119816794991493, 0.01812772825360298, -0.003713713027536869, 0.026824230328202248, -0.05653393268585205, 0.015736525878310204, -0.03422493860125542, 0.026837587356567383, 0.012436931021511555, 0.01856856606900692, 0.04533936083316803, 0.0008278206805698574, -0.013291887007653713, 0.0043014949187636375, 0.021106714382767677, -0.04173251613974571, -0.02715819701552391, -0.013625853694975376, -0.04595385864377022, -0.03857986629009247, -0.026810871437191963, 0.011575296521186829, 0.062411751598119736, -0.013746081851422787, 0.011201253160834312, 0.0022709756158292294, 0.028747878968715668, -0.037270717322826385, -0.03986230120062828, 0.04376303404569626, -0.018648717552423477, 0.011528541333973408, -0.03088526800274849, 0.055572107434272766, -0.03163335472345352, 0.000434157089330256, -0.06989261507987976, 0.00549375731498003, 0.050950005650520325, 0.026343317702412605, 0.0023411086294800043, -0.053381286561489105, -0.014948363415896893, 0.04592714086174965, -0.007280480582267046, -0.002955608069896698, 0.019704053178429604, 0.007394029293209314, 0.014427374117076397, 0.009337717667222023, 0.02037198655307293, -0.03224785253405571, -0.03435852378606796, -0.021520834416151047, 0.01669834926724434, -0.0340646356344223, -0.017580023035407066, 0.014026613906025887, 0.019503673538565636, -0.07181626558303833, -0.015282330103218555, -0.017820479348301888, 0.02061244286596775, 0.009304320439696312, -0.024085700511932373, 0.004451780114322901, 0.032915785908699036, -0.005453681107610464, -0.017433077096939087, -0.03545393794775009, 0.005707495845854282, -0.056694239377975464, -0.009384472854435444, 0.003267867024987936, -0.025568513199687004, 0.006816266570240259, 0.038419563323259354, 0.013933103531599045, 0.02898833528161049, 0.04972100630402565, 0.00885680504143238, -0.027385294437408447, 0.0054670399986207485, 0.0003684073453769088, 0.07208343595266342, 0.0344119593501091, -0.026076143607497215, -0.060755275189876556, 0.021013204008340836, -0.024913938716053963, -0.00515979016199708, 0.0026483582332730293, -0.008295740000903606, -0.013018033467233181, -0.021106714382767677, -0.029121922329068184, -0.01806093566119671, 0.011408313177525997, -0.02659713104367256, -0.0012373477220535278, 0.035106610506772995, 0.008963674306869507, -0.031018855050206184, -0.035640958696603775, 0.00634537311270833, -0.011915942654013634, -0.012904484756290913, 0.001846837461926043, 0.05052252858877182, 0.02837383560836315, -0.0008641396416351199, -0.0217345729470253, -0.026810871437191963, -0.0015445973258465528, -0.0031359500717371702, 0.022749831900000572, 0.00289883348159492, 0.020839540287852287, 0.009083902463316917, 0.010132558643817902, -0.0021975028794258833, 0.029282227158546448, 0.0006374595104716718, 0.03085855022072792, -0.03713713213801384, -0.019677335396409035, -0.014053331688046455, -0.01635102368891239, -0.013205055147409439, 0.011515182442963123, -0.008756615221500397, 0.004969428759068251, -0.0009793582139536738, -0.015015156008303165, 0.01596362330019474, 0.009518059901893139, 0.004241380840539932, 0.011101063340902328, 0.016925446689128876, -0.05471715331077576, -0.05249961093068123, 0.005994707811623812, 0.007748034317046404, 0.0007284655002877116, -0.02952268347144127, 0.010099162347614765, 0.007140214554965496, 0.00334968906827271, 0.00894363597035408, -0.01951703242957592, 0.025621948763728142, 0.020959768444299698, -0.023404408246278763, 0.0347592867910862, -0.025274623185396194, -0.025568513199687004, 0.006478959694504738, -0.0037805065512657166, -0.04338899254798889, 0.023431124165654182, 0.00933103822171688, 0.012717463076114655, -0.00981862936168909, -0.045766837894916534, -0.026904381811618805, -0.008269023150205612, -0.03224785253405571, 0.04258747026324272, -0.02523454651236534, 0.0073472741059958935, 0.03759132698178291, -0.020933052524924278, -0.03278220072388649, -0.03136618062853813, -0.0009234187309630215, 0.018942607566714287, -0.003924112301319838, 0.05904536694288254, 0.004752350505441427, 0.040797408670186996, -0.030938703566789627, 0.003439860185608268, 0.014681189320981503, 0.006565791089087725, -0.024419667199254036, 0.010920721106231213, -0.030244052410125732, 0.006816266570240259, 0.004976108204573393, 0.01086728647351265, 0.0026233107782900333, -0.0238051675260067, -0.004775728099048138, 0.03526691347360611, 0.00632199551910162, 0.0027318501379340887, 0.03636232763528824, -0.002207521814852953, -0.0011171195656061172, 0.026837587356567383, -0.0059880283661186695, -0.00204721768386662, 0.0029906744603067636, -0.024299439042806625, -0.00944458693265915, -0.011301442980766296, 0.01815444603562355, 0.018675435334444046, -0.016270872205495834, -0.019864358007907867, 0.003381415968760848, 0.007026665844023228, 0.023284180089831352, -0.015041873790323734, 0.02075938880443573, 0.03604171797633171, -0.016177361831068993, -0.02620973065495491, -0.01762009970843792, 0.05754919350147247, 0.012390175834298134, 0.038953911513090134, 0.0068863993510603905, 0.02487386204302311, -0.014093407429754734, -0.028213532641530037, 0.0012648999691009521, -0.0018601962365210056, -0.027492163702845573, 0.02321738563477993, 0.025982633233070374, 0.04119816794991493, 0.04961413890123367, -0.021066637709736824, -0.02051893249154091, -0.004795765969902277, -0.01529568899422884, 0.010346298106014729, -0.006632584612816572, 0.003563427831977606, 0.012042850255966187, 0.04373631998896599, -0.0010378024308010936, 0.00956481508910656, 0.013004674576222897, 0.03411806747317314, 0.011575296521186829, 0.009310999885201454, -0.010800492949783802, 0.013158299960196018, -0.004959410056471825, 0.016097210347652435, 0.011187894269824028, 0.015202177688479424, -0.0032528385054320097, -0.026931099593639374, 0.042988233268260956, -0.03109900653362274, 0.03379746153950691, -0.015268971212208271, -0.00745414337143302, 0.010586753487586975, -0.00731387734413147, -0.0072537632659077644, -0.01166880689561367, -0.04395005851984024, -0.07363304495811462, -0.032862354069948196, -0.01158197596669197, -0.008182191289961338, -0.01017263438552618, -0.04806452989578247, -0.01628423109650612, 0.03906077891588211, 0.023497918620705605, -0.01892925053834915, -0.024740274995565414, -0.007494219578802586, -0.02611622028052807, 0.019944509491324425, 0.014146842062473297, 0.021654419600963593, 0.010219390504062176, -0.01732620783150196, -0.020131530240178108, -0.014614395797252655, 0.015282330103218555, -0.05129733309149742, 0.009604890830814838, 0.008248984813690186, 0.05247289687395096, -0.04720957577228546, -0.002645018743351102, 0.04317525401711464, 0.0030491186771541834, 0.019236499443650246, 0.030778398737311363, 0.0024563272017985582, -0.01886245608329773, 0.018849097192287445, 0.028453988954424858, 0.011702204123139381, 0.006522375624626875, -0.0377783477306366, 0.011822432279586792, 0.008743256330490112, -0.03548065572977066, 0.04499203339219093, -0.01214304007589817, -0.003473256714642048, 0.028587576001882553, -0.02214869111776352, -0.01679186150431633, 0.017686892300844193, 0.0054670399986207485, -0.056159891188144684, 0.0363088920712471, -0.003262857673689723, 0.011468427255749702, -0.016658274456858635, 0.005530493333935738, 0.014814776368439198, 0.03379746153950691, -0.0058043464086949825, 0.01711246930062771, 0.0016397780273109674, 0.030270768329501152, 0.03270204737782478, 0.002563196700066328, 0.0005080472910776734, -0.020665878430008888, -0.023417765274643898, 0.007741354871541262, 0.007828186266124249, -0.016043774783611298, -0.015562862157821655, 0.005133072845637798, 0.024566613137722015, -0.003546729451045394, 0.014267070218920708, -0.03524019941687584, 0.01922314055263996, -0.006535734049975872, 0.0036335610784590244, 0.02209525741636753, 0.016898730769753456, 0.04886605218052864, -0.006639264058321714, 0.03299593925476074, -0.013358679600059986, 0.002349457936361432, -0.002030519302934408, -0.03224785253405571, 0.010446487925946712, 0.002813671948388219, -0.013746081851422787, -0.017539946362376213, 0.005346811842173338, -0.01110774278640747, 0.003944150172173977, -0.022576170042157173, 0.007153572980314493, -0.006472280248999596, -0.010099162347614765, -0.05089657008647919, 0.0056106457486748695, 0.013879668898880482, 0.01351898442953825, -0.01100087258964777, -0.017900630831718445, 0.026396751403808594, 0.030724963173270226, 0.0344119593501091, -0.004518573638051748, 0.00961157027631998, -0.002501412760466337, -0.015322405844926834, 0.011281405575573444, -0.008716538548469543, 0.03705697879195213, -0.006071520037949085, -0.01079381350427866, -0.043576013296842575, -0.026343317702412605, -0.004251400008797646, 0.025875763967633247, -0.058297280222177505, 0.004020962864160538, 0.015122026205062866, 0.023030364885926247, -0.006335353944450617, 0.005393567029386759, -0.01502851489931345, -0.001993783051148057, 0.021226942539215088, -0.017286131158471107, 0.00664928276091814, 0.005787648260593414, 0.004164568614214659, 0.006198427639901638, -0.023083798587322235, -0.01717926189303398, 0.020719312131404877, -0.026129577308893204, -0.021921593695878983, -0.026704002171754837, 0.021507475525140762, 0.0015003466978669167, 0.04175923392176628, -0.01446745079010725, 0.004077737219631672, -0.010399732738733292, 0.00155628623906523, -0.005841082893311977, 0.02890818379819393, 0.007754713762551546, 0.009083902463316917, -0.0012849380727857351, -0.021106714382767677, -0.00889688078314066, 0.01818116381764412, -0.03521348163485527, 0.02448645979166031, -0.013084826990962029, -0.005316754803061485, -0.012062887661159039, 0.005490417592227459, -0.01611056737601757, 0.0027568975929170847, 0.003646919736638665, 0.019343368709087372, 0.009170733392238617, -0.003214432392269373, -0.001126303686760366, -0.006305296905338764, -0.025247905403375626, 0.006816266570240259, -0.029843291267752647, -0.020184965804219246, -0.010887323878705502, 0.003750449512153864, 0.023497918620705605, -0.019263217225670815, 0.0030975439585745335, -0.013933103531599045, -0.028293684124946594, -0.009310999885201454, -0.024780351668596268, -0.055358368903398514, -0.029148640111088753, 0.019717412069439888, -0.0019820942543447018, -0.047369878739118576, -0.01079381350427866, 0.029308943077921867, -0.0020939731039106846, 0.009230847470462322, -0.0213471706956625, -0.019583825021982193, 0.02197502925992012, -0.03911421447992325, -0.00885680504143238, 0.0012640651548281312, 0.05605302006006241, -0.010032368823885918, -0.0038873758167028427, 0.005597286857664585, -0.010853927582502365, -0.007367311976850033, 0.0015287339920178056, 0.020385345444083214, -0.023230744525790215, 0.0198376402258873, 0.008048605173826218, 0.006291938479989767, -0.0036636178847402334, -0.00981862936168909, -0.03377074375748634, 0.017660174518823624, 0.02981657348573208, 0.0029906744603067636, -0.02606278471648693, 0.019196422770619392, -0.006338693667203188, -0.020679237321019173, 0.005971329752355814, -0.013432152569293976, -0.03195396438241005, 0.002461336785927415, 0.027385294437408447, -0.02129373513162136, 0.0023644864559173584, -0.015736525878310204, -0.09030468016862869, 0.04405692592263222, -0.0036135229747742414, 0.034251656383275986, -0.0022008426021784544, -0.03369059041142464, -0.02250937558710575, 0.003897394984960556, -0.001957046566531062, 0.01599033921957016, 0.053675174713134766, -0.017005600035190582, -0.007694599684327841, 0.04266762360930443, 0.013839592225849628, 0.010025689378380775, -0.007941734977066517, -0.01800750009715557, 0.004007603973150253, -0.008108718320727348, -0.009571494534611702, -0.017219338566064835, 0.04202640801668167, 0.04961413890123367, 0.01159533392637968, -0.0382058247923851, 0.036228738725185394, -0.03628217428922653, 0.006101577077060938, -0.018101012334227562, -0.04173251613974571, -0.02372501604259014, 0.006372090429067612, -0.025995992124080658, -0.040049321949481964, -0.005510455463081598, -0.013038071803748608, -0.006906437687575817, -0.03144633397459984, -0.007153572980314493, 0.006124954670667648, 0.012911164201796055, 0.0017182602314278483, 0.011014231480658054, -0.06577814370393753, 0.022322354838252068, -0.004020962864160538, 0.04507218673825264, 0.005597286857664585, 0.010887323878705502, 0.01812772825360298, 0.01015927642583847, -0.007427426055073738, -0.059152234345674515, 0.02428608015179634, 0.056640803813934326, -0.018408261239528656, -0.01803421787917614, 0.0035266915801912546, 0.02978985570371151, 0.03558752313256264, 0.003316292306408286, -0.011174536310136318, -0.012637311592698097, -0.03735087066888809, -0.03203411400318146, 0.005072958767414093, -0.0033062733709812164, 0.022763190791010857, 0.03411806747317314, -0.02550172060728073, 0.03964856266975403, 0.015349123626947403, -0.0036335610784590244, -0.008442685939371586, -0.0013684297446161509, -0.005533833056688309, -0.007534295320510864, -0.02635667659342289, -0.005103015806525946, 0.005507115740329027, -0.03393104672431946, -0.03334326669573784, 0.011288085021078587, 0.021133432164788246, 0.014614395797252655, -0.006422185339033604, -0.005811025854200125, -0.027679184451699257, 0.03791193291544914, -0.01474798284471035, 0.023765092715620995, -0.01339875627309084, -0.04539279639720917, -0.014961721375584602, 0.017419718205928802, 0.012784256599843502, -0.008369212970137596, 0.003713713027536869, -0.031179159879684448, 0.01159533392637968, -0.004461799282580614, 0.011014231480658054, -0.03724399954080582, -0.0033680573105812073, -0.00319439428858459, 0.03141961619257927, 0.0018034217646345496, -0.01827467419207096, 0.05244617909193039, -0.012904484756290913, -0.03759132698178291, -0.004979447927325964, 0.02706468664109707, -0.02455325424671173, -0.00028762908186763525, -0.006318655796349049, 0.028026510030031204, -0.0041178129613399506, -0.000986872473731637, 0.011488464660942554, 0.02200174517929554, 0.011495144106447697, 0.04565996676683426, -0.004044340457767248, -0.009711760096251965, -0.015976982191205025, -0.0006483134347945452, 0.021427322179079056, -0.03502646088600159, 0.04020962864160538, -0.013311924412846565, -0.017259415239095688, 0.0024847143795341253, 0.009518059901893139, -0.0275990329682827, 0.007006627507507801, -0.027144838124513626, 0.031820375472307205, 0.039995886385440826, 0.00013410861720331013, -0.008128756657242775, 0.020118171349167824, 0.005253301002085209, 0.007153572980314493, -0.010473204776644707, 0.022576170042157173, -0.011608692817389965, -0.015896828845143318, 0.01949031464755535, 0.04146534204483032, 0.015402558259665966, 0.022469298914074898, 0.028587576001882553, -0.02351127751171589, 0.012550479732453823, -0.017700251191854477, -0.014961721375584602, -0.007968452759087086, -0.030537942424416542, 0.017726968973875046, 0.037831783294677734, -0.01541591715067625, 0.01572316698729992, -0.021454039961099625, -0.00539690675213933, -0.040797408670186996, -0.006789549253880978, 0.03387761116027832, -0.010406412184238434, 0.02606278471648693, 0.046488206833601, -0.00013744829630013555, -0.01942352019250393, 0.024299439042806625, 0.01949031464755535, -0.003307943232357502, -0.0013275188393890858, 0.05990032106637955, -0.00868982169777155, -0.01186250802129507, 0.014988439157605171, 0.016778502613306046, 0.03828597813844681, 0.015923546627163887, 0.010012330487370491, 0.006809587124735117, -0.015789959579706192, 0.010145917534828186, -0.016684992238879204, 0.003550069173797965, -0.03825926035642624, -0.011962697841227055, 0.024646764621138573, 0.004000924527645111, -0.006215125788003206, -0.022469298914074898, 0.010306221432983875, -0.009484662674367428, -0.0004247642937116325, -0.030190616846084595, -0.010740378871560097, -0.034786004573106766, -0.013719364069402218, -0.012637311592698097, -0.012490365654230118, -0.02375173382461071, 0.020839540287852287, 0.006539073772728443, -0.03003031201660633, -0.012470328249037266, -0.035373784601688385, 0.010813851840794086, 0.003344679484143853, 0.03008374758064747, -6.491483509307727e-05, 0.020625801756978035, -0.007380670867860317, -0.005637363065034151, -0.0325150266289711, 0.020946409553289413, 0.07630477845668793, -0.014280429109930992, -0.028881466016173363, 0.008803370408713818, -0.019850999116897583, -0.014440733008086681, 0.01708575151860714, -0.00981862936168909, 0.022870060056447983, 0.03243487328290939, 0.002349457936361432, -0.02866772748529911, 0.009264244697988033, -0.033450134098529816, 0.031232593581080437, 0.025154395028948784, 0.002518111141398549, 0.030992137268185616, -0.03574782609939575, -0.004421723075211048, 0.00885680504143238, 0.00430817436426878, -0.008255664259195328, -8.93622654984938e-07, -0.022349072620272636, -0.021039921790361404, 0.034572262316942215, 0.01490828674286604, 0.02713147923350334, 0.021654419600963593, 0.021868159994482994, -0.0313928984105587, -0.03601500019431114, 0.015736525878310204, 0.024593329057097435, -0.02365822158753872, 0.002227559918537736, 0.012243229895830154, 0.036495912820100784, 0.0033597080036997795, -0.006468940991908312, -0.00033104477915912867, 0.010580074973404408, -0.03991573676466942, 0.016217436641454697, 0.01311822421848774, 0.011181214824318886, -0.013866310007870197, -0.006729435175657272, -0.018101012334227562, -0.020532291382551193, 0.009357755072414875, -0.015736525878310204, 0.019330009818077087, -0.027759337797760963, -0.03195396438241005, 0.0015729846199974418, -0.031847093254327774, 0.01039305329322815, 0.03414478525519371, -0.0010127549758180976, -0.022963570430874825, -0.002723500831052661, 0.0028854748234152794, 0.008936956524848938, -0.02200174517929554, -0.003550069173797965, -0.021841442212462425, -0.00634537311270833, 0.026957815513014793, 0.008783332072198391, 0.015335764735937119, -0.005400246474891901, -0.054209522902965546, 0.017753684893250465, -0.024499818682670593, 0.025127677246928215, 0.003583465935662389, 0.01003904826939106, 0.03000359609723091, 0.009270924143493176, -0.009157375432550907, 0.006478959694504738, 0.006612546741962433, 0.003917432855814695, -0.025354774668812752, -0.013111544772982597, 0.033744025975465775, -0.008135436102747917, -0.03166007250547409, 0.014828135259449482, 0.02981657348573208, 0.013218414038419724, -0.023431124165654182, 0.017606740817427635, 0.00372707168571651, -0.003750449512153864, 0.0024746954441070557, 0.01957046613097191, -0.015789959579706192, 0.05057596415281296, -0.02221548557281494, -0.024219287559390068, 0.036469195038080215, -0.02010481432080269, 0.0005460360553115606, 0.029896726831793785, -0.020866258069872856, -0.0009083902696147561, -0.004565328825265169, 0.02538149245083332, 0.0036736370529979467, -0.002833710052073002, -0.0029906744603067636, 0.027492163702845573, 0.009364434517920017, 0.012016132473945618, -0.05428967624902725, -0.006348712835460901, -0.012677387334406376, -0.003374736523255706, -0.024473100900650024, -0.02049221470952034, 0.01747315376996994, 0.026570415124297142, 0.005400246474891901, 0.009464625269174576, 0.045499663800001144, 0.05797667056322098, -0.019450237974524498, 0.022789908573031425, 0.03524019941687584, 0.03246159106492996, 0.008041925728321075, 0.03149976581335068, 0.014454091899096966, 0.015215536579489708, -0.01159533392637968, 0.0035968245938420296, -0.004675537813454866, 0.011248008348047733, 0.014293788000941277, 0.012984637171030045, -0.008476082235574722, -0.012296664528548717, -0.001970405224710703, 0.004749010782688856, -0.0007459988119080663, -0.020559009164571762, 0.007133535109460354, -0.023150593042373657, -0.0013200045796111226, 0.03411806747317314, -0.02224220149219036, -0.03959512710571289, 0.008055283688008785, -0.0245799720287323, 0.004408364184200764, -0.016310948878526688, -0.02635667659342289, 0.00854287575930357, -0.02129373513162136, -0.0006716911448165774, 0.01611056737601757, -0.008950315415859222, 0.010760417208075523, 0.010232748463749886, 0.00991882011294365, -0.016070492565631866, 0.005410265643149614, 0.0003231130831409246, 0.009785233065485954, -0.015095308423042297, -0.03577454388141632, 0.01432050485163927, 0.013619174249470234, -0.002746878657490015, -0.019036119803786278, 0.021721214056015015, -0.01599033921957016, -0.01628423109650612, -0.01584339514374733, -0.01774032786488533, 0.019049476832151413, 0.02282998338341713, 0.01446745079010725, -0.011187894269824028, -0.003603504039347172, -0.01798078417778015, 0.0015253942692652345, -0.00228433427400887, -0.007814827375113964, 0.004411703906953335, 0.007040024269372225, 0.00991882011294365, 0.02280326746404171, -0.020331911742687225, 0.005213224794715643, -0.038392845541238785, -0.011708882637321949, -0.004334891680628061, -0.042213428765535355, 0.002447978127747774, 0.02141396328806877, 0.0029990237671881914, -0.015736525878310204, 0.016604838892817497, 0.00466551911085844, -0.022723114117980003, 0.005310075357556343, -0.018728869035840034, 0.006919796112924814, -0.008055283688008785, -0.02031855285167694, -0.0002629990049172193, 0.008035246282815933, -0.0019219800597056746, 0.0382058247923851, 0.021307094022631645, 0.01142835058271885, -0.009391152299940586, -0.034251656383275986, -0.07128191739320755, -0.008476082235574722, -0.05701484531164169, -0.010566716082394123, 0.020305193960666656, -0.03831269592046738, -0.01436058059334755, 0.006358731538057327, -0.0066526224836707115, 0.027171555906534195, 0.03906077891588211, 0.027705902233719826, 0.019997943192720413, -0.006712736561894417, -0.018234597519040108, -0.028534140437841415, -0.0015596258454024792, -0.013999897055327892, -0.03377074375748634, -0.0038172428030520678, -0.013746081851422787, 0.024980731308460236, -0.013986538164317608, 0.043816469609737396, -0.0053835478611290455, -0.0257021002471447, 0.006776190362870693, -0.029976878315210342, -0.015228895470499992, -0.013812875375151634, -0.014574320055544376, -0.013278528116643429, -0.0036302213557064533, 0.04061038792133331, -0.06016749516129494, -0.010907362215220928, -0.005881159100681543, 0.02620973065495491, -0.021160149946808815, -0.033182960003614426, -0.03109900653362274, -0.013038071803748608, 0.0031476388685405254, -0.015162101946771145, -0.040289778262376785, -0.0035968245938420296, 0.008355854079127312, -0.02197502925992012, -0.021694496273994446, 0.0026066123973578215, -0.02558187209069729, -0.006632584612816572, 0.015776600688695908, -0.023791808634996414, 0.01194933895021677, 0.005747572053223848, 0.00937111396342516, 0.008489441126585007, -0.007487540133297443, 0.007547654211521149, 0.026490261778235435, -0.00977187417447567, -0.013158299960196018, -0.00913733709603548, -0.04210655763745308, 0.04117145016789436, 0.01474798284471035, -0.006726095452904701, 0.017018958926200867, -0.009504701010882854, -0.017139187082648277, 0.0070199863985180855, 0.030644811689853668, 0.021066637709736824, -0.009197451174259186, -0.004201305098831654, -0.016270872205495834, 0.012269947677850723, 0.005724194459617138, 0.013579098507761955, -0.0340646356344223, -0.030751680955290794, -0.010760417208075523, 0.047396596521139145, -0.02319066785275936, 0.056106455624103546, 0.009050506167113781, -0.012049529701471329, 0.018675435334444046, -0.01036633551120758, -0.006101577077060938, -0.017139187082648277, -0.009050506167113781, 0.023497918620705605, 0.02866772748529911, -0.0024145813658833504, -0.008776652626693249, 0.01711246930062771, 0.03556080535054207, -0.008415968157351017, 0.022282278165221214, 0.00764784449711442, -0.05022863671183586, -0.0017716949805617332, 0.004174587316811085, -0.05594615265727043, 0.004238041117787361, -0.014120125211775303, 0.007547654211521149, 0.05236602574586868, -0.02046549692749977, 0.0014460771344602108, -0.006873040925711393, 0.018461694940924644, -0.050148483365774155, 0.03377074375748634, -0.011254687793552876, -0.04798438027501106, 0.004845861345529556, 0.03801880404353142, 0.02645018696784973, 0.044671427458524704, 0.013138261623680592, 0.043335556983947754, 0.04835842177271843, 0.0238051675260067, -0.026009349152445793, -0.0013692646753042936, -0.04061038792133331, -0.014454091899096966, 0.02297692932188511, -0.0014869880396872759, -0.0007209512405097485, 0.0013133252505213022, 0.01391974464058876, -0.013305244967341423, -0.010199352167546749, 0.0529538094997406, -0.003104223171249032, 0.0052399421110749245, 0.023858603090047836, -0.02309715747833252, -0.0347592867910862, -0.025154395028948784, 0.0015228894772008061, 0.013271848671138287, 0.028213532641530037, -0.0031593278981745243, 0.011835790239274502, 0.0004900965723209083, 0.001551276771351695, -0.02706468664109707, 0.011541899293661118, -0.05648050084710121, -0.05057596415281296, -0.05073626711964607, -0.03628217428922653, -0.004889276809990406, 0.006662641651928425, -0.01264399103820324, 0.029041770845651627, -0.015455992892384529, 0.03366387262940407, 0.012590555474162102, 0.008215588517487049, -0.01990443281829357, -0.015041873790323734]
# 1536

docs = [document.page_content for document in documents]
vects = embedding_model.embed_documents(docs)

print(len(vects))		# 35
print(len(vects[0]))	# 1536

 

  • Vector Store
!pip install faiss-cpu
from langchain.vectorstores import FAISS

text_embeddings = list(zip(docs, vects))
vector_store = FAISS.from_embeddings(text_embeddings, embedding_model)
# vector_store = FAISS.from_documents(documents, embedding_model)

vector_store.save_local('./db/faiss')	# 인덱스 파일이 저장됨

vector_db = FAISS.load_local(			# 저장된 FAISS 모델 불러오기
    './db/faiss',
    embedding_model,
    allow_dangerous_deserialization=True
)
# vector_db

vector_store.similarity_search('Tom Sawyer', k=3)	# k 기본값은 4
"""
[Document(id='22a42251-5157-4f30-924f-3d093249e70a', metadata={}, page_content='Introduction \n \n \nOne Saturday afternoon Tom wanted to have an adventure                    \nbecause he didn’t want to think about Injun Joe. He went \nto Huck and said, “I’m going to  look for treasure. Do you \nwant to come with me?” \n \nTom Sawyer loves adventures. He has a lot of adventures \nat home, at school, and with his friends. He has one \nadventure in a cave. But why is he there? What does he \nsee in the cave? And why is he afraid? \n \nMark Twain (1835-1910) is a famous American writer. \nHis name was Samuel Clemens. Young Samuel lived in \nHannibal, Missouri, a small town on the Mississippi River. \nHe loved the river and he liked watching the big boats                  \non it. \nSamuel loved adventures. He worked on boats on the \nMississippi River for two years. Then he went to Nevada. \nHe looked for treasure, but he didn’t find it. He worked for \na newspaper there. His stories were in the name of Mark \nTwain, and people loved them. \nLater, Samuel lived in New York. His book The \nAdventures of Tom Sawyer (1876) is about a young boy in \na small town in the 1800s. Huck Finn is his friend. The \nAdventures of Huckleberry Finn (1884) is about Huck’s \nadventures. These two books are very famous. \nToday, many people visit Hannibal because they want to \nsee Mark Twain’s home and the Mark Twain Cave, the \ncave in The Adventures of Tom Sawyer. \n \niii'),
 Document(id='6823a55c-ae6c-43f8-b413-519de941ac66', metadata={}, page_content='Tom Sawyer loves adventures. He has them at home,                \nat school, and with his friends—Huck Finn and Joe                \nHarper. Tom has one adventure in a graveyard, and one                \nin a cave.  Who does  he  see there,  and why is he afraid? \nPenguin Readers are simplified texts designed in association with Longman, \nthe world famous educational publi sher, to provide a step-by-step  \napproach to this joys of reading for pleasure. Each book has an \nintroduction and extensive activity material. They are published              \nat   seven  levels  from  Easystarts  (200 words) to Advanced (3000 words). \nSeries Editors: Andy Hopkins and Jocelyn Potter \n \n \nwww.penguinreaders.com\nCover photograph © Frank Hopkinson 2000'),
 Document(id='14f9896d-ed8b-4129-88ab-032d89ca80d0', metadata={}, page_content='“I’m late because I talked to Huck Finn,” Tom said.              \nThen the teacher was very angry. “Sit with the girls,” he \nsaid to Tom. \nTom sat near the beautiful new girl. He was happy. He \nlooked at her. \n“What’s your name?” he asked. \n“Becky,” she answered. \nTom smiled and said, “My name’s Tom.” \nThe teacher was angry again. “Tom Sawyer, stop \ntalking! Go to your place now,” he said. Tom went to his \nplace. \nAt twelve o’clock Tom and Becky didn’t go home. They \nstayed in the school yard and talked. Tom said, “I love \nyou. Do you love me?” \n“Yes,” Becky answered. \n“Good,” Tom said. “Then you’re going to walk to \nschool with me every day. Amy always walked with me.” \n“Amy!” Becky said angrily. “Do you love her?” \n“No,” Tom answered. “I love you now. Do you want to \nwalk with me?” \nBut Becky was angry with Tom. She walked away and \ndidn’t answer. Tom was unhappy. He didn’t go to school \nin the afternoon. \nThat night Tom went to bed at nine o’clock, but he \ndidn’t sleep. At eleven o’clock he went out his bedroom \nwindow to the yard. Huck was there. They walked to the \ngraveyard. They stopped behind some big trees and talked \nquietly. \nSuddenly, there was a noise. Three men came into the \ngraveyard—the doctor, Muff Potter, and Injun Joe. Injun \nJoe and the doctor talked angrily. Then Injun Joe \n \n4')]
"""

 

  • Retriever
retriever = vector_store.as_retriever()
print(retriever)

retriever.batch(['인디언 조'])		# batch로 유사도 검색
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model='gpt-4o-mini',
    temperature=0
)

retrieval_qa = RetrievalQA.from_chain_type(
    llm=model,
    retriever=retriever,
    chain_type='stuff'
)

retrieval_qa.invoke('인디언 조가 누구를 죽였나요?')
# {'query': '인디언 조가 누구를 죽였나요?', 'result': '인디언 조는 의사를 죽였습니다.'}

retrieval_qa.invoke('인디언 조가 의사를 어떻게 죽였나요?')
# {'query': '인디언 조가 의사를 어떻게 죽였나요?', 'result': '인디언 조는 의사를 칼로 죽였습니다.'}

 

 

실습 (LangChain - LangSmith Tracing)

 

from dotenv import load_dotenv, find_dotenv
load_dotenv()

find_dotenv()
# 'c:\\skn_17\\llm\\04_langchain\\.env'

 

  • Logging 확인
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI

model = ChatOpenAI(model='gpt-4o-mini')

messages = [
    SystemMessage(content='다음 문장을 영어로 번역해'),
    HumanMessage(content='안녕, 이제 곧 목요일이 끝나네.')
]

response = model.invoke(messages)
print(response.content)
# Hello, Thursday is about to end soon.