Work/기타

Langflow를 통한 이메일 요약 서비스 구현

raeul0304 2025. 9. 23. 16:26

입사 초반에는 MCP가 크게 주목받기 이전이었기 때문에, 중부발전은 GridOne이라는 기업을 통해 AI 서비스를 활용하고 있었다.

GridOne은 RPA와 더불어 Langflow를 이미 도입하여 사용 중이었고, 따라서 나는 개발을 진행할 때도 해당 환경에 최대한 맞추어 시스템을 설계하고 구현해야 했다.

 

그 과정에서 여러 시도를 정리해 두기는 했지만, 노션에는 기록을 남겨두었어도 블로그에는 따로 정리하지 않았다는 점을 뒤늦게 알게 되었다. 그래서 지금이라도 경험을 정리해 글로 남기려 한다.

 

📌 Langflow란?

 

https://www.langflow.org/

 

Langflow | Low-code AI builder for agentic and RAG applications

Langflow is a low-code AI builder for agentic and retrieval-augmented generation (RAG) apps. Code in Python and use any LLM or vector database.

www.langflow.org

 

Langflow는 LLM(대규모 언어 모델) 기반 어플리케이션을 손쉽게 설계, 구현할 수 있도록 도와주는 오픈소스 도구다.

일반적으로 LLM을 활용한 어플리케이션을 만들려면 다양한 모듈 (LangChain, VectorDB, API 등)을 직접 코드로 연결해야 하는데, Langflow는 이러한 과정을 시각적인 노드 기반 UI로 제공한다.

 

그래서 본 페이지에 들어가보면 알겠지만, 원하는 컴포넌트 간에 엣지를 연결을 해주면 flow를 만들어줄 수 있다.

또한, 대부분의 컴포넌트는 플레이 아이콘이 있는데, 이 플레이 아이콘을 클릭하면 해당 컴포넌트와 연결된 모든 선행 컴포넌트들이 연계적으로 실행이 되어 말 그대로 flow를 실행시킬 수 있어 간단한 시스템의 경우 쉽게 활용하여 AI기능을 구현 가능하다.

 

개발자는 블록을 끌어다 놓듯이 컴포넌트를 연결하면서 RAG, 프롬프트 체인, 외부 API 연동 등을 빠르게 구현할 수 있다.

 

🔻 Langflow의 주요 특징

 

▪️ 시각적 워크플로우 설계

 

Drag & Drop 방식으로 LLM 체인을 구성할 수 있어, 개발 지식이 적은 사람도 빠르게 프로토타입을 만들 수 있다.

 

 

▪️ LangChain 호환성

 

Langflow의 백엔드는 LangChain을 기반으로 하기 때문에, 기존에 코드로 작성했던 체인 로직을 그대로 활용할 수 있다.

 

 

▪️ 빠른 프로토타이핑

 

복잡한 설정을 코드로 작성하지 않아도, UI에서 매개변수를 조정하며 실험할 수 있다.

 

 

▪️ 확장성

 

단순한 프롬프트 테스트를 넘어, DB, API, RPA 등과 연계하여 실제 서비스 수준으로 확장할 수 있다.

 

 

 

 

🔻 Email Summary Assistant 구현 개요

본 작업은 사용자의 질의에 따라 이메일 데이터를 자동으로 주제별, 발신인별, 개별 요약 또는 사용자 질의 처리를 하는 Langflow 기반 이메일 요약 시스템이다. 이메일 데이터는 RPA를 통해 원하는 개수만큼의 이메일 데이터를 가져오도록 설계하였다.

 

[RPA 연결 전]

 

[RPA 연결 후]

 

 

흐름을 설명하자면,

 

1. Chat Input 컴포넌트를 통해, 사용자의 자연어 요청 입력을 받는다

이메일을 주제별로 요약해줘
발신인별로 요약해줘
각각의 이메일을 요약해줘
이수민의 메일을 모두 요약해줘

 

 

 

2. RPA에 요청을 하여 이메일을 원하는 개수만큼 가져온다.

이메일 가져온 결과

 

3. Query Routing (커스텀 컴포넌트)를 통해 사용자의 질문이 어떤 카테고리에 속하는지 분류한다.

 

본 이메일 요약 서비스는 개별 요약, 주제별 요약, 사용자별 요약 기능을 제공하기 때문에

카테고리는 individual, topic, user 로 구분을 해두었다.

 

 

 

4. 위 카테고리에 따라 분기처리를 진행한다.

 

주제별 요약의 경우, 이메일의 내용을 기반으로 하여 이메일을 특정 주제로 분류를 하고

그 주제별로 이메일들이 그룹핑이 되도록 해야했다.

 

개별 요약과 사용자별 요약 역시 각기 다른 프롬프트가 필요했던 상황!

 

하나의 프롬프트로 처리해도 되지 않냐는 의문을 가질 수 있겠지만, gpt-4o 모델을 사용해도 prompt가 정교하게 작성되어있지 않거나 정교하더라도 생각보다 요약을 잘 해내지 못한다..^^

 

따라서 최대한 실패를 줄이기 위해서 prompt 길이를 제한을 해서 분기처리가 되도록 설계를 하였다.

 

 

 

5-1. Chat Output 컴포넌트와 연결하여 Langflow에서 제공하는 채팅창에서도 활용이 가능할 수 있도록 한다.

5-2.  API를 통해 streamlit과 연동하여 langflow에서 구현한 서비스를 활용할 수 있도록 한다.

 

 

 

 

 

 

 

🔻 FastAPI > SQLite3  > Streamlit

Langflow의 Python REPL (python 코드를 입력할 수 있는 컴포넌트) 실행 시, Langflow에서 생성된 이메일 요약 결과를 FastAPI 서버를 통해 수신하고, SQLite DB에 저장한 뒤, Streamlit을 통해 주제별/발신인별로 시각화한다.

 

📍 Endpoints

Endpoints  설명
POST /receive_topic_summary 주제별 요약 결과 수신
POST /receive_sender_summary 발신인별 요약 결과 수신

 

 

  1. FastAPI → SQLite DB : 요약 결과 저장

FastAPI는 수신된 JSON에서 이메일별 email_id와 topic/sender, summary를 파싱하여 다음의 SQLite DB 파일에 저장합니다.

  • email_topic_summaries.db
  • email_sender_summaries.db

🔻 저장 테이블 구조

  • email_topic_summaries : email_id, topic, summary
  • email_sender_summaries : email_id, sender, summary

각 summary는 정규표현식으로 [Email ID: N] 형식으로 분리해 저장됩니다.

 

 

  1. Streamlit : 요약 결과 시각화

위 테이블에 저장된 데이터를 시각적으로 열람할 수 있는 streamlit 페이지를 구성하였습니다.

 

 

주제별 요약 결과 페이지 예시

 

 

 

발신인별 요약 결과 페이지 예시

 

 

 

 

 

 

 

🔻 회고

본론부터 말하자면, 난 Langflow가 싫다! (ㅎㅎㅎㅎㅎ)

구현 부문의 Langflow 구성 화면 사진을 보면 알 수 있지만,

 

▪️우선 간단한 기능을 구현하더라도 많은 컴포넌트가 필요하다.

 

예를 들어, if문을 사용하고 싶다고 했을 때 코드로는 간단하게 if - elif- else 구조를 사용하면 된다.

하지만, langflow에서는 if-else 컴포넌트 세개를 이어주어야 한다.

 

LLM을 사용을 할 때도, 코드로는 하나의 모델을 정의하고, 여러 개의 prompt를 구성하여 상황에 맞게 다른 prompt 값을 모델에 던져주면 된다. 하지만, langflow에서는 하나의 llm 모델 컴포넌트에 하나의 system prompt와 일반 prompt 컴포넌트만 연결이 가능하다. 따라서 상황에 따라 다른 prompt 메시지를 모델에 전달하고 싶다면, 그 개수 만큼의 llm 모델 컴포넌트를 사용해야 하는 것이다! (so inefficient...init???)

 

 

 

▪️컴포넌트 간 연결이 자유롭지 못하다.

 

각 컴포넌트마다 input과 ouput에 연결될 수 있는 데이터타입이 엄격하게 정해져있다.

컴포넌트마다 구성 코드를 살펴보고 수정이 가능하긴 하지만 이 역시도 편하게 적용이 불가하여 컴포넌트 간 연결이 너무너무 까다롭다!

 

예를 들어, 특정 컴포넌트는 (ex. API 컴포넌트) input으로 json 형식의 데이터만 받게 되어있다고 해보자.

그러면 LLM이 아무리 json 형식으로 답변을 출력했더라도 LLM 컴포넌트의 ouput 데이터타입은 Message로 되어있다.

따라서 API 컴포넌트와 연결이 직접적으로 불가하다.

 

그러면 Json 형식의 output을 가지는 컴포넌트를 bridge 역할로 넣어줘야 하는데, 이 역시도 지원되지 않아 내가 직접 컴포넌트를 만들어야 한다. 하지만? 만들어도 연결이 안되는 경우가 많음! (왜인지 나도 모름ㅎㅎ 하하하)

 

코드로 구현하면 간단하게 해결될 일이 Langflow에서는 너무 번거롭다.

그래서 가공이 별로 필요없고, langflow 내에서 가볍게 시연을 할만한 서비스는 좋을지 몰라도

원하는 설정/구성이 많으면 사용하기 불편하다고 생각한다...

 

'Work > 기타' 카테고리의 다른 글

WebSocket을 통한 실시간 데이터 처리  (0) 2025.10.20
Sankey Graph에 대하여  (0) 2025.08.25