This commit is contained in:
Timothy Jaeryang Baek
2026-03-17 17:58:01 -05:00
parent fcf7208352
commit de3317e26b
220 changed files with 17200 additions and 22836 deletions
+103 -136
View File
@@ -40,33 +40,30 @@ def get_sorted_filters(model_id, models):
filters = [
model
for model in models.values()
if "pipeline" in model
and "type" in model["pipeline"]
and model["pipeline"]["type"] == "filter"
if 'pipeline' in model
and 'type' in model['pipeline']
and model['pipeline']['type'] == 'filter'
and (
model["pipeline"]["pipelines"] == ["*"]
or any(
model_id == target_model_id
for target_model_id in model["pipeline"]["pipelines"]
)
model['pipeline']['pipelines'] == ['*']
or any(model_id == target_model_id for target_model_id in model['pipeline']['pipelines'])
)
]
sorted_filters = sorted(filters, key=lambda x: x["pipeline"]["priority"])
sorted_filters = sorted(filters, key=lambda x: x['pipeline']['priority'])
return sorted_filters
async def process_pipeline_inlet_filter(request, payload, user, models):
user = {"id": user.id, "email": user.email, "name": user.name, "role": user.role}
model_id = payload["model"]
user = {'id': user.id, 'email': user.email, 'name': user.name, 'role': user.role}
model_id = payload['model']
sorted_filters = get_sorted_filters(model_id, models)
model = models[model_id]
if "pipeline" in model:
if 'pipeline' in model:
sorted_filters.append(model)
async with aiohttp.ClientSession(trust_env=True) as session:
for filter in sorted_filters:
urlIdx = filter.get("urlIdx")
urlIdx = filter.get('urlIdx')
try:
urlIdx = int(urlIdx)
@@ -79,15 +76,15 @@ async def process_pipeline_inlet_filter(request, payload, user, models):
if not key:
continue
headers = {"Authorization": f"Bearer {key}"}
headers = {'Authorization': f'Bearer {key}'}
request_data = {
"user": user,
"body": payload,
'user': user,
'body': payload,
}
try:
async with session.post(
f"{url}/{filter['id']}/filter/inlet",
f'{url}/{filter["id"]}/filter/inlet',
headers=headers,
json=request_data,
ssl=AIOHTTP_CLIENT_SESSION_SSL,
@@ -95,31 +92,27 @@ async def process_pipeline_inlet_filter(request, payload, user, models):
response.raise_for_status()
payload = await response.json()
except aiohttp.ClientResponseError as e:
res = (
await response.json()
if response.content_type == "application/json"
else {}
)
if "detail" in res:
raise Exception(response.status, res["detail"])
res = await response.json() if response.content_type == 'application/json' else {}
if 'detail' in res:
raise Exception(response.status, res['detail'])
except Exception as e:
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
return payload
async def process_pipeline_outlet_filter(request, payload, user, models):
user = {"id": user.id, "email": user.email, "name": user.name, "role": user.role}
model_id = payload["model"]
user = {'id': user.id, 'email': user.email, 'name': user.name, 'role': user.role}
model_id = payload['model']
sorted_filters = get_sorted_filters(model_id, models)
model = models[model_id]
if "pipeline" in model:
if 'pipeline' in model:
sorted_filters = [model] + sorted_filters
async with aiohttp.ClientSession(trust_env=True) as session:
for filter in sorted_filters:
urlIdx = filter.get("urlIdx")
urlIdx = filter.get('urlIdx')
try:
urlIdx = int(urlIdx)
@@ -132,15 +125,15 @@ async def process_pipeline_outlet_filter(request, payload, user, models):
if not key:
continue
headers = {"Authorization": f"Bearer {key}"}
headers = {'Authorization': f'Bearer {key}'}
request_data = {
"user": user,
"body": payload,
'user': user,
'body': payload,
}
try:
async with session.post(
f"{url}/{filter['id']}/filter/outlet",
f'{url}/{filter["id"]}/filter/outlet',
headers=headers,
json=request_data,
ssl=AIOHTTP_CLIENT_SESSION_SSL,
@@ -149,17 +142,13 @@ async def process_pipeline_outlet_filter(request, payload, user, models):
payload = await response.json()
except aiohttp.ClientResponseError as e:
try:
res = (
await response.json()
if "application/json" in response.content_type
else {}
)
if "detail" in res:
res = await response.json() if 'application/json' in response.content_type else {}
if 'detail' in res:
raise Exception(response.status, res)
except Exception:
pass
except Exception as e:
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
return payload
@@ -173,72 +162,68 @@ async def process_pipeline_outlet_filter(request, payload, user, models):
router = APIRouter()
@router.get("/list")
@router.get('/list')
async def get_pipelines_list(request: Request, user=Depends(get_admin_user)):
responses = await get_all_models_responses(request, user)
log.debug(f"get_pipelines_list: get_openai_models_responses returned {responses}")
log.debug(f'get_pipelines_list: get_openai_models_responses returned {responses}')
urlIdxs = [
idx
for idx, response in enumerate(responses)
if response is not None and "pipelines" in response
]
urlIdxs = [idx for idx, response in enumerate(responses) if response is not None and 'pipelines' in response]
return {
"data": [
'data': [
{
"url": request.app.state.config.OPENAI_API_BASE_URLS[urlIdx],
"idx": urlIdx,
'url': request.app.state.config.OPENAI_API_BASE_URLS[urlIdx],
'idx': urlIdx,
}
for urlIdx in urlIdxs
]
}
@router.post("/upload")
@router.post('/upload')
async def upload_pipeline(
request: Request,
urlIdx: int = Form(...),
file: UploadFile = File(...),
user=Depends(get_admin_user),
):
log.info(f"upload_pipeline: urlIdx={urlIdx}, filename={file.filename}")
log.info(f'upload_pipeline: urlIdx={urlIdx}, filename={file.filename}')
filename = os.path.basename(file.filename)
# Check if the uploaded file is a python file
if not (filename and filename.endswith(".py")):
if not (filename and filename.endswith('.py')):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Only Python (.py) files are allowed.",
detail='Only Python (.py) files are allowed.',
)
upload_folder = f"{CACHE_DIR}/pipelines"
upload_folder = f'{CACHE_DIR}/pipelines'
os.makedirs(upload_folder, exist_ok=True)
file_path = os.path.join(upload_folder, filename)
response = None
try:
# Save the uploaded file
with open(file_path, "wb") as buffer:
with open(file_path, 'wb') as buffer:
shutil.copyfileobj(file.file, buffer)
url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = request.app.state.config.OPENAI_API_KEYS[urlIdx]
headers = {"Authorization": f"Bearer {key}"}
headers = {'Authorization': f'Bearer {key}'}
async with aiohttp.ClientSession(trust_env=True) as session:
with open(file_path, "rb") as f:
with open(file_path, 'rb') as f:
form_data = aiohttp.FormData()
form_data.add_field(
"file",
'file',
f,
filename=filename,
content_type="application/octet-stream",
content_type='application/octet-stream',
)
async with session.post(
f"{url}/pipelines/upload",
f'{url}/pipelines/upload',
headers=headers,
data=form_data,
ssl=AIOHTTP_CLIENT_SESSION_SSL,
@@ -249,7 +234,7 @@ async def upload_pipeline(
return {**data}
except Exception as e:
# Handle connection error here
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
detail = None
status_code = status.HTTP_404_NOT_FOUND
@@ -257,14 +242,14 @@ async def upload_pipeline(
status_code = response.status
try:
res = await response.json()
if "detail" in res:
detail = res["detail"]
if 'detail' in res:
detail = res['detail']
except Exception:
pass
raise HTTPException(
status_code=status_code,
detail=detail if detail else "Pipeline not found",
detail=detail if detail else 'Pipeline not found',
)
finally:
# Ensure the file is deleted after the upload is completed or on failure
@@ -277,10 +262,8 @@ class AddPipelineForm(BaseModel):
urlIdx: int
@router.post("/add")
async def add_pipeline(
request: Request, form_data: AddPipelineForm, user=Depends(get_admin_user)
):
@router.post('/add')
async def add_pipeline(request: Request, form_data: AddPipelineForm, user=Depends(get_admin_user)):
response = None
try:
urlIdx = form_data.urlIdx
@@ -290,9 +273,9 @@ async def add_pipeline(
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.post(
f"{url}/pipelines/add",
headers={"Authorization": f"Bearer {key}"},
json={"url": form_data.url},
f'{url}/pipelines/add',
headers={'Authorization': f'Bearer {key}'},
json={'url': form_data.url},
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
response.raise_for_status()
@@ -301,22 +284,20 @@ async def add_pipeline(
return {**data}
except Exception as e:
# Handle connection error here
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
detail = None
if response is not None:
try:
res = await response.json()
if "detail" in res:
detail = res["detail"]
if 'detail' in res:
detail = res['detail']
except Exception:
pass
raise HTTPException(
status_code=(
response.status if response is not None else status.HTTP_404_NOT_FOUND
),
detail=detail if detail else "Pipeline not found",
status_code=(response.status if response is not None else status.HTTP_404_NOT_FOUND),
detail=detail if detail else 'Pipeline not found',
)
@@ -325,10 +306,8 @@ class DeletePipelineForm(BaseModel):
urlIdx: int
@router.delete("/delete")
async def delete_pipeline(
request: Request, form_data: DeletePipelineForm, user=Depends(get_admin_user)
):
@router.delete('/delete')
async def delete_pipeline(request: Request, form_data: DeletePipelineForm, user=Depends(get_admin_user)):
response = None
try:
urlIdx = form_data.urlIdx
@@ -338,9 +317,9 @@ async def delete_pipeline(
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.delete(
f"{url}/pipelines/delete",
headers={"Authorization": f"Bearer {key}"},
json={"id": form_data.id},
f'{url}/pipelines/delete',
headers={'Authorization': f'Bearer {key}'},
json={'id': form_data.id},
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
response.raise_for_status()
@@ -349,29 +328,25 @@ async def delete_pipeline(
return {**data}
except Exception as e:
# Handle connection error here
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
detail = None
if response is not None:
try:
res = await response.json()
if "detail" in res:
detail = res["detail"]
if 'detail' in res:
detail = res['detail']
except Exception:
pass
raise HTTPException(
status_code=(
response.status if response is not None else status.HTTP_404_NOT_FOUND
),
detail=detail if detail else "Pipeline not found",
status_code=(response.status if response is not None else status.HTTP_404_NOT_FOUND),
detail=detail if detail else 'Pipeline not found',
)
@router.get("/")
async def get_pipelines(
request: Request, urlIdx: Optional[int] = None, user=Depends(get_admin_user)
):
@router.get('/')
async def get_pipelines(request: Request, urlIdx: Optional[int] = None, user=Depends(get_admin_user)):
response = None
try:
url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx]
@@ -379,8 +354,8 @@ async def get_pipelines(
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get(
f"{url}/pipelines",
headers={"Authorization": f"Bearer {key}"},
f'{url}/pipelines',
headers={'Authorization': f'Bearer {key}'},
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
response.raise_for_status()
@@ -389,26 +364,24 @@ async def get_pipelines(
return {**data}
except Exception as e:
# Handle connection error here
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
detail = None
if response is not None:
try:
res = await response.json()
if "detail" in res:
detail = res["detail"]
if 'detail' in res:
detail = res['detail']
except Exception:
pass
raise HTTPException(
status_code=(
response.status if response is not None else status.HTTP_404_NOT_FOUND
),
detail=detail if detail else "Pipeline not found",
status_code=(response.status if response is not None else status.HTTP_404_NOT_FOUND),
detail=detail if detail else 'Pipeline not found',
)
@router.get("/{pipeline_id}/valves")
@router.get('/{pipeline_id}/valves')
async def get_pipeline_valves(
request: Request,
urlIdx: Optional[int],
@@ -422,8 +395,8 @@ async def get_pipeline_valves(
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get(
f"{url}/{pipeline_id}/valves",
headers={"Authorization": f"Bearer {key}"},
f'{url}/{pipeline_id}/valves',
headers={'Authorization': f'Bearer {key}'},
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
response.raise_for_status()
@@ -432,26 +405,24 @@ async def get_pipeline_valves(
return {**data}
except Exception as e:
# Handle connection error here
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
detail = None
if response is not None:
try:
res = await response.json()
if "detail" in res:
detail = res["detail"]
if 'detail' in res:
detail = res['detail']
except Exception:
pass
raise HTTPException(
status_code=(
response.status if response is not None else status.HTTP_404_NOT_FOUND
),
detail=detail if detail else "Pipeline not found",
status_code=(response.status if response is not None else status.HTTP_404_NOT_FOUND),
detail=detail if detail else 'Pipeline not found',
)
@router.get("/{pipeline_id}/valves/spec")
@router.get('/{pipeline_id}/valves/spec')
async def get_pipeline_valves_spec(
request: Request,
urlIdx: Optional[int],
@@ -465,8 +436,8 @@ async def get_pipeline_valves_spec(
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get(
f"{url}/{pipeline_id}/valves/spec",
headers={"Authorization": f"Bearer {key}"},
f'{url}/{pipeline_id}/valves/spec',
headers={'Authorization': f'Bearer {key}'},
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
response.raise_for_status()
@@ -475,26 +446,24 @@ async def get_pipeline_valves_spec(
return {**data}
except Exception as e:
# Handle connection error here
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
detail = None
if response is not None:
try:
res = await response.json()
if "detail" in res:
detail = res["detail"]
if 'detail' in res:
detail = res['detail']
except Exception:
pass
raise HTTPException(
status_code=(
response.status if response is not None else status.HTTP_404_NOT_FOUND
),
detail=detail if detail else "Pipeline not found",
status_code=(response.status if response is not None else status.HTTP_404_NOT_FOUND),
detail=detail if detail else 'Pipeline not found',
)
@router.post("/{pipeline_id}/valves/update")
@router.post('/{pipeline_id}/valves/update')
async def update_pipeline_valves(
request: Request,
urlIdx: Optional[int],
@@ -509,8 +478,8 @@ async def update_pipeline_valves(
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.post(
f"{url}/{pipeline_id}/valves/update",
headers={"Authorization": f"Bearer {key}"},
f'{url}/{pipeline_id}/valves/update',
headers={'Authorization': f'Bearer {key}'},
json={**form_data},
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
@@ -520,21 +489,19 @@ async def update_pipeline_valves(
return {**data}
except Exception as e:
# Handle connection error here
log.exception(f"Connection error: {e}")
log.exception(f'Connection error: {e}')
detail = None
if response is not None:
try:
res = await response.json()
if "detail" in res:
detail = res["detail"]
if 'detail' in res:
detail = res['detail']
except Exception:
pass
raise HTTPException(
status_code=(
response.status if response is not None else status.HTTP_404_NOT_FOUND
),
detail=detail if detail else "Pipeline not found",
status_code=(response.status if response is not None else status.HTTP_404_NOT_FOUND),
detail=detail if detail else 'Pipeline not found',
)