step B.6 complete: POST /api/v1/storage/vectors/embed endpoint
This commit is contained in:
@@ -205,7 +205,7 @@ Tools must use **camelCase** field names (Drizzle maps them to snake_case intern
|
|||||||
- **Outcome:** Clean final frame. No more action descriptors in the protocol.
|
- **Outcome:** Clean final frame. No more action descriptors in the protocol.
|
||||||
|
|
||||||
### Step B.6 — Add `/vectors/embed` endpoint
|
### Step B.6 — Add `/vectors/embed` endpoint
|
||||||
- [ ] Add to `app/api/routes/vectors.py`:
|
- [x] Add to `app/api/routes/vectors.py`:
|
||||||
- `POST /api/v1/storage/vectors/embed`:
|
- `POST /api/v1/storage/vectors/embed`:
|
||||||
- Request: `{ text: str }`
|
- Request: `{ text: str }`
|
||||||
- Response: `{ vector: list[float] }` (1536-dim from `text-embedding-3-small`)
|
- Response: `{ vector: list[float] }` (1536-dim from `text-embedding-3-small`)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Vectors routes: upsert, search, and delete cloud vector store entries."""
|
"""Vectors routes: upsert, search, delete cloud vector store entries, and embed text."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -6,6 +6,7 @@ from fastapi import APIRouter, Depends
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from app.api.deps import get_current_user
|
from app.api.deps import get_current_user
|
||||||
|
from app.core.llm import embed
|
||||||
from app.schemas import (
|
from app.schemas import (
|
||||||
UserProfile,
|
UserProfile,
|
||||||
VectorSearchRequest,
|
VectorSearchRequest,
|
||||||
@@ -24,6 +25,14 @@ class _VectorDeleteRequest(BaseModel):
|
|||||||
ids: list[str]
|
ids: list[str]
|
||||||
|
|
||||||
|
|
||||||
|
class _EmbedRequest(BaseModel):
|
||||||
|
text: str
|
||||||
|
|
||||||
|
|
||||||
|
class _EmbedResponse(BaseModel):
|
||||||
|
vector: list[float]
|
||||||
|
|
||||||
|
|
||||||
@router.post("/vectors/upsert", response_model=dict)
|
@router.post("/vectors/upsert", response_model=dict)
|
||||||
async def upsert_vectors(
|
async def upsert_vectors(
|
||||||
body: VectorUpsertRequest,
|
body: VectorUpsertRequest,
|
||||||
@@ -54,3 +63,17 @@ async def delete_vectors(
|
|||||||
"""Delete vectors by ID, scoped to the authenticated user."""
|
"""Delete vectors by ID, scoped to the authenticated user."""
|
||||||
await _vector_store.delete(current_user.id, body.ids)
|
await _vector_store.delete(current_user.id, body.ids)
|
||||||
return {"ok": True}
|
return {"ok": True}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/vectors/embed", response_model=_EmbedResponse)
|
||||||
|
async def embed_text(
|
||||||
|
body: _EmbedRequest,
|
||||||
|
current_user: UserProfile = Depends(get_current_user),
|
||||||
|
) -> _EmbedResponse:
|
||||||
|
"""Generate a 1536-dim embedding vector for the given text.
|
||||||
|
|
||||||
|
Uses ``text-embedding-3-small`` via OpenAI. Auth required (JWT).
|
||||||
|
Used by backend tools (note_agent) and Electron (vectordb.ts) alike.
|
||||||
|
"""
|
||||||
|
vector = await embed(body.text)
|
||||||
|
return _EmbedResponse(vector=vector)
|
||||||
|
|||||||
Reference in New Issue
Block a user