code에 AI 를 품다...

엠칩 2026. 2. 26. 11:03

google ai developer program  이라는게 있더군요..

무려 $300 짜리인데 무료로 사용가능... 서비스 기간인듯 싶습니다.

 

서버를 운영하거나 ai 등 각종 프로그램을 구글 서버를 이용해서 돌릴 수 있습니다.

 

간단히 프로젝트 생성하고..

 API키를 생성해서...

ai 기능을 내장한 프로그램을 만들어보았습니다.

 

 

동영상이나 문서 내용을 요약해주는 프로그램입니다.

 

 

음.. 건강에 주의해야겠네요..

 

 

import sys
import time
import google.generativeai as genai
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout,
                             QPushButton, QLineEdit, QTextEdit, QFileDialog, QMessageBox, QLabel, QComboBox)
from PyQt5.QtCore import QThread, pyqtSignal

class AnalysisWorker(QThread):
    progress_signal = pyqtSignal(str)
    result_signal = pyqtSignal(str)
    error_signal = pyqtSignal(str)

    def __init__(self, api_key, model_name, file_path, user_question):
        super().__init__()
        self.api_key = api_key
        self.model_name = model_name
        self.file_path = file_path
        self.user_question = user_question

    def run(self):
        try:
            genai.configure(api_key=self.api_key)
           
            # 2. 모델 설정
            model = genai.GenerativeModel(self.model_name)

            # 3. 파일 업로드 (PDF, MP4, MP3 모두 가능)
            self.progress_signal.emit(f"파일 업로드 중: {self.file_path}...")
            sample_file = genai.upload_file(path=self.file_path)

            # 4. 영상 파일의 경우 처리 완료까지 대기 (문서는 거의 즉시 완료)
            while sample_file.state.name == "PROCESSING":
                self.progress_signal.emit("처리 중...")
                time.sleep(2)
                sample_file = genai.get_file(sample_file.name)

            self.progress_signal.emit("분석 시작!")

            # 5. 질문 던지기
            response = model.generate_content([sample_file, self.user_question])
            self.result_signal.emit(response.text)

        except Exception as e:
            self.error_signal.emit(str(e))

class AIApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Google AI File Analyzer')
        self.resize(600, 500)
        layout = QVBoxLayout()

        # API Key 입력
        api_layout = QHBoxLayout()
        api_layout.addWidget(QLabel("API Key:"))
        self.api_key_input = QLineEdit()
        self.api_key_input.setPlaceholderText("Google AI Studio API Key 입력")
        self.api_key_input.setText("자신의 API코드를 여기에 삽입하세요.")
        self.api_key_input.setEchoMode(QLineEdit.Password)
        api_layout.addWidget(self.api_key_input)
        layout.addLayout(api_layout)

        # 모델 선택
        model_layout = QHBoxLayout()
        model_layout.addWidget(QLabel("Model:"))
        self.model_combo = QComboBox()
        btn_load_models = QPushButton("모델 목록 불러오기")
        btn_load_models.clicked.connect(self.load_models)
        model_layout.addWidget(self.model_combo, 1)
        model_layout.addWidget(btn_load_models)
        layout.addLayout(model_layout)

        # 파일 선택
        file_layout = QHBoxLayout()
        self.path_input = QLineEdit()
        self.path_input.setPlaceholderText("파일 경로 (PDF, MP4 등)")
        btn_file = QPushButton("파일 선택")
        btn_file.clicked.connect(self.select_file)
        file_layout.addWidget(self.path_input)
        file_layout.addWidget(btn_file)
        layout.addLayout(file_layout)

        # 질문 입력
        self.question_input = QLineEdit()
        self.question_input.setPlaceholderText("질문을 입력하세요")
        self.question_input.setText("이 문서의 핵심 내용을 3가지 요약해줘.")
        layout.addWidget(self.question_input)

        # 실행 버튼
        self.btn_run = QPushButton("분석 실행")
        self.btn_run.clicked.connect(self.run_analysis)
        layout.addWidget(self.btn_run)

        # 결과 출력
        self.result_area = QTextEdit()
        self.result_area.setReadOnly(True)
        layout.addWidget(self.result_area)

        self.setLayout(layout)

    def select_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "파일 선택")
        if file_path:
            self.path_input.setText(file_path)

    def load_models(self):
        api_key = self.api_key_input.text().strip()
        if not api_key:
            QMessageBox.warning(self, "경고", "API Key를 입력해주세요.")
            return

        try:
            genai.configure(api_key=api_key)
            self.model_combo.clear()
            for m in genai.list_models():
                if 'generateContent' in m.supported_generation_methods:
                    self.model_combo.addItem(m.name)
            QMessageBox.information(self, "알림", "모델 목록을 불러왔습니다.")
        except Exception as e:
            QMessageBox.critical(self, "오류", f"모델 목록 로드 실패: {e}")

    def run_analysis(self):
        api_key = self.api_key_input.text().strip()
        model_name = self.model_combo.currentText()
        path = self.path_input.text()
        question = self.question_input.text()

        if not api_key:
            QMessageBox.warning(self, "경고", "API Key를 입력해주세요.")
            return

        if not model_name:
            QMessageBox.warning(self, "경고", "모델을 선택해주세요 (목록 불러오기 필요).")
            return

        if not path:
            QMessageBox.warning(self, "경고", "파일을 선택해주세요.")
            return

        self.btn_run.setEnabled(False)
        self.result_area.clear()
       
        self.worker = AnalysisWorker(api_key, model_name, path, question)
        self.worker.progress_signal.connect(self.update_log)
        self.worker.result_signal.connect(self.show_result)
        self.worker.error_signal.connect(self.show_error)
        self.worker.start()

    def update_log(self, msg):
        self.result_area.append(msg)

    def show_result(self, text):
        self.result_area.append("\n=== 결과 ===\n")
        self.result_area.append(text)
        self.btn_run.setEnabled(True)

    def show_error(self, err):
        self.result_area.append(f"\n[오류] {err}")
        self.btn_run.setEnabled(True)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = AIApp()
    ex.show()
    sys.exit(app.exec_())

 

 

 

프로그램을 업그레이드 해봤는데 재미나네요..

인터넷 문서나 유투브 영상도 분석할 수 있게 해봤습니다. txt하고 pdf 만 되던 것도 xls doc ppt도 추가했습니다.

문서는 거의 즉시 처리되고...

영상은 다운로드해서 시청한다음 결과를 분석해서 출력하느라 조금 오래 걸립니다.

 

 

 
"""
Google AI File Analyzer (Gemini 기반 파일/URL 분석기) - 사용 설명서

== 개요 ==
이 프로그램은 Google Gemini AI 모델을 사용하여 로컬 파일(PDF, MP4 등) 또는
YouTube URL의 내용을 분석하고 사용자의 질문에 답변하는 도구입니다.

== 주요 기능 ==
1. 파일 분석: PDF, MP4, MP3, DOCX, PPTX, XLSX 등 다양한 형식의 파일을 분석합니다.
2. YouTube 분석: YouTube 영상 URL을 입력하면 영상을 다운로드하여 내용을 분석합니다.
3. 모델 선택: 다양한 Gemini 모델(gemini-1.5-flash, gemini-1.5-pro 등)을 선택하여 사용할 수 있습니다.

== 사전 준비 ==
1. Google AI Studio API Key 발급: https://aistudio.google.com/app/apikey
2. 필수 라이브러리 설치:
   pip install google-generativeai PyQt5 yt-dlp python-docx python-pptx openpyxl

== 사용 방법 ==
1. API Key 입력: 발급받은 API Key를 입력창에 넣습니다. (기본값 제공됨)
2. 모델 선택: '모델 목록 불러오기' 버튼을 눌러 사용 가능한 모델을 확인하고 선택합니다.
   - 기본적으로 'gemini-2.5-flash' 또는 'gemini-1.5-flash'가 선택됩니다.
3. 파일/URL 입력:
   - '파일 선택' 버튼을 눌러 로컬 파일을 선택하거나,
   - 입력창에 YouTube URL (https://...)을 직접 붙여넣습니다.
4. 질문 입력: 분석하고 싶은 내용을 질문창에 입력합니다. (예: "이 문서의 핵심 내용을 3가지 요약해줘.")
5. 분석 실행: '분석 실행' 버튼을 누르면 파일 업로드 및 AI 분석이 시작됩니다.
   - 영상 파일이나 YouTube URL의 경우 처리 시간이 소요될 수 있습니다.

== 주의 사항 ==
- YouTube 분석 시 `yt-dlp` 라이브러리가 필요하며, 최신 버전 유지를 권장합니다. (pip install -U yt-dlp)
- 대용량 파일이나 긴 영상은 업로드 및 처리 시간이 길어질 수 있습니다.
"""
import sys
import time
import os
import google.generativeai as genai
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout,
                             QPushButton, QLineEdit, QTextEdit, QFileDialog, QMessageBox, QLabel, QComboBox)
from PyQt5.QtCore import QThread, pyqtSignal

class AnalysisWorker(QThread):
    progress_signal = pyqtSignal(str)
    result_signal = pyqtSignal(str)
    error_signal = pyqtSignal(str)

    def __init__(self, api_key, model_name, file_path, user_question):
        super().__init__()
        self.api_key = api_key
        self.model_name = model_name
        self.file_path = file_path
        self.user_question = user_question

    def run(self):
        try:
            genai.configure(api_key=self.api_key)
           
            # 2. 모델 설정
            model = genai.GenerativeModel(self.model_name)

            content = []

            if self.file_path.lower().startswith(('http://', 'https://')):
                self.progress_signal.emit(f"URL 처리 중: {self.file_path}...")
               
                try:
                    import yt_dlp
                    import tempfile
                except ImportError:
                    raise Exception("유튜브 분석을 위해서는 'yt-dlp' 라이브러리가 필요합니다.\n설치: pip install yt-dlp")

                self.progress_signal.emit("동영상 다운로드 중... (잠시만 기다려주세요)")
               
                with tempfile.TemporaryDirectory() as temp_dir:
                    ydl_opts = {
                        'format': 'best[ext=mp4]',
                        'outtmpl': os.path.join(temp_dir, '%(title)s.%(ext)s'),
                        'quiet': True,
                        'noplaylist': True,
                        # 403 Forbidden 에러 방지를 위해 안드로이드 클라이언트로 위장
                        'extractor_args': {'youtube': {'player_client': ['android']}},
                    }
                    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                        info = ydl.extract_info(self.file_path, download=True)
                        filename = ydl.prepare_filename(info)
                   
                    self.progress_signal.emit(f"파일 업로드 중: {os.path.basename(filename)}...")
                    sample_file = genai.upload_file(path=filename)

                    while sample_file.state.name == "PROCESSING":
                        self.progress_signal.emit("서버 처리 중...")
                        time.sleep(2)
                        sample_file = genai.get_file(sample_file.name)
                   
                content.append(sample_file)
            else:
                file_ext = os.path.splitext(self.file_path)[1].lower()
               
                # Office 문서 처리 (텍스트 추출)
                if file_ext == '.docx':
                    try:
                        import docx
                    except ImportError:
                        raise Exception("docx 파일 처리를 위해서는 'python-docx' 라이브러리가 필요합니다.\n설치: pip install python-docx")
                   
                    self.progress_signal.emit(f"docx 파일에서 텍스트 추출 중...")
                    document = docx.Document(self.file_path)
                    full_text = [para.text for para in document.paragraphs]
                    content.append("\n".join(full_text))

                elif file_ext == '.pptx':
                    try:
                        import pptx
                    except ImportError:
                        raise Exception("pptx 파일 처리를 위해서는 'python-pptx' 라이브러리가 필요합니다.\n설치: pip install python-pptx")
                   
                    self.progress_signal.emit(f"pptx 파일에서 텍스트 추출 중...")
                    prs = pptx.Presentation(self.file_path)
                    full_text = []
                    for slide in prs.slides:
                        for shape in slide.shapes:
                            if shape.has_text_frame:
                                for paragraph in shape.text_frame.paragraphs:
                                    for run in paragraph.runs:
                                        full_text.append(run.text)
                    content.append("\n".join(full_text))

                elif file_ext == '.xlsx':
                    try:
                        import openpyxl
                    except ImportError:
                        raise Exception("xlsx 파일 처리를 위해서는 'openpyxl' 라이브러리가 필요합니다.\n설치: pip install openpyxl")

                    self.progress_signal.emit(f"xlsx 파일에서 텍스트 추출 중...")
                    workbook = openpyxl.load_workbook(self.file_path, read_only=True, data_only=True)
                    full_text = []
                    for sheetname in workbook.sheetnames:
                        sheet = workbook[sheetname]
                        full_text.append(f"\n--- 시트: {sheetname} ---\n")
                        for row in sheet.iter_rows():
                            row_text = [str(cell.value) for cell in row if cell.value is not None]
                            if row_text:
                                full_text.append('\t'.join(row_text))
                    content.append("\n".join(full_text))
               
                # 기타 지원 파일 (PDF, MP4 등) 직접 업로드
                else:
                    self.progress_signal.emit(f"파일 업로드 중: {self.file_path}...")
                    sample_file = genai.upload_file(path=self.file_path)

                    while sample_file.state.name == "PROCESSING":
                        self.progress_signal.emit("서버 처리 중...")
                        time.sleep(2)
                        sample_file = genai.get_file(sample_file.name)
                    content.append(sample_file)

            self.progress_signal.emit("분석 시작!")

            # 5. 질문 던지기
            content.append(self.user_question)
            response = model.generate_content(content)
            self.result_signal.emit(response.text)

        except Exception as e:
            self.error_signal.emit(str(e))

class AIApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Google AI File Analyzer')
        self.resize(600, 500)
        layout = QVBoxLayout()

        # API Key 입력
        api_layout = QHBoxLayout()
        api_layout.addWidget(QLabel("API Key:"))
        self.api_key_input = QLineEdit()
        self.api_key_input.setPlaceholderText("Google AI Studio API Key 입력")
        self.api_key_input.setText("AIzaSyCPNU6UzjKMaQL_0JlXvrLGv9OTKX8aFjU")
        self.api_key_input.setEchoMode(QLineEdit.Password)
        api_layout.addWidget(self.api_key_input)
        layout.addLayout(api_layout)

        # 모델 선택
        model_layout = QHBoxLayout()
        model_layout.addWidget(QLabel("Model:"))
        self.model_combo = QComboBox()
        btn_load_models = QPushButton("모델 목록 불러오기")
        btn_load_models.clicked.connect(self.load_models)
        model_layout.addWidget(self.model_combo, 1)
        model_layout.addWidget(btn_load_models)
        layout.addLayout(model_layout)

        # 파일 선택
        file_layout = QHBoxLayout()
        self.path_input = QLineEdit()
        self.path_input.setPlaceholderText("파일 경로 (PDF, MP4, docx, xlsx, pptx 등) 또는 URL 입력")
        btn_file = QPushButton("파일 선택")
        btn_file.clicked.connect(self.select_file)
        file_layout.addWidget(self.path_input)
        file_layout.addWidget(btn_file)
        layout.addLayout(file_layout)

        # 질문 입력
        self.question_input = QLineEdit()
        self.question_input.setPlaceholderText("질문을 입력하세요")
        self.question_input.setText("이 문서의 핵심 내용을 3가지 요약해줘.")
        layout.addWidget(self.question_input)

        # 실행 버튼
        self.btn_run = QPushButton("분석 실행")
        self.btn_run.clicked.connect(self.run_analysis)
        layout.addWidget(self.btn_run)

        # 결과 출력
        self.result_area = QTextEdit()
        self.result_area.setReadOnly(True)
        layout.addWidget(self.result_area)

        self.setLayout(layout)

    def select_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "파일 선택")
        if file_path:
            self.path_input.setText(file_path)

    def load_models(self):
        api_key = self.api_key_input.text().strip()
        if not api_key:
            QMessageBox.warning(self, "경고", "API Key를 입력해주세요.")
            return

        try:
            genai.configure(api_key=api_key)
            self.model_combo.clear()
            for m in genai.list_models():
                if 'generateContent' in m.supported_generation_methods:
                    self.model_combo.addItem(m.name)
           
            # 기본 모델 자동 선택 (gemini-2.5-flash 우선)
            default_index = self.model_combo.findText("models/gemini-2.5-flash")
            if default_index == -1:
                default_index = self.model_combo.findText("models/gemini-1.5-flash")
            if default_index != -1:
                self.model_combo.setCurrentIndex(default_index)
               
            QMessageBox.information(self, "알림", "모델 목록을 불러왔습니다.")
        except Exception as e:
            QMessageBox.critical(self, "오류", f"모델 목록 로드 실패: {e}")

    def run_analysis(self):
        api_key = self.api_key_input.text().strip()
        model_name = self.model_combo.currentText()
        path = self.path_input.text()
        question = self.question_input.text()

        if not api_key:
            QMessageBox.warning(self, "경고", "API Key를 입력해주세요.")
            return

        if not model_name:
            QMessageBox.warning(self, "경고", "모델을 선택해주세요 (목록 불러오기 필요).")
            return

        if not path:
            QMessageBox.warning(self, "경고", "파일을 선택해주세요.")
            return

        self.btn_run.setEnabled(False)
        self.result_area.clear()
       
        self.worker = AnalysisWorker(api_key, model_name, path, question)
        self.worker.progress_signal.connect(self.update_log)
        self.worker.result_signal.connect(self.show_result)
        self.worker.error_signal.connect(self.show_error)
        self.worker.start()

    def update_log(self, msg):
        self.result_area.append(msg)

    def show_result(self, text):
        self.result_area.append("\n=== 결과 ===\n")
        self.result_area.append(text)
        self.btn_run.setEnabled(True)

    def show_error(self, err):
        self.result_area.append(f"\n[오류] {err}")
        self.btn_run.setEnabled(True)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = AIApp()
    ex.show()
    sys.exit(app.exec_())
반응형

'' 카테고리의 다른 글

한국전쟁 vs 러우전쟁 비교  (0) 2026.02.24
iShares Core MSCI Emerging Markets  (0) 2026.02.17
Boston Dynamics 의 상장시 현대자동차그룹 내 지분 관계 변화  (0) 2026.02.09
excel 신박한 단축키들  (11) 2026.02.08
독립  (0) 2026.02.07