Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,107 +1,132 @@
|
|
| 1 |
import os
|
| 2 |
import time
|
| 3 |
-
import google.generativeai as genai
|
| 4 |
-
from PyPDF2 import PdfReader
|
| 5 |
import streamlit as st
|
|
|
|
|
|
|
|
|
|
| 6 |
import markdown
|
| 7 |
import pyperclip
|
|
|
|
| 8 |
|
| 9 |
-
# Google Gemini API 설정 (
|
| 10 |
genai.configure(api_key=os.environ["GEMINI_API_KEY"])
|
| 11 |
|
| 12 |
-
#
|
| 13 |
generation_config = {
|
| 14 |
-
"temperature":
|
| 15 |
"top_p": 0.95,
|
| 16 |
"top_k": 40,
|
| 17 |
-
"max_output_tokens":
|
| 18 |
"response_mime_type": "text/plain",
|
| 19 |
}
|
| 20 |
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
"""PDF 파일에서 텍스트를 추출합니다."""
|
|
|
|
| 23 |
try:
|
| 24 |
-
pdf_reader = PdfReader(
|
| 25 |
-
text = ""
|
| 26 |
for page_num in range(len(pdf_reader.pages)):
|
| 27 |
page = pdf_reader.pages[page_num]
|
| 28 |
-
text += page.extract_text()
|
| 29 |
-
return text
|
| 30 |
except Exception as e:
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
try:
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
# 프롬프트 생성
|
| 45 |
-
prompt = (
|
| 46 |
-
f"다음 서식을 사용하여 보고서를 작성하십시오:\n\n"
|
| 47 |
-
f"{report_format}\n\n"
|
| 48 |
-
f"다음 참고 자료를 사용하십시오:\n\n"
|
| 49 |
-
f"{reference_text}\n\n"
|
| 50 |
-
f"추가 지침:\n\n"
|
| 51 |
-
f"{additional_instructions}\n\n"
|
| 52 |
-
f"보고서를 최대한 자세하고 유익하게 작성하십시오."
|
| 53 |
-
)
|
| 54 |
-
|
| 55 |
-
# Gemini API 호출
|
| 56 |
-
response = genai.generate_text(prompt, **generation_config)
|
| 57 |
-
if hasattr(response, 'result'):
|
| 58 |
-
full_text = response.result
|
| 59 |
-
elif isinstance(response, dict) and 'result' in response:
|
| 60 |
-
full_text = response['result']
|
| 61 |
-
else:
|
| 62 |
-
raise Exception("Gemini API로부터 올바르지 않은 응답을 받지 못했습니다.")
|
| 63 |
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
except Exception as e:
|
| 66 |
-
st.error(f"
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
# Streamlit
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
#
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
#
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
output_area.markdown(html_text, unsafe_allow_html=True)
|
| 91 |
|
| 92 |
-
# 복사 버튼
|
| 93 |
-
|
| 94 |
-
pyperclip.copy(generated_report)
|
| 95 |
st.success("복사되었습니다!")
|
| 96 |
-
|
| 97 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
-
# 이미 생성된
|
| 100 |
-
if "
|
| 101 |
-
html_text = markdown.markdown(st.session_state.
|
| 102 |
output_area.markdown(html_text, unsafe_allow_html=True)
|
| 103 |
|
| 104 |
-
# 복사 버튼 추가 (이미 생성된 경우)
|
| 105 |
if st.button("출력 내용 복사", key="copy_button_2"):
|
| 106 |
-
pyperclip.copy(st.session_state.
|
| 107 |
st.success("복사되었습니다!")
|
|
|
|
| 1 |
import os
|
| 2 |
import time
|
|
|
|
|
|
|
| 3 |
import streamlit as st
|
| 4 |
+
from PIL import Image # 이미지 관련 라이브러리는 필요 없을 수 있지만, 일단 포함
|
| 5 |
+
import google.generativeai as genai
|
| 6 |
+
from streamlit_extras.colored_header import colored_header
|
| 7 |
import markdown
|
| 8 |
import pyperclip
|
| 9 |
+
import PyPDF2 # PDF 처리 라이브러리 추가
|
| 10 |
|
| 11 |
+
# Google Gemini API 키 설정 (기존 코드와 동일)
|
| 12 |
genai.configure(api_key=os.environ["GEMINI_API_KEY"])
|
| 13 |
|
| 14 |
+
# 모델 설정 (기존 코드와 동일)
|
| 15 |
generation_config = {
|
| 16 |
+
"temperature": 0.7, # temperature 값 조정 (보고서/계획서는 창의성보다 정확성이 중요할 수 있음)
|
| 17 |
"top_p": 0.95,
|
| 18 |
"top_k": 40,
|
| 19 |
+
"max_output_tokens": 4096,
|
| 20 |
"response_mime_type": "text/plain",
|
| 21 |
}
|
| 22 |
|
| 23 |
+
model = genai.GenerativeModel(
|
| 24 |
+
model_name="gemini-2.0-flash-exp", # 필요에 따라 모델 변경 가능 (pro, flash 등)
|
| 25 |
+
generation_config=generation_config,
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
# PDF 텍스트 추출 함수
|
| 29 |
+
def extract_text_from_pdf(uploaded_pdf_file):
|
| 30 |
"""PDF 파일에서 텍스트를 추출합니다."""
|
| 31 |
+
text = ""
|
| 32 |
try:
|
| 33 |
+
pdf_reader = PyPDF2.PdfReader(uploaded_pdf_file)
|
|
|
|
| 34 |
for page_num in range(len(pdf_reader.pages)):
|
| 35 |
page = pdf_reader.pages[page_num]
|
| 36 |
+
text += page.extract_text()
|
|
|
|
| 37 |
except Exception as e:
|
| 38 |
+
st.error(f"PDF 파일 처리 오류: {e}")
|
| 39 |
+
return None
|
| 40 |
+
return text
|
| 41 |
+
|
| 42 |
+
def generate_report_or_plan(pdf_text, user_instructions):
|
| 43 |
+
"""
|
| 44 |
+
PDF 텍스트와 사용자 지시사항을 기반으로 보고서 또는 계획서를 생성합니다.
|
| 45 |
+
Args:
|
| 46 |
+
pdf_text: 추출된 PDF 텍스트
|
| 47 |
+
user_instructions: 사용자 지시사항
|
| 48 |
+
Returns:
|
| 49 |
+
str: 생성된 보고서 또는 계획서 텍스트
|
| 50 |
+
"""
|
| 51 |
+
full_text = ""
|
| 52 |
try:
|
| 53 |
+
prompt_text = f"""
|
| 54 |
+
# PDF 문서 분석 및 보고서/계획서 작성
|
| 55 |
+
|
| 56 |
+
## PDF 문서 내용:
|
| 57 |
+
```
|
| 58 |
+
{pdf_text}
|
| 59 |
+
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
+
## 사용자 지시사항:
|
| 62 |
+
{user_instructions}
|
| 63 |
+
|
| 64 |
+
---
|
| 65 |
+
|
| 66 |
+
**지시사항에 따라 PDF 문서 내용을 분석하고, 보고서 또는 계획서를 작성하세요.**
|
| 67 |
+
**한국어로 작성하며, 명확하고 논리적인 구조로 작성해주세요.**
|
| 68 |
+
**필요하다면, PDF 문서 내용을 참고하여 추가적인 정보를 생성하거나 확장해도 좋습니다.**
|
| 69 |
+
**만약 PDF 내용이 부족하거나 지시사항을 수행하기 어렵다면, 솔직하게 답변해주세요.**
|
| 70 |
+
|
| 71 |
+
""" # 프롬프트 개선: 더 명확하고 구체적인 지시 포함
|
| 72 |
+
|
| 73 |
+
response = model.generate_content([prompt_text]) # 이미지 대신 텍스트 프롬프트만 사용
|
| 74 |
+
for chunk in response.text:
|
| 75 |
+
full_text += chunk
|
| 76 |
+
time.sleep(0.01)
|
| 77 |
+
st.session_state.generated_result += chunk
|
| 78 |
+
output_area.markdown(st.session_state.generated_result, unsafe_allow_html=True)
|
| 79 |
except Exception as e:
|
| 80 |
+
st.error(f"보고서/계획서 생성 중 오류 발생: {str(e)}")
|
| 81 |
+
return full_text
|
| 82 |
+
|
| 83 |
+
# Streamlit 인터페이스 설정 (기존 코드와 유사)
|
| 84 |
+
colored_header(
|
| 85 |
+
label="PDF 보고서/계획서 자동 작성 AI",
|
| 86 |
+
description="PDF 서식 파일을 업로드하고 지시사항을 입력하면 보고서/계획서를 작성해줍니다.",
|
| 87 |
+
color_name="blue-70", # 색상 변경
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
# 파일 업로드 버튼 (PDF 파일만 허용)
|
| 91 |
+
uploaded_pdf_file = st.file_uploader("PDF 서식 파일 업로드", type=["pdf"])
|
| 92 |
+
|
| 93 |
+
# 지시사항 입력 텍스트 영역 추가
|
| 94 |
+
user_instructions = st.text_area("작성 지시사항 입력 (예: '이 PDF를 바탕으로 2024년 마케팅 계획 보고서를 작성해주세요.', '핵심 내용을 요약하고, 개선 방안을 3가지 제시해주세요.')",
|
| 95 |
+
placeholder="자세하고 명확하게 지시사항을 입력하세요.") # placeholder 추가
|
| 96 |
+
|
| 97 |
+
generate_button = st.button("보고서/계획서 생성")
|
| 98 |
+
|
| 99 |
+
output_area = st.empty() # 출력 영역 (기존 코드와 동일)
|
| 100 |
+
|
| 101 |
+
if generate_button and uploaded_pdf_file and user_instructions: # 지시사항도 입력되었는지 확인
|
| 102 |
+
try:
|
| 103 |
+
pdf_text = extract_text_from_pdf(uploaded_pdf_file) # PDF 텍스트 추출
|
| 104 |
+
if pdf_text: # 텍스트 추출 성공 시
|
| 105 |
+
st.session_state.generated_result = "" # 결과 초기화
|
| 106 |
+
result = generate_report_or_plan(pdf_text, user_instructions) # 보고서/계획서 생성
|
| 107 |
+
|
| 108 |
+
html_text = markdown.markdown(result, extensions=['tables']) # Markdown 형식으로 변환 (필요에 따라 조정)
|
| 109 |
output_area.markdown(html_text, unsafe_allow_html=True)
|
| 110 |
|
| 111 |
+
if st.button("출력 내용 복사", key="copy_button_1"): # 복사 버튼 (기존 코드와 동일)
|
| 112 |
+
pyperclip.copy(result)
|
|
|
|
| 113 |
st.success("복사되었습니다!")
|
| 114 |
+
else:
|
| 115 |
+
st.warning("PDF 파일에서 텍스트를 추출하는데 실패했습니다. 파일 형식을 확인해주세요.")
|
| 116 |
+
|
| 117 |
+
except Exception as e:
|
| 118 |
+
st.error(f"보고서/계획서 생성 중 오류 발생: {str(e)}")
|
| 119 |
+
|
| 120 |
+
elif generate_button and not uploaded_pdf_file:
|
| 121 |
+
st.warning("PDF 서식 파일을 업로드하세요.")
|
| 122 |
+
elif generate_button and not user_instructions:
|
| 123 |
+
st.warning("작성 지시사항을 입력하세요.")
|
| 124 |
|
| 125 |
+
# 이미 생성된 결과가 있을 경우 출력 (기존 코드와 동일)
|
| 126 |
+
if "generated_result" in st.session_state and st.session_state.generated_result:
|
| 127 |
+
html_text = markdown.markdown(st.session_state.generated_result, extensions=['tables'])
|
| 128 |
output_area.markdown(html_text, unsafe_allow_html=True)
|
| 129 |
|
|
|
|
| 130 |
if st.button("출력 내용 복사", key="copy_button_2"):
|
| 131 |
+
pyperclip.copy(st.session_state.generated_result)
|
| 132 |
st.success("복사되었습니다!")
|