안녕하세요. 18기 n8n자동화 수업에 버디로 참여한 디디 입니다.
n8n에서 구동되는 slack봇으로 네이버지도 리뷰 크롤링을 하며, 챗봇으로 작동하게 만들었었는데요. https://www.gpters.org/nocode/post/making-slack-bot-driven-vW8rSJsTxcmdbUm
사용자들과 상호작용하는데 있어, 조금 더 Human-Like 챗봇으로 느낄 수 있는 방법을 찾아 보고자 합니다.
작동 구조와 문제점
메세지 반응 : 유저 메세지에 호출명(디디, DIDI) 혹은 네이버지도 단축 URL이 포함된 경우, 혹은 스레드인 경우 작동하는데, 이는 호출명으로 작동되어 스레드로 대화가 진행되는 구조로, 호출명 없이 작동되지는 못합니다. 예) 디디야 돈까스 맛집 찾아줘.
Chat Memory : 스레드(메세지)의 타임스탬프를 키로 가지고 있어, Context WIndow를 늘리긴 했지만, 스레드 안의 대화만을 기억합니다.
튜닝 방향
직접적인 호출어 없이도 자연스러운 대화 참여
Long term memory에 대한 가능성 검토
유저명 호칭하기
개선 작업 진행
1. 어미 분류 코드 노드 적용
기존의 호출명(디디, DIDI) 혹은 네이버지도 단축 URL이 포함된 경우 외에 유저 입력 메세지에서, 봇 호출을 의도하는 어미를 분류하여 스위치 노드에서 작동 될 수 있도록 변견하였습니다.
예) 돈까스 맛집 좀 찾아봐. 오늘 점심은 해장국 어떨까? 최근 LLM 모델 트랜드에 대해 설명해줘
메세지의 의도 분류를 별도의 AI Agent를 앞에 하나 두어 판단하게 하는 방법도 시도해 보았으나, 분류 결과를 예측할 수 없고, LLM의 결과를 기다리는 약간의 지연시간이 추가되기에. 직접적인 어미 분류 형태로 갔습니다.
2. Chat Memory의 키 값을 채널ID 최우선으로 변경
봇이 채널 단위에서 기본적으로 작동하고 있기에, 기존의 스레드 단위의 대화 맥락 유지 보다는 채널 전체의 대화 흐름을 기억하는 것이 더 메모리 휘발성이 더 낮다고 보여 키값을 채널ID로 변경하고, Context Window Length를 충분히 늘려줍니다.
RAG형태의 벡터 메모리를 사용하는 방법들도 시도 가능한 것으로 보이나, 디디봇의 서비스 목적상 오버엔지니어링으로 판단되었고, 그 외에 user ID를 키로 하여 Chat Memory외 별도의 DB에 저장 후 프롬프트 상에서 가져와 개인화된 대화 맥락을 이어 가는 방법도 유용해 보임
3. 사용자 프로파일 수집 및 프롬프트 적용
Slack APP의 Bot Token Scopes 에서 users관련 프로필 리드 권한을 추가 합니다.
n8n에서 Slack - Get information about a user 노드를 추가하고 사용자의 이름 정보를 얻습니다.
시스템 프롬프트에 반영합니다.
대화상대(user)의 성을 제외한 이름을 'XX님'(예시 : 홍길동 -> 길동님) 형식으로 첫번째 답변 시작에서 적절하게 호칭 한다. 두 번째 턴부터는 바로 본론으로 시작하라(인사/호칭 반복 금지).
적용 결과 및 배운점
호출명이 없이도, agent작동이 필요하다고 구분되는 메세지에서는 반응하여 답하며, 채널 내에서 새로운 스레드가 생성되어도 기존의 대화를 기억하고 맥락을 이어갈 수 있게 되었습니다. 또한 사용자를 OO님 호칭하며, 대화에서 적절하게 표현합니다.
디디봇 생성 후 팀 구성원들이 관계적 상호작용을 하며, 봇을 대상이나 기능이 아닌 고유한 존재로 마주할 수 있는 가능성을 보았고, 슬랙의 USER PROFILE 읽기 권한을 이용한 개선 사항을 적용해 보았습니다.
rag을 활용한 사내 데이터 기반 답변 등, 다시 뭔가 새로운 기능 개선이 이뤄지면 작업 내용 소개해 보도록 하겠습니다.
여러분들도 n8n으로 즐거운 자동화 플로우 구축 해보시기 바랍니다.