Share
Sign In
SSE(Server-Sent Events)를 활용한 실시간 스트리밍 도입 고민
박진훈
최근 웹 애플리케이션에서 실시간 기능의 중요성이 점점 더 커지고 있는 것을 체감하고 있는 중에 벨루가도 SSE(Server-Sent Events) 을 적용하여 AI 답변을 제공하면 어떨까를 고민하며 프로젝트를 진행해보고 그 경험을 공유하고자 합니다.
지금도 벨루가는 스트리밍 방식으로 AI답변을 제공하고 있지만 단순 텍스트를 스트리밍하고 있는 구조로 되어 있어 클라이언트 개발자의 부담이 크며 유지보수 또한 쉽지 않은 구조로 이루어져 있습니다. 모든 메타데이터(출처, 답변생성 프로세스등..)를 답변과 함께 텍스트로 전달 되기 때문입니다.
SSE(Server-Sent Events)란 무엇인가?
SSE(Server-Sent Events)서버클라이언트(웹 브라우저)에 정보를 푸시하는 방식입니다. 웹에서는 보통 클라이언트가 서버에 요청(request)을 보내고 서버가 응답(response)을 반환하는 구조인데, SSE는 이와 반대로 서버에서 초기 연결 후 계속해서 데이터를 클라이언트에게 보낼 수 있게 해줍니다. 이 기술은 특히 뉴스 피드, 실시간 알림, 또는 챗봇과 같은 애플리케이션에 매우 유용합니다.
SSE의 선택 이유
WebSocket과 같은 다른 기술들도 고려했지만, SSE를 선택한 이유는 서버 설정이 간단하고, 양방향이 아닌 클라이언트와의 단방향 통신만 하면 되기 때문입니다. SSE는 HTTP를 사용하기 때문에 기존 웹 인프라와의 호환성도 뛰어나다는 장점이 있습니다.
구현 과정
API 서버
PythonFastAPI 프레임워크를 사용하여 서버를 구축했습니다. 이 서버는 사용자로부터 질문을 받아 OpenAIGPT-3.5 모델에 전달하고, 생성된 응답을 실시간으로 사용자에게 스트리밍하는 역할을 합니다.
1.
챗봇 서버 생성: FastAPI를 사용하여 웹 서버를 구축하고, CORS 설정을 통해 모든 출처에서의 접근을 허용했습니다.
2.
GPT-3.5 연동: 사용자의 입력을 받아 처리한 후, 생성된 텍스트를 실시간으로 스트리밍하기 위해 SSE를 구현했습니다.
3.
스트리밍 로직: sse_generator 함수는 GPT 모델로부터 받은 데이터를 yield를 통해 클라이언트에 전송하고 await asyncio.sleep(0) 을 사용하여 이벤트 루프의 블로킹을 방지하고 다른 네트워크 태스크에 CPU 자원을 제공해서 클라이언트가 실시간으로 데이터를 받을 수 있도록 구현했습니다.
클라이언트 서버
웹 클라이언트는 React를 사용하여 구현했습니다. React를 선택한 이유는 특별한 이유가 있다기 보다는 벨루가 클라이언트가 React로 개발되어 있기 때문입니다. React는 동적인 UI를 구축하기에 적합하며, 컴포넌트 기반의 구조 덕분에 유지보수와 코드 관리가 용이하다는 장점이 있고 무엇보다 중요한건 Server-Sent Events(SSE) 를 활용하여 서버로부터의 스트리밍 데이터를 효과적으로 처리할 수 있다는 것입니다.
코드
주요 구성 요소
1.
메시지 상태 관리
messages: 이 상태 배열은 채팅방에서 교환되는 모든 메시지를 저장합니다. 각 메시지는 고유 ID, 텍스트 내용, 그리고 메시지를 보낸 발신자(사용자 또는 AI)를 포함합니다.
useState 훅을 사용하여 메시지 배열의 상태를 관리하고, 새로운 메시지가 추가될 때마다 상태를 업데이트 합니다.
2.
사용자 입력 처리
input: 사용자가 입력창에 입력하는 텍스트를 저장하는 상태입니다.
사용자가 텍스트를 입력할 때마다 이 상태가 업데이트되며, 메시지를 전송한 후에는 이 입력 필드를 비웁니다.
3.
메시지 ID 관리
nextMsgId: 메시지마다 고유한 ID를 할당하기 위해 사용되는 useRef 훅입니다.
이는 컴포넌트가 리렌더링될 때마다 초기화되지 않고, 메시지를 추가할 때마다 증가하여 각 메시지가 고유한 식별자를 가질 수 있도록 구성했습니다.
4.
서버와의 실시간 통신
EventSource: 서버로부터 실시간으로 메시지를 받기 위해 사용되는 Web API입니다.
이 객체를 통해 위에서 만든 FastAPI 서버로부터 메시지 스트림을 실시간으로 받아, 메시지 상태에 추가할 수 있습니다.
5.
UI 구성 요소
채팅창을 표시하는 영역과 입력을 받는 입력박스을 추가했습니다.
익숙한 채팅창 스타일을 적용해서 질문과 답변을 구분할 수 있게 디자인 했습니다.
완성된 챗봇의 모습 입니다. 기획했던 대로 사용자의 입력을 API 서버로 전달하고 실시간으로 AI답변을 스트리밍하는 구조로 구현 되었습니다.
결론
AI가 제공하는 답변을 스트리밍 방식으로 받는 것과 모든 답변이 완성된 후 한번에 받는 것 사이에 실제 답변을 받는 총 시간은 차이가 없지만 사용자 경험 측면에서 보면, 스트리밍 방식이 마치 더 빠르게 응답을 받는 것 같은 느낌을 줄 수 있습니다. 따라서 사용자가 기다림을 덜 느끼게 하여 전반적인 만족도를 향상시키는 효과를 볼 수 있습니다.
특히, 사용자의 질문을 해석하고 답변을 생성하는 과정에서 프롬프트 체인 기법과 같은 동적인 처리가 필요한 챗봇을 구현할 때, 이벤트 스트리밍을 활용하면 답변 생성 과정을 사용자에게 실시간으로 보여주어서, 답변 처리 시간이 길어지는 불편함을 줄이는 데 효과적일 것입니다.
벨루가에서 기획중인 템플릿 중에 고급요약이나 모의면접등과 같은 AI 답변을 생성하는 프로세스가 복잡한 템플릿에 적용하게 된다면 사용자의 경험에서 만족도를 크게 높일 수 있을것 같습니다.
👍
1
/velugadoc
Subscribe
데이터 임베딩을 향상시키는 문서(데이터) 정리법 FAQ
우리가 업무나 일상에서 작성하는 보고서에서 복잡한 구조의 표들은 많은 경우 AI에 그대로 이해되기 어렵습니다. 이런 경우 따로 엑셀이나 스프레드 시트 등에서 해당 내용을 AI가 이해할 수 있는 구조로 정리하여 학습 시키면 해당 정보를 정확하게 이해하여 답변하게 하실 수 있습니다. (가장 뛰어난 GPT4-o 모델의 경우도 표의 구조를 제대로 이해하지 못하고 캐롯 손보 등의 내용을 누락하여 잘못 작성하는 것을 볼 수 있습니다.) 그렇다면, 벨루가에 문서 학습을 잘 시키기 위해서는 어떻게 데이터를 정리해야할까요? 기존의 문서관리 글에서도 정리되어 있지만, 그동안 많이 받은 질문들을 토대로 FAQ를 정리해보았습니다!:) Q1: 데이터를 어떻게 구조화해야 하나요? PDF를 그대로 학습시키고 싶으실 경우, 글자 크기에 유의해주세요. 제목은 큰 글씨로 작성해야지 주제라는 것을 이해합니다. 빈 행과 열이 있어서는 안됩니다. 빈칸도 되도록 아님, 해당 없음 등으로 채워두시는게 좋습니다. 엑셀 파일에서 대분류에 너무 지엽적인 키워드가 들어가게 되면, 해당 표의 모든 내용에 관련 태그가 붙게 됩니다. 대분류에는 지나치게 상세한 키워드 대신 일반적인 키워드(예: 분류, 구분, 주제)를 사용하세요. 병합 된 셀이 있으면 이해하기 어렵습니다. 꼭! 병합된 셀은 풀어서 내용을 중복 입력하세요. 첫 번째 행은 반드시 대분류로 채우세요. 표의 구분/대분류가 변경될 경우 새로운 시트를 만드세요. Q2: 데이터 길이에 제한이 있나요? 내용이 많이 긴 pdf, docs 파일의 경우 시트에 청크 단위로 질문과 답변들의 정리가 필요합니다. len() 함수를 사용해 작성한 글자 수를 확인하실 수 있습니다. 시트에서 각 행이 2000자를 넘지 않도록 주의하세요. 긴 내용은 주제를 나누어 똑같은 태그로 나누어 입력하셔도 좋습니다. 시트 개수에는 제한이 없으므로 필요시 여러 시트를 만들어 사용하세요.
Staff_Veluga
🐳벨루가 카카오톡 채널 정식 오픈
안녕하세요! 여러분:) 저번 주부터 벨루가에 합류하여 벨루가의 소식을 전해드리고 있는 스태프_벨루벨루입니다🐣 벨루가의 6/25 최신 업데이트 소식을 통해 카카오톡 채널 커머스카드 기능도 추가했다는 소식을 전해드렸습니다. 그리고 이번에 벨루가 자체 카카오톡 채널도 오픈하게 되어 벨루가 챗봇을 카카오톡에서도 써보실 수 있게 되고, 카카오톡 채널 소식을 통해 더 활발히 공유드릴 수 있게 되었습니다🎉🎉 💌벨루가 카카오톡 채널을 오픈했습니다!! 벨루가랑 친구하실 분~?🙋‍♂️🙋🙋‍♀️💞 벨루가 카카오톡 친구 추가를 해주시면, 앞으로 벨루가의 중요한 소식들과 이벤트들을 놓치지 않으실 수 있습니다🙌 👇아래의 링크를 눌러서 지금 바로 친구추가 해주세요🤗👇
Staff_Veluga
벡터 데이터베이스 vs 그래프 데이터베이스 차이
최근 검색 증강 생성(RAG: Retrieval Augmented Generation)에 대한 관심이 급증하고 있습니다. 이 기술에 대한 기대와 함께 실망도 많습니다. 문서나 데이터를 나누는 방법에서부터 임베딩 방법, 그 외 전처리 및 후처리 등 다양한 방법이 문제 해결에 적용될 수 있습니다. 하지만 일반적인 RAG 기술을 적용할 때는 생각보다 만족스러운 결과를 얻지 못하는 경우가 많습니다. 이번 글에서는 벡터 데이터베이스와 그래프 데이터베이스의 차이를 예시를 통해 가볍게 설명해 보고자 합니다. 대규모 언어 모델(LLM)을 핵심 애플리케이션에 도입하려는 경우, LLM의 예측 불가능한 특성으로 인해 부정확한 추론이나 명백한 오류 같은 문제가 발생할 수 있습니다. 이는 정확성, 설명 가능성, 신뢰성을 중시하는 기업들에게 큰 문제로 다가옵니다. 이러한 문제를 극복하기 위해 검색 증강 생성이 주요 고려 사항이 됩니다. 지식 그래프와 벡터 데이터베이스는 검색 증강 생성을 구현하기 위한 잠재적인 솔루션으로 주목받고 있습니다. 그렇다면 LLM에 보다 정확하고 신뢰할 수 있으며 설명 가능한 기반을 제공하는 것은 무엇일까요? LLM 기반 구축을 위해 지식 그래프와 벡터 데이터베이스 중 하나를 선택할 때 고려해야 할 몇 가지 핵심 요소를 살펴보겠습니다. 복잡한 질문에 대한 답변 질문의 복잡성이 높을수록 벡터 데이터베이스가 빠르고 효율적으로 결과를 반환하기 어려워집니다. 쿼리에 더 많은 주제를 추가하면 데이터베이스가 원하는 정보를 찾기 힘들어집니다. 예를 들어, 지식 그래프와 벡터 데이터베이스 모두 "우리 회사의 CEO는 누구인가?"라는 질문에 쉽게 답변할 수 있지만, "지난 12개월 동안 최소 두 명의 구성원이 투표를 기권한 이사회 회의는 무엇인가?"와 같은 질문에는 지식 그래프가 벡터 데이터베이스보다 더 빠르게 답변할 수 있습니다. 벡터 데이터베이스는 벡터 공간 내 주제들의 유사성을 기반으로 답을 찾을 가능성이 높지만, 지식 그래프는 관계를 통해 정확한 정보를 찾아 반환합니다. 완전한 응답 얻기 벡터 데이터베이스는 유사성 점수 및 사전 정의된 결과 제한에 의존하기 때문에 답변을 반환할 때 불완전하거나 관련 없는 결과를 제공할 가능성이 있습니다. 예를 들어, "윤선도가 쓴 모든 책을 나열하시오"라는 질문에 벡터 데이터베이스는 다음과 같은 결과를 반환할 수 있습니다. 불완전한 제목 목록 (사전 정의된 제한이 너무 낮음): 예를 들어, 결과 제한이 3으로 설정되어 있고 윤선도가 쓴 책이 10권이라면, 벡터 데이터베이스는 3권의 책 제목만 반환하고 나머지 7권은 누락됩니다. 윤선도의 모든 제목과 다른 저자의 일부 제목 (사전 정의된 제한이 너무 높음): 반대로, 결과 제한이 20으로 설정되어 있고 윤선도가 쓴 책이 10권이라면, 벡터 데이터베이스는 윤선도의 모든 책 10권과 함께 다른 저자의 책 10권을 추가로 반환할 수 있습니다. 이는 사용자가 원하는 정보 외에 불필요한 정보까지 포함되어 검색 결과의 정확성을 떨어뜨립니다. 사용자 또는 개발자가 모든 가능한 쿼리에 대한 사전 정의된 제한을 알 수 없기 때문에 벡터 데이터베이스만으로 정확한 답변을 얻는 것은 쉽지 않습니다. 그래서 결과를 이용해 LLM에 보내어 다시 응답을 생성합니다. 반면, 그래프 데이터베이스를 사용한 지식 그래프는 엔티티가 관계에 의해 직접 연결되므로 각 엔티티마다 관계 수가 다릅니다. 지식 그래프는 정확한 답변만 검색하여 반환합니다. 이 경우 지식 그래프 쿼리는 윤선도가 쓴 모든 책만 반환하고 다른 것은 반환하지 않습니다. 다만, 그래프 데이터베이스의 단점은 초기 데이터베이스를 잘 구축해야 한다는 점입니다. 신뢰할 수 있는 응답 얻기 벡터 데이터베이스는 두 개의 사실 정보를 연결하여 부정확한 추론을 할 수 있습니다. 예를 들어, "제품 관리 팀에는 누가 있습니까?"라는 질문에 벡터 데이터베이스는 제품 팀이 생성한 문서(사실)에 대한 빈번한 댓글 액세스 권한(사실)이 있는 사람이 제품 팀에 속한다고 잘못 추론하여 결과에 이름을 반환할 수 있습니다. 그래프 데이터베이스로 구현한 지식 그래프는 노드와 관계를 사용하여 조직 내 사람들의 관계를 식별하기 때문에 제품 팀에 속한 사람만 반환합니다. 지식 그래프 쿼리는 연결된 정보의 흐름을 따라가므로 응답이 일관되게 정확하고 설명 가능합니다. 벡터 데이터베이스의 장단점 장점: 고차원 벡터 공간에서의 유사성 검색에 강점이 있습니다. 다양한 종류의 데이터를 빠르게 검색하고 분석할 수 있습니다.
SangYeon_Lee