LLM 에이전트 오케스트레이션은 AI 시스템 내에서 복잡한 작업을 수행하기 위해 대규모 언어 모델(LLM)과 다양한 도구, API 또는 프로세스 간의 상호 작용을 관리하고 조정하는 프로세스를 의미합니다. 여기에는 인공 지능으로 구동되는 AI 에이전트가 중앙 의사 결정권자 또는 추론 엔진 역할을 하여 외부 시스템의 입력, 컨텍스트 및 아웃풋을 기반으로 행동을 오케스트레이트하는 워크플로를 구성하는 것이 포함됩니다. LLM은 오케스트레이션 프레임워크를 사용하여 API, 데이터베이스 및 기타 AI 애플리케이션과 원활하게 통합되어 챗봇 및 자동화 도구와 같은 기능을 사용할 수 있습니다. 오픈 소스 에이전트 프레임워크는 이러한 시스템의 적응성을 더욱 향상시켜 LLM가 실제 시나리오에서 더 효과적으로 작동할 수 있도록 합니다.
많은 사람이 LLM 오케스트레이션과 LLM 에이전트 오케스트레이션의 차이점을 오해하고 있습니다. 다음 그림은 주요 차이점을 보여줍니다.
LLM 오케스트레이션과 LLM 에이전트 오케스트레이션의 주요 차이점
이 튜토리얼에서는 IBM® Granite 모델과 LangChain을 사용하여 대규모 언어 모델(LLM)로 구동되는 자율 에이전트를 구축하는 방법을 알아봅니다. 에이전트가 메모리, 계획, 행동과 같은 주요 구성 요소를 활용하여 지능형 작업을 수행하는 방법을 살펴보겠습니다. 또한 책의 텍스트를 처리하고, 쿼리에 동적으로 답변하며, BLEU, 정밀도, 재현율 및 F1 점수와 같은 정확도 지표를 사용하여 성능을 평가하는 실용적인 시스템을 구현합니다.
LLM 기반 자율 에이전트를 위한 프레임워크
그림 1에 제시된 프레임워크는 대규모 언어 모델(LLM) 기반 자율 에이전트를 위한 통합적인 설계를 제공하며, 프로필, 메모리, 계획, 행동과 같은 주요 구성 요소 간의 상호 작용을 강조합니다. 각 구성 요소는 추론, 의사 결정, 동적 환경과의 상호 작용이 가능한 자율 에이전트를 구축하는 데 중요한 단계를 나타냅니다.1
LLM 기반 자율 에이전트를 위한 프레임워크
1. 프로필: 에이전트의 정체성 정의
프로필은 인구 통계, 성격 특성, 사회적 맥락과 같은 정보를 임베딩하여 에이전트에게 정체성을 제공합니다. 이 프로세스를 통해 에이전트는 개인화된 방식으로 상호 작용할 수 있습니다. 프로필은 수동으로 제작하거나 IBM Granite 모델 또는 OpenAI의 GPT(생성형 사전 학습 트랜스포머)와 같은 생성형 AI 모델을 통해 생성하거나 작업 요구 사항을 충족하도록 특정 데이터 세트와 연계할 수 있습니다. 프롬프트 엔지니어링을 활용하여 프로필을 동적으로 세분화하여 대응을 최적화할 수 있습니다. 또한, 다중 에이전트 오케스트레이션 내에서 프로필은 역할과 행동을 정의하는 데 도움이 되며, AI 알고리즘과 의사 결정 시스템 전반에서 원활한 조정을 보장합니다.
2. 메모리: 컨텍스트 저장 및 사용
메모리는 에이전트가 과거 상호 작용을 유지하고 검색하여 상황에 맞는 응답을 할 수 있도록 합니다. 통합형(모든 데이터를 한 곳에 통합) 또는 하이브리드형(정형 및 비정형)으로 구현될 수 있습니다. 에이전트는 읽기, 쓰기, 성찰을 포함한 작업을 통해 경험에서 학습하고 일관되고 정보에 기반한 아웃풋을 제공할 수 있습니다. 잘 구조화된 메모리는 특정 작업을 위해 설계된 특수 에이전트를 포함한 다양한 에이전트가 관련 데이터를 효율적으로 공유하고 검색할 수 있도록 하여 다중 에이전트 오케스트레이션을 향상시킵니다. AutoGen 및 Crew AI와 같은 프레임워크에서 메모리는 협업 에이전트의 에코시스템 내에서 연속성을 유지하고 원활한 조정과 최적화된 작업 실행을 보장하는 데 중요한 역할을 합니다.
3. 계획: 행동 전략 수립
에이전트는 계획 구성 요소를 통해 목표를 달성하기 위한 전략을 고안할 수 있습니다. 사전 정의된 단계를 따르거나 환경, 인간 또는 LLM 자체의 피드백을 기반으로 동적으로 적응할 수 있습니다. AI 알고리즘을 통합하고 지식 기반을 활용함으로써 계획을 최적화하여 추론 효율성과 문제 해결 정확도를 향상시킬 수 있습니다. LLM 애플리케이션에서 계획은 Natural Language Understanding과 의사 결정 프로세스가 에이전트의 목표에 부합하도록 하는 데 중요한 역할을 합니다. 또한 검색 증강 기술은 에이전트가 관련 정보에 동적으로 액세스하는 능력을 향상시켜 응답 정확도를 높입니다. 이러한 유연성은 에이전트가 변화하는 시나리오, 특히 다양한 에이전트가 대규모의 다양한 작업을 처리하기 위한 확장성을 유지하면서 복잡한 목표를 달성하기 위해 계획을 조정하는 다중 에이전트 오케스트레이션에서 효과적으로 유지될 수 있도록 합니다.
4. 행동: 의사 결정 실행
행동은 작업 완료, 정보 수집, 의사소통 등 에이전트가 세상과 상호 작용하는 방식입니다. 메모리와 계획을 사용하여 실행을 안내하고, 필요할 때 도구를 사용하며, 결과에 따라 내부 상태를 조정하여 지속적인 개선을 이루어냅니다. 행동 실행 알고리즘을 최적화하면 특히 실시간 의사 결정을 위해 GPT 기반 추론 모델과 생성형 AI 기술을 통합할 때 효율성이 보장됩니다.
이러한 구성 요소를 결합함으로써 프레임워크는 LLM을 자율적으로 추론, 학습 및 작업을 수행할 수 있는 적응 가능한 에이전트로 변환합니다. 이 모듈식 설계는 고객 서비스, 연구 지원, 창의적인 문제 해결 등의 애플리케이션에 적합합니다.
사용 사례: 쿼리가 가능한 지식 에이전트 구축
이 튜토리얼에서는 (책과 같은) 대규모 텍스트 문서를 처리하고 사용자 쿼리에 정확하게 응답하도록 설계된 쿼리 가능한 지식 에이전트를 만드는 방법을 보여 줍니다. IBM Granite 모델과 LangChain을 사용하여 LLM 기반 자율 에이전트를 위한 프레임워크에서 제시된 원칙에 따라 에이전트가 구축되었습니다. 프레임워크의 구성 요소는 에이전트의 워크플로와 원활하게 조정되어 적응성과 지능적인 응답을 보장합니다.
프레임워크가 이 사용 사례에 어떻게 적용되는지 알아보겠습니다.
프레임워크 애플리케이션
프로필: 에이전트는 요약, 질문 답변 및 추론 작업에 중점을 둔 '지식 어시스턴트' 프로필로 설계되었습니다. 컨텍스트는 특정 문서(예: 셜록 홈즈의 모험)를 처리하도록 개인화되어 있습니다.
메모리: 에이전트는 책의 일부를 FAISS 벡터 스토어에 임베딩하여 하이브리드 메모리를 사용합니다. 이 기능을 사용하면 쿼리 중에 관련 컨텍스트를 동적으로 검색할 수 있습니다. 읽기(검색) 및 쓰기(임베딩 업데이트)와 같은 메모리 작업을 통해 에이전트는 시간이 지남에 따라 새로운 쿼리에 적응할 수 있습니다.
계획: 쿼리 해결에는 단일 경로 추론이 포함됩니다. 에이전트는 관련 텍스트 청크를 검색하고, IBM Granite LLM을 사용하여 답변을 생성하며, 아웃풋의 정확성을 평가합니다. 피드백 없이 계획하면 단순성이 보장되며, 시스템의 모듈성을 통해 피드백 루프를 향후 반복에 통합할 수 있습니다.
행동: 에이전트는 메모리 검색과 LLM 처리를 통합하여 쿼리 해결을 수행합니다. 답변 생성, 정확도 지표(BLEU, 정밀도, 재현율 및 F1 점수) 계산, 사용자 해석을 위한 결과 시각화와 같은 작업을 완료합니다. 이러한 아웃풋은 에이전트가 추론과 계획을 기반으로 지능적으로 행동하는 능력을 반영합니다.
이 단계에서는 이 튜토리얼의 코드를 복사할 수 있는 Notebook 환경이 열립니다. 또는 이 노트북을 로컬 시스템에 다운로드하여 watsonx.ai 프로젝트에 에셋으로 업로드할 수 있습니다. 더 많은 Granite 튜토리얼을 보려면 IBM Granite 커뮤니티를 확인하세요. 이 튜토리얼은 GitHub에서도 보실 수 있습니다.
LangChain 프레임워크로 작업하고 IBM® WatsonxLLM을 통합하려면 몇 가지 필수 라이브러리를 설치해야 합니다. 필요한 패키지를 설치하는 것부터 시작해 보겠습니다.
참고: 이전 버전의pip
을 사용하는 경우pip install --upgrade pip
명령어를 사용하여 최신 패키지를 쉽게 설치하기 위해 업그레이드할 수 있습니다. 이 패키지는 이전 버전과 호환되지 않을 수 있습니다. 그러나 이미 최신 버전을 사용하고 있거나 최근에 패키지를 업그레이드한 경우 이 명령어를 건너뛸 수 있습니다.
faiss-cpu
효율적인 유사성 검색을 위한 것으로, 벡터 인덱스를 만들고 쿼리하는 데 사용됩니다.
pandas
데이터 조작 및 분석을 위한 것입니다.
sentence-transformers
시맨틱 검색을 위한 임베딩을 생성하는 것입니다.
langchain-ibm
IBM WatsonxLLM(이 튜토리얼에서는 Granite-3-8b-instruct)을 LangChain과 통합하는 것입니다.
이 단계를 통해 사용자 환경이 향후 작업을 수행할 준비가 되었는지 확인할 수 있습니다.
4단계. 필요한 라이브러리 가져오기
이제 필요한 라이브러리를 설치했으므로 이 튜토리얼에 필요한 모듈을 가져와 보겠습니다.
import os
from langchain_ibm import WatsonxLLM
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
import pandas as pd
import getpass
앞의 코드 셀에서
os
운영 체제와 상호 작용하는 방법(예: 환경 변수 액세스)을 제공합니다.
langchain_ibm.WatsonxLLM
LangChain 프레임워크 내에서 IBM® Watson Granite LLM을 원활하게 사용할 수 있도록 합니다.
langchain.embeddings.HuggingFaceEmbeddings
시맨틱 검색에 필수적인 HuggingFace 모델을 사용하여 텍스트에 대한 임베딩을 생성합니다.
langchain.vectorstores.FAISS
효율적인 벡터 스토리지 및 유사성 검색을 위한 라이브러리로, 벡터 인덱스를 구축하고 쿼리할 수 있도록 합니다.
RecursiveCharacterTextSplitter
큰 텍스트 블록을 더 작은 덩어리로 분할하는 데 도움이 되며, 이는 문서를 효율적으로 처리하는 데 중요합니다.
pandas
데이터 분석 및 조작을 위한 강력한 라이브러리로, 여기에서는 표 형식 데이터를 처리하는 데 사용됩니다.
getpass
API 키와 같은 민감한 입력을 화면에 표시하지 않고 안전하게 캡처하는 방법입니다.
이 단계에서는 텍스트를 처리하고, 임베딩을 생성하고, 임베딩을 벡터 데이터베이스에 저장하고, IBM의 WatsonxLLM과 상호 작용하는 데 필요한 모든 도구와 모듈을 설정합니다.
5단계. 자격 증명 설정
이 코드는 IBM® Watson Machine Learning(WML) API에 액세스하기 위한 자격 증명을 설정하고 프로젝트 ID가 올바르게 구성되었는지 확인합니다.
딕셔너리자격 증명
이WML service URL
및API 키
과 함께 생성됩니다. API 키는 민감한 정보 노출을 방지하기 위해 `getpass.getpass` 를 사용하여 안전하게 수집됩니다.
코드는 환경 변수에서 PROJECT_ID
를 가져오려고 시도하며 os.environ
을 사용합니다. PROJECT_ID
를 찾을 수 없는 경우 사용자에게 수동으로 입력하라는 프롬프트가 표시됩니다.
# Set up credentials
credentials = {
"url": "https://us-south.ml.cloud.ibm.com", # Replace with the correct region if needed
"apikey": getpass.getpass("Please enter your WML API key (hit enter): ")
}
# Set up project_id
try:
project_id = os.environ["PROJECT_ID"]
except KeyError:
project_id = input("Please enter your project_id (hit enter): ")
6단계. 대규모 언어 모델 초기화
이 코드는 IBM WatsonxLLM을 애플리케이션에서 사용할 수 있도록 초기화합니다.
이 코드는 WatsonxLLM
를 생성하며 명령어 기반 생성형 AI 작업을 위해 설계된ibm/granite-3-8b-instruct
모델을 사용해 생성됩니다.
이러한URL
,api 키
및project_id
등 이전에 설정된 자격 증명의 값이 전달되어 IBM WatsonxLLM 서비스를 인증 및 연결합니다.
각 응답에서max_new_tokens
매개 변수를 구성하여 모델에서 생성된 토큰 수(이 경우 150개 토큰)를 제한합니다.
이 단계는 WatsonxLLM이 워크플로에서 응답을 생성하도록 준비합니다.
# Initialize the IBM Granite LLM
llm = WatsonxLLM(
model_id="ibm/granite-3-8b-instruct",
url=credentials["url"],
apikey=credentials["apikey"],
project_id=project_id,
params={
"max_new_tokens": 150
}
)
7단계. 파일에서 텍스트를 추출하는 함수 정의
문서의 텍스트를 처리하려면 내용을 읽고 추출할 수 있는 함수가 필요합니다. 다음 함수는 일반 텍스트 파일을 처리하도록 설계되었습니다.
def extract_text_from_txt(file_path):
"""Extracts text from a plain text file."""
with open(file_path, "r", encoding="utf-8") as file:
text = file.read()
return text
이extract_text_from_txt
함수는 일반 텍스트 파일의 내용을 읽고 추출하도록 설계되었습니다. 파일 경로를 인수로 받아들이고UTF-8 encoding
을 사용하여 읽기 모드에서 파일을 열어 특수 문자가 올바르게 처리되도록 합니다.
파일의 전체 내용이텍스트
라는 이름의 변수로 일혀진 후 반환됩니다. 이 함수는 문서에서 원시 텍스트를 추출하여 입력 데이터를 준비하는 데 중요한 역할을 하며, 청킹, 임베딩, 쿼리와 같은 후속 작업을 준비합니다. 모든 일반 텍스트 파일의 텍스트 데이터를 처리하는 간단하고 효율적인 방법을 제공합니다.
이 함수를 사용하면 입력 파일(셜록 홈즈의 모험)을 처리하고 텍스트 청킹 및 임베딩과 같은 추가 작업을 위해 내용을 추출할 수 있습니다. 이를 통해 원시 텍스트를 분석에 쉽게 사용할 수 있습니다.
8단계. 텍스트를 청크로 분할
대량의 텍스트 블록을 효율적으로 처리하고 인덱싱하려면 텍스트를 더 작고 관리 가능한 청크로 나누어야 합니다. 이 작업을 처리하는 함수는 다음과 같습니다.
def split_text_into_chunks(text, chunk_size=500, chunk_overlap=50):
"""Splits text into smaller chunks for indexing."""
splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
return splitter.split_text(text)
이러한split_text_into_chunks
함수는 효율적인 처리 및 인덱싱을 위해 큰 텍스트 블록을 더 작고 관리 가능한 청크로 나누도록 설계되었습니다. 원시 텍스트를 다음의 선택적 매개변수 두 개와 함께 입력으로 사용합니다.chunk_size
는 각 청크의 최대 크기(기본값은 500자)를 정의하고,chunk_overlap
은 연속 청크 사이에 겹치는 문자 수(기본값은 50)를 지정합니다.
이 함수는 청크 전체에서 컨텍스트 연속성을 보장합니다. 이 기능은RecursiveCharacterTextSplitter
를 사용하며(LangChain
에서) 컨텍스트를 유지하면서 텍스트를 지능적으로 분할합니다. 이 함수는 더 작은 텍스트 청크 목록을 반환하여 임베딩 및 인덱싱과 같은 추가 작업을 위해 입력을 준비합니다.
언어 모델에는 토큰 제한이 있고 긴 텍스트를 직접 처리할 수 없는 경우가 많기 때문에 대용량 문서로 작업할 때 필수적입니다.
9단계: 벡터 인덱스 생성
효율적인 시맨틱 검색을 위해 텍스트 청크를 벡터 임베딩으로 변환하고 검색 가능한 인덱스에 저장해야 합니다. 이 단계에서는 FAISS 및 HuggingFace 임베딩을 사용하여 벡터 인덱스를 생성하고 쿼리를 기반으로 관련 정보를 검색하기 위한 기반을 형성합니다.
def create_vector_index(chunks):
"""Creates a FAISS vector index from text chunks."""
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
vector_store = FAISS.from_texts(chunks, embeddings)
return vector_store
이러한create_vector_index
함수는 이전 단계에서 생성된 텍스트 청크에서FAISS vector
인덱스를 생성합니다. 이 함수는 임베딩을 사용하여 각 청크를 고차원 벡터 공간에 매핑하여 시맨틱 검색을 가능하게 하는 데 필수적입니다.
이 함수는 먼저 HuggingFaceEmbeddings 모델sentence-transformers/all-MiniLM-L6-v2
을 초기화하며, 이는 텍스트 청크에 대한 벡터 임베딩을 생성합니다. 이러한 임베딩은 각 청크의 의미론적 의미를 캡처합니다.
그런 다음 함수는FAISS
를 사용하여 이러한 임베딩을 인덱싱하여 벡터 스토어를 생성함으로써, 나중에 효율적인 유사성 검색을 가능하게 합니다.
결과로 생성된 벡터 스토어가 반환되고 사용자 쿼리를 기반으로 관련 청크를 찾는 데 사용되어 에이전트의 검색 및 검색 프로세스의 중추를 형성합니다.
10단계. Granite로 벡터 인덱스 쿼리
이 단계에는 벡터 인덱스를 쿼리하여 관련 정보를 검색하고 IBM의 Granite을 사용하여 세분화된 응답을 생성하는 작업이 포함됩니다. 이 기능은 유사성 검색과 LLM 추론을 통합함으로써 역동적이고 지능적인 쿼리 해결 프로세스를 제공합니다.
def query_index_with_granite_dynamic(vector_store, query, llm):
"""Searches the vector index, uses Granite to refine the response, and returns all components."""
# Perform similarity search
print("\n> Entering new AgentExecutor chain...")
thought = f"The query '{query}' requires context from the book to provide an accurate response."
print(f" Thought: {thought}")
action = "Search FAISS Vector Store"
print(f" Action: {action}")
action_input = query
print(f" Action Input: \"{action_input}\"")
# Retrieve context
results = vector_store.similarity_search(query, k=3)
observation = "\n".join([result.page_content for result in results])
print(f" Observation:\n{observation}\n")
# Generate response with Granite
prompt = f"Context:\n{observation}\n\nQuestion: {query}\nAnswer:"
print(f" Thought: Combining retrieved context with the query to generate a detailed answer.")
final_answer = llm(prompt)
print(f" Final Answer: {final_answer.strip()}")
print("\n> Finished chain.")
# Return all components as a dictionary
return {
"Thought": thought,
"Action": action,
"Action Input": action_input,
"Observation": observation,
"Final Answer": final_answer.strip()
}
이러한query_index_with_granite_dynamic
이 함수는 세 가지 입력을 받으며, 첫 번째는 벡터 스토어(vector_store
), 두 번째는 사용자의 쿼리(query
), 세 번째는 Granite LLM 인스턴스(LLM
)를 강조 표시하여 에이전트의 성능을 직관적으로 분석할 수 있습니다.
먼저 벡터 인덱스에 대한 유사성 검색을 수행하여 가장 관련성이 높은 텍스트 청크를 검색합니다. 이러한 청크는observation
로 지칭되며, 단일 컨텍스트 블록으로 결합됩니다.
그런 다음 함수는 쿼리와 검색된 컨텍스트를 결합하여 프롬프트를 구성합니다. 이 프롬프트는Granite LLM
으로 전달되고, 상세하고 맥락에 맞는 정확한 응답을 생성합니다(final_answer
)를 강조 표시하여 에이전트의 성능을 직관적으로 분석할 수 있습니다.
프로세스 전반에 걸쳐 에이전트의thought
,조치
및action input
등의 중단 간계가 투명성을 위해 인쇄됩니다.
마지막으로 이 함수는 생각 과정, 수행한 행동, 검색된 관찰, 최종 답변을 포함한 모든 구성 요소가 포함된 딕셔너리를 반환합니다.
이 단계는 LLM의 추론 기능을 사용하여 원시 데이터 검색을 실행 가능하고 의미 있는 인사이트로 변환하는 데 매우 중요합니다.
11단계. 쿼리 결과에 대한 'DataFrame' 생성
이 단계는 여러 쿼리를 동적으로 처리하고, 관련 정보를 검색하고, 분석을 위해 결과를 구조화된 형식으로 저장합니다. 이 함수는 쿼리, 데이터 구조화, 내보내기 기능을 통합합니다.
def dynamic_output_to_dataframe(vector_store, queries, llm, csv_filename="output.csv"):
"""Generates a DataFrame dynamically for multiple queries and saves it as a CSV file."""
# List to store all query outputs
output_data = []
# Process each query
for query in queries:
# Capture the output dynamically
output = query_index_with_granite_dynamic(vector_store, query, llm)
output_data.append(output)
# Convert the list of dictionaries into a DataFrame
df = pd.DataFrame(output_data)
# Display the DataFrame
print("\nFinal DataFrame:")
print(df)
# Save the DataFrame as a CSV file
df.to_csv(csv_filename, index=False)
print(f"\nOutput saved to {csv_filename}")
이러한dynamic_output_to_dataframe
함수가 받는 네 가지 입력값: 벡터 스토어(vector_store
), 쿼리 목록(queries
), Granite LLM 인스턴스(LLM
) 및 선택적 CSV 파일 이름(csv_filename
, 기본값은output.csv
)를 강조 표시하여 에이전트의 성능을 직관적으로 분석할 수 있습니다.
각 쿼리에 대해query_index_with_granite_dynamic
함수를 사용하여 관련 컨텍스트를 검색하고 LLM을 사용하여 응답을 생성합니다. 그런 다음Thought
,Observation
및Final Answer
등의 중간 구성 요소가 포함된 결과가 목록에 저장됩니다.
모든 쿼리가 처리되면 결과 목록이 pandas DataFrame으로 변환됩니다. 이 표 형식을 사용하면 쿼리 결과를 쉽게 분석하고 시각화할 수 있습니다. DataFrame은 검토를 위해 인쇄되고 나중에 사용할 수 있도록 CSV 파일로 저장됩니다.
이 단계는 아웃풋을 사용자 친화적인 형식으로 구성하여 정확도 평가 및 시각화와 같은 다운스트림 작업을 가능하게 하는 데 필수적입니다.
12단계: 기본 워크플로 실행
이 단계는 이전의 모든 단계를 단일 워크플로로 결합하여 텍스트 파일을 처리하고, 사용자 쿼리에 응답하고, 결과를 구조화된 형식으로 저장합니다.main_workflow function
은 튜토리얼의 중앙 오케스트레이터 역할을 합니다.
def main_workflow():
# Replace with your text file
file_path = "aosh.txt"
# Extract text from the text file
text = extract_text_from_txt(file_path)
# Split the text into chunks
chunks = split_text_into_chunks(text)
# Create a vector index
vector_store = create_vector_index(chunks)
# Define queries
queries = [
"What is the plot of 'A Scandal in Bohemia'?",
"Who is Dr. Watson, and what role does he play in the stories?",
"Describe the relationship between Sherlock Holmes and Irene Adler.",
"What methods does Sherlock Holmes use to solve cases?"
]
# Generate and save output dynamically
dynamic_output_to_dataframe(vector_store, queries, llm)
이 워크플로가 어떻게 실행되는지 알아보겠습니다.
텍스트 파일 입력: file_path
변수는 처리할 텍스트 파일을 지정합니다. 이 튜토리얼에서 입력 파일은"aosh.txt"
이며, 셜록 홈즈의 모험의 텍스트가 포함되어 있습니다.
텍스트 추출:extract_text_from_txt
함수는 입력 텍스트 파일의 내용을 읽고 추출하기 위해 호출됩니다.
텍스트 청킹: 임베딩 및 인덱싱을 용이하게 하기 위해 추출된 텍스트를split_text_into_chunks
함수를 통해 더 작은 청크로 나눕니다.
벡터 인덱스 생성: 텍스트 청크는 임베딩으로 변환되어FAISS vector
인덱스에 저장되며, 이는create_vector_index
함수를 사용해 이루어집니다.
쿼리 정의: 텍스트에서 특정 정보를 검색하도록 설계된 샘플 쿼리 목록이 제공됩니다. 이러한 쿼리는 에이전트가 답변합니다.
프로세스 쿼리:dynamic_output_to_dataframe
함수는 벡터 인덱스와 IBM Granite LLM을 사용하여 쿼리를 처리합니다. 관련 컨텍스트를 검색하고, 답변을 생성하고, 추가 분석을 위해 결과를 CSV 파일로 저장합니다.
이 단계에서는 튜토리얼의 모든 구성 요소를 일관된 워크플로로 통합합니다. 텍스트 추출부터 쿼리 해결까지의 프로세스를 자동화하여 에이전트의 능력을 테스트하고 구조화된 형식으로 결과를 검사할 수 있습니다.
워크플로를 실행하려면main_workflow()
함수를 호출하기만 하면 전체 파이프라인이 원활하게 실행됩니다.
# Run the workflow
main_workflow()
아웃풋
> Entering new AgentExecutor chain...
Thought: The query 'What is the plot of 'A Scandal in Bohemia'?' requires context from the book to provide an accurate response.
Action: Search FAISS Vector Store
Action Input: "What is the plot of 'A Scandal in Bohemia'?"
Observation:
I. A SCANDAL IN BOHEMIA
I.
“I was aware of it,” said Holmes dryly.
“The circumstances are of great delicacy, and every precaution has to
be taken to quench what might grow to be an immense scandal and
seriously compromise one of the reigning families of Europe. To speak
plainly, the matter implicates the great House of Ormstein, hereditary
kings of Bohemia.”
“I was also aware of that,” murmured Holmes, settling himself down in
his armchair and closing his eyes.
Contents
I. A Scandal in Bohemia
II. The Red-Headed League
III. A Case of Identity
IV. The Boscombe Valley Mystery
V. The Five Orange Pips
VI. The Man with the Twisted Lip
VII. The Adventure of the Blue Carbuncle
VIII. The Adventure of the Speckled Band
IX. The Adventure of the Engineer’s Thumb
X. The Adventure of the Noble Bachelor
XI. The Adventure of the Beryl Coronet
XII. The Adventure of the Copper Beeches
Thought: Combining retrieved context with the query to generate a detailed answer.
/var/folders/4w/smh16qdx6l98q0534hr9v52r0000gn/T/ipykernel_2648/234523588.py:23: LangChainDeprecationWarning: The method `BaseLLM.__call__` was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use :meth:`~invoke` instead.
final_answer = llm(prompt)
Final Answer: Step 1: Identify the main characters and their roles.
- Sherlock Holmes: The detective who is approached by a client with a delicate matter.
- An unnamed client: A representative of the great House of Ormstein, hereditary kings of Bohemia, who seeks Holmes' help to prevent a potential scandal.
Step 2: Understand the main issue or conflict.
- The main issue is a delicate matter that, if exposed, could lead to a massive scandal and compromise one of the reigning families of Europe, specifically the House of Ormstein.
Step 3: Ident
> Finished chain.
> Entering new AgentExecutor chain...
Thought: The query 'Who is Dr. Watson, and what role does he play in the stories?' requires context from the book to provide an accurate response.
Action: Search FAISS Vector Store
Action Input: "Who is Dr. Watson, and what role does he play in the stories?"
Observation:
“Sarasate plays at the St. James’s Hall this afternoon,” he remarked.
“What do you think, Watson? Could your patients spare you for a few
hours?”
“I have nothing to do to-day. My practice is never very absorbing.”
“Try the settee,” said Holmes, relapsing into his armchair and putting
his fingertips together, as was his custom when in judicial moods. “I
know, my dear Watson, that you share my love of all that is bizarre and
outside the conventions and humdrum routine of everyday life. You have
shown your relish for it by the enthusiasm which has prompted you to
chronicle, and, if you will excuse my saying so, somewhat to embellish
so many of my own little adventures.”
“My God! It’s Watson,” said he. He was in a pitiable state of reaction,
with every nerve in a twitter. “I say, Watson, what o’clock is it?”
“Nearly eleven.”
“Of what day?”
“Of Friday, June 19th.”
“Good heavens! I thought it was Wednesday. It is Wednesday. What d’you
want to frighten a chap for?” He sank his face onto his arms and began
to sob in a high treble key.
“I tell you that it is Friday, man. Your wife has been waiting this two
days for you. You should be ashamed of yourself!”
Thought: Combining retrieved context with the query to generate a detailed answer.
Final Answer: Dr. Watson is a character in the Sherlock Holmes stories, written by Sir Arthur Conan Doyle. He is a former military surgeon who becomes the narrator and chronicler of Holmes' adventures. Watson is a close friend and confidant of Holmes, often accompanying him on cases and providing a more human perspective to the stories. He is known for his enthusiasm for the bizarre and unconventional, as well as his skill in recording the details of their investigations. Watson's role is crucial in presenting the narrative and offering insights into Holmes' character and methods.
> Finished chain.
Final DataFrame:
Thought \
0 The query 'What is the plot of 'A Scandal in B...
1 The query 'Who is Dr. Watson, and what role do...
2 The query 'Describe the relationship between S...
3 The query 'What methods does Sherlock Holmes u...
Action \
0 Search FAISS Vector Store
1 Search FAISS Vector Store
2 Search FAISS Vector Store
3 Search FAISS Vector Store
Action Input \
0 What is the plot of 'A Scandal in Bohemia'?
1 Who is Dr. Watson, and what role does he play ...
2 Describe the relationship between Sherlock Hol...
3 What methods does Sherlock Holmes use to solve...
Observation \
0 I. A SCANDAL IN BOHEMIA\n\n\nI.\n“I was aware ...
1 “Sarasate plays at the St. James’s Hall this a...
2 “You have really got it!” he cried, grasping S...
3 to learn of the case was told me by Sherlock H...
Final Answer
0 Step 1: Identify the main characters and their...
1 Dr. Watson is a character in the Sherlock Holm...
2 Sherlock Holmes and Irene Adler have a profess...
3 Sherlock Holmes uses a variety of methods to s...
Output saved to output.csv
함수main_workflow()
실행 후 텍스트 파일(aosh.txt)을 처리하고 셜록 홈즈의 모험에 대한 네 가지 사용자 정의 쿼리를 실행했습니다. 아웃풋은 다음과 같이 각 쿼리가 처리된 방식에 대한 자세한 분석을 제공합니다.
생각은 쿼리의 이면에 있는 추론과 정확한 답변에 필요한 맥락을 설명합니다.
행동은 수행된 단계를 나타내며, 이 경우 FAISS 벡터 인덱스를 사용하여 유사성 검색을 수행하는 것입니다.
행동 입력은 한 번의 반복에서 처리되는 특정 쿼리입니다.
관찰은 쿼리와 관련된 벡터 인덱스에서 검색된 텍스트 청크입니다.
최종 답변은 검색된 컨텍스트를 사용하여 IBM Granite LLM이 생성한 자세한 응답입니다.
또한 모든 쿼리에 대한 결과는 DataFrame으로 구조화되고output.csv
로 저장됩니다. 이 파일에는 추가로 분석 또는 공유할 수 있도록 위의 모든 구성 요소가 포함되어 있습니다.
이 과정에서 텍스트 검색과 LLM 추론을 결합하여 책에 대한 복잡한 쿼리에 답했습니다. 에이전트는 관련 정보를 동적으로 검색하고, 컨텍스트를 사용하여 정확한 답변을 생성하며, 쉽게 분석할 수 있도록 구조화된 형식으로 아웃풋을 구성했습니다.
결과 시각화
output.csv 파일이 생성되면 이제 쿼리 결과 및 관련 성능 지표를 시각화하여 에이전트의 성능에 대한 심층적인 인사이트를 제공하겠습니다.
다음 코드 셀에서는 시각화 및 분석을 준비하기 위해output.csv
파일에서 저장된 쿼리 결과를 pandas DataFrame으로 변환합니다. DataFrame을 사용하면 구조화된 형식으로 데이터를 조작하고 탐색할 수 있습니다.
# Load the output.csv file into a DataFrame
df = pd.read_csv("output.csv")
print(df.head()) # Display the first few rows
아웃풋
Thought \
0 The query 'What is the plot of 'A Scandal in B...
1 The query 'Who is Dr. Watson, and what role do...
2 The query 'Describe the relationship between S...
3 The query 'What methods does Sherlock Holmes u...
Action \
0 Search FAISS Vector Store
1 Search FAISS Vector Store
2 Search FAISS Vector Store
3 Search FAISS Vector Store
Action Input \
0 What is the plot of 'A Scandal in Bohemia'?
1 Who is Dr. Watson, and what role does he play ...
2 Describe the relationship between Sherlock Hol...
3 What methods does Sherlock Holmes use to solve...
Observation \
0 I. A SCANDAL IN BOHEMIA\n\n\nI.\n“I was aware ...
1 “Sarasate plays at the St. James’s Hall this a...
2 “You have really got it!” he cried, grasping S...
3 to learn of the case was told me by Sherlock H...
Final Answer
0 Step 1: Identify the main characters and their...
1 Dr. Watson is a character in the Sherlock Holm...
2 Sherlock Holmes and Irene Adler have a profess...
3 Sherlock Holmes uses a variety of methods to s...
이 코드에서 DataFrame에는 각 쿼리에 대해Thought
,조치
,Observation
및Final Answer
등의 주요 구성 요소가 포함되어 있습니다. 처음 몇 행을df.head()
를 통해 표시하여 데이터가 올바르게 형식화되고 다음 단계인 의미 있는 시각화 생성으로 넘어가기 위한 준비가 되었는지 확인합니다.
시각화 라이브러리 가져오기
쿼리 결과의 시각화를 생성하기 위해 필요한 라이브러리를 가져옵니다.
import matplotlib.pyplot as plt
from wordcloud import WordCloud
matplotlib.pyplot
은 Python에서 정적, 대화형, 애니메이션 시각화를 만드는 데 널리 사용되는 라이브러리입니다. 막대 차트, 원형 차트 및 기타 시각화를 생성하는 데 사용됩니다.
wordcloud
는 데이터에서 가장 자주 등장하는 단어를 시각적으로 강조 표시하는 워드 클라우드 생성용 라이브러리입니다. 이 단계는 텍스트에서 검색한 컨텍스트를 요약하고 탐색하는 데 도움을 줍니다.
중요 참고 사항:"WordCloud not found"
오류가 발생하면pip install wordcloud
명령어를 사용하여 라이브러리를 설치하여 문제를 해결할 수 있습니다.
관찰 및 답변 길이 시각화
이 코드는 각 쿼리에 대한 관찰(검색된 컨텍스트)과 답변(생성된 응답)의 길이를 비교하는 가로 막대 차트를 생성합니다. 이 시각화는 생성된 답변의 길이와 비교하여 에이전트가 사용하는 컨텍스트의 양에 대한 인사이트를 제공합니다.
def visualize_lengths_with_queries(df):
"""Visualizes the lengths of observations and answers with queries on the y-axis."""
df["Observation Length"] = df["Observation"].apply(len)
df["Answer Length"] = df["Final Answer"].apply(len)
# Extract relevant data
queries = df["Action Input"]
observation_lengths = df["Observation Length"]
answer_lengths = df["Answer Length"]
# Create a horizontal bar chart
plt.figure(figsize=(10, 6))
bar_width = 0.4
y_pos = range(len(queries))
plt.barh(y_pos, observation_lengths, bar_width, label="Observation Length", color="skyblue", edgecolor="black")
plt.barh([y + bar_width for y in y_pos], answer_lengths, bar_width, label="Answer Length", color="lightgreen", edgecolor="black")
plt.yticks([y + bar_width / 2 for y in y_pos], queries, fontsize=10)
plt.xlabel("Length (characters)", fontsize=14)
plt.ylabel("Queries", fontsize=14)
plt.title("Observation and Answer Lengths by Query", fontsize=16)
plt.legend(fontsize=12)
plt.tight_layout()
plt.show()# Call the visualization function
visualize_lengths_with_queries(df)
이visualize_lengths_with_queries
는 각 쿼리에 대한 관찰(검색된 컨텍스트)과 답변(생성된 응답)의 길이를 비교하는 가로 막대 차트를 생성합니다.
관측과 답변의 문자 길이를 계산하여 새 열(Observation Length
및Answer Length
)로 DataFrame에 추가합니다. 그런 다음Matplotlib
를 사용하여 각 쿼리에 대해 해당 길이를 표시하고 가독성을 높이기 위해 쿼리를 y축에 표시합니다.
막대 차트는 관찰 길이와 답변 길이를 구분하기 위해 색상으로 구분되어 있으며 명확성을 위해 레이블, 범례, 제목이 포함되어 있습니다.
이 시각화는 검색된 컨텍스트의 크기와 생성된 응답의 세부 정보 간의 균형을 분석하는 데 도움을 주며 에이전트가 쿼리를 처리하고 응답하는 방법에 대한 인사이트를 제공합니다.
관찰에 사용된 텍스트의 비율 시각화
이 단계는 에이전트가 처리한 전체 텍스트 중 나머지 텍스트와 비교하여 관찰(검색된 컨텍스트)에 사용되는 양을 시각화합니다. 비율을 직관적으로 표현하기 위해 원형 차트로 생성됩니다.
def visualize_text_proportion(df):
"""Visualizes the proportion of text used in observations."""
total_text_length = sum(df["Observation"].apply(len)) + sum(df["Final Answer"].apply(len))
observation_text_length = sum(df["Observation"].apply(len))
sizes = [observation_text_length, total_text_length - observation_text_length]
labels = ["Observation Text", "Remaining Text"]
colors = ["#66b3ff", "#99ff99"]
plt.figure(figsize=(4, 4))
plt.pie(sizes, labels=labels, colors=colors, autopct="%1.1f%%", startangle=140)
plt.title("Proportion of Text Used in Observations", fontsize=16)
plt.show()# Call the visualization function
visualize_text_proportion(df)
이러한visualize_text_proportion
함수는 나머지 텍스트와 비교하여 관찰(검색된 컨텍스트)에 사용되는 전체 텍스트의 비율을 설명하기 위한 원형 차트를 만듭니다. 모든 관찰과 답변의 문자 길이를 합산하여 총 텍스트 길이를 계산한 다음 관찰만 기여한 부분을 판단합니다.
이 데이터는 원형 차트로 시각화되며,"관찰 텍스트"
및"나머지 텍스트"
의 명확한 라벨과 뚜렷한 색상을 통해 가독성을 높입니다. 이 차트에는 비율을 쉽게 해석할 수 있도록 백분율 값이 포함되어 있습니다.
이 시각화는 에이전트가 쿼리 처리 중에 컨텍스트로 사용하는 텍스트의 양에 대한 높은 수준의 개요를 제공하여 검색 프로세스의 효율성과 초점에 대한 인사이트를 제공합니다.
관찰 및 최종 답변의 워드 클라우드 생성
이 코드는 두 개의 단어 구름을 생성하여 Observation
및 Final Answer
텍스트에서 가장 자주 발생하는 단어를 시각적으로 나타냅니다.
def generate_wordclouds_side_by_side(df):
"""Generates and displays word clouds for Observations and Final Answers side by side."""
# Combine text for Observations and Final Answers
observation_text = " ".join(df["Observation"])
final_answer_text = " ".join(df["Final Answer"])
# Create word clouds
observation_wordcloud = WordCloud(width=800, height=400, background_color="white").generate(observation_text)
final_answer_wordcloud = WordCloud(width=800, height=400, background_color="white").generate(final_answer_text)
# Create a side-by-side visualization
plt.figure(figsize=(16, 8))
# Plot the Observation word cloud
plt.subplot(1, 2, 1)
plt.imshow(observation_wordcloud, interpolation="bilinear")
plt.axis("off")
plt.title("Word Cloud of Observations", fontsize=16)
# Plot the Final Answer word cloud
plt.subplot(1, 2, 2)
plt.imshow(final_answer_wordcloud, interpolation="bilinear")
plt.axis("off")
plt.title("Word Cloud of Final Answers", fontsize=16)
plt.tight_layout()
plt.show()# Call the function to generate and display the word clouds
generate_wordclouds_side_by_side(df)
이 코드는 두 개의 단어 구름을 생성하여Observation
및Final Answer
텍스트에서 가장 자주 등장하는 단어를 시각적으로 표현하고, 비교하기 쉽도록 나란히 배치됩니다.Observation
및Final Answer
텍스트는 먼저" ".join()
을 사용해 두 개의 개별 문자열로 연결하여 각 열의 모든 행을 결합합니다. 그런 다음WordCloud
라이브러리를 사용하여 특정 구성을 가진 각 텍스트에 대한 워드 클라우드를 생성합니다.
나란히 배치된 시각화를 만들기 위해 하위 플롯이 사용됩니다. 첫 번째 하위 플롯은Observation
에 대한 워드 클라우드를 표시하고, 두 번째가 표시하는 워드 클라우드는Final Answer
. 이tight_layout()
함수는 플롯 사이의 간격을 깔끔하게 유지합니다. 이러한 단어 구름을 사용하면 컨텍스트에서 검색된 핵심 용어(Observation
및 응답에서 강조된 핵심 용어(Final Answer
)를 강조 표시하여 에이전트의 성능을 직관적으로 분석할 수 있습니다.
에이전트의 정확도 테스트
이 섹션에서는 다음과 같은 여러 정확도 지표를 사용하여 에이전트의 성능을 평가합니다.키워드 일치
,BLEU 점수
,정밀도/재현율
및F1 점수
. 이러한 지표는 에이전트가 사용자 쿼리를 기반으로 정확하고 관련성 높은 응답을 얼마나 잘 생성하는지에 대한 포괄적인 보기를 제공합니다.
필요한 라이브러리 가져오기
테스트를 시작하기 전에 정확도 평가에 필요한 라이브러리를 가져옵니다.
from sklearn.feature_extraction.text import CountVectorizer
from nltk.translate.bleu_score import sentence_bleu
from sklearn.metrics import precision_score, recall_score
이러한 라이브러리에는 키워드 일치, BLEU 점수 계산, 정밀도 및 재현율 평가를 위한 도구가 포함되어 있습니다. 환경에 이러한 라이브러리를 설치했는지 확인하여 가져오기 오류가 발생하지 않도록 하세요.
키워드 일치 정확도
이 테스트는 생성된 답변에 쿼리의 키워드가 얼마나 잘 포함되어 있는지 평가합니다.CountVectorizer
를 사용하여 쿼리와 답변에서 키워드를 토큰화하고 추출합니다. 이 함수는 생성된 답변에 존재하는 쿼리 키워드의 비율을 계산하여 이 비율이 임계값(기본적으로 0.5)을 초과하면 응답을 정확한 것으로 표시합니다. 결과가 추가되는 DataFrame의 위치:키워드 일치 점수
및정확성 여부 열
.
def keyword_matching_accuracy(df):
"""Checks if key phrases from the query are present in the final answer."""
vectorizer = CountVectorizer(stop_words='english')
def check_keywords(query, answer):
query_keywords = set(vectorizer.build_tokenizer()(query.lower()))
answer_keywords = set(vectorizer.build_tokenizer()(answer.lower()))
common_keywords = query_keywords & answer_keywords
return len(common_keywords) / len(query_keywords) # Proportion of matched keywords
df["Keyword Match Score"] = df.apply(lambda row: check_keywords(row["Action Input"], row["Final Answer"]), axis=1)
df["Is Accurate"] = df["Keyword Match Score"] >= 0.5 # Set a threshold for accuracy
return df# Apply keyword matching
df = keyword_matching_accuracy(df)
df.to_csv("output_with_accuracy.csv", index=False)
df
BLEU 점수 계산
이 테스트는 생성된 답변이 검색된 관찰과 얼마나 밀접하게 일치하는지 측정합니다.BLEU(Bilingual Evaluation Understudy)
는n-gram
오버랩을 기반으로 텍스트 유사성을 평가하는 데 널리 사용되는 지표입니다. 이 함수는 각 쿼리-답변 쌍에 대해BLEU 점수
를 계산하고 BLEU 점수 열 아래의 DataFrame에 추가합니다.
Total Entries: 4
Accurate Entries: 4 (100.00%)
Average BLEU Score: 0.04
Average F1 Score: 0.24
이러한 정확도 테스트는 에이전트가 관련성 있고 정확한 답변을 생성하는 능력에 대한 자세한 평가를 제공합니다. 각 테스트는 키워드 포함부터 텍스트 유사성 및 답변 완성도에 이르기까지 특정 측면에 중점을 둡니다. 요약은 이러한 지표를 통합하여 전반적인 성능 스냅샷을 제공합니다.
요약
이 튜토리얼에서는 IBM Granite LLM과 LangChain으로 구동되는 자율 에이전트를 구축하는 과정을 안내했습니다. 텍스트 추출부터 벡터화 및 쿼리 해결에 이르기까지 기능적인 LLM 기반 에이전트를 설계하고 구현하는 전체 프로세스를 다루었습니다. 주요 단계에는 벡터 스토어를 통한 메모리 관리, 쿼리 처리 및 Granite를 사용한 응답 생성 등이 포함되었습니다.
키워드 일치, BLEU 점수, 정밀도, 재현율, F1 점수와 같은 지표를 사용하여 에이전트의 성능을 평가했습니다. 막대 차트, 원형 차트, 워드 클라우드와 같은 시각화는 에이전트의 행동과 효과성에 대한 추가 인사이트를 제공했습니다.
이 튜토리얼을 완료함으로써 LLM 에이전트의 성능을 설계, 테스트 및 시각화하는 방법을 배웠습니다. 이 기반은 더 복잡한 데이터 세트를 처리하고, 정확성을 향상시키며, 다중 에이전트 시스템과 같은 고급 기능을 탐색하는 데 확장될 수 있습니다.