1. 업데이트 현황
현재까지 구현된 기능에 대한 요약입니다.
- LLM 에이전트 생성 및 응답 받기 (ollama, openai, genai(gemini) 지원)
- Discord로 메시지 보내기 (메시지 청크 분할 및 겹침 지원)
- 음성 파일을 텍스트로 변환하기 (whisper 사용)
- 텍스트 청크 분할 및 겹침 지원
- 2025/09/17 에이전트 메모리 기능 구현
- 2025/09/21 LLM_Agent 클래스에 __call__ 매직 메서드가 추가되어 agent.generate_response() 대신 agent() 직접 호출이 가능해졌습니다.
- 2025/09/21 LLM_Agent 멀티모달 사용 추가
- 2025/09/22 멀티 에이전트 시험 문제 생성기 예제 추가 (YouTube → 시험 문제 자동 생성)
- 2025/09/23 메모리 저장 로직 개선 (실제 LLM 전송 컨텍스트와 메모리 저장 내용 일치화)
2. 모듈 소개
LLM 에이전트 핵심 모듈
1) 인스턴스 생성 - 📄 llm_agent.py
# 기본 LLM 에이전트
from module.llm_agent import LLM_Agent
agent = LLM_Agent(
model_name="gemini-2.5-flash",
provider="genai", # ollama, genai, openai
api_key="your_api_key",
session_id="chat_session",
max_history=10
)
# 멀티모달 에이전트
from module.llm_agent import Multi_modal_agent
modal_agent = Multi_modal_agent(
model_name="gemma3:12b",
provider="ollama", # ollama, genai
api_key=None
)
지원 기능: 다중 LLM 프로바이더 지원 (Ollama, OpenAI, Google Gemini), 대화 기억 기능, 멀티 에이전트 협업, 이미지 분석 및 OCR (멀티모달), __call__ 매직 메서드로 간편한 호출
2) 에이전트 호출하고 응답받기 - 📄 llm_agent.py
# 기본 텍스트 대화
response = agent(
system_prompt="당신은 친근한 AI 비서입니다.",
user_message="오늘 날씨가 어때요?"
)
print(response) # AI의 답변이 출력됩니다
# 메모리 기능으로 이전 대화 기억하기
response_with_memory = agent(
system_prompt="당신은 친근한 AI 비서입니다.",
user_message="제 이름을 기억하시나요?",
memory=True # 이전 대화를 기억합니다
)
# 이미지와 함께 대화하기 (멀티모달)
image_response = modal_agent(
system_prompt="당신은 이미지 분석 전문가입니다.",
user_message="이 사진에 뭐가 보이나요?",
image_path="my_photo.jpg" # 분석할 이미지 파일
)
print(image_response) # 이미지 분석 결과가 출력됩니다
위의 코드 예시는 다양한 방식으로 LLM 에이전트를 활용하는 방법을 보여줍니다. 기본 대화, 메모리 기능을 활용한 연속 대화, 그리고 이미지를 포함한 멀티모달 대화까지 지원합니다.
Discord 웹훅 연동 모듈
Discord 메시지 전송 - 📄 discord.py
from module.discord import Send_to_discord
discord = Send_to_discord(
base_url="your_discord_webhook_url", # Discord 웹훅 URL
chunk_size=1900, # 메시지 청크 크기 (기본: 1900)
overlap=0 # 청크 간 겹침 크기 (기본: 0)
)
주요 기능: LLM 응답을 Discord 채널로 자동 전송, 긴 메시지 청크 분할 처리
음성 처리 모듈
음성을 텍스트로 변환 - 📄 audio_tool.py
from module.audio_tool import Audio
audio = Audio(
text_output="transcripts", # 텍스트 출력 폴더 (기본: "text")
source_file="audio_files", # 음성 파일 폴더 (기본: "source_file")
whisper_model="large-v3", # Whisper 모델 (기본: "large-v3")
preferred_codec="mp3", # 선호 오디오 코덱 (기본: "mp3")
preferred_quality="192" # 오디오 품질 (기본: "192")
)
주요 기능: Whisper를 사용한 음성-텍스트 변환, 다양한 오디오 포맷 지원, 배치 처리
대화 기억 관리 모듈
대화 기록 SQLite 저장 - 📄 memory.py
from module.memory import MemoryManager
memory = MemoryManager(
db_path="memory.db", # 데이터베이스 파일 경로 (기본: "memory.db")
session_id="user_session_01", # 세션 ID (기본: None)
messages=[] # 초기 메시지 리스트 (기본: [])
)
주요 기능: LLM 에이전트의 대화 기록을 SQLite에 저장하고 관리 (챗봇 메모리 기능에 사용)
텍스트 처리 유틸리티
긴 텍스트 청킹 분할 - 📄 text_tool.py
from module.text_tool import Text_tool
text_tool = Text_tool(
chunk_size=1000, # 청크 크기 (기본: 1000)
overlap=100, # 청크 간 겹침 (기본: 0)
max_length=5000 # 최대 길이 제한 (기본: None)
)
주요 기능: 긴 텍스트를 적절한 크기로 분할, JSON 결과 자동 저장 (Discord 메시지 전송, 대용량 문서 처리, 멀티 에이전트 결과 저장에 사용)
JSON 결과 저장 기능 - 📄 text_tool.py
# JSON 결과 자동 저장 기능
text_tool = Text_tool()
# LLM 에이전트 결과를 JSON 파일로 저장
final_output = {
"concepts_and_terms": ["관계대수", "조인", "차집합"],
"questions": [
{
"question": "관계대수에서 '보타이기호'는 어떤 연산자를 의미하나요?",
"options": ["셀렉트", "프로젝트", "조인", "디비전"],
"answer": "조인",
"explanation": "보타이기호는 관계대수에서 조인 연산자를 나타냅니다."
}
]
}
# 자동으로 final_outputs/quiz_result.json 파일로 저장
text_tool.save_result_json(
final_output=final_output, # 저장할 데이터 (dict, list, 또는 JSON 문자열)
output_filename="quiz_result", # 파일명 (확장자 자동 추가)
save_foldername="final_outputs" # 저장할 폴더명 (자동 생성)
)
# 결과: final_outputs/quiz_result.json 파일이 생성됨
print("✅ JSON 파일 저장 완료: final_outputs/quiz_result.json")
자동 기능: 폴더 자동 생성, 파일명 안전화 처리, JSON 파싱 오류 시 텍스트로 저장, 한글 파일명 지원
3. LLM 에이전트 사용하기
llm에이전트 생성하기
📋 사전 요구사항
# 필요한 모듈 임포트
from module.llm_agent import LLM_Agent
# LLM 에이전트 인스턴스 생성
agent = LLM_Agent(
model_name="gemini-2.5-flash", # 사용할 모델명 (예: "gemma:12b", "gpt-4", "gemini-2.5-flash")
provider="genai", # LLM 제공자 ("ollama", "openai", "genai")
api_key="your_api_key", # API 키 (ollama는 None, 나머지는 필수)
session_id="chat_session", # 메모리 기능용 세션 ID (선택사항)
max_history=10 # 기억할 대화 수 (선택사항, 기본: 10)
)
LLM_Agent 클래스의 필수 파라미터와 선택 파라미터를 미리 확인하세요.
model_name = 'gemma:12b' #사용할 모델명을 입력하세요
system_prompt = '당신은 유능한 비서입니다. 이용자에게 도움이 되는 답변을 제공합니다.'
user_prompt = '프랑스의 수도는 어디인가요?'
provider = 'ollama' #현재 사용가능한 provier는 "ollama", "openai","genai(gemini)"입니다
agent = LLM_Agent(model_name, provider, api_key=None)
response = agent(system_prompt, user_prompt, task=None)
print(response)
다음과 같이 에이전트를 생성하세요.
위 코드에서
위 코드에서
model_name
은 사용할 모델의 이름을 지정합니다. system_prompt
는 모델에게 주어지는 시스템 메시지이므로 역할 및 페르소나를 지정하세요. user_prompt
는 llm에게 질문 및 작업을 요청하세요. provider
는 사용할 LLM 제공자를 지정합니다.task
의 기본값은 None이고 필요시 추가 하세요.api_key
의 기본값을 None이므로, ollama를 사용할 경우 API 키가 필요하지 않습니다.
멀티 에이전트 활용하기
📋 사전 요구사항
# 필요한 모듈 임포트
from module.llm_agent import LLM_Agent
# 멀티 에이전트용 LLM 에이전트 생성
multi_agent = LLM_Agent(
model_name="gemma3n", # 사용할 모델명
provider="ollama" # LLM 제공자 (ollama/openai/genai)
)
# 첫 번째 에이전트 실행
agent1_response = multi_agent(
system_prompt="You are a helpful assistant.",
user_message="리눅스에 대해서 설명해주세요.",
task=None # 추가 작업 내용 (선택사항)
)
# 두 번째 에이전트 실행 (첫 번째 응답 활용)
agent2_response = multi_agent(
system_prompt="You are a helpful assistant.",
user_message="앞선 답변을 읽고 내용을 보충해 주세요",
task=None,
multi_agent_response=agent1_response # 이전 에이전트 응답을 전달
)
멀티 에이전트는 하나의 LLM_Agent 인스턴스를 여러 번 호출하여 순차적으로 작업을 처리하는 방식입니다.
from module.llm_agent import LLM_Agent
system_prompt = "You are a helpful assistant."
agent1_user_prompt = "리눅스에 대해서 설명해주세요."
agent2_user_prompt = "앞선 답변을 읽고 내용을 보충해 주세요"
# 복수의 에이전트의 프롬프트를 정의합니다.
multi_agent = LLM_Agent(model_name="gemma3n", provider="ollama")
agent1 = multi_agent(system_prompt, agent1_user_prompt, task=None)
agent2 = multi_agent(system_prompt, agent2_user_prompt, task=None, multi_agent_response=agent1)
# agent1의 답변을 이어 받아, agent2의 프롬프트에 포함시킵니다.
print("Agent 1 Response:", agent1)
print("Agent 2 Response:", agent2)
멀티 에이전트를 활용하려면 다음과 같이 하세요. 여러개의 LLM 에이전트를 구성하세요. 순차적으로 에이전트를 호출하고, 앞의 에이전트의 응답을 다음 에이전트의 프롬프트에 포함시킵니다.
위 코드에서
첫번째 에이전트의 작업을 두번째 에이전트에 전달하여, 각 에이전트가
위 코드에서
multi_agent_response
매개변수를 사용하여 이전 에이전트의 응답을 다음 에이전트에게 전달합니다. 작업을 분할하고 각 에이전트에 맞게 프롬프트를 조정할 수 있습니다.첫번째 에이전트의 작업을 두번째 에이전트에 전달하여, 각 에이전트가
task
를 심화하여 수행할 수 있도록 설정하세요.
모든 에이전트의 응답 통합하기
📋 사전 요구사항
# 필요한 모듈 임포트
from module.llm_agent import LLM_Agent
# 멀티 에이전트 시스템 생성
multi_agent = LLM_Agent(
model_name="gemini-2.5-flash", # 사용할 모델명
provider="genai", # LLM 제공자
api_key="your_api_key" # API 키
)
# 각 에이전트별 역할과 작업 정의
multi_agent_tasks = {
"Agent 1": "환경 문제 분석 작업",
"Agent 2": "교통 인프라 계획 작업",
"Agent 3": "에너지 공급 방안 설계",
"Agent 4": "도시 공간 구조 최적화"
}
# 각 에이전트 실행 후 응답 수집
agent_responses = {
name: multi_agent(system_prompt, user_prompt, task)
for name, task in multi_agent_tasks.items()
}
# 최종 통합 에이전트 실행
final_response = multi_agent(
"통합 전문가 시스템 프롬프트",
"모든 전문가 의견을 종합하여 최종 결론을 내려주세요",
"최종 통합 작업",
list(agent_responses.values()) # 모든 에이전트 응답을 리스트로 전달
)
여러 전문가 에이전트의 의견을 하나의 최종 결론으로 통합하는 고급 멀티 에이전트 패턴입니다.
from module.llm_agent import LLM_Agent
#각 에이전트의 시스템 프롬프트, 사용자 프롬프트, 작업을 정의합니다.
multi_agent_tasks = {
"Agent 1": "도시에서 발생하는 환경 문제(대기, 수질, 쓰레기 등)를 정리하고, 가장 시급한 과제를 제시한다.",
"Agent 2": "친환경 교통수단(대중교통, 자전거, 전기차 등)을 기반으로 지속 가능한 교통 인프라 계획을 제안한다.",
"Agent 3": "재생에너지(태양광, 풍력, 스마트 그리드 등)를 활용하여 효율적인 에너지 공급 방안을 설계한다.",
"Agent 4": "도시 공간 구조(공원, 주거, 상업지구 배치 등)를 최적화한다."
}
multi_agent_system_prompts = {
"Agent 1": "당신은 환경 전문가입니다. 도시의 환경 문제를 분석하고, 가장 시급한 문제를 제시하세요.",
"Agent 2": "당신은 교통 전문가입니다. 지속 가능한 교통 인프라 계획을 제안하세요.",
"Agent 3": "당신은 에너지 전문가입니다. 재생에너지를 활용한 에너지 공급 방안을 설계하세요.",
"Agent 4": "당신은 도시 계획 전문가입니다. 도시 공간 구조를 최적화하는 방안을 제시하세요."
}
user_prompts = {
"Agent 1": "도시에서 발생하는 환경 문제를 분석하고, 가장 시급한 문제를 제시하세요.",
"Agent 2": "지속 가능한 교통 인프라 계획을 제안하세요.",
"Agent 3": "재생에너지를 활용한 에너지 공급 방안을 설계하세요.",
"Agent 4": "도시 공간 구조를 최적화하는 방안을 제시하세요."
}
order = ["Agent 1", "Agent 2", "Agent 3", "Agent 4"]
multi_agent = LLM_Agent(model_name="gemini-2.5-flash", provider="genai", api_key="your_api_key") #여러 에이전트를 생성합니다.
agent_responses = {
name: multi_agent(multi_agent_system_prompts[name], user_prompts[name], multi_agent_tasks[name])
for name in order
}
response_list = [agent_responses[name] for name in order] #각 에이전트의 응답을 순서대로 리스트에 저장합니다.
multi_agent_responses = multi_agent(
"당신은 도시 계획 전문가입니다. 지속 가능한 도시 설계 방안을 제시하세요.",
"다음은 여러 전문가의 의견입니다. 이를 바탕으로 최종 요약 및 통합된 지속 가능한 도시 설계 방안을 제시하세요.",
"최종 요약 및 통합된 지속 가능한 도시 설계 방안을 제시한다.",
response_list
) #모든 에이전트의 응답을 통합하여 최종 응답을 생성합니다.
print("Agent 1 Response:", agent_responses["Agent 1"])
print("Agent 2 Response:", agent_responses["Agent 2"])
print("Agent 3 Response:", agent_responses["Agent 3"])
print("Agent 4 Response:", agent_responses["Agent 4"])
print("Multi-Agent Responses:", multi_agent_responses)
에이전트에게 작업을 각각 할당하고 통합하여 최종 응답을 생성합니다.
위 코드에서 각 에이전트는 특정 작업을 수행하고, 그 응답은 최종 통합 응답을 생성하는 데 사용됩니다. 에이전트 별로 각각의 작업을 할당하고, 하나로 통합한 답을 생성합니다.
위 코드에서 각 에이전트는 특정 작업을 수행하고, 그 응답은 최종 통합 응답을 생성하는 데 사용됩니다. 에이전트 별로 각각의 작업을 할당하고, 하나로 통합한 답을 생성합니다.
LLM에이전트에 기억력 붙이기
📋 사전 요구사항
# 필요한 모듈 임포트
import dotenv, os
from module.llm_agent import LLM_Agent
# 환경변수 로드
dotenv.load_dotenv()
# 메모리 기능이 있는 LLM 에이전트 생성
llm = LLM_Agent(
model_name="gemini-2.5-flash", # 사용할 모델명
provider="genai", # LLM 제공자
api_key=os.getenv("GENAI_API_KEY"), # API 키 (환경변수에서 불러오기)
session_id="user_chat_session", # 대화 세션 구분 ID (선택사항)
max_history=10 # 기억할 대화 수 (선택사항, 기본: 10)
)
# 메모리 기능 활성화하여 대화하기
response = llm(
system_prompt="You are a helpful assistant.",
user_message="안녕하세요, 제 이름은 김철수입니다.",
memory=True # 메모리 기능 활성화 (중요!)
)
# 다음 대화에서 이전 내용 기억됨
next_response = llm(
system_prompt="You are a helpful assistant.",
user_message="제 이름이 뭐라고 했죠?",
memory=True # 이전 대화 기억하여 응답
)
메모리 기능은 SQLite 데이터베이스에 대화 기록을 저장하여 연속적인 대화를 가능하게 합니다.
import dotenv
import os
dotenv.load_dotenv()
# LLM_Agent 인스턴스 생성
llm = LLM_Agent(model_name="gemini-2.5-flash", provider="genai", api_key=os.getenv("GENAI_API_KEY"), max_history=10) #max_history = 기억할 대화 수
# 대화 루프 예시
while True:
user_input = input("You: ")
response = llm(system_prompt="You are a helpful assistant.", user_message=user_input, memory=True) #memory=True로 설정하여 기억력 활성화
print("Assistant:", response)
if user_input.lower() in ['exit', 'quit']:
break
LLM 에이전트에 기억력을 추가하여 이전 대화 내용을 기억하고 활용할 수 있습니다.
간단한 대화 예시입니다. max_history=10으로 설정하여 10개의 이전 대화를 기억합니다.
memory를 활성화 시켜 이전 대화 내용을 활용할 수 있습니다. DB = sqlite3로 제작되었습니다.
간단한 대화 예시입니다. max_history=10으로 설정하여 10개의 이전 대화를 기억합니다.
memory를 활성화 시켜 이전 대화 내용을 활용할 수 있습니다. DB = sqlite3로 제작되었습니다.
LLM에이전트 멀티모달 활용하기
📋 사전 요구사항
# 필요한 모듈 임포트
import os, sys, json, re
from module.llm_agent import Multi_modal_agent
import dotenv
# 멀티모달 에이전트 생성
modal_agent = Multi_modal_agent(
model_name="gemma3:12b", # 멀티모달 지원 모델 (이미지 처리 가능)
provider="ollama", # "ollama" 또는 "genai" 지원
api_key=None # Ollama는 None, Gemini는 API 키 필요
)
# 이미지와 함께 AI에게 질문하기
response = modal_agent(
system_prompt="당신은 영수증 분석 전문가입니다.",
user_prompt="이 영수증의 세부내역을 분석해주세요.",
image_path="receipt.jpg", # 분석할 이미지 파일 경로
task=None # 추가 작업 내용 (선택사항)
)
print(response) # AI가 이미지를 보고 분석한 결과
멀티모달 에이전트는 텍스트와 이미지를 동시에 처리할 수 있는 특별한 에이전트입니다. 영수증 분석, OCR, 이미지 설명 등에 활용됩니다.
import os
import sys
import json
import re
from module.llm_agent import Multi_modal_agent
import dotenv
dotenv.load_dotenv()
# 1) 모델 응답에서 JSON만 뽑아내는 유틸리티 함수입니다.
def extract_json_from_response(response_text):
"""응답에서 JSON 부분만 추출하여 파싱"""
try:
# 우선 ```json ... ``` 코드블록을 찾습니다.
json_match = re.search(r'```json\s*(.*?)\s*```', response_text, re.DOTALL)
if json_match:
json_str = json_match.group(1)
else:
# 없으면 중괄호로 둘러싸인 JSON을 직접 탐색합니다.
json_match = re.search(r'\{.*\}', response_text, re.DOTALL)
if json_match:
json_str = json_match.group(0)
else:
return None, "JSON 형태를 찾을 수 없습니다."
# 문자열을 실제 dict로 파싱합니다.
parsed_json = json.loads(json_str)
return parsed_json, None
except json.JSONDecodeError as e:
return None, f"JSON 파싱 오류: {e}"
except Exception as e:
return None, f"예상치 못한 오류: {e}"
model_name = 'gemma3:12b' # 사용할 모델명(멀티모달 지원 모델)로 교체하세요.
system_prompt = '''당신은 영수증 분석 전문가입니다.
영수증을 보고 다음 JSON 형태로 정확히 반환해주세요:
{
"store_name": "매장명",
"date": "YYYY-MM-DD",
"time": "HH:MM",
"items": [
{"name": "상품명", "price": 가격, "quantity": 수량}
],
"subtotal": 소계,
"tax": 세금,
"total": 총액,
"payment_method": "결제방법"
}'''
user_prompt = '다음 영수증의 세부내역을 위의 JSON 형태로 정확히 반환해주세요. JSON만 반환하고 다른 설명은 추가하지 마세요.'
image_path = "image.png" # 실제 이미지 경로로 교체하세요.
provider = 'ollama' # 제공자 선택: 'ollama' 또는 'genai' (Gemini). 멀티모달 지원 모델 필요.
# 2) 멀티모달 에이전트를 생성하고 호출합니다.
agent = Multi_modal_agent(model_name, provider, api_key=None)
response = agent(system_prompt, user_prompt, image_path=image_path, task=None)
print("=== 원본 응답 ===")
print(response)
print("\n" + "="*50)
# 3) 응답에서 JSON을 파싱하고, 실패 시 원문을 저장합니다.
parsed_data, error = extract_json_from_response(response)
with open("parsed_receipt.json", "w", encoding="utf-8") as f:
if parsed_data:
json.dump(parsed_data, f, ensure_ascii=False, indent=2)
else:
f.write(response) # 파싱 실패 시 원본 텍스트 저장
if parsed_data:
print("=== 파싱된 JSON ===")
print(json.dumps(parsed_data, ensure_ascii=False, indent=2))
print("\n=== 사용 예시 ===")
print(f"매장명: {parsed_data.get('store_name', 'N/A')}")
print(f"총액: {parsed_data.get('total', 'N/A')}원")
print(f"상품 개수: {len(parsed_data.get('items', []))}")
else:
print(f"=== JSON 파싱 실패 ===")
print(f"오류: {error}")
print("원본 텍스트 그대로 사용하세요.")
LLM 에이전트를 멀티모달로 활용하여 이미지와 텍스트를 동시에 처리할 수 있습니다.
위 코드는
활용 예시: 멀티모달+RAG로 고객문의 AI봇 구성 — 사용자가 올린 제품 사진과 설명서/FAQ 검색 결과를 결합해 정확한 답변을 생성하고, 콜센터/FAQ 응답을 자동으로 생성합니다.
위 코드는
Multi_modal_agent
를 사용해 이미지+텍스트를 처리합니다. 응답에서 JSON만 추출하여 parsed_receipt.json
로 저장하고, 파싱에 성공하면 주요 필드를 출력합니다.활용 예시: 멀티모달+RAG로 고객문의 AI봇 구성 — 사용자가 올린 제품 사진과 설명서/FAQ 검색 결과를 결합해 정확한 답변을 생성하고, 콜센터/FAQ 응답을 자동으로 생성합니다.
4. 멀티 에이전트 시험 문제 생성기
YouTube 오디오 → 시험 문제 생성 자동화
📋 사전 요구사항
# 필요한 모듈 임포트
from module.llm_agent import LLM_Agent
from module.audio_tool import Audio
from module.text_tool import Text_tool
import dotenv, os, json
# 오디오 처리기 생성
audio_processor = Audio(
text_output="text_output", # 변환된 텍스트를 저장할 폴더명
source_file="source_file", # 원본 오디오 파일이 있는 폴더명
whisper_model="large-v3", # Whisper 모델 크기 (base/small/medium/large/large-v3)
preferred_codec="mp3", # 선호하는 오디오 코덱 (mp3/wav/m4a)
preferred_quality="192" # 오디오 품질 (128/192/256/320)
)
# LLM 에이전트 생성
llm_agent = LLM_Agent(
model_name="gemini-2.5-flash", # 사용할 LLM 모델명
provider="genai", # LLM 제공자 (ollama/openai/genai)
api_key=os.getenv("GENAI_API_KEY") # API 키 (환경변수에서 불러오기)
)
# 텍스트 분할 도구 생성
text_tool = Text_tool(
chunk_size=2000, # 각 청크의 최대 문자 수
overlap=200, # 청크 간 겹치는 문자 수 (연결성 유지용)
max_length=100 # 파일명 최대 길이 제한
)
주요 파라미터: audio_processor는 Whisper 모델과 출력 경로를 설정하고, llm_agent는 사용할 LLM과 API 키를 설정하며, text_tool은 텍스트 분할 방식을 설정합니다.
📄 generate_quiz.py - 전체 소스코드
from module.llm_agent import LLM_Agent
import dotenv
from module.audio_tool import Audio
from module.text_tool import Text_tool
import os
import json
def main():
print("🗣️ YouTube 시험문제 생성기 시작!")
# --- 1단계: YouTube 영상 다운로드 및 음성 전사 ---
print("\n📹 1단계: YouTube 영상 다운로드 및 음성 전사")
# 오디오 처리 도구 설정 (출력 폴더와 소스 폴더 지정)
audio_processor = Audio(
text_output="text_output", # 전사된 텍스트가 저장될 폴더
source_file="source_file" # 다운로드된 음성 파일이 저장될 폴더
)
# 처리할 YouTube URL 목록 (여러 개 가능)
urls = [
"https://youtu.be/VIDEO_ID_HERE" # 실제 YouTube URL로 교체하세요
]
try:
# YouTube 영상에서 오디오 추출 및 다운로드
audio_processor.download_youtube_audio(urls=urls)
# Whisper AI로 음성을 텍스트로 전사
result = audio_processor.transcribe_audio(whisper_model="large-v3")
print(f"✅ 음성 전사 완료: {result}")
except Exception as e:
print(f"❌ 오디오 처리 중 오류 발생: {e}")
return
# --- 2단계: AI 에이전트로 시험문제 생성 ---
print("\n🤖 2단계: AI 에이전트로 시험문제 생성")
# 전사된 텍스트 파일이 저장된 폴더 확인
text_folder = "text_output"
if not os.path.exists(text_folder):
print(f"❌ 오류: {text_folder} 폴더가 없습니다. 먼저 음성 전사를 완료하세요.")
return
# 전사된 JSON 파일들을 찾아서 정렬
json_files = sorted([
os.path.join(text_folder, f)
for f in os.listdir(text_folder)
if f.endswith('.json')
])
if not json_files:
print(f"❌ {text_folder} 폴더에 JSON 파일이 없습니다.")
return
print(f"📂 발견된 전사 파일: {len(json_files)}개")
# 환경변수에서 API 키 불러오기
dotenv.load_dotenv()
# Gemini AI 에이전트 설정
llm_agent = LLM_Agent(
model_name="gemini-2.5-flash",
provider="genai",
api_key=os.getenv("GENAI_API_KEY")
)
# 3단계 AI 에이전트 프롬프트 설정
agent_user_prompt = {
# 1단계: 개념 추출 에이전트
"agent1": "텍스트에서 시험 문제로 만들 수 있는 핵심 개념과 용어를 추출하세요. JSON 형식: {'concepts_and_terms': ['개념1', '개념2', ...]}",
# 2단계: 문제 생성 에이전트
"agent2": "추출된 개념으로 4지선다 객관식 문제를 3-5개 생성하세요. JSON 형식: [{'question': '문제내용', 'options': ['선택지1', '선택지2', '선택지3', '선택지4'], 'answer': '정답', 'explanation': '해설'}]",
# 3단계: 검토 및 수정 에이전트
"agent3": "생성된 문제들의 오타, 문법, 논리적 오류를 검토하고 수정하세요. 최종 결과를 JSON 형식으로 출력: {'concepts_and_terms': [], 'questions': [], '검토가 필요한 문제 목록': [], '오타 및 수정사항': []}"
}
# 각 에이전트의 역할 정의
agent_system_prompt = {
"agent1": "교육 전문가로서 텍스트에서 중요한 학습 개념을 추출합니다.",
"agent2": "시험 출제 전문가로서 실제 시험과 같은 품질의 4지선다 문제를 만듭니다.",
"agent3": "교정 전문가로서 문제의 오류를 찾아 수정하고 품질을 보장합니다."
}
# 에이전트 실행 순서 정의
order = ["agent1", "agent2", "agent3"]
# 텍스트 분할 도구 설정 (긴 텍스트를 작은 단위로 나누기)
text_tool = Text_tool(
chunk_size=2000, # 각 청크의 최대 크기
overlap=200, # 청크 간 겹치는 부분
max_length=100 # 최대 처리 길이
)
all_chunks = []
# 전사된 텍스트 파일들을 작은 단위로 분할
for json_file in json_files:
try:
print(f"📖 파일 처리 중: {json_file}")
with open(json_file, 'r', encoding='utf-8') as file:
json_content = json.load(file)
# 텍스트를 작은 청크로 분할
chunks = text_tool.split_text_with_overlap(json_content.get("text", ""))
all_chunks.extend(chunks)
print(f" ✅ {len(chunks)}개 텍스트 청크 생성")
except Exception as e:
print(f" ❌ 파일 읽기 오류: {e}")
continue
if not all_chunks:
print("❌ 처리할 텍스트가 없습니다.")
return
print(f"\n🔄 총 {len(all_chunks)}개 텍스트 청크 처리 시작")
# 각 텍스트 청크마다 3단계 에이전트 순차 실행
for i, chunk in enumerate(all_chunks):
print(f"\n📝 === 청크 {i+1}/{len(all_chunks)} 처리 중 ===")
print(f" 내용 미리보기: {chunk[:100]}...")
try:
# Agent1(개념추출) → Agent2(문제생성) → Agent3(검토수정) 순차 실행
agent_responses = {}
current_input = chunk
for agent_name in order:
print(f" 🤖 {agent_name} 실행 중...")
response = llm_agent(
agent_system_prompt[agent_name],
agent_user_prompt[agent_name],
task=current_input
)
agent_responses[agent_name] = response
current_input = response # 다음 에이전트의 입력으로 사용
print(f" ✅ {agent_name} 완료")
# 최종 검토된 시험문제를 JSON 파일로 저장
final_output = agent_responses["agent3"]
print(f"\n✅ 청크 {i+1} 시험문제 생성 완료")
# final_outputs 폴더에 결과 저장
output_filename = f"final_output_chunk_{i+1}"
save_foldername = "final_outputs"
text_tool.save_result_json(final_output, output_filename, save_foldername)
except Exception as e:
print(f"❌ 청크 {i+1} 처리 중 오류: {e}")
continue
print("\n🎉 모든 처리 완료! final_outputs 폴더에서 결과를 확인하세요.")
if __name__ == "__main__":
main()
완전한 파이프라인: YouTube URL → 오디오 다운로드 → Whisper 전사 → text_output 폴더 생성 → 3단계 에이전트 처리 → final_outputs 폴더에 시험문제 저장. Audio 모듈과 Text_tool 모듈을 사용한 완전한 멀티모달 AI 워크플로우입니다.
📁 실행 결과 파일 구조
# 실행 명령어
python generate_quiz.py
# 실행 후 생성되는 파일 구조
final_outputs/
├── final_output_chunk_1.json # 첫 번째 청크 처리 결과
├── final_output_chunk_2.json # 두 번째 청크 처리 결과
├── final_output_chunk_3.json # 세 번째 청크 처리 결과
└── final_output_chunk_N.json # 마지막 청크 처리 결과
# 활용 방법
# 1. 생성된 JSON 파일을 직접 사용
# 2. 교육 플랫폼/시험 시스템에 임포트
# 3. 웹 애플리케이션에서 문제 출제용 데이터로 활용
완성된 워크플로우: YouTube URL 입력 → 자동 전사 → AI 문제 생성 → JSON 저장. 생성된 JSON 파일은 바로 활용 가능한 표준 형태입니다.
📋 실제 생성 결과 예시
{
"concepts_and_terms": [],
"questions": [
{
"question": "다음 중 데이터 조작어(DML)에 해당하는 명령어가 아닌 것은?",
"options": [
"SELECT",
"INSERT",
"UPDATE",
"CREATE"
],
"answer": "CREATE",
"explanation": "CREATE는 데이터 정의어(DDL)에 해당하며, 데이터베이스 객체를 생성하는 데 사용됩니다. SELECT, INSERT, UPDATE는 데이터 조작어(DML)로서 데이터를 검색, 삽입, 수정하는 데 사용됩니다."
},
{
"question": "컴퓨터 기반 시험(CBT)에 대한 설명으로 가장 적절하지 않은 것은?",
"options": [
"시험이 컴퓨터 시스템을 통해 진행된다.",
"대부분의 필기시험에서는 활용되지 않는다.",
"시험 종료 후 즉시 결과를 확인할 수 있는 경우가 많다.",
"문제 은행 방식으로 다양한 난이도의 문제 출제가 가능하다."
],
"answer": "대부분의 필기시험에서는 활용되지 않는다.",
"explanation": "CBT는 컴퓨터를 이용하여 시험을 진행하는 방식으로, 최근 많은 자격증 시험의 필기시험에 널리 활용되고 있습니다. 시험 종료 후 즉시 결과 확인이 가능하며, 문제 은행 방식으로 운영될 수 있습니다."
},
{
"question": "시험 대비를 위해 '기출 문제'를 효과적으로 활용하는 방법으로 가장 올바른 것은?",
"options": [
"단순히 정답만 암기하여 시험에 임한다.",
"출제 경향을 파악하고 자신의 약점을 보완하는 자료로 활용한다.",
"실기시험 준비에는 기출 문제가 전혀 필요 없다고 판단한다.",
"기출 문제만 풀고 새로운 이론 학습은 하지 않는다."
],
"answer": "출제 경향을 파악하고 자신의 약점을 보완하는 자료로 활용한다.",
"explanation": "기출 문제는 시험의 전반적인 출제 경향과 문제 유형을 파악하고, 본인의 부족한 부분을 찾아 보완하는 데 매우 유용한 학습 자료입니다. 단순히 정답만 암기하거나 기출 문제에만 의존하는 것은 올바른 학습 방법이 아닙니다."
}
],
"검토가 필요한 문제 목록": [],
"오타 및 수정사항": []
}
실제 결과물: 위는 실제 generate_quiz.py로 생성된 시험 문제 예시입니다. 데이터베이스 관련 강의에서 CBT, DML, 기출문제 활용법에 대한 실제 4지선다 문제가 자동 생성되었습니다.
5. Discord로 메시지 보내기
LLM응답 결과를 Discord로 전송하기
📋 사전 요구사항
# 필요한 모듈 임포트
from module.discord import Send_to_discord
from module.llm_agent import LLM_Agent
# Discord 메시지 발송기 생성
discord = Send_to_discord(
base_url="https://discord.com/api/webhooks/YOUR_WEBHOOK_URL", # Discord 웹훅 URL (필수)
chunk_size=1900, # 한 번에 보낼 메시지 최대 길이 (선택, 기본: 1900)
overlap=0 # 분할된 메시지 간 겹침 문자 수 (선택, 기본: 0)
)
# LLM 에이전트 생성 및 응답 받기
agent = LLM_Agent(
model_name="gemma3:12b", # 사용할 모델명
provider="ollama", # LLM 제공자
api_key=None # API 키 (ollama는 None)
)
response = agent(
system_prompt="당신은 유능한 비서입니다.",
user_message="프랑스의 수도는 어디인가요?"
)
# AI 응답을 Discord로 전송
discord.send_message(response)
Discord 웹훅 URL은 Discord 채널 설정에서 생성할 수 있습니다. 메시지 길이 제한을 고려하여 적절한 chunk_size를 설정하세요.
from module.discord import Send_to_discord
from module.llm_agent import LLM_Agent
model_name = 'gemma3:12b' #사용할 모델명을 입력하세요
system_prompt = '당신은 유능한 비서입니다. 이용자에게 도움이 되는 답변을 제공합니다.'
user_prompt = '프랑스의 수도는 어디인가요?'
provider = 'ollama' #현재 사용가능한 provier는 "ollama", "openai","genai(gemini)"입니다
agent = LLM_Agent(model_name, provider, api_key=None)
response = agent(system_prompt, user_prompt, task=None)
discord = Send_to_discord(base_url="your_discord_webhook_url") #청크 사이즈 및 겹침 크기 설정
discord.send_message(response)
다음과 같이 Discord로 메시지를 전송할 수 있습니다.
메시지 청크 분할 및 겹침 설정하기
📋 사전 요구사항
# 필요한 모듈 임포트
from module.discord import Send_to_discord
from module.llm_agent import LLM_Agent
# 긴 메시지 자동 분할 Discord 발송기 생성
discord = Send_to_discord(
base_url="https://discord.com/api/webhooks/YOUR_WEBHOOK_URL",
chunk_size=1900, # 각 메시지 청크 최대 크기 (Discord 2000자 제한 고려)
overlap=50 # 청크 간 겹침 문자 수 (연결성 유지용)
)
# 여러 에이전트로 긴 응답 생성
multi_agent = LLM_Agent(
model_name="gemini-2.5-flash", # 사용할 모델명
provider="genai", # LLM 제공자
api_key="your_api_key" # API 키
)
# 긴 응답을 생성하는 멀티 에이전트 실행
long_response = multi_agent(
"당신은 도시 계획 전문가입니다.",
"지속 가능한 도시 설계 방안을 상세히 제시하세요.",
"5000자 이상의 상세한 도시 계획서를 작성한다."
)
# 긴 응답을 자동으로 분할하여 Discord에 순차 전송
discord.send_message(long_response) # 자동으로 1900자씩 나누어 전송
멀티 에이전트의 긴 응답을 Discord 메시지 제한에 맞게 분할하여 전송하는 고급 기능입니다.
from module.discord import Send_to_discord
from module.llm_agent import LLM_Agent
#각 에이전트의 시스템 프롬프트, 사용자 프롬프트, 작업을 정의합니다.
multi_agent_tasks = {
"Agent 1": "도시에서 발생하는 환경 문제(대기, 수질, 쓰레기 등)를 정리하고, 가장 시급한 과제를 제시한다.",
"Agent 2": "친환경 교통수단(대중교통, 자전거, 전기차 등)을 기반으로 지속 가능한 교통 인프라 계획을 제안한다.",
"Agent 3": "재생에너지(태양광, 풍력, 스마트 그리드 등)를 활용하여 효율적인 에너지 공급 방안을 설계한다.",
"Agent 4": "도시 공간 구조(공원, 주거, 상업지구 배치 등)를 최적화한다."
}
multi_agent_system_prompts = {
"Agent 1": "당신은 환경 전문가입니다. 도시의 환경 문제를 분석하고, 가장 시급한 문제를 제시하세요.",
"Agent 2": "당신은 교통 전문가입니다. 지속 가능한 교통 인프라 계획을 제안하세요.",
"Agent 3": "당신은 에너지 전문가입니다. 재생에너지를 활용한 에너지 공급 방안을 설계하세요.",
"Agent 4": "당신은 도시 계획 전문가입니다. 도시 공간 구조를 최적화하는 방안을 제시하세요."
}
user_prompts = {
"Agent 1": "도시에서 발생하는 환경 문제를 분석하고, 가장 시급한 문제를 제시하세요.",
"Agent 2": "지속 가능한 교통 인프라 계획을 제안하세요.",
"Agent 3": "재생에너지를 활용한 에너지 공급 방안을 설계하세요.",
"Agent 4": "도시 공간 구조를 최적화하는 방안을 제시하세요."
}
order = ["Agent 1", "Agent 2", "Agent 3", "Agent 4"]
multi_agent = LLM_Agent(model_name="gemini-2.5-flash", provider="genai", api_key="your_api_key") #여러 에이전트를 생성합니다.
agent_responses = {
name: multi_agent(multi_agent_system_prompts[name], user_prompts[name], multi_agent_tasks[name])
for name in order
}
response_list = [agent_responses[name] for name in order] #각 에이전트의 응답을 순서대로 리스트에 저장합니다.
multi_agent_responses = multi_agent(
"당신은 도시 계획 전문가입니다. 지속 가능한 도시 설계 방안을 제시하세요.",
"다음은 여러 전문가의 의견입니다. 이를 바탕으로 최종 요약 및 통합된 지속 가능한 도시 설계 방안을 제시하세요.",
"최종 요약 및 통합된 지속 가능한 도시 설계 방안을 제시한다.",
response_list
) #모든 에이전트의 응답을 통합하여 최종 응답을 생성합니다.
print("Agent 1 Response:", agent_responses["Agent 1"])
print("Agent 2 Response:", agent_responses["Agent 2"])
print("Agent 3 Response:", agent_responses["Agent 3"])
print("Agent 4 Response:", agent_responses["Agent 4"])
print("Multi-Agent Responses:", multi_agent_responses)
discord = Send_to_discord(base_url="your_discord_webhook_url", chunk_size=1900) #청크 사이즈 및 겹침 크기 설정
discord.send_message(multi_agent_responses)
Discord로 메시지를 보낼 때, 메시지가 너무 길 경우 청크로 나누어 전송할 수 있습니다. 다음과 같이 설정할 수 있습니다.
위 코드에서
청크로 나누어진 메시지는 순차적으로 Discord 채널에 전송됩니다.
위 코드에서
chunk_size
매개변수를 사용하여 각 메시지 청크의 최대 길이를 설정할 수 있습니다. Discord의 메시지 길이 제한을 고려하여 적절한 크기로 설정하세요. overlap
매개변수는 청크 간의 겹침 크기를 설정합니다. 기본값은 0이며, 필요에 따라 조정할 수 있습니다.청크로 나누어진 메시지는 순차적으로 Discord 채널에 전송됩니다.