### 로컬 AI 서버 (Mac mini M4 Pro 64GB) 이 저장소는 Apple Silicon(M4 Pro, RAM 64GB) 환경에서 로컬 AI 모델을 실행해 API 서버로 활용하기 위한 기본 구성과 가이드를 제공합니다. ## 현재 설치 상태 - **러너**: Ollama 0.11.4 확인됨 - **Ollama 로컬 모델**: - qwen2.5:1.5b - mistral:7b - **LM Studio 로컬 모델**: - gemma-3-4b-it ## 하드웨어 요약 (권장 기준) - **칩셋**: Apple M4 Pro (Metal/ANE 가속 활용 가능) - **메모리**: 64GB 통합 메모리 - **권장 동시성**: 1–3 세션(프롬프트 길이에 따라 조절) ## 권장 모델 (M4 Pro 64GB) - **일반 대화/업무** - Llama 3.1 8B Instruct: 품질·속도 밸런스 좋음, 긴 문서 요약/대화에 적합 - Qwen2.5 7B Instruct: 정보 회수/한글 대응 우수, 속도 양호 - Mistral 7B Instruct: 경량/속도 지향, 기본 품질 안정적 - Gemma 2 9B IT: 간결한 답변과 대화 품질 균형 - **코딩 보조** - Qwen2.5-Coder 7B: 코드 생성/수정/해설에 실용적, 메모리 요구도 낮음 - DeepSeek-Coder 6.7B 또는 16B(Lite): 코드 품질 강점, 16B는 속도·메모리 여유 필요 - **초경량** - Phi-3.5/3.1 Mini(3–4B): 간단 질의응답/요약, 서버 부하가 낮음 - 참고: 14–32B급도 구동 가능하나(예: Qwen2.5 14B/32B), 긴 컨텍스트/동시성 시 메모리 여유가 적어질 수 있음. 70B급은 64GB 환경에서 가능하더라도 속도·안정성 상 비권장. ## 설치 (Ollama) 아래 명령으로 권장 모델을 내려받을 수 있습니다. 태그는 상황에 따라 업데이트될 수 있으니 `ollama run ` 시 안내를 확인하세요. ```bash # 일반 대화 ollama pull llama3.1:8b-instruct ollama pull qwen2.5:7b-instruct ollama pull mistral:7b ollama pull gemma2:9b-instruct # 코딩 보조 ollama pull qwen2.5-coder:7b ollama pull deepseek-coder:6.7b # 초경량 ollama pull phi3:mini ``` 이미 설치된 모델 확인: ```bash ollama list ``` 모델 실행(대화형 테스트): ```bash ollama run qwen2.5:7b-instruct ``` ## REST API로 바로 쓰기 (Ollama 내장 서버) Ollama는 기본적으로 `http://localhost:11434`에서 API를 제공합니다. ```bash # 단발성 텍스트 생성 curl http://localhost:11434/api/generate \ -H "Content-Type: application/json" \ -d '{ "model": "qwen2.5:7b-instruct", "prompt": "한국어로 이 모델의 장점을 3가지로 요약해줘", "stream": false }' # Chat 형식 curl http://localhost:11434/api/chat \ -H "Content-Type: application/json" \ -d '{ "model": "llama3.1:8b-instruct", "messages": [ {"role": "user", "content": "로컬 LLM 서버 운영 팁을 알려줘"} ], "stream": false }' ``` TIP: 긴 문서를 다루려면 `num_ctx`(컨텍스트 길이)와 `num_thread`를 모델/하드웨어에 맞춰 조정하세요. 과도하게 늘리면 속도와 메모리 사용량이 크게 증가합니다. ## 포트 정책 - **AI 서버 표준 포트**: 26000 이상 사용 권장 (예: 26000) - 환경 변수 `AI_SERVER_PORT`로 조정 가능. 기본값 26000. 개발 서버 실행 스크립트(`scripts/dev_server.sh`)는 위 정책을 따릅니다. ## 레포지토리/데이터 정책 - **커밋 제외**: 문서 원본(PDF 등)과 런타임 산출물(추출 텍스트/인덱스)은 저장소에 커밋하지 않습니다. - `.gitignore`: `data/`, `*.pdf` 적용됨 - **재현 방법(로컬에서 데이터 생성)**: - PDF → 텍스트/토큰 산출: `scripts/venv_setup.sh` → `source .venv/bin/activate` → `python scripts/pdf_stats.py` - 텍스트 임베딩/인덱스 생성: Ollama 실행 후 `python scripts/embed_ollama.py` - 서버 기동: `scripts/dev_server.sh` (기본 포트 26000) ## 운영 워크플로(요약) - **모델 정책(24/7 + 부스팅)** - 기본 상시: `BASE_MODEL`(권장: `qwen2.5:7b-instruct` 또는 `llama3.1:8b-instruct`) - 필요 시 부스팅: `BOOST_MODEL`(권장: `qwen2.5:14b-instruct`)으로 자동/강제 전환 - 장문은 32k 컨텍스트 + RAG(인덱스 Top-k 주입)로 처리 - **Paperless 연동** - 문서 처리 완료 시(웹훅/잡) → 본문 텍스트 추출 → `/index/upsert`로 인덱스 갱신 - 선택적으로 `/paperless/hook`에 문서 ID를 통지 후 서버가 Paperless API로 조회하도록 확장 가능 - **시놀로지 메일/오피스 연동** - 본문/첨부 텍스트를 `/index/upsert`로 누적(사전 색인) - 사용자 질의는 `/chat` 호출(`use_rag=true`, 필요 시 `force_boost=true`) - 자동 라우팅 규칙(기본): - 영어 비율이 높으면 `ENGLISH_MODEL`(기본 `llama3:8b-instruct`) - 그 외는 길이/강제 부스팅 기준으로 `BASE_MODEL`(7B) 또는 `BOOST_MODEL`(14B) ## API 개요(요약) - 헬스: `GET /health` - 검색: `POST /search` `{ query, top_k }` - 챗: `POST /chat` `{ messages, use_rag, top_k, force_boost, options }` - 인덱스 업서트: `POST /index/upsert` `{ rows:[{id,text,source}], embed }` - 인덱스 리로드: `POST /index/reload` - Paperless 훅 자리표시자: `POST /paperless/hook` ## API 개요 (Paperless/시놀로지 연동) - 기본 베이스 모델(24/7): `BASE_MODEL` (기본: `qwen2.5:7b-instruct`) - 온디맨드 부스팅 모델: `BOOST_MODEL` (기본: `qwen2.5:14b-instruct`) - 임베딩(RAG): `EMBEDDING_MODEL` (기본: `nomic-embed-text`), 인덱스 파일 `INDEX_PATH` (기본: `data/index.jsonl`) - 문서화: `http://localhost:26000/docs` (FastAPI 자동 문서) ### 헬스체크 ```bash curl -s http://localhost:26000/health ``` ### 검색(Search, RAG용) ```bash curl -s -X POST http://localhost:26000/search \ -H 'Content-Type: application/json' \ -d '{ "query": "질문 내용", "top_k": 5 }' ``` ### 채팅(Chat, RAG/부스팅 자동) ```bash curl -s -X POST http://localhost:26000/chat \ -H 'Content-Type: application/json' \ -d '{ "messages": [ {"role": "user", "content": "문서 내용 기반으로 요약해줘"} ], "use_rag": true, "top_k": 5, "force_boost": false, "options": {"num_ctx": 32768, "temperature": 0.3} }' ``` 필드 설명: - `use_rag`: 인덱스(`INDEX_PATH`)에서 상위 청크를 검색해 시스템 프롬프트로 주입 - `force_boost`: 강제로 부스팅 모델 사용(고난도/장문) - `options`: Ollama 옵션(예: `num_ctx`, `temperature` 등) ### 인덱스 갱신(Upsert) Paperless/시놀로지에서 추출한 본문 텍스트를 직접 인덱스에 추가합니다. ```bash curl -s -X POST http://localhost:26000/index/upsert \ -H 'Content-Type: application/json' \ -d '{ "rows": [ {"id": "paperless:123", "text": "문서 본문 텍스트", "source": "paperless"} ], "embed": true }' ``` ### 인덱스 리로드 ```bash curl -s -X POST http://localhost:26000/index/reload ``` ### Paperless 훅(Webhook) 자리표시자 ```bash curl -s -X POST http://localhost:26000/paperless/hook \ -H 'Content-Type: application/json' \ -d '{"document_id": 123, "title": "문서제목", "tags": ["finance"]}' ``` 해당 훅은 문서 도착을 통지받는 용도로 제공됩니다. 실제 본문 텍스트는 Paperless API로 조회해 `/index/upsert`로 추가하세요. ### Paperless 배치 동기화(`/paperless/sync`) ### 문서 파이프라인(`/pipeline/ingest`) 첨부 문서(텍스트가 준비된 상태: OCR/추출 선행) → (옵션)요약 → (옵션)번역 → 임베딩 → HTML 생성까지 처리합니다. ```bash curl -s -X POST http://localhost:26000/pipeline/ingest \ -H 'Content-Type: application/json' -H 'X-API-Key: <키>' \ -d '{ "doc_id": "doc-2025-08-13-001", "text": "(여기에 문서 텍스트)", "generate_html": true, "translate": true, "target_language": "ko", "summarize": false, "summary_sentences": 5, "summary_language": null }' ``` 응답에 `html_path`가 포함됩니다. - 요약 켜짐(`summarize=true`): 청크별 요약 후 통합 요약을 생성해 사용(기본 5문장). `summary_language`로 요약 언어 선택 가능(기본 번역 언어와 동일, 번역 off면 ko). - 번역 켜짐(`translate=true`): 최종 텍스트를 대상 언어로 번역해 HTML+인덱스화. - 번역 꺼짐(`translate=false`): 최종 텍스트(요약 또는 원문)로 HTML+인덱스화. 파일 업로드 버전(`/pipeline/ingest_file`): `.txt`/`.pdf` 지원 ```bash curl -s -X POST http://localhost:26000/pipeline/ingest_file \ -H 'X-API-Key: <키>' \ -F 'file=@/path/to/file.pdf' \ -F 'doc_id=doc-001' \ -F 'generate_html=true' \ -F 'translate=false' \ -F 'target_language=ko' ``` Paperless에서 다수 문서를 일괄 인덱싱합니다. ```bash curl -s -X POST http://localhost:26000/paperless/sync \ -H 'Content-Type: application/json' -H 'X-API-Key: <키>' \ -d '{ "page_size": 50, "ordering": "-created", "tags": null, "query": null, "limit": 200 }' ``` ## 시놀로지 메일/오피스 연동 가이드(요약) - **검색/QA 호출 엔드포인트**: `http://:26000/search`, `http://:26000/chat` - **권장 흐름**: - 메일/문서 본문 → `/index/upsert`로 인덱스 추가(임베딩 생성) - 사용자 질의 → `/chat` 호출(`use_rag=true`) → 관련 청크 Top-k 주입 후 응답 - **모델 라우팅**: - 기본: 베이스 모델(7B/8B) - 장문/고난도: `force_boost=true` 또는 메시지 길이에 따라 자동 부스팅(14B) ## 환경 변수 - `AI_SERVER_PORT`(기본 26000): 서버 포트 - `OLLAMA_HOST`(기본 `http://localhost:11434`): Ollama API 호스트 - `BASE_MODEL`(기본 `qwen2.5:7b-instruct`) - `BOOST_MODEL`(기본 `qwen2.5:14b-instruct`) - `ENGLISH_MODEL`(기본 `llama3:8b-instruct`): 영어 감지 시 라우팅 대상 - `ENGLISH_RATIO_THRESHOLD`(기본 `0.65`): 영어 비율 임계값(초과 시 영어 모델) - `EMBEDDING_MODEL`(기본 `nomic-embed-text`) - `INDEX_PATH`(기본 `data/index.jsonl`) - `PAPERLESS_BASE_URL`, `PAPERLESS_TOKEN`(선택): Paperless API 연동 시 사용 - `PAPERLESS_VERIFY_SSL`(기본 `true`): Paperless HTTPS 검증 비활성화는 `false` - `PAPERLESS_CA_BUNDLE`(선택): 신뢰할 CA 번들 경로 지정 시 해당 번들로 검증 - `OUTPUT_DIR`(기본 `outputs`): 파이프라인 산출물(HTML) 저장 루트 - `EXPORT_HTML_DIR`(선택): HTML 산출물 사본을 내보낼 디렉터리(예: 시놀로지 공유 폴더) - `EXPORT_UPLOAD_DIR`(선택): 업로드 원본 파일 보관 디렉터리 - `API_KEY`(선택): 설정 시 모든 민감 엔드포인트 호출에 `X-API-Key` 헤더 필요 - `CORS_ORIGINS`(선택): CORS 허용 오리진(쉼표 구분), 미설정 시 `*` `.env` 예시: ```bash AI_SERVER_PORT=26000 OLLAMA_HOST=http://localhost:11434 BASE_MODEL=qwen2.5:7b-instruct BOOST_MODEL=qwen2.5:14b-instruct EMBEDDING_MODEL=nomic-embed-text INDEX_PATH=data/index.jsonl API_KEY=changeme CORS_ORIGINS=http://localhost:5173,http://synology.local ``` OpenAI 호환 호출 예시: ```bash curl -s -X POST http://localhost:26000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "X-API-Key: changeme" \ -d '{ "model":"qwen2.5:14b-instruct", "messages":[{"role":"user","content":"이 서버 기능을 한 줄로 설명"}], "temperature":0.3 }' ``` ## AI 서버 관리 페이지 (Admin Dashboard) AI 서버의 효율적인 관리를 위한 웹 기반 관리 페이지를 제공합니다. ### 관리 페이지 접근 - **URL**: `http://localhost:26000/admin` - **인증**: API 키 기반 (환경변수 `API_KEY` 설정 필요) ### 주요 기능 #### Phase 1: 기본 관리 기능 ✅ - **시스템 상태 대시보드**: 서버/Ollama/모델 상태 실시간 모니터링 - **모델 관리**: 설치된 모델 목록, 활성 모델 현황, 모델별 사용 통계 - **API 키 관리**: 키 생성/조회/삭제, 사용량 모니터링 #### Phase 2: 고급 기능 (계획) - **모델 다운로드/삭제**: Ollama 모델 원격 관리 - **실시간 모니터링**: CPU/메모리/GPU 사용률, API 호출 통계 - **설정 관리**: 환경변수 편집, Paperless 연동 설정 #### Phase 3: 보안 강화 (계획) - **인증 시스템**: JWT 기반 로그인, 2FA 지원 - **접근 제어**: IP 화이트리스트, 권한 관리 - **감사 로그**: 모든 관리 작업 기록 및 추적 ### 보안 고려사항 - **API 키 암호화**: AES-256 암호화 저장 - **HTTPS 강제**: SSL/TLS 인증서 필수 - **접근 로그**: 모든 관리 페이지 접근 기록 - **민감 정보 보호**: 로그에서 API 키 자동 마스킹 ### 사용 예시 ```bash # API 키 설정 export API_KEY=your-secure-api-key # 서버 실행 python -m server.main # 관리 페이지 접근 curl -H "X-API-Key: your-secure-api-key" http://localhost:26000/admin ``` ## 이 저장소 사용 계획 1) ✅ Ollama API를 감싸는 경량 서버(FastAPI) 구현 완료 2) ✅ 표준화된 엔드포인트(`/v1/chat/completions`, `/v1/completions`) 제공 3) ✅ 헬스체크/모델 선택/리밋/로깅 옵션 제공 4) 🚧 웹 기반 관리 페이지 구현 중 (Phase 1) 우선 본 문서로 설치/선택 가이드를 정리했으며, 현재 관리 페이지와 고급 기능들을 단계적으로 추가하고 있습니다.