기간: 10/18(금) - 10/24(목)
1. 이슈 개요
1.1 목표
- 외국인과 자연스러운 한국어 대화 스타일 구현하기 위해 한국 대학생 ' Minji Kim' 페르소나를 가진 프롬프트로 입력하려고 했음
1.2 발생한 문제
- 그런데, 설정한 시스템 메세지(페르소나가 전혀 적용되지 않음
- AI가 일반적인 ChatGPT처럼 응답
1.3 초기 구현 코드
rtmt = RTMiddleTier(llm_endpoint, llm_deployment, llm_credential)
rtmt.system_message = "You are Minji Kim, a 22-year-old Korean university student..."
2. 문제 분석 과정
2.1 로그 분석
# app.py, rtmt.py에 로깅 추가
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
- 목적: 시스템 메시지 전달 과정 추적
- 발견: WebSocket을 통해 메시지는 전송됨
- 의문점: 웹소켓 메시지가 서버에서 Azure로 전송되는데 왜 AI는 반영하지 않을까? 백엔드에서는 잘되고 있는데 프론트에서 문제가 생기는 게 아닐까?
2.2 프론트엔드 분석
// static/index.html 웹소켓 부분 확인
const ws = new WebSocket(`ws://${window.location.host}/realtime`);
ws.onmessage = async (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);// 여기서 메시지 흐름 확인
};
- 목적: 클라이언트-서버 간 메시지 흐름 파악
- 주목한 부분: 메시지 수신 시점과 처리 순서
- 발견: 없었음. 코드 이해가 부족했고, 잘 작동하고 있다는 사실만 AI 툴 이용해서 알게 됨.
2.3 백엔드 통신 구조 검토
# rtmt.py의 WebSocket 처리 부분
async def _process_message_to_server(self, msg: str, ws: web.WebSocketResponse):
message = json.loads(msg.data)
# 여기서 시스템 메시지 처리 시점 확인
- 목적: 서버 측 메시지 처리 순서 파악
- 확인 포인트: 시스템 메시지 설정 타이밍
- 의문점: 로깅을 더 추가하면서 세션 초기화 시점과 세션 설정 관련 메시지 전달 시점 불일치하는 게 아닐까?라는 의문점 발생
- 로그를 분석하면서 흥미로운 점을 발견했는데, 시스템 메시지는 분명히 전송되고 있었지만 AI는 이를 반영하지 않고 있었음.
- 이 과정에서 저는 처음에 async/await의 비동기 처리 때문에 문제가 발생한다고 생각함. from_server_to_client와 _process_message_to_server 함수의 비동기 처리 순서가 꼬여서 시스템 메시지가 세션 초기화 이후에 전달되어 반영이 안된다고 추측함
- 발견: 하지만, await 함수를 확인한 결과, 이 함수로 인해 비동기 처리 순서가 꼬였다는 게 문제가 아니라는 점을 알게 됨.
3. 세션 설정 관련 JSON 데이터 곧바로 전송하기
- 웹소켓이란 쉽게 말해서 실시간으로 대화하는 전화기와 유사. 일반적인 인터넷 통신이 편지를 주고받는 것이라면, 웹소켓은 전화처럼 계속 연결된 상태로 대화하는 것.
- 이번 문제의 핵심은 '전화를 처음 걸었을 때 상대방에게 누구인지 제대로 알려주지 않은 것'과 비슷.
예를 들어보겠음
- 우리가 만든 AI 챗봇은 "안녕, 나는 김민지야. 22살 대학생이고..."라고 먼저 자기소개를 해야 함.
- 하지만 처음에 전화를 걸자마자 자기소개를 하지 않고, 대화를 좀 하다가 "아, 그러고 보니 나는 민지야!"라고 뒤늦게 말하는 것과 같은 상황이 발생했던 거임.
- 그러다 보니 AI는 처음부터 김민지라는 정체성을 가지고 대화를 시작하지 못했던 것.
해결의 핵심 포인트:
- WebSocket 연결이 설정되자마자 initial_session을 전송함으로써, 서버의 기본 설정이 적용되기 전에 우리가 원하는 설정을 먼저 전달해야 함.
- 시스템 메시지를 포함한 모든 필요한 설정이 세션 시작 시점에 한 번에 전송됩니다.
- 이로 인해 이전에 발생하던 시스템 메시지 지연 문제가 해결됨.
4. 결과 검증
수정 후 로그 확인
2024-10-23 19:37:30,319 - rtmt - INFO - Sent initial session configuration:
{"type": "session.update", "session": {"instructions": "You are Minji Kim..."}}
- 시스템 메시지가 연결 직후 전송 확인
- AI 응답이 한국 대학생 페르소나로 변경
5. 학습 포인트
이 문제를 해결하면서 교훈을 얻음
- API 문서의 한계와 대응 방법
- Azure OpenAI의 실시간 API는 아직 초기 단계라 문서가 거의 없었음.
- 그래서 Open AI의 실시간 API를 참조했는데, 오히려 시간을 낭비.
- 새로운 기술을 도입할 때 본 서비스를 제공하는 API를 공식 문서만 의존하면 안 된다는 교훈 얻음
- 로그 분석의 중요성
- 로그를 자세히 남기고 분석하면서 문제의 실마리를 찾을 수 있었음.
- 특히 메시지가 언제 전송되고, 어떤 순서로 처리되는지 파악할 수 있었음.
- 로깅을 위한 코드
logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) logger.info(f"Sent initial session configuration: {json.dumps(initial_session)}") - 샘플 코드의 가치
- 문서가 부족할 때는 공식 샘플 코드가 최고의 선생님이 될 수 있는 것 같음.
- 샘플 코드를 통해 웹소켓 연결 직후의 초기화 패턴을 발견했고, 이것이 해결책이 됨.
# 마이크로소프트 샘플 앱에서 발견한 패턴 initial_session = { "type": "session.update", "session": { "instructions": self.system_message, # ... 다른 설정들 } } await target_ws.send_json(initial_session)
6. 클라우드 서비스 이용시 교훈
- 초기 단계 서비스 활용 전략
- 새로운 클라우드 서비스는 문서화가 완벽하지 않을 수 있음.
- 이럴 때는 공식 샘플 코드를 꼼꼼히 분석하는 것이 큰 도움이 됨.
- 샘플 코드에 숨어있는 모범 사례(Best Practices)를 발견하려 노력해야 함.
- 문제 해결 접근 방식
- 로그를 활용한 단계적 분석
- 샘플 코드와 내 코드의 차이점 비교
- 공식 문서가 부족할 때의 대안 전략 수립
7. 한계
근본 원인 분석
이런 현상이 발생한 이유는 아마도 다음과 같은 상황 때문일 가능성이 높음:
- Azure OpenAI 서비스의 변경
- 초기에는 서버가 클라이언트의 설정을 좀 더 유연하게 받아들였을 수 있음
- 서비스 업데이트나 변경으로 인해 초기화 순서가 더 엄격해졌을 가능성
- 타이밍 이슈
- 초기에는 우연히 시스템 메시지가 서버의 기본 설정보다 먼저 적용되었을 수 있음
- 서비스 부하나 네트워크 상태에 따라 간헐적으로 발생하다가, 결국 문제가 고착화
- 서버 동작 방식의 변화
- 처음에는 서버가 후속 설정을 덮어쓰기 허용
- 이후 보안이나 안정성을 위해 초기 세션 설정을 더 엄격하게 관리하도록 변경되었을 수 있음
아직 3가지 중 이유를 정확한 이유는 발견하지 못한 상황
8. 다음 단계
- RAG 구현으로 대화 품질 향상
'KB' 카테고리의 다른 글
메타인지: Chat GPT o1도 하는데 나도 해야제? (2) | 2024.11.22 |
---|---|
이퀄라이저 기능 추가 회고 (1) | 2024.11.20 |
우리 앱의 피지컬과 뇌를 해부해보자 (18) | 2024.11.15 |
처음 해보는 네이버 API 연동 이것만 알았어도... : HyperCLOVA 도입 회고 (3) | 2024.11.07 |
Open AI Realtime RAG 앱 구현 전체 과정 회고 [2편] (0) | 2024.10.31 |