Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- expo 51 오류
- expo 안드로이드
- expo 버전 오류
- expo 51 버전
- 네스트시큐리티
- expo 아이폰
- 스프링 공부
- langchain
- langchain react agent
- langgraph
- 리액트 네이티브
- jotai
- langchain tools
- rnn gnsfus
- VectorDB
- 타입스크립트상태관리
- nestjs시큐리티
- 리액트 네이티브 오류
- react
- 랭체인 툴
- AI
- 이미지처리
- expo 아이폰 오류
- 상태관리
- comfyui
- vllmmcp
- langgraph mcp
- expo go 오류
- 자바공부
- 크로마DB
Archives
- Today
- Total
영리의 테크블로그
소설 캐릭터 정보 추출 & 대화 토이프로젝트 (Book Buddy) 본문
소설 캐릭터 챗봇 개발기: 텍스트 처리부터 채팅 구현까지
웹소설을 읽다가 궁금한 점이 생기면 바로 캐릭터와 대화하면서 확인하고 싶었습니다. 소설을 읽기 전 등장인물들과 대화할 수 있는 기능을 만들고자 했습니다.

https://github.com/YoonJae00/BookBuddy
GitHub - YoonJae00/BookBuddy: 소설원문 기반 채팅 app
소설원문 기반 채팅 app. Contribute to YoonJae00/BookBuddy development by creating an account on GitHub.
github.com
1. 텍스트 분할 (Text Splitting)
소설 텍스트를 효율적으로 처리하기 위해 청크 단위로 분할했습니다:
# 2. 텍스트 분할
chunks = self.text_splitter.split_text(content)
if not chunks:
raise NovelProcessingError("Failed to split text into chunks")
이 과정에서 고려한 점들:
- 문맥 유지를 위한 적절한 청크 크기 설정
- 청크 간 오버랩으로 문맥 연결성 확보
- 메모리 효율성 고려
https://smith.langchain.com/public/8bc2632b-70ea-4471-9e1c-0ae45b153331/r
LangSmith
smith.langchain.com
2. 캐릭터 추출 (Character Extraction)
분할된 텍스트에서 등장인물 정보를 추출합니다:
# 1. 초기 캐릭터 식별
characters = await self._identify_characters(content, novel_id)
if not characters:
raise NovelProcessingError("No characters found in the novel")
for char in characters:
self.name_resolver.add_character(char['full_name'], char['aliases'])
self.logger.log_character_found(char['full_name'], char)
# 캐릭터 정보 저장 (동기식)
db.save_character({
'id': str(uuid.uuid4()),
'novel_id': novel_id,
**char
})
추출하는 캐릭터 정보:
- 이름과 별칭
- 성격 특성
- 배경 정보
- 관계도
- 역할



3. 이벤트 추출 (Event Extraction)
캐릭터들의 행동과 사건을 추출합니다:
# 3. 각 청크 처리
all_events = []
for i, chunk in enumerate(chunks):
try:
normalized_chunk = self._normalize_names(chunk)
events = await self._extract_events(normalized_chunk, i)
for event in events:
# 이벤트 저장 (동기식)
event['id'] = str(uuid.uuid4())
event['novel_id'] = novel_id
db.save_event(event)
self.logger.log_event_extracted(event['summary'], i)
all_events.extend(events)
except Exception as e:
self.logger.log_error(f"Error processing chunk {i}", {"error": str(e)})
continue
이벤트 데이터 구조:
- 사건 요약
- 관련 캐릭터
- 발생 위치(챕터)
- 중요도
- 감정 상태
https://smith.langchain.com/public/8cc0e5b5-c393-4745-8f09-a237c7856b8d/r
LangSmith
smith.langchain.com

4. 채팅 시스템 구현
추출된 정보를 바탕으로 캐릭터와의 대화를 구현합니다:
class CharacterChatbot:
def __init__(self, character_data: Dict, events: List[Dict], settings, user_id: str):
self.character = character_data
self.events = events
self.user_id = user_id
self.db = DatabaseService()
self.vector_store = VectorStore(settings)
self.llm = ChatOpenAI(
temperature=0.7,
model="gpt-4o-mini",
openai_api_key=settings.OPENAI_API_KEY
)
)
self.chat_history = ChatMessageHistory()
# 응답 생성
# 이전 대화 기록 로드
history = self.db.get_chat_history(
character_id=character_data['id'],
user_id=user_id
)
성격: {character[personality_traits]}
for msg in history:
if msg['role'] == 'user':
self.chat_history.add_user_message(msg['content'])
else:
self.chat_history.add_ai_message(msg['content'])
채팅 시스템의 주요 특징:
- 캐릭터 성격 반영
- 관련 이벤트 참조
- 대화 맥락 유지
- 이전 대화 기록 활용
데이터 구조 설계
캐릭터 정보
def save_character(self, character_data: Dict) -> None:
"""캐릭터 정보 저장"""
try:
character_id = character_data.get('id')
if not character_id:
raise Exception("Character ID is required")
.where('novel_id', '==', novel_id)\
self.db.collection('characters')\
.document(character_id)\
.set(character_data)
.where('novel_id', '==', novel_id)\
except Exception as e:
raise Exception(f"Failed to save character: {str(e)}")
이벤트 저장
def save_event(self, event_data: Dict) -> None:
"""이벤트 정보 저장"""
try:
self.db.collection('events').document(event_data['id']).set(event_data)
except Exception as e:
raise Exception(f"Failed to save event: {str(e)}")
대화 기록
def save_chat_history(self, character_id: str, user_id: str, message: Dict) -> None:
"""대화 기록 저장"""
try:
self.db.collection('chat_history').add({
'character_id': character_id,
'user_id': user_id,
'content': message['content'],
'role': message['role'],
'timestamp': firestore.SERVER_TIMESTAMP
})
except Exception as e:
print(f"Failed to save chat history: {str(e)}")
개발 과정에서 배운 점
- 텍스트 처리 최적화
- 전체 텍스트를 저장할 필요 없이, 필요한 정보만 추출하여 저장
- 벡터 검색으로 관련 컨텍스트 효율적 검색
- 캐릭터 정보 구조화
- 캐릭터의 다양한 특성을 체계적으로 저장
- 관계 정보를 통한 캐릭터 간 상호작용 지원
- 이벤트 기반 기억
- 캐릭터의 경험과 기억을 이벤트 단위로 관리
- 대화 중 관련 이벤트 참조로 맥락 유지
- 실시간 대화 처리
- 대화 기록 유지로 일관성 있는 대화 흐름
- 캐릭터 특성에 맞는 응답 생성
향후 개선 방향
- 텍스트 분석 고도화
- 더 정확한 캐릭터 정보 추출
- 감정 분석 추가
- 대화 품질 향상
- 캐릭터 성격 더 정교하게 반영
- 다중 캐릭터 대화 지원
- 사용자 경험 개선
- 실시간 피드백 반영
- 대화 컨텍스트 시각화
'dev > AI' 카테고리의 다른 글
| [Agent 연습] Claude MCP 알아보기 (0) | 2025.04.13 |
|---|---|
| Agent 만들기 [8] - 분신 성격 업데이트: LLM과 상호작용 분석을 활용한 페르소나 발전 (1) | 2024.11.21 |
| Agent 만들기 [7] - LLM 과 SLLM 사이의 고민 (0) | 2024.11.12 |