feat: Google Drive API 인증 및 에러 처리 개선
This commit is contained in:
@@ -6,13 +6,13 @@
|
|||||||
|
|
||||||
- Hugging Face 모델 (jxm/gpt-oss-20b-base)을 사용하여 AI 에이전트 실행
|
- Hugging Face 모델 (jxm/gpt-oss-20b-base)을 사용하여 AI 에이전트 실행
|
||||||
- 웹 크롤링을 통한 정보 수집
|
- 웹 크롤링을 통한 정보 수집
|
||||||
- 수집된 데이터의 Google Drive 저장
|
- 수집된 데이터의 Google Drive 저장 (마운트 방식 기본, API 선택)
|
||||||
- Colab Pro 환경에서 A100 GPU 활용
|
- Colab Pro 환경에서 A100 GPU 활용
|
||||||
|
|
||||||
## 요구사항
|
## 요구사항
|
||||||
|
|
||||||
- Python 3.8 이상
|
- Python 3.8 이상
|
||||||
- Google Drive API 인증 파일 (credentials.json)
|
- (옵션) Google Drive API 인증 파일 (credentials.json)
|
||||||
- Colab Pro 계정 (A100 GPU 지원)
|
- Colab Pro 계정 (A100 GPU 지원)
|
||||||
|
|
||||||
## 설치 방법
|
## 설치 방법
|
||||||
@@ -23,15 +23,18 @@ pip install -r requirements.txt
|
|||||||
|
|
||||||
## 설정
|
## 설정
|
||||||
|
|
||||||
1. `config.json` 파일에서 다음 항목들을 설정하세요:
|
1. `config.json` 파일 설정:
|
||||||
- `google_drive_folder_id`: 데이터를 저장할 Google Drive 폴더 ID
|
- `data_storage.drive_mount_path`: 기본 저장 경로 (마운트 방식)
|
||||||
- `google_credentials_path`: Google API 인증 파일 경로
|
- (옵션) `google_drive_folder_id`: Google Drive API 업로드 대상 폴더 ID
|
||||||
|
- (옵션) `google_credentials_path`: Google API 인증 파일 경로
|
||||||
|
|
||||||
2. Google Drive API 설정:
|
2. (옵션) Google Drive API 설정:
|
||||||
- Google Cloud Console에서 Drive API 활성화
|
- Google Cloud Console에서 Drive API 활성화
|
||||||
- OAuth 2.0 클라이언트 ID 생성
|
- OAuth 2.0 클라이언트 ID 생성
|
||||||
- credentials.json 파일 다운로드
|
- credentials.json 파일 다운로드
|
||||||
|
|
||||||
|
credentials.json 또는 folder_id가 없으면 API 업로드는 자동 비활성화되고, 마운트 방식 저장만 사용됩니다.
|
||||||
|
|
||||||
## 실행 방법
|
## 실행 방법
|
||||||
|
|
||||||
자세한 실행 방법은 `run_guide.md` 파일을 참고하세요.
|
자세한 실행 방법은 `run_guide.md` 파일을 참고하세요.
|
||||||
|
|||||||
@@ -28,9 +28,28 @@ class AIAgent:
|
|||||||
|
|
||||||
# 도구들 초기화
|
# 도구들 초기화
|
||||||
self.web_scraper = WebScraper(config_path)
|
self.web_scraper = WebScraper(config_path)
|
||||||
self.drive_uploader = GoogleDriveUploader(config_path)
|
|
||||||
self.simple_saver = SimpleDriveSaver(self.config['data_storage']['drive_mount_path'])
|
self.simple_saver = SimpleDriveSaver(self.config['data_storage']['drive_mount_path'])
|
||||||
|
|
||||||
|
# Google Drive API는 선택 사항: 자격증명 파일이 존재할 때만 활성화
|
||||||
|
self.drive_uploader = None
|
||||||
|
try:
|
||||||
|
drive_folder_id = self.config.get('google_drive_folder_id', '').strip()
|
||||||
|
creds_path = self.config.get('google_credentials_path', '').strip()
|
||||||
|
has_valid_folder = bool(drive_folder_id) and drive_folder_id != 'YOUR_GOOGLE_DRIVE_FOLDER_ID'
|
||||||
|
has_creds_file = bool(creds_path) and __import__('os').path.isfile(creds_path)
|
||||||
|
if has_valid_folder and has_creds_file:
|
||||||
|
self.drive_uploader = GoogleDriveUploader(config_path)
|
||||||
|
else:
|
||||||
|
reason = []
|
||||||
|
if not has_valid_folder:
|
||||||
|
reason.append('folder_id 미설정')
|
||||||
|
if not has_creds_file:
|
||||||
|
reason.append('credentials 파일 없음')
|
||||||
|
print(f"Google Drive API 비활성화 ({', '.join(reason)}) — SimpleDriveSaver만 사용")
|
||||||
|
except Exception as e:
|
||||||
|
# 어떤 이유로든 초기화 실패 시 API 도구는 비활성화하고 계속 진행
|
||||||
|
print(f"Google Drive API 초기화 실패: {e} — SimpleDriveSaver만 사용")
|
||||||
|
|
||||||
# LangChain 도구 정의
|
# LangChain 도구 정의
|
||||||
self.tools = [
|
self.tools = [
|
||||||
Tool(
|
Tool(
|
||||||
@@ -38,11 +57,6 @@ class AIAgent:
|
|||||||
func=self.scrape_web,
|
func=self.scrape_web,
|
||||||
description="웹사이트에서 정보를 수집합니다. URL을 입력하세요."
|
description="웹사이트에서 정보를 수집합니다. URL을 입력하세요."
|
||||||
),
|
),
|
||||||
Tool(
|
|
||||||
name="GoogleDriveUploader",
|
|
||||||
func=self.upload_to_drive_api,
|
|
||||||
description="Google Drive API를 사용하여 데이터를 업로드합니다. 데이터와 파일명을 입력하세요."
|
|
||||||
),
|
|
||||||
Tool(
|
Tool(
|
||||||
name="SimpleDriveSaver",
|
name="SimpleDriveSaver",
|
||||||
func=self.save_to_drive_simple,
|
func=self.save_to_drive_simple,
|
||||||
@@ -50,6 +64,16 @@ class AIAgent:
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Google Drive API 도구는 사용 가능할 때만 추가
|
||||||
|
if self.drive_uploader is not None:
|
||||||
|
self.tools.append(
|
||||||
|
Tool(
|
||||||
|
name="GoogleDriveUploader",
|
||||||
|
func=self.upload_to_drive_api,
|
||||||
|
description="Google Drive API를 사용하여 데이터를 업로드합니다. 데이터(JSON)|파일명 형식으로 입력하세요."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# 메모리
|
# 메모리
|
||||||
self.memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
|
self.memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,18 @@ class GoogleDriveUploader:
|
|||||||
"""
|
"""
|
||||||
Google Drive API 인증
|
Google Drive API 인증
|
||||||
"""
|
"""
|
||||||
|
# 자격증명 파일 존재 여부 확인 (명시적으로 친절한 메시지 제공)
|
||||||
|
if not self.creds_path or not os.path.isfile(self.creds_path):
|
||||||
|
raise FileNotFoundError(
|
||||||
|
f"Google Drive API 자격증명 파일을 찾을 수 없습니다: {self.creds_path}.\n"
|
||||||
|
f"config.json의 'google_credentials_path'를 올바른 credentials.json 경로로 설정하거나, API 업로드를 사용하지 마세요."
|
||||||
|
)
|
||||||
|
|
||||||
|
token_path = os.path.join(os.path.dirname(self.creds_path) or '.', 'token.json')
|
||||||
creds = None
|
creds = None
|
||||||
|
|
||||||
if os.path.exists('token.json'):
|
if os.path.exists(token_path):
|
||||||
creds = Credentials.from_authorized_user_file('token.json', self.scopes)
|
creds = Credentials.from_authorized_user_file(token_path, self.scopes)
|
||||||
|
|
||||||
if not creds or not creds.valid:
|
if not creds or not creds.valid:
|
||||||
if creds and creds.expired and creds.refresh_token:
|
if creds and creds.expired and creds.refresh_token:
|
||||||
@@ -35,7 +43,7 @@ class GoogleDriveUploader:
|
|||||||
self.creds_path, self.scopes)
|
self.creds_path, self.scopes)
|
||||||
creds = flow.run_local_server(port=0)
|
creds = flow.run_local_server(port=0)
|
||||||
|
|
||||||
with open('token.json', 'w') as token:
|
with open(token_path, 'w') as token:
|
||||||
token.write(creds.to_json())
|
token.write(creds.to_json())
|
||||||
|
|
||||||
self.service = build('drive', 'v3', credentials=creds)
|
self.service = build('drive', 'v3', credentials=creds)
|
||||||
@@ -44,6 +52,9 @@ class GoogleDriveUploader:
|
|||||||
"""
|
"""
|
||||||
파일을 Google Drive에 업로드
|
파일을 Google Drive에 업로드
|
||||||
"""
|
"""
|
||||||
|
if self.service is None:
|
||||||
|
raise RuntimeError('Google Drive API가 초기화되지 않았습니다. credentials.json과 folder_id를 설정하세요.')
|
||||||
|
|
||||||
if file_name is None:
|
if file_name is None:
|
||||||
file_name = os.path.basename(file_path)
|
file_name = os.path.basename(file_path)
|
||||||
|
|
||||||
@@ -87,6 +98,9 @@ class GoogleDriveUploader:
|
|||||||
"""
|
"""
|
||||||
폴더 내 파일 목록 조회
|
폴더 내 파일 목록 조회
|
||||||
"""
|
"""
|
||||||
|
if self.service is None:
|
||||||
|
raise RuntimeError('Google Drive API가 초기화되지 않았습니다. credentials.json과 folder_id를 설정하세요.')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
results = self.service.files().list(
|
results = self.service.files().list(
|
||||||
q=f"'{self.folder_id}' in parents",
|
q=f"'{self.folder_id}' in parents",
|
||||||
|
|||||||
@@ -194,6 +194,16 @@ os.environ["HF_TOKEN"] = "hf_********************************"
|
|||||||
```
|
```
|
||||||
또는 양자화된/경량화된 공개 모델을 사용하면 메모리 요구량이 크게 줄어듭니다.
|
또는 양자화된/경량화된 공개 모델을 사용하면 메모리 요구량이 크게 줄어듭니다.
|
||||||
|
|
||||||
|
### 6.4 Google Drive API 인증 오류 (credentials.json 없음)
|
||||||
|
|
||||||
|
- 기본 동작은 Google Drive 마운트 기반 저장(SimpleDriveSaver)입니다. 이 방법은 API 자격증명이 필요하지 않습니다.
|
||||||
|
- `config.json`의 `google_credentials_path`가 가리키는 `credentials.json` 파일이 없거나, `google_drive_folder_id`가 기본값이라면 Google Drive API 업로드 도구는 자동으로 비활성화되고, 마운트 저장만 사용합니다.
|
||||||
|
- Google Drive API 업로드가 필요하다면:
|
||||||
|
1) Google Cloud Console에서 OAuth 2.0 클라이언트 ID(데스크톱)를 만들고 JSON을 다운로드
|
||||||
|
2) 프로젝트가 접근 가능한 경로에 파일을 두고 `config.json`의 `google_credentials_path`를 해당 경로로 설정
|
||||||
|
3) 업로드 대상 폴더의 ID를 `google_drive_folder_id`에 설정
|
||||||
|
4) 첫 실행 시 브라우저 인증을 완료하면 `token.json`이 같은 폴더에 생성됩니다.
|
||||||
|
|
||||||
## 7. 확장 및 커스터마이징
|
## 7. 확장 및 커스터마이징
|
||||||
|
|
||||||
### 7.1 새로운 도구 추가
|
### 7.1 새로운 도구 추가
|
||||||
|
|||||||
Reference in New Issue
Block a user