Repository navigation
Expand file tree
/
Copy pathserver.py
More file actions
100 lines (75 loc) · 2.84 KB
/
Copy pathserver.py
File metadata and controls
100 lines (75 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""Local HTTP bridge for Perplexify."""
from __future__ import annotations
from typing import Literal
from fastapi import FastAPI
from pydantic import BaseModel, Field
from config import ensure_import_paths, load_cookie
from engine import run_query
from models import MODEL_CHOICES
class QueryRequest(BaseModel):
query: str = Field(..., min_length=1)
model: str | None = None
context: str = ""
class ChatRequest(QueryRequest):
history: list[dict[str, str]] = Field(default_factory=list)
def create_app() -> FastAPI:
ensure_import_paths()
app = FastAPI(
title="Perplexify CLI Local Bridge",
version="1.0.0",
description="Local HTTP wrapper around the Perplexify reverse-web stack.",
)
@app.get("/health")
async def health() -> dict[str, object]:
cookie = load_cookie()
return {
"ok": bool(cookie.cookie),
"service": "perplexify",
"cookie_configured": bool(cookie.cookie),
"cookie_source": cookie.source,
}
@app.get("/models")
async def models() -> dict[str, object]:
return {
"ok": True,
"models": list(MODEL_CHOICES),
"note": "Model values are reverse-web preferences; Perplexity reports the effective model_used.",
}
@app.post("/ask")
async def ask(payload: QueryRequest) -> dict[str, object]:
return await _run_endpoint(payload, mode="ask")
@app.post("/search")
async def search(payload: QueryRequest) -> dict[str, object]:
return await _run_endpoint(payload, mode="search")
@app.post("/chat")
async def chat(payload: ChatRequest) -> dict[str, object]:
context = payload.context or _history_to_context(payload.history)
result = await run_query(
payload.query,
mode="chat",
model=payload.model,
context=context,
)
return result.to_dict()
return app
async def _run_endpoint(payload: QueryRequest, *, mode: Literal["ask", "search"]) -> dict[str, object]:
result = await run_query(
payload.query,
mode=mode,
model=payload.model,
context=payload.context,
)
return result.to_dict()
def _history_to_context(history: list[dict[str, str]]) -> str:
lines: list[str] = []
for item in history[-8:]:
role = str(item.get("role") or "user")
content = str(item.get("content") or "")
if content:
lines.append(f"{role}: {content}")
return "\n".join(lines)
def run_server(*, host: str = "127.0.0.1", port: int = 8787, reload: bool = False) -> None:
import uvicorn
target = "server:create_app"
uvicorn.run(target, factory=True, host=host, port=port, reload=reload)
app = create_app()