FilozofMuhendis
Initial model upload - Industrial Cost Calculation Chatbot
8223b74 verified
from fastapi import FastAPI, Depends, HTTPException, BackgroundTasks, File, UploadFile, Form, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from sqlalchemy.orm import Session
from typing import List, Optional, Dict, Any
import os
import shutil
import json
from datetime import datetime
from app.db.database import get_db, engine
from app.db.models import Base, ChatHistory, Document
from app.agent import create_agent
from app import document_processor
from app import document_generator
# Create tables if they don't exist
Base.metadata.create_all(bind=engine)
# Initialize FastAPI app
app = FastAPI(
title="Endüstri Chatbot API",
description="Endüstriyel maliyet hesaplama için chatbot API",
version="0.1.0"
)
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # In production, replace with specific origins
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Define request and response models
class ChatRequest(BaseModel):
message: str
class ChatResponse(BaseModel):
response: str
class HealthResponse(BaseModel):
status: str
model_name: str
class DocumentResponse(BaseModel):
id: int
filename: str
content_type: str
file_size: int
document_type: Optional[str] = None
template_type: Optional[str] = None
uploaded_at: datetime
analyzed_at: Optional[datetime] = None
analysis_summary: Optional[str] = None
class DocumentAnalysisResponse(BaseModel):
id: int
filename: str
analysis_result: Dict[str, Any]
analyzed_at: datetime
class DocumentGenerateRequest(BaseModel):
document_type: str # 'word' veya 'excel'
template_type: str # 'maliyet_raporu', 'teklif', vs.
data: Dict[str, Any] # Doküman içeriği için veriler
class DocumentGenerateResponse(BaseModel):
id: int
filename: str
document_type: str
template_type: str
file_path: str
file_size: int
uploaded_at: datetime
# Save chat history to database
def save_chat_history(db: Session, user_input: str, assistant_response: str):
chat_entry = ChatHistory(
user_input=user_input,
assistant_response=assistant_response
)
db.add(chat_entry)
db.commit()
# Health check endpoint
@app.get("/health", response_model=HealthResponse)
def health_check():
return {
"status": "ok",
"model_name": os.getenv("MODEL_NAME", "bigscience/bloomz-560m")
}
# Chat endpoint
@app.post("/chat", response_model=ChatResponse)
async def chat(request: ChatRequest, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
try:
# Create agent
agent_executor = create_agent(db)
# Run agent
result = agent_executor.invoke({"input": request.message})
response = result["output"]
# Save chat history in background
background_tasks.add_task(save_chat_history, db, request.message, response)
return {"response": response}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error processing request: {str(e)}")
# Get chat history endpoint
@app.get("/chat/history", response_model=List[dict])
def get_chat_history(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
history = db.query(ChatHistory).order_by(ChatHistory.created_at.desc()).offset(skip).limit(limit).all()
return [{
"id": entry.id,
"user_input": entry.user_input,
"assistant_response": entry.assistant_response,
"created_at": entry.created_at
} for entry in history]
# Belge yükleme endpoint'i
@app.post("/documents/upload", response_model=DocumentResponse)
async def upload_document(
file: UploadFile = File(...),
analyze: bool = Form(False),
db: Session = Depends(get_db)
):
# Desteklenen dosya türlerini kontrol et
if file.content_type not in document_processor.SUPPORTED_CONTENT_TYPES:
raise HTTPException(
status_code=400,
detail=f"Desteklenmeyen dosya türü: {file.content_type}. Desteklenen türler: {list(document_processor.SUPPORTED_CONTENT_TYPES.keys())}"
)
try:
# Dosyayı kaydet
filename = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{file.filename}"
file_path = document_processor.save_uploaded_file(file, filename)
file_size = os.path.getsize(file_path)
# Metin çıkar ve analiz et
content_text = None
analysis_result = None
if analyze:
content_text = document_processor.process_document(file_path, file.content_type)
if content_text:
analysis_result = document_processor.analyze_document_content(content_text, db)
# Veritabanına kaydet
document = document_processor.save_document_to_db(
db, filename, file.content_type, file_path, file_size, content_text, analysis_result
)
# Yanıt oluştur
response = {
"id": document.id,
"filename": document.filename,
"content_type": document.content_type,
"file_size": document.file_size,
"uploaded_at": document.uploaded_at,
"analyzed_at": document.analyzed_at
}
if analysis_result:
response["analysis_summary"] = "Belge analiz edildi. /documents/{id}/analysis endpoint'inden sonuçları görüntüleyebilirsiniz."
return response
except Exception as e:
raise HTTPException(status_code=500, detail=f"Belge yükleme hatası: {str(e)}")
# Belge analiz endpoint'i
@app.post("/documents/{document_id}/analyze", response_model=DocumentAnalysisResponse)
async def analyze_document(
document_id: int,
db: Session = Depends(get_db)
):
# Belgeyi veritabanından al
document = db.query(Document).filter(Document.id == document_id).first()
if not document:
raise HTTPException(status_code=404, detail=f"Belge bulunamadı: {document_id}")
try:
# Eğer metin çıkarılmamışsa, çıkar
if not document.content_text:
document.content_text = document_processor.process_document(document.file_path, document.content_type)
db.commit()
# Metni analiz et
analysis_result = document_processor.analyze_document_content(document.content_text, db)
# Analiz sonucunu güncelle
document.analysis_result = analysis_result
document.analyzed_at = datetime.now()
db.commit()
# Yanıt oluştur
return {
"id": document.id,
"filename": document.filename,
"analysis_result": json.loads(document.analysis_result),
"analyzed_at": document.analyzed_at
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Belge analiz hatası: {str(e)}")
# Belge listesi endpoint'i
@app.get("/documents", response_model=List[DocumentResponse])
async def list_documents(
skip: int = 0,
limit: int = 10,
db: Session = Depends(get_db)
):
documents = db.query(Document).order_by(Document.uploaded_at.desc()).offset(skip).limit(limit).all()
return [
{
"id": doc.id,
"filename": doc.filename,
"content_type": doc.content_type,
"file_size": doc.file_size,
"uploaded_at": doc.uploaded_at,
"analyzed_at": doc.analyzed_at,
"analysis_summary": "Analiz sonuçları mevcut" if doc.analysis_result else None
}
for doc in documents
]
# Belge detayı endpoint'i
@app.get("/documents/{document_id}", response_model=DocumentResponse)
async def get_document(
document_id: int,
db: Session = Depends(get_db)
):
document = db.query(Document).filter(Document.id == document_id).first()
if not document:
raise HTTPException(status_code=404, detail=f"Belge bulunamadı: {document_id}")
return {
"id": document.id,
"filename": document.filename,
"content_type": document.content_type,
"file_size": document.file_size,
"uploaded_at": document.uploaded_at,
"analyzed_at": document.analyzed_at,
"analysis_summary": "Analiz sonuçları mevcut" if document.analysis_result else None
}
# Belge analiz sonucu endpoint'i
@app.get("/documents/{document_id}/analysis", response_model=DocumentAnalysisResponse)
async def get_document_analysis(
document_id: int,
db: Session = Depends(get_db)
):
document = db.query(Document).filter(Document.id == document_id).first()
if not document:
raise HTTPException(status_code=404, detail=f"Belge bulunamadı: {document_id}")
if not document.analysis_result:
raise HTTPException(status_code=404, detail=f"Belge henüz analiz edilmemiş: {document_id}")
return {
"id": document.id,
"filename": document.filename,
"analysis_result": json.loads(document.analysis_result),
"analyzed_at": document.analyzed_at
}
# Root endpoint
@app.get("/")
def read_root():
return {"message": "Endüstri Chatbot API'ye Hoş Geldiniz! /docs adresinden API dokümantasyonuna ulaşabilirsiniz."}
# Statik dosyaları sunmak için
app.mount("/uploads", StaticFiles(directory="uploads"), name="uploads")
# Doküman oluşturma endpoint'i
@app.post("/documents/generate", response_model=DocumentGenerateResponse)
async def generate_document(
request: DocumentGenerateRequest,
db: Session = Depends(get_db)
):
try:
# Doküman türüne göre oluştur
if request.document_type.lower() == 'word':
file_path = document_generator.create_word_document(request.data, request.template_type)
elif request.document_type.lower() == 'excel':
file_path = document_generator.create_excel_document(request.data, request.template_type)
else:
raise HTTPException(status_code=400, detail=f"Desteklenmeyen doküman türü: {request.document_type}. Desteklenen türler: word, excel")
# Dosya boyutunu al
file_size = os.path.getsize(file_path)
# Dosya adını al
filename = os.path.basename(file_path)
# İçerik türünü belirle
content_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" if request.document_type.lower() == 'word' else "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
# Veritabanına kaydet
document = document_generator.save_document_to_db(
db, filename, content_type, file_path, file_size,
request.document_type.lower(), request.template_type
)
# Yanıt oluştur
return {
"id": document.id,
"filename": document.filename,
"document_type": document.document_type,
"template_type": document.template_type,
"file_path": document.file_path,
"file_size": document.file_size,
"uploaded_at": document.uploaded_at
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Doküman oluşturma hatası: {str(e)}")
# Doküman şablonları endpoint'i
@app.get("/documents/templates")
async def get_document_templates():
return {
"templates": [
{
"id": "maliyet_raporu",
"name": "Maliyet Raporu",
"description": "İşçilik ve malzeme maliyetlerini içeren detaylı maliyet raporu",
"supported_formats": ["word", "excel"]
},
{
"id": "teklif",
"name": "Teklif",
"description": "Müşteriye sunulacak resmi teklif dokümanı",
"supported_formats": ["word", "excel"]
}
]
}
# Run with: uvicorn app.main:app --reload
if __name__ == "__main__":
import uvicorn
uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)