Files
lang-agent/fastapi_server/front_apis.py
2026-02-11 16:22:49 +08:00

168 lines
4.7 KiB
Python

from typing import Dict, List, Optional
import os
import os.path as osp
import sys
import uuid
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
# Ensure we can import from project root.
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from lang_agent.config.db_config_manager import DBConfigManager
from lang_agent.front_api.build_server import GRAPH_BUILD_FNCS
class GraphConfigUpsertRequest(BaseModel):
pipeline_id: str
prompt_set_id: Optional[str] = Field(default=None)
tool_keys: List[str] = Field(default_factory=list)
prompt_dict: Dict[str, str] = Field(default_factory=dict)
class GraphConfigUpsertResponse(BaseModel):
pipeline_id: str
prompt_set_id: str
tool_keys: List[str]
prompt_keys: List[str]
class PipelineCreateRequest(BaseModel):
graph_id: str = Field(
description="Graph key from GRAPH_BUILD_FNCS, e.g. routing or react"
)
pipeline_id: str
prompt_set_id: str
tool_keys: List[str] = Field(default_factory=list)
port: int
entry_point: str = Field(default="fastapi_server/server_dashscope.py")
llm_name: str = Field(default="qwen-plus")
class PipelineCreateResponse(BaseModel):
run_id: str
pid: int
graph_id: str
pipeline_id: str
prompt_set_id: str
url: str
port: int
app = FastAPI(
title="Front APIs",
description="Manage graph configs and launch graph pipelines.",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
_db = DBConfigManager()
_running_pipelines: Dict[str, Dict[str, object]] = {}
@app.get("/health")
async def health():
return {"status": "healthy"}
@app.get("/")
async def root():
return {
"message": "Front APIs",
"endpoints": [
"/v1/graph-configs (POST)",
"/v1/graph-configs/{pipeline_id}/{prompt_set_id} (DELETE)",
"/v1/pipelines/graphs (GET)",
"/v1/pipelines (POST)",
],
}
@app.post("/v1/graph-configs", response_model=GraphConfigUpsertResponse)
async def upsert_graph_config(body: GraphConfigUpsertRequest):
try:
resolved_prompt_set_id = _db.set_config(
pipeline_id=body.pipeline_id,
prompt_set_id=body.prompt_set_id,
tool_list=body.tool_keys,
prompt_dict=body.prompt_dict,
)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
return GraphConfigUpsertResponse(
pipeline_id=body.pipeline_id,
prompt_set_id=resolved_prompt_set_id,
tool_keys=body.tool_keys,
prompt_keys=list(body.prompt_dict.keys()),
)
@app.delete("/v1/graph-configs/{pipeline_id}/{prompt_set_id}")
async def delete_graph_config(pipeline_id: str, prompt_set_id: str):
try:
_db.remove_config(pipeline_id=pipeline_id, prompt_set_id=prompt_set_id)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
return {
"status": "deleted",
"pipeline_id": pipeline_id,
"prompt_set_id": prompt_set_id,
}
@app.get("/v1/pipelines/graphs")
async def available_graphs():
return {"available_graphs": sorted(GRAPH_BUILD_FNCS.keys())}
@app.post("/v1/pipelines", response_model=PipelineCreateResponse)
async def create_pipeline(body: PipelineCreateRequest):
build_fn = GRAPH_BUILD_FNCS.get(body.graph_id)
if build_fn is None:
raise HTTPException(
status_code=400,
detail=f"Unknown graph_id '{body.graph_id}'. Valid options: {sorted(GRAPH_BUILD_FNCS.keys())}",
)
try:
proc, url = build_fn(
pipelin_id=body.pipeline_id,
prompt_set=body.prompt_set_id,
tool_keys=body.tool_keys,
port=str(body.port),
entry_pnt=body.entry_point,
llm_name=body.llm_name,
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to start pipeline: {e}")
run_id = str(uuid.uuid4())
_running_pipelines[run_id] = {
"proc": proc,
"graph_id": body.graph_id,
"pipeline_id": body.pipeline_id,
"prompt_set_id": body.prompt_set_id,
"url": url,
"port": body.port,
}
return PipelineCreateResponse(
run_id=run_id,
pid=proc.pid,
graph_id=body.graph_id,
pipeline_id=body.pipeline_id,
prompt_set_id=body.prompt_set_id,
url=url,
port=body.port,
)