Skip to content

Commit f5f8258

Browse files
committed
refactor(api): enhance APISearchRequest model with improved structure and documentation
- Reorganize fields with clear section comments (Basic inputs, Cube scoping, Search mode, etc.) - Add comprehensive field descriptions for better API documentation - Add new 'filter' field for structured filter conditions with support for logical operators, comparisons, and string operations - Add 'pref_top_k' and 'include_preference' fields for preference memory handling - Mark 'mem_cube_id' as deprecated, recommend 'readable_cube_ids' for multi-cube search - Make 'user_id' required field (was optional) - Add validation constraints (e.g., top_k >= 1) - Improve backward compatibility notes and internal field descriptions - Add 'threshold' field for internal similarity threshold control
1 parent b0e4afe commit f5f8258

File tree

1 file changed

+106
-14
lines changed

1 file changed

+106
-14
lines changed

src/memos/api/product_models.py

Lines changed: 106 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
import uuid
33

4-
from typing import Generic, Literal, TypeVar
4+
from typing import Any, Generic, Literal, TypeVar
55

66
from pydantic import BaseModel, Field
77

@@ -175,25 +175,117 @@ class SearchRequest(BaseRequest):
175175
class APISearchRequest(BaseRequest):
176176
"""Request model for searching memories."""
177177

178-
query: str = Field(..., description="Search query")
179-
user_id: str = Field(None, description="User ID")
180-
mem_cube_id: str | None = Field(None, description="Cube ID to search in")
178+
# ==== Basic inputs ====
179+
query: str = Field(
180+
...,
181+
description=("User search query"),
182+
)
183+
user_id: str = Field(..., description="User ID")
184+
185+
# ==== Cube scoping ====
186+
mem_cube_id: str | None = Field(
187+
None,
188+
description=(
189+
"(Deprecated) Single cube ID to search in. "
190+
"Prefer `readable_cube_ids` for multi-cube search."
191+
),
192+
)
181193
readable_cube_ids: list[str] | None = Field(
182-
None, description="List of cube IDs user can read for multi-cube search"
194+
None,
195+
description=(
196+
"List of cube IDs that are readable for this request. "
197+
"Required for algorithm-facing API; optional for developer-facing API."
198+
),
183199
)
200+
201+
# ==== Search mode ====
184202
mode: SearchMode = Field(
185-
os.getenv("SEARCH_MODE", SearchMode.FAST), description="search mode: fast, fine, or mixture"
203+
os.getenv("SEARCH_MODE", SearchMode.FAST),
204+
description="Search mode: FAST, FINE, or MIXTURE.",
186205
)
187-
internet_search: bool = Field(False, description="Whether to use internet search")
188-
moscube: bool = Field(False, description="Whether to use MemOSCube")
189-
top_k: int = Field(10, description="Number of results to return")
190-
chat_history: list[MessageDict] | None = Field(None, description="Chat history")
191-
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
206+
207+
session_id: str | None = Field(
208+
None,
209+
description=(
210+
"Session ID used as a soft signal to prioritize more relevant memories. "
211+
"Only used for weighting, not as a hard filter."
212+
),
213+
)
214+
215+
# ==== Result control ====
216+
top_k: int = Field(
217+
10,
218+
ge=1,
219+
description="Number of textual memories to retrieve (top-K). Default: 10.",
220+
)
221+
222+
pref_top_k: int = Field(
223+
6,
224+
ge=0,
225+
description="Number of preference memories to retrieve (top-K). Default: 6.",
226+
)
227+
228+
include_preference: bool = Field(
229+
True,
230+
description=(
231+
"Whether to retrieve preference memories along with general memories. "
232+
"If enabled, the system will automatically recall user preferences "
233+
"relevant to the query. Default: True."
234+
),
235+
)
236+
237+
# ==== Filter conditions ====
238+
filter: dict[str, Any] | None = Field(
239+
None,
240+
description=(
241+
"Structured filter conditions for searching memories. "
242+
"Supports logical operators: AND, OR, NOT; "
243+
"comparison: E (==), NE (!=), GT (>), LT (<), GTE (>=), LTE (<=); "
244+
"arithmetic: +, -, *, /, %, **; "
245+
"set: IN, CONTAINS, ICONTAINS; "
246+
"string: LIKE. "
247+
"This nested dict will be converted into an internal expression tree."
248+
),
249+
)
250+
251+
# ==== Extended capabilities ====
252+
internet_search: bool = Field(
253+
False,
254+
description=(
255+
"Whether to enable internet search in addition to memory search. "
256+
"Primarily used by internal algorithms. Default: False."
257+
),
258+
)
259+
260+
# Inner user, not supported in API yet
261+
threshold: float | None = Field(
262+
None,
263+
description=(
264+
"Internal similarity threshold for searching plaintext memories. "
265+
"If None, default thresholds will be applied."
266+
),
267+
)
268+
269+
# ==== Context ====
270+
chat_history: list[MessageDict] | None = Field(
271+
None,
272+
description=(
273+
"Historical chat messages used internally by algorithms. "
274+
"If None, internal stored history may be used; "
275+
"if provided (even an empty list), this value will be used as-is."
276+
),
277+
)
278+
279+
# ==== Backward compatibility ====
280+
moscube: bool = Field(
281+
False,
282+
description="(Deprecated / internal) Whether to use legacy MemOSCube path.",
283+
)
284+
192285
operation: list[PermissionDict] | None = Field(
193-
None, description="operation ids for multi cubes"
286+
None,
287+
description="(Internal) Operation definitions for multi-cube read permissions.",
194288
)
195-
include_preference: bool = Field(True, description="Whether to handle preference memory")
196-
pref_top_k: int = Field(6, description="Number of preference results to return")
197289

198290

199291
class APIADDRequest(BaseRequest):

0 commit comments

Comments
 (0)