feat: 用 Ragflow 搭建鲜境方案客服
咨询台接 Ragflow 检索与示例知识库,支持追问、判定、引用和留资。 Co-authored-by: haijd <haijd@163.com>
This commit is contained in:
+79
-2
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
@@ -8,12 +9,16 @@ from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from .config_loader import business_config
|
||||
from .leads import add_lead, list_leads
|
||||
from .ragflow_client import RagflowClient, RagflowError
|
||||
from .scheme_engine import create_session, handle_message
|
||||
from .settings import settings
|
||||
from .session_store import store
|
||||
from .settings import ROOT, settings
|
||||
|
||||
STATIC_DIR = Path(__file__).resolve().parent / "static"
|
||||
CORPUS_DIR = ROOT / "knowledge" / "corpus"
|
||||
|
||||
app = FastAPI(title=settings.app_name, version="0.1.0")
|
||||
app = FastAPI(title=settings.app_name, version="0.2.0")
|
||||
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
|
||||
|
||||
|
||||
@@ -26,6 +31,13 @@ class SessionResponse(BaseModel):
|
||||
session_id: str
|
||||
|
||||
|
||||
class HandoffRequest(BaseModel):
|
||||
session_id: str
|
||||
name: str = Field(..., min_length=1, max_length=40)
|
||||
phone: str = Field(..., min_length=5, max_length=30)
|
||||
note: str = ""
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def index() -> FileResponse:
|
||||
return FileResponse(STATIC_DIR / "index.html")
|
||||
@@ -33,12 +45,16 @@ def index() -> FileResponse:
|
||||
|
||||
@app.get("/api/health")
|
||||
def health() -> dict:
|
||||
rag = RagflowClient().health()
|
||||
return {
|
||||
"ok": True,
|
||||
"app": settings.app_name,
|
||||
"retrieval_backend": settings.retrieval_backend,
|
||||
"slots": len(business_config.slots),
|
||||
"rules": len(business_config.rules),
|
||||
"ragflow": rag,
|
||||
"ragflow_web": settings.ragflow_web_url,
|
||||
"dataset_ids_configured": bool(settings.ragflow_dataset_ids.strip()),
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +74,49 @@ def reload_config() -> dict:
|
||||
return {"reloaded": True, "slots": len(business_config.slots), "rules": len(business_config.rules)}
|
||||
|
||||
|
||||
@app.get("/api/knowledge/files")
|
||||
def knowledge_files() -> dict:
|
||||
files = []
|
||||
if CORPUS_DIR.exists():
|
||||
for path in sorted(CORPUS_DIR.glob("*.md")):
|
||||
files.append({"name": path.name, "bytes": path.stat().st_size})
|
||||
return {"files": files}
|
||||
|
||||
|
||||
@app.get("/api/ragflow/status")
|
||||
def ragflow_status() -> dict:
|
||||
client = RagflowClient()
|
||||
health = client.health()
|
||||
datasets: list[dict] = []
|
||||
error = ""
|
||||
if health.get("ok") and settings.ragflow_api_key:
|
||||
try:
|
||||
for item in client.list_datasets():
|
||||
datasets.append(
|
||||
{
|
||||
"id": item.get("id"),
|
||||
"name": item.get("name"),
|
||||
"document_count": item.get("document_count"),
|
||||
"chunk_count": item.get("chunk_count"),
|
||||
}
|
||||
)
|
||||
except Exception as exc:
|
||||
error = str(exc)
|
||||
return {
|
||||
"health": health,
|
||||
"web": settings.ragflow_web_url,
|
||||
"api_key_set": bool(settings.ragflow_api_key),
|
||||
"dataset_ids": [x for x in settings.ragflow_dataset_ids.split(",") if x.strip()],
|
||||
"datasets": datasets,
|
||||
"error": error,
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/leads")
|
||||
def api_leads() -> dict:
|
||||
return {"leads": list_leads()}
|
||||
|
||||
|
||||
@app.post("/api/sessions", response_model=SessionResponse)
|
||||
def api_create_session() -> SessionResponse:
|
||||
session = create_session()
|
||||
@@ -73,3 +132,21 @@ def api_chat(body: ChatRequest) -> dict:
|
||||
return handle_message(session_id, body.message)
|
||||
except KeyError:
|
||||
raise HTTPException(status_code=404, detail="session_not_found") from None
|
||||
|
||||
|
||||
@app.post("/api/handoff")
|
||||
def api_handoff(body: HandoffRequest) -> dict:
|
||||
session = store.get(body.session_id)
|
||||
slots = session.slots if session else {}
|
||||
scheme = session.last_scheme if session else None
|
||||
lead_id = add_lead(
|
||||
session_id=body.session_id,
|
||||
name=body.name.strip(),
|
||||
phone=body.phone.strip(),
|
||||
note=body.note.strip(),
|
||||
slots_json=json.dumps(slots, ensure_ascii=False),
|
||||
scheme_json=json.dumps(scheme or {}, ensure_ascii=False),
|
||||
)
|
||||
if session:
|
||||
session.phase = "handoff"
|
||||
return {"ok": True, "lead_id": lead_id}
|
||||
|
||||
Reference in New Issue
Block a user