AInfo 챗봇 구조 #5 - LangChain 기반 도구 및 에이전트 구성 방법
AInfo 프로젝트에서 LangChain 기반으로 도구(Tool)와 에이전트(Agent)를 어떻게 구성했는지 설계 흐름과 구현 코드 중심으로 소개합니다.
AInfo 챗봇 구조 #5 - LangChain 기반 도구 및 에이전트 구성 방법
LangChain Agent 구성 전략
AInfo 프로젝트에서는 LangChain의 공식 Agent 체계를 직접 사용하지 않고, 대신 다음과 같은 방식으로 Agent와 유사한 구조를 직접 설계해 활용했습니다:
- LangChain의
@tool
기반 사용자 정의 툴 생성 RunnableMap
과PromptTemplate
을 활용한 흐름 제어- 내부적으로는
VectorRetriever
를 호출하여 실질적인 검색 수행
즉, initialize_agent
나 AgentExecutor
없이도, Tool + Prompt + LLM 조합으로 에이전트처럼 동작하는 구조를 만들었습니다.
1. 사용자 정의 툴 구성
예시: 정책 추천용 RAG Tool
1
2
3
4
5
6
7
8
9
10
@tool("detail_rag_tool", args_schema=RAGsearchInput)
def detail_rag_tool(query: str, k: int = 3, filters: Optional[dict] = None):
retriever = VectorRetriever()
docs = retriever.search(
query=query,
k=k,
filters=filters,
collection_names=["gov24_service_detail", "youth_policy_list", "employment_programs", "pdf_sections"]
)
return retriever.format_docs(docs)
args_schema
를 통해 입력 인자 자동 검증 및 구조화- VectorRetriever를 활용한 Chroma 벡터 기반 검색
- Markdown 포맷으로 결과 정리 후 반환
2. 입력 스키마 설계
1
2
3
4
class RAGsearchInput(BaseModel):
query: str
k: Optional[int] = 3
filters: Optional[dict] = None
- 입력을 구조화하여 LLM 또는 외부 시스템에서도 명확하게 파싱 가능
- 추후 API 확장, 크루 툴 통합 시에도 재사용 가능
3. 프롬프트 템플릿 구성
LangChain의 ChatPromptTemplate
을 활용하여 다음과 같은 구성으로 프롬프트를 설계했습니다:
- 시스템 프롬프트: 정책 추천, 형식, 필터 조건 안내 등 역할 부여
- 사용자 프롬프트: 질문과 문서(context)를 바탕으로 답변 요청
- 채팅 히스토리: 멀티턴 흐름 유지 가능
1
2
3
4
5
DETAIL_RAG_PROMPT = ChatPromptTemplate.from_messages([
system_message,
MessagesPlaceholder(variable_name="chat_history"),
user_prompt,
])
4. 체인 구성 with RunnableMap
LangChain의 RunnableMap
을 활용해 도구 호출 → 프롬프트 생성 → LLM 실행 흐름을 체인으로 구성했습니다.
1
2
3
4
5
6
7
8
9
10
11
12
DETAIL_CHAIN = (
RunnableMap({
"question": lambda x: x["question"],
"context": lambda x: detail_rag_tool.run({"query": " ".join(x["keywords"])}),
"web_search": lambda x: tavily_web_search_tool.invoke({"query": " ".join(x["keywords"])}),
"current_year_month": lambda _: current_year_month,
"chat_history": lambda x: x.get("chat_history", []),
})
| DETAIL_RAG_PROMPT
| ChatOpenAI(...)
| StrOutputParser()
)
이 흐름은
initialize_agent()
없이도 Agent처럼 Tool을 호출하고 응답을 생성하는 구조입니다.
5. Agent 없이 Agent처럼 동작한 이유
AInfo에서는 CrewAI 구조와의 통합을 고려해 LangChain 기본 Agent 체계(AgentExecutor
)는 사용하지 않았지만, Tool과 Prompt, Runnable 체인을 통해 실제 Agent처럼 다음 흐름을 구현했습니다:
- 사용자 질문 기반 도구 선택
- 문서 검색 및 응답 포맷 구성
- 프롬프트 실행 및 멀티턴 응답 제공
이 방식은 필요할 경우 LangChain Agent 구조로도 바로 이식 가능합니다.
마무리
LangChain의 공식 Agent 구조를 그대로 사용하지 않고도, 도구 중심 구조와 체인 조합을 통해 에이전트처럼 유연하게 동작하는 챗봇 응답 흐름을 구성할 수 있습니다.
This post is licensed under CC BY 4.0 by the author.