lily_fast_api / docs /API_REFERENCE.md
gbrabbit's picture
Fresh start for HF Spaces deployment
526927a
# Lily LLM API ์ฐธ์กฐ ๋ฌธ์„œ
## ๐Ÿ“‹ ๊ฐœ์š”
Lily LLM API๋Š” ๋‹ค์–‘ํ•œ ์–ธ์–ด ๋ชจ๋ธ์„ ์ง€์›ํ•˜๋Š” RESTful API ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. ํ…์ŠคํŠธ ์ƒ์„ฑ, ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ์ฒ˜๋ฆฌ, RAG(Retrieval-Augmented Generation) ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
## ๐Ÿ”— ๊ธฐ๋ณธ ์ •๋ณด
- **Base URL**: `http://localhost:8001`
- **API ๋ฌธ์„œ**: `http://localhost:8001/docs`
- **ReDoc ๋ฌธ์„œ**: `http://localhost:8001/redoc`
## ๐Ÿ” ์ธ์ฆ
### JWT ํ† ํฐ ์ธ์ฆ
```bash
# ๋กœ๊ทธ์ธ
curl -X POST "http://localhost:8001/auth/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=your_username&password=your_password"
# ์‘๋‹ต
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"token_type": "bearer"
}
```
### ๋ณดํ˜ธ๋œ ์—”๋“œํฌ์ธํŠธ ์‚ฌ์šฉ
```bash
curl -X GET "http://localhost:8001/auth/me" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```
## ๐Ÿค– AI ๋ชจ๋ธ ๊ด€๋ จ
### 1. ๋ชจ๋ธ ๋ชฉ๋ก ์กฐํšŒ
```http
GET /models
```
**์‘๋‹ต ์˜ˆ์‹œ:**
```json
{
"available_models": [
{
"model_id": "polyglot-ko-1.3b-chat",
"display_name": "Polyglot Korean 1.3B Chat",
"model_type": "text",
"description": "ํ•œ๊ตญ์–ด ํŠนํ™” ํ…์ŠคํŠธ ์ƒ์„ฑ ๋ชจ๋ธ"
},
{
"model_id": "kanana-1.5-v-3b-instruct",
"display_name": "Kanana 1.5 v3B Instruct",
"model_type": "multimodal",
"description": "๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ์ด๋ฏธ์ง€+ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ ๋ชจ๋ธ"
}
],
"current_model": "polyglot-ko-1.3b-chat"
}
```
### 2. ํ…์ŠคํŠธ ์ƒ์„ฑ
```http
POST /generate
```
**์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ:**
```json
{
"prompt": "์•ˆ๋…•ํ•˜์„ธ์š”, AI์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.",
"model_id": "polyglot-ko-1.3b-chat",
"max_length": 200,
"temperature": 0.7,
"top_p": 0.9,
"do_sample": true
}
```
**์‘๋‹ต ์˜ˆ์‹œ:**
```json
{
"generated_text": "์•ˆ๋…•ํ•˜์„ธ์š”! AI(์ธ๊ณต์ง€๋Šฅ)๋Š” ์ธ๊ฐ„์˜ ํ•™์Šต๋Šฅ๋ ฅ๊ณผ ์ถ”๋ก ๋Šฅ๋ ฅ์„ ์ธ๊ณต์ ์œผ๋กœ ๊ตฌํ˜„ํ•œ ์ปดํ“จํ„ฐ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค...",
"model_name": "polyglot-ko-1.3b-chat",
"processing_time": 2.34,
"tokens_generated": 45
}
```
### 3. ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ์ƒ์„ฑ (์ด๋ฏธ์ง€ + ํ…์ŠคํŠธ)
```http
POST /generate-multimodal
```
**์š”์ฒญ (multipart/form-data):**
```
prompt: "์ด ์ด๋ฏธ์ง€์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”"
model_id: "kanana-1.5-v-3b-instruct"
max_length: 200
temperature: 0.7
image_files: [ํŒŒ์ผ1, ํŒŒ์ผ2, ...]
```
**์‘๋‹ต ์˜ˆ์‹œ:**
```json
{
"generated_text": "์ด ์ด๋ฏธ์ง€๋Š” ์•„๋ฆ„๋‹ค์šด ์ž์—ฐ ํ’๊ฒฝ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค...",
"model_name": "kanana-1.5-v-3b-instruct",
"processing_time": 15.67,
"images_processed": 2
}
```
## ๐Ÿ“„ ๋ฌธ์„œ ์ฒ˜๋ฆฌ (RAG)
### 1. ๋ฌธ์„œ ์—…๋กœ๋“œ
```http
POST /document/upload
```
**์š”์ฒญ (multipart/form-data):**
```
file: [PDF/DOC/DOCX/PPTX ํŒŒ์ผ]
user_id: "user123"
```
**์‘๋‹ต ์˜ˆ์‹œ:**
```json
{
"document_id": "doc_123456",
"filename": "sample.pdf",
"file_type": "pdf",
"file_size": 1024000,
"pages": 15,
"chunks": 45,
"upload_time": "2025-08-04T10:30:00Z"
}
```
### 2. RAG ์ฟผ๋ฆฌ
```http
POST /rag/generate
```
**์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ:**
```json
{
"query": "์ธ๊ณต์ง€๋Šฅ์˜ ๋ฏธ๋ž˜์— ๋Œ€ํ•ด ์•Œ๋ ค์ฃผ์„ธ์š”",
"user_id": "user123",
"max_length": 300,
"temperature": 0.7
}
```
**์‘๋‹ต ์˜ˆ์‹œ:**
```json
{
"response": "์ธ๊ณต์ง€๋Šฅ์˜ ๋ฏธ๋ž˜๋Š” ๋งค์šฐ ๋ฐ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด...",
"sources": [
{
"document_id": "doc_123456",
"page": 5,
"chunk": "AI ๊ธฐ์ˆ ์˜ ๋ฐœ์ „ ๋ฐฉํ–ฅ..."
}
],
"confidence": 0.85,
"processing_time": 3.45
}
```
### 3. ํ•˜์ด๋ธŒ๋ฆฌ๋“œ RAG (์ด๋ฏธ์ง€ + ๋ฌธ์„œ)
```http
POST /rag/generate-hybrid
```
**์š”์ฒญ (multipart/form-data):**
```
query: "์ด ์ด๋ฏธ์ง€์™€ ๊ด€๋ จ๋œ ๋ฌธ์„œ ๋‚ด์šฉ์„ ์ฐพ์•„์ฃผ์„ธ์š”"
user_id: "user123"
image_files: [์ด๋ฏธ์ง€ ํŒŒ์ผ๋“ค]
max_length: 300
temperature: 0.7
```
## ๐Ÿ’ฌ ์ฑ„ํŒ… ๋ฐ ์„ธ์…˜ ๊ด€๋ฆฌ
### 1. ์‚ฌ์šฉ์ž ์ƒ์„ฑ
```http
POST /user/create
```
**์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ:**
```json
{
"user_id": "user123",
"username": "ํ…Œ์ŠคํŠธ์‚ฌ์šฉ์ž",
"email": "test@example.com"
}
```
### 2. ์ฑ„ํŒ… ์„ธ์…˜ ์ƒ์„ฑ
```http
POST /session/create
```
**์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ:**
```json
{
"user_id": "user123",
"session_name": "AI ์ƒ๋‹ด ์„ธ์…˜"
}
```
### 3. ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
```http
POST /chat/message
```
**์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ:**
```json
{
"session_id": "session_123",
"user_id": "user123",
"message_type": "text",
"content": "์•ˆ๋…•ํ•˜์„ธ์š”!"
}
```
### 4. ์ฑ„ํŒ… ๊ธฐ๋ก ์กฐํšŒ
```http
GET /chat/history/{session_id}
```
## ๐Ÿ”„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…
### 1. ๋ฌธ์„œ ์ฒ˜๋ฆฌ ์ž‘์—…
```http
POST /tasks/document/process
```
**์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ:**
```json
{
"file_path": "/uploads/document.pdf",
"user_id": "user123"
}
```
**์‘๋‹ต ์˜ˆ์‹œ:**
```json
{
"task_id": "task_123456",
"status": "PENDING",
"message": "๋ฌธ์„œ ์ฒ˜๋ฆฌ ์ž‘์—…์ด ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
}
```
### 2. ์ž‘์—… ์ƒํƒœ ํ™•์ธ
```http
GET /tasks/{task_id}
```
**์‘๋‹ต ์˜ˆ์‹œ:**
```json
{
"task_id": "task_123456",
"status": "SUCCESS",
"result": {
"document_id": "doc_123456",
"chunks": 45
},
"progress": 100
}
```
## ๐Ÿ“Š ๋ชจ๋‹ˆํ„ฐ๋ง
### 1. ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์ž‘
```http
POST /monitoring/start
```
### 2. ์„ฑ๋Šฅ ์ƒํƒœ ์กฐํšŒ
```http
GET /monitoring/status
```
**์‘๋‹ต ์˜ˆ์‹œ:**
```json
{
"current_metrics": {
"cpu_percent": 25.5,
"memory_percent": 68.2,
"memory_used_mb": 8192.0,
"disk_usage_percent": 45.0
},
"performance_stats": {
"avg_response_time": 1.23,
"avg_inference_time": 2.45,
"total_requests": 1250,
"success_rate": 98.5
},
"system_health": {
"status": "healthy",
"recommendations": []
}
}
```
### 3. ์‹œ์Šคํ…œ ๊ฑด๊ฐ• ์ƒํƒœ
```http
GET /monitoring/health
```
## ๐Ÿ”Œ WebSocket
### ์—ฐ๊ฒฐ
```javascript
const ws = new WebSocket('ws://localhost:8001/ws/user123');
ws.onopen = function() {
console.log('WebSocket ์—ฐ๊ฒฐ๋จ');
};
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('๋ฉ”์‹œ์ง€ ์ˆ˜์‹ :', data);
};
```
### ๋ฉ”์‹œ์ง€ ์ „์†ก
```javascript
ws.send(JSON.stringify({
type: 'chat',
message: '์•ˆ๋…•ํ•˜์„ธ์š”!',
session_id: 'session_123'
}));
```
## ๐Ÿšจ ์˜ค๋ฅ˜ ์ฝ”๋“œ
| ์ฝ”๋“œ | ์˜๋ฏธ | ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• |
|------|------|-----------|
| 400 | ์ž˜๋ชป๋œ ์š”์ฒญ | ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ํ™•์ธ |
| 401 | ์ธ์ฆ ์‹คํŒจ | ํ† ํฐ ํ™•์ธ |
| 403 | ๊ถŒํ•œ ์—†์Œ | ๊ถŒํ•œ ํ™•์ธ |
| 404 | ๋ฆฌ์†Œ์Šค ์—†์Œ | URL ํ™•์ธ |
| 422 | ๊ฒ€์ฆ ์‹คํŒจ | ์š”์ฒญ ๋ฐ์ดํ„ฐ ํ˜•์‹ ํ™•์ธ |
| 500 | ์„œ๋ฒ„ ์˜ค๋ฅ˜ | ์„œ๋ฒ„ ๋กœ๊ทธ ํ™•์ธ |
| 503 | ์„œ๋น„์Šค ๋ถˆ๊ฐ€ | ์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ |
## ๐Ÿ“ ์˜ˆ์ œ ์ฝ”๋“œ
### Python ํด๋ผ์ด์–ธํŠธ
```python
import requests
import json
class LilyLLMClient:
def __init__(self, base_url="http://localhost:8001"):
self.base_url = base_url
self.token = None
def login(self, username, password):
response = requests.post(f"{self.base_url}/auth/login",
data={"username": username, "password": password})
if response.status_code == 200:
self.token = response.json()["access_token"]
return True
return False
def generate_text(self, prompt, model_id="polyglot-ko-1.3b-chat"):
headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
data = {
"prompt": prompt,
"model_id": model_id,
"max_length": 200,
"temperature": 0.7
}
response = requests.post(f"{self.base_url}/generate",
data=data, headers=headers)
return response.json()
def upload_document(self, file_path, user_id):
headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
with open(file_path, 'rb') as f:
files = {'file': f}
data = {'user_id': user_id}
response = requests.post(f"{self.base_url}/document/upload",
files=files, data=data, headers=headers)
return response.json()
# ์‚ฌ์šฉ ์˜ˆ์ œ
client = LilyLLMClient()
if client.login("username", "password"):
result = client.generate_text("์•ˆ๋…•ํ•˜์„ธ์š”!")
print(result["generated_text"])
```
### JavaScript ํด๋ผ์ด์–ธํŠธ
```javascript
class LilyLLMClient {
constructor(baseUrl = 'http://localhost:8001') {
this.baseUrl = baseUrl;
this.token = null;
}
async login(username, password) {
const response = await fetch(`${this.baseUrl}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `username=${username}&password=${password}`
});
if (response.ok) {
const data = await response.json();
this.token = data.access_token;
return true;
}
return false;
}
async generateText(prompt, modelId = 'polyglot-ko-1.3b-chat') {
const headers = this.token ?
{'Authorization': `Bearer ${this.token}`} : {};
const formData = new FormData();
formData.append('prompt', prompt);
formData.append('model_id', modelId);
formData.append('max_length', '200');
formData.append('temperature', '0.7');
const response = await fetch(`${this.baseUrl}/generate`, {
method: 'POST',
headers,
body: formData
});
return await response.json();
}
}
// ์‚ฌ์šฉ ์˜ˆ์ œ
const client = new LilyLLMClient();
client.login('username', 'password').then(async (success) => {
if (success) {
const result = await client.generateText('์•ˆ๋…•ํ•˜์„ธ์š”!');
console.log(result.generated_text);
}
});
```
## ๐Ÿ”ง ์„ค์ •
### ํ™˜๊ฒฝ ๋ณ€์ˆ˜
```bash
# ์„œ๋ฒ„ ์„ค์ •
HOST=0.0.0.0
PORT=8001
LOG_LEVEL=INFO
# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
DATABASE_URL=sqlite:///app/data/lily_llm.db
# Redis
REDIS_URL=redis://localhost:6379
# Celery
CELERY_BROKER_URL=redis://localhost:6379/0
CELERY_RESULT_BACKEND=redis://localhost:6379/0
# ๋ณด์•ˆ
SECRET_KEY=your-secret-key
JWT_SECRET_KEY=your-jwt-secret-key
```
## ๐Ÿ“š ์ถ”๊ฐ€ ๋ฆฌ์†Œ์Šค
- [FastAPI ๋ฌธ์„œ](https://fastapi.tiangolo.com/)
- [Celery ๋ฌธ์„œ](https://docs.celeryproject.org/)
- [Redis ๋ฌธ์„œ](https://redis.io/documentation)
- [LangChain ๋ฌธ์„œ](https://python.langchain.com/)