Spaces:
Sleeping
Sleeping
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 ν ν° μΈμ¦
# λ‘κ·ΈμΈ
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"
}
보νΈλ μλν¬μΈνΈ μ¬μ©
curl -X GET "http://localhost:8001/auth/me" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
π€ AI λͺ¨λΈ κ΄λ ¨
1. λͺ¨λΈ λͺ©λ‘ μ‘°ν
GET /models
μλ΅ μμ:
{
"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. ν μ€νΈ μμ±
POST /generate
μμ² νλΌλ―Έν°:
{
"prompt": "μλ
νμΈμ, AIμ λν΄ μ€λͺ
ν΄μ£ΌμΈμ.",
"model_id": "polyglot-ko-1.3b-chat",
"max_length": 200,
"temperature": 0.7,
"top_p": 0.9,
"do_sample": true
}
μλ΅ μμ:
{
"generated_text": "μλ
νμΈμ! AI(μΈκ³΅μ§λ₯)λ μΈκ°μ νμ΅λ₯λ ₯κ³Ό μΆλ‘ λ₯λ ₯μ μΈκ³΅μ μΌλ‘ ꡬνν μ»΄ν¨ν° μμ€ν
μ
λλ€...",
"model_name": "polyglot-ko-1.3b-chat",
"processing_time": 2.34,
"tokens_generated": 45
}
3. λ©ν°λͺ¨λ¬ μμ± (μ΄λ―Έμ§ + ν μ€νΈ)
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, ...]
μλ΅ μμ:
{
"generated_text": "μ΄ μ΄λ―Έμ§λ μλ¦λ€μ΄ μμ° νκ²½μ 보μ¬μ€λλ€...",
"model_name": "kanana-1.5-v-3b-instruct",
"processing_time": 15.67,
"images_processed": 2
}
π λ¬Έμ μ²λ¦¬ (RAG)
1. λ¬Έμ μ λ‘λ
POST /document/upload
μμ² (multipart/form-data):
file: [PDF/DOC/DOCX/PPTX νμΌ]
user_id: "user123"
μλ΅ μμ:
{
"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 쿼리
POST /rag/generate
μμ² νλΌλ―Έν°:
{
"query": "μΈκ³΅μ§λ₯μ λ―Έλμ λν΄ μλ €μ£ΌμΈμ",
"user_id": "user123",
"max_length": 300,
"temperature": 0.7
}
μλ΅ μμ:
{
"response": "μΈκ³΅μ§λ₯μ λ―Έλλ λ§€μ° λ°μ΅λλ€. νμ¬ λ¬Έμμ λ°λ₯΄λ©΄...",
"sources": [
{
"document_id": "doc_123456",
"page": 5,
"chunk": "AI κΈ°μ μ λ°μ λ°©ν₯..."
}
],
"confidence": 0.85,
"processing_time": 3.45
}
3. νμ΄λΈλ¦¬λ RAG (μ΄λ―Έμ§ + λ¬Έμ)
POST /rag/generate-hybrid
μμ² (multipart/form-data):
query: "μ΄ μ΄λ―Έμ§μ κ΄λ ¨λ λ¬Έμ λ΄μ©μ μ°Ύμμ£ΌμΈμ"
user_id: "user123"
image_files: [μ΄λ―Έμ§ νμΌλ€]
max_length: 300
temperature: 0.7
π¬ μ±ν λ° μΈμ κ΄λ¦¬
1. μ¬μ©μ μμ±
POST /user/create
μμ² νλΌλ―Έν°:
{
"user_id": "user123",
"username": "ν
μ€νΈμ¬μ©μ",
"email": "test@example.com"
}
2. μ±ν μΈμ μμ±
POST /session/create
μμ² νλΌλ―Έν°:
{
"user_id": "user123",
"session_name": "AI μλ΄ μΈμ
"
}
3. λ©μμ§ μΆκ°
POST /chat/message
μμ² νλΌλ―Έν°:
{
"session_id": "session_123",
"user_id": "user123",
"message_type": "text",
"content": "μλ
νμΈμ!"
}
4. μ±ν κΈ°λ‘ μ‘°ν
GET /chat/history/{session_id}
π λ°±κ·ΈλΌμ΄λ μμ
1. λ¬Έμ μ²λ¦¬ μμ
POST /tasks/document/process
μμ² νλΌλ―Έν°:
{
"file_path": "/uploads/document.pdf",
"user_id": "user123"
}
μλ΅ μμ:
{
"task_id": "task_123456",
"status": "PENDING",
"message": "λ¬Έμ μ²λ¦¬ μμ
μ΄ μμλμμ΅λλ€."
}
2. μμ μν νμΈ
GET /tasks/{task_id}
μλ΅ μμ:
{
"task_id": "task_123456",
"status": "SUCCESS",
"result": {
"document_id": "doc_123456",
"chunks": 45
},
"progress": 100
}
π λͺ¨λν°λ§
1. μ±λ₯ λͺ¨λν°λ§ μμ
POST /monitoring/start
2. μ±λ₯ μν μ‘°ν
GET /monitoring/status
μλ΅ μμ:
{
"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. μμ€ν κ±΄κ° μν
GET /monitoring/health
π WebSocket
μ°κ²°
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);
};
λ©μμ§ μ μ‘
ws.send(JSON.stringify({
type: 'chat',
message: 'μλ
νμΈμ!',
session_id: 'session_123'
}));
π¨ μ€λ₯ μ½λ
| μ½λ | μλ―Έ | ν΄κ²° λ°©λ² |
|---|---|---|
| 400 | μλͺ»λ μμ² | μμ² νλΌλ―Έν° νμΈ |
| 401 | μΈμ¦ μ€ν¨ | ν ν° νμΈ |
| 403 | κΆν μμ | κΆν νμΈ |
| 404 | 리μμ€ μμ | URL νμΈ |
| 422 | κ²μ¦ μ€ν¨ | μμ² λ°μ΄ν° νμ νμΈ |
| 500 | μλ² μ€λ₯ | μλ² λ‘κ·Έ νμΈ |
| 503 | μλΉμ€ λΆκ° | μλΉμ€ μν νμΈ |
π μμ μ½λ
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 ν΄λΌμ΄μΈνΈ
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);
}
});
π§ μ€μ
νκ²½ λ³μ
# μλ² μ€μ
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