Description
Describe the bug
The DatabaseSessionService class (in adk/sessions/database_session_service.py) fetches StorageEvent records without any ORDER BY clause. As a result, events are returned in a non-deterministic order determined by the database’s query planner. When building the context for inference via the Gemini API, messages end up shuffled, leading to hallucinations because the model receives them out of their original sequence.
To Reproduce
On src\google\adk\sessions\database_session_service.py:
Line 329:
`
def get_session(
self,
*,
app_name: str,
user_id: str,
session_id: str,
config: Optional[GetSessionConfig] = None,
) -> Optional[Session]:
# 1. Get the storage session entry from session table
# 2. Get all the events based on session id and filtering config
# 3. Convert and return the session
with self.DatabaseSessionFactory() as sessionFactory:
storage_session = sessionFactory.get(
StorageSession, (app_name, user_id, session_id)
)
if storage_session is None:
return None
storage_events = (
sessionFactory.query(StorageEvent)
.filter(StorageEvent.session_id == storage_session.id)
.filter(
StorageEvent.timestamp < config.after_timestamp
if config
else True
)
.limit(config.num_recent_events if config else None)
.all()
)
`
on storage_events, is missing .sort:
Fixed:
`
def get_session(
self,
*,
app_name: str,
user_id: str,
session_id: str,
config: Optional[GetSessionConfig] = None,
) -> Optional[Session]:
# 1. Get the storage session entry from session table
# 2. Get all the events based on session id and filtering config
# 3. Convert and return the session
with self.DatabaseSessionFactory() as sessionFactory:
storage_session = sessionFactory.get(
StorageSession, (app_name, user_id, session_id)
)
if storage_session is None:
return None
storage_events = (
sessionFactory.query(StorageEvent)
.filter(StorageEvent.session_id == storage_session.id)
.filter(
StorageEvent.timestamp < config.after_timestamp
if config
else True
)
.limit(config.num_recent_events if config else None)
.order_by(StorageEvent.timestamp.asc())
.all()
)
`
Expected behavior
Events should always be returned in ascending order of their timestamp field, preserving the chronological sequence of messages.
Actual Behavior
The StorageEvent list is returned without ordering, resulting in a non-deterministic sequence.
Desktop (please complete the following information):
- OS: Windows
- Python 3.12.8
- ADK version 0.3.0