HTTP Transport

FastAPI dependencies, SSE streaming, and HTTP-layer utilities. Connects the HTTP API to the chat and strategy services.

Overview

  • Dependencies — Request-scoped deps: auth, DB session, repository injection. Injected into router handlers.

  • Streaming — SSE (Server-Sent Events) for chat. Event formatting, chunk encoding, stream lifecycle.

Application Factory

Purpose: FastAPI application entrypoint. Creates the app with middleware, lifecycle management (database init, Redis, Qdrant), router registration, and startup background tasks (RAG ingestion).

Design: The factory pattern (create_app()) enables testing with different configurations and ensures clean setup/teardown of database connections, Redis pools, and Qdrant clients via FastAPI lifespan events.

FastAPI application entrypoint.

veupath_chatbot.main.lifespan(app)[source]

Application lifespan handler.

Return type:

AsyncGenerator[None]

veupath_chatbot.main.create_app()[source]

Create and configure FastAPI application.

Return type:

FastAPI

Background Jobs

Purpose: Background job for RAG ingestion at API startup. Incrementally ingests WDK catalog data and public strategies into Qdrant when rag_enabled=true and OPENAI_API_KEY is set.

async veupath_chatbot.jobs.rag_startup.start_rag_startup_ingestion_background()[source]

Fire-and-forget incremental ingestion at API startup.

  • Runs only when rag_enabled=true and OPENAI_API_KEY is set.

  • Never blocks API startup.

  • Only runs once per process.

Developer Tools

Purpose: Developer tooling for keeping the OpenAPI spec in sync with the FastAPI application. Generates packages/spec/openapi.yaml and packages/shared-ts/src/openapi.generated.ts from the running app’s schema. This is intentionally NOT run at runtime — it writes repo files during development.

Developer tooling for keeping OpenAPI spec in sync.

This is intentionally NOT run by the API at runtime. It writes repo files.

veupath_chatbot.devtools.openapi.generate_openapi_yaml(*, out_path=None)[source]
Return type:

Path

veupath_chatbot.devtools.openapi.check_openapi_yaml(*, openapi_path=None)[source]
Return type:

bool

veupath_chatbot.devtools.openapi.main(argv=None)[source]
Return type:

int

Dependencies

Purpose: FastAPI dependencies. Provide auth context, DB session, repository injection, and experiment ownership checks. Used by routers.

Key functions: get_current_user_with_db_row(), get_experiment_owned_by_user()

Dependency injection for HTTP routes.

async veupath_chatbot.transport.http.deps.get_user_repo(session)[source]

Get user repository.

Return type:

UserRepository

async veupath_chatbot.transport.http.deps.get_control_set_repo(session)[source]

Get control set repository.

Return type:

ControlSetRepository

async veupath_chatbot.transport.http.deps.get_stream_repo(session)[source]

Get stream repository.

Return type:

StreamRepository

async veupath_chatbot.transport.http.deps.get_current_user_with_db_row(user_id, user_repo)[source]

Ensure authenticated users exist in the local DB.

We persist user IDs because many tables have a FK to users.id. Without this, first-time sessions can trigger integrity errors that bubble up as 500s.

Return type:

UUID

async veupath_chatbot.transport.http.deps.get_experiment_owned_by_user(experiment_id, user_id)[source]

Resolve an experiment by ID and verify the current user owns it.

Return type:

Experiment

async veupath_chatbot.transport.http.deps.get_experiments_owned_by_user(experiment_ids, user_id)[source]

Fetch multiple experiments by ID and verify ownership (parallel).

Return type:

list[Experiment]

SSE Helpers

Purpose: SSE event formatting utilities. Encode events as SSE-formatted strings with proper data: prefixes and newline terminators.

Reusable SSE (Server-Sent Events) stream helpers for experiment endpoints.

All experiment SSE generators share a common pattern: 1. Create an asyncio queue for events 2. Launch a background task that produces events via the queue 3. Format each event as SSE text and yield to the client 4. Terminate when a sentinel event type is received

This module extracts that pattern into sse_stream().

async veupath_chatbot.transport.http.sse.sse_stream(producer, end_event_types)[source]

Generic SSE event stream driven by an async producer function.

Parameters:
  • producer (Callable[[Callable[[JSONObject], Awaitable[None]]], Awaitable[None]]) – An async callable that receives a send(event) callback and pushes {"type": ..., "data": ...} dicts into it.

  • end_event_types (set[str]) – Set of event type strings that signal end-of-stream. When the consumer sees one of these, it yields the final SSE frame and stops iterating.

Return type:

AsyncIterator[str]

If the producer raises without sending an end event, an internal_error event is injected automatically so the consumer never hangs.

Routers

FastAPI routers that define the HTTP API surface. Each router handles a specific domain area.

Chat endpoint — starts a background chat operation.

async veupath_chatbot.transport.http.routers.chat.chat(request, body, user_repo, stream_repo, user_id)[source]

Start a chat operation and return its operation ID.

The client subscribes to GET /operations/{operationId}/subscribe for SSE events.

Return type:

JSONResponse

Site listing, record types, and search catalog endpoints.

async veupath_chatbot.transport.http.routers.sites.catalog.list_sites()[source]

List all available VEuPathDB sites.

Return type:

list[SiteResponse]

async veupath_chatbot.transport.http.routers.sites.catalog.get_record_types(siteId)[source]

Get record types available on a site.

Return type:

list[RecordTypeResponse]

async veupath_chatbot.transport.http.routers.sites.catalog.get_searches(siteId, record_type=None)[source]

Get searches available on a site, optionally filtered by record type.

Return type:

list[SearchResponse]

Gene search and resolve endpoints.

class veupath_chatbot.transport.http.routers.sites.genes.GeneSearchResultResponse(*, geneId, displayName='', organism='', product='', geneName='', geneType='', location='', matchedFields=[])[source]

Bases: BaseModel

A single gene result from site-search.

geneId: str
displayName: str
organism: str
product: str
geneName: str
geneType: str
location: str
matchedFields: list[str]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.routers.sites.genes.GeneSearchResponse(*, results, totalCount, suggestedOrganisms=[])[source]

Bases: BaseModel

Paginated gene search response.

results: list[GeneSearchResultResponse]
totalCount: int
suggestedOrganisms: list[str]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.routers.sites.genes.GeneResolveRequest(*, geneIds)[source]

Bases: BaseModel

Request body for gene ID resolution.

geneIds: list[str]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.routers.sites.genes.ResolvedGeneResponse(*, geneId, displayName='', organism='', product='', geneName='', geneType='', location='')[source]

Bases: BaseModel

A resolved gene record.

geneId: str
displayName: str
organism: str
product: str
geneName: str
geneType: str
location: str
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.routers.sites.genes.GeneResolveResponse(*, resolved, unresolved)[source]

Bases: BaseModel

Gene ID resolution response.

resolved: list[ResolvedGeneResponse]
unresolved: list[str]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.routers.sites.genes.OrganismsResponse(*, organisms)[source]

Bases: BaseModel

Available organisms for a site.

organisms: list[str]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

async veupath_chatbot.transport.http.routers.sites.genes.list_organisms(siteId)[source]

Return all available organism names for a site via site-search.

Return type:

OrganismsResponse

async veupath_chatbot.transport.http.routers.sites.genes.search_genes(siteId, q='', organism=None, limit=50, offset=0)[source]

Search genes by text using multi-strategy gene lookup.

Return type:

GeneSearchResponse

async veupath_chatbot.transport.http.routers.sites.genes.resolve_genes(siteId, payload)[source]

Resolve gene IDs to full records via WDK standard reporter.

Return type:

GeneResolveResponse

Parameter-related endpoints: dependent params, validation, param specs.

async veupath_chatbot.transport.http.routers.sites.params.validate_search_params(siteId, recordType, searchName, payload)[source]

Validate search parameters (UI-friendly).

Return type:

SearchValidationResponse

async veupath_chatbot.transport.http.routers.sites.params.get_param_specs_with_context(siteId, recordType, searchName, payload)[source]

Return normalized parameter specs, using contextual WDK vocab when provided.

Return type:

list[ParamSpecResponse]

Models endpoint — exposes available LLM models and their status.

class veupath_chatbot.transport.http.routers.models.ModelCatalogEntryResponse(*, id, name, provider, model, description='', supportsReasoning=False, enabled=True, contextSize=0, defaultReasoningBudget=0, inputPrice=0.0, cachedInputPrice=0.0, outputPrice=0.0)[source]

Bases: BaseModel

A single model in the catalog — for API responses.

id: str
name: str
provider: Literal['openai', 'anthropic', 'google', 'ollama', 'mock']
model: str
description: str
supports_reasoning: bool
enabled: bool
context_size: int
default_reasoning_budget: int
input_price: float
cached_input_price: float
output_price: float
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.routers.models.ModelListResponse(*, models, default, defaultReasoningEffort)[source]

Bases: BaseModel

Response for the /models endpoint.

models: list[ModelCatalogEntryResponse]
default: str
default_reasoning_effort: Literal['none', 'low', 'medium', 'high']
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

async veupath_chatbot.transport.http.routers.models.list_models()[source]

Return available models grouped by provider.

Models whose provider has no API key are returned with enabled: false so the frontend can render them as disabled in the picker.

Return type:

ModelListResponse

Health check endpoints.

async veupath_chatbot.transport.http.routers.health.health_check()[source]

Liveness check - is the service running?

Return type:

HealthResponse

async veupath_chatbot.transport.http.routers.health.system_config()[source]

Report whether the system has LLM provider keys configured.

This is unauthenticated so the frontend can show a setup-required screen before asking users to log in.

Return type:

SystemConfigResponse

async veupath_chatbot.transport.http.routers.health.readiness_check()[source]

Readiness check - is the service ready to accept requests?

Checks database connectivity and Qdrant availability (if RAG is enabled). Returns 503 if any dependency is unreachable.

Return type:

HealthResponse | JSONResponse

CRUD endpoints for reusable control gene sets.

class veupath_chatbot.transport.http.routers.control_sets.CreateControlSetRequest(*, name, siteId, recordType, positiveIds=<factory>, negativeIds=<factory>, source=None, tags=<factory>, provenanceNotes=None, isPublic=False)[source]

Bases: BaseModel

Payload for creating a new control set.

name: str
site_id: str
record_type: str
positive_ids: list[str]
negative_ids: list[str]
source: str | None
tags: list[str]
provenance_notes: str | None
is_public: bool
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.routers.control_sets.ControlSetResponse(*, id, name, siteId, recordType, positiveIds, negativeIds, source=None, tags, provenanceNotes=None, version, isPublic, userId=None, createdAt)[source]

Bases: BaseModel

Serialized control set returned to the client.

id: str
name: str
site_id: str
record_type: str
positive_ids: list[str]
negative_ids: list[str]
source: str | None
tags: list[str]
provenance_notes: str | None
version: int
is_public: bool
user_id: str | None
created_at: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

async veupath_chatbot.transport.http.routers.control_sets.list_control_sets(repo, user_id, site_id=Query(None), tags=None)[source]

List control sets visible to the current user.

Return type:

list[ControlSetResponse]

async veupath_chatbot.transport.http.routers.control_sets.get_control_set(control_set_id, repo, user_id)[source]

Get a single control set by ID.

Return type:

ControlSetResponse

async veupath_chatbot.transport.http.routers.control_sets.create_control_set(body, repo, user_id)[source]

Create a new control set.

Return type:

ControlSetResponse

async veupath_chatbot.transport.http.routers.control_sets.delete_control_set(control_set_id, repo, user_id)[source]

Delete a control set owned by the current user.

VEuPathDB OAuth login bridge.

On successful VEuPathDB login the endpoint also creates/looks-up the internal Pathfinder user (via User.external_id = email) and returns a pathfinder-auth token so the frontend has a stable identity across sessions.

class veupath_chatbot.transport.http.routers.veupathdb_auth.LoginPayload(*, email, password)[source]

Bases: BaseModel

email: str
password: str
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

async veupath_chatbot.transport.http.routers.veupathdb_auth.login_with_password(user_repo, payload=None, redirect_to=Query(None), site_id=Query(veupathdb))[source]

Login via VEuPathDB /login, link internal user, and store auth cookies.

Return type:

JSONResponse

async veupath_chatbot.transport.http.routers.veupathdb_auth.logout(site_id=Query(veupathdb))[source]

Clear local auth cookie and log out of VEuPathDB.

Return type:

JSONResponse

async veupath_chatbot.transport.http.routers.veupathdb_auth.refresh_internal_auth(request, user_repo, site_id=Query(veupathdb))[source]

Re-derive the internal pathfinder-auth token from a live VEuPathDB session.

Called on page load when the internal token is missing/expired but the VEuPathDB Authorization cookie is still valid.

Return type:

JSONResponse

async veupath_chatbot.transport.http.routers.veupathdb_auth.auth_status(request, site_id=Query(veupathdb))[source]

Return current VEuPathDB auth status.

In mock mode (PATHFINDER_CHAT_PROVIDER=mock), a valid pathfinder-auth cookie is sufficient — the dev-login endpoint doesn’t create a VEuPathDB session, so we skip the real WDK call.

Return type:

_AuthStatusDict

Development-only endpoints (available only when chat_provider=mock).

async veupath_chatbot.transport.http.routers.dev.dev_login(user_repo, user_id=None)[source]

Create a test user and return a valid auth token.

Only available when PATHFINDER_CHAT_PROVIDER=mock (e2e / local dev).

Pass ?user_id=worker-0 to create isolated users per Playwright worker so parallel tests don’t share data.

Return type:

JSONResponse

Download endpoint for AI-generated export files.

async veupath_chatbot.transport.http.routers.exports.download_export(export_id)[source]

Serve a previously generated export file.

Export IDs are uuid4 tokens with a 10-minute TTL. No auth required.

Return type:

StreamingResponse

Gene set management endpoints.

Thin transport layer: parse HTTP request, call service, return HTTP response. All business logic lives in services.gene_sets.operations.

async veupath_chatbot.transport.http.routers.gene_sets.create_gene_set(request, body, user_id)[source]

Create a new gene set.

Return type:

GeneSetResponse

async veupath_chatbot.transport.http.routers.gene_sets.list_gene_sets(user_id, site_id=Query(None))[source]

List all gene sets for the current user, optionally filtered by site.

Return type:

list[GeneSetResponse]

async veupath_chatbot.transport.http.routers.gene_sets.get_gene_set(gene_set_id, user_id)[source]

Get a gene set by ID.

Return type:

GeneSetResponse

async veupath_chatbot.transport.http.routers.gene_sets.delete_gene_set(gene_set_id, user_id)[source]

Delete a gene set.

Return type:

dict[str, bool]

async veupath_chatbot.transport.http.routers.gene_sets.set_operations(request, user_id)[source]

Perform set operations (intersect, union, minus) between two gene sets.

Return type:

GeneSetResponse

Rank the user’s gene sets by how well they recover the given positive genes.

Return type:

list[ReverseSearchResultItem]

async veupath_chatbot.transport.http.routers.gene_sets.ensemble_scoring(body, user_id)[source]

Score genes by frequency across multiple gene sets.

Return type:

list[EnsembleScore]

async veupath_chatbot.transport.http.routers.gene_sets.enrich_gene_set(gene_set_id, request, user_id)[source]

Run enrichment analysis on a gene set.

Return type:

list[JSONObject]

async veupath_chatbot.transport.http.routers.gene_sets.get_gene_set_attributes(gene_set_id, user_id)[source]

Get available attributes for a gene set’s record type.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.gene_sets.get_gene_set_records(gene_set_id, user_id, offset=Query(0), limit=Query(50), sort=None, dir='ASC', attributes=None, filter_attribute=Query(None), filter_value=Query(None))[source]

Get paginated result records for a gene set.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.gene_sets.get_gene_set_distribution(gene_set_id, attribute_name, user_id)[source]

Get distribution data for an attribute using the byValue column reporter.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.gene_sets.get_gene_set_record_detail(gene_set_id, body, user_id)[source]

Get a single record’s full details by primary key.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.gene_sets.gene_confidence(body)[source]

Compute per-gene composite confidence scores from classification data.

Return type:

list[GeneConfidenceScoreResponse]

Internal endpoints — not for production use.

class veupath_chatbot.transport.http.routers.internal.SSESchemaIndex(*, message_start=None, user_message=None, assistant_delta=None, assistant_message=None, tool_call_start=None, tool_call_end=None, subkani_task_start=None, subkani_tool_call_start=None, subkani_tool_call_end=None, subkani_task_end=None, token_usage_partial=None, model_selected=None, optimization_progress=None, optimization_trial=None, optimization_parameter_spec=None, error=None, graph_snapshot=None, strategy_meta=None, graph_plan=None, strategy_update=None, strategy_link=None, graph_cleared=None, executor_build_request=None, gene_set_summary=None, workbench_gene_set=None, citations=None, planning_artifact=None, reasoning=None, message_end=None)[source]

Bases: BaseModel

Index of all SSE event data schemas. Never called – exists for OpenAPI generation.

message_start: MessageStartEventData | None
user_message: UserMessageEventData | None
assistant_delta: AssistantDeltaEventData | None
assistant_message: AssistantMessageEventData | None
tool_call_start: ToolCallStartEventData | None
tool_call_end: ToolCallEndEventData | None
subkani_task_start: SubKaniTaskStartEventData | None
subkani_tool_call_start: SubKaniToolCallStartEventData | None
subkani_tool_call_end: SubKaniToolCallEndEventData | None
subkani_task_end: SubKaniTaskEndEventData | None
token_usage_partial: TokenUsagePartialEventData | None
model_selected: ModelSelectedEventData | None
optimization_progress: OptimizationProgressEventData | None
optimization_trial: OptimizationTrialData | None
optimization_parameter_spec: OptimizationParameterSpecData | None
error: ErrorEventData | None
graph_snapshot: GraphSnapshotEventData | None
strategy_meta: StrategyMetaEventData | None
graph_plan: GraphPlanEventData | None
strategy_update: StrategyUpdateEventData | None
graph_cleared: GraphClearedEventData | None
executor_build_request: ExecutorBuildRequestEventData | None
gene_set_summary: GeneSetSummary | None
workbench_gene_set: WorkbenchGeneSetEventData | None
citations: CitationsEventData | None
planning_artifact: PlanningArtifactEventData | None
reasoning: ReasoningEventData | None
message_end: MessageEndEventData | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

async veupath_chatbot.transport.http.routers.internal.sse_schemas()[source]

SSE event data schemas – for OpenAPI generation only.

Return type:

SSESchemaIndex

class veupath_chatbot.transport.http.routers.internal.ExperimentSchemaIndex(*, experiment=None, experiment_summary=None, experiment_config=None, confusion_matrix=None, experiment_metrics=None, gene_info=None, fold_metrics=None, cross_validation_result=None, enrichment_term=None, enrichment_result=None, rank_metrics=None, confidence_interval=None, negative_set_variant=None, bootstrap_result=None, step_evaluation=None, operator_variant=None, operator_comparison=None, step_contribution=None, parameter_sweep_point=None, parameter_sensitivity=None, step_analysis_result=None, optimization_spec=None, threshold_knob=None, operator_knob=None, tree_optimization_trial=None, tree_optimization_result=None, trial_progress_data=None, step_analysis_progress_data=None, experiment_progress_data=None, optimization_result=None, control_set_summary=None, citation=None, planning_artifact=None)[source]

Bases: BaseModel

Index of all experiment response schemas. Never called – exists for OpenAPI generation.

experiment: ExperimentResponse | None
experiment_summary: ExperimentSummaryResponse | None
experiment_config: ExperimentConfigResponse | None
confusion_matrix: ConfusionMatrixResponse | None
experiment_metrics: ExperimentMetricsResponse | None
gene_info: GeneInfoResponse | None
fold_metrics: FoldMetricsResponse | None
cross_validation_result: CrossValidationResultResponse | None
enrichment_term: EnrichmentTermResponse | None
enrichment_result: EnrichmentResultResponse | None
rank_metrics: RankMetricsResponse | None
confidence_interval: ConfidenceIntervalResponse | None
negative_set_variant: NegativeSetVariantResponse | None
bootstrap_result: BootstrapResultResponse | None
step_evaluation: StepEvaluationResponse | None
operator_variant: OperatorVariantResponse | None
operator_comparison: OperatorComparisonResponse | None
step_contribution: StepContributionResponse | None
parameter_sweep_point: ParameterSweepPointResponse | None
parameter_sensitivity: ParameterSensitivityResponse | None
step_analysis_result: StepAnalysisResultResponse | None
optimization_spec: OptimizationSpecResponse | None
threshold_knob: ThresholdKnobResponse | None
operator_knob: OperatorKnobResponse | None
tree_optimization_trial: TreeOptimizationTrialResponse | None
tree_optimization_result: TreeOptimizationResultResponse | None
trial_progress_data: TrialProgressDataResponse | None
step_analysis_progress_data: StepAnalysisProgressDataResponse | None
experiment_progress_data: ExperimentProgressDataResponse | None
optimization_result: OptimizationResultResponse | None
control_set_summary: ControlSetSummaryResponse | None
citation: CitationResponse | None
planning_artifact: PlanningArtifactResponse | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

async veupath_chatbot.transport.http.routers.internal.experiment_schemas()[source]

Experiment response schemas – for OpenAPI generation only.

Return type:

ExperimentSchemaIndex

Operations endpoints: subscribe via Redis Streams, discover active operations.

async veupath_chatbot.transport.http.routers.operations.subscribe(operation_id, session, user_id, last_event_id=Query(None))[source]

SSE stream backed by Redis Streams.

Catchup: replays events from lastEventId (or from the beginning). Live: uses XREAD BLOCK for new events until a terminal event is seen.

Return type:

StreamingResponse

async veupath_chatbot.transport.http.routers.operations.cancel(operation_id, session, user_id)[source]

Cancel a running operation.

For chat operations this cancels the background asyncio task running the LLM agent. The producer’s CancelledError handler emits a message_end event so any connected subscribers close cleanly.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.operations.list_active(session, user_id, stream_id=Query(None), type=Query(None))[source]

List active operations, optionally filtered by stream and/or type.

Return type:

list[JSONObject]

Tools endpoint — returns the list of AI tools available to the agent.

class veupath_chatbot.transport.http.routers.tools.ToolListResponse[source]

Bases: TypedDict

tools: list[_ToolItem]
async veupath_chatbot.transport.http.routers.tools.list_tools()[source]

Return the list of AI tools registered on the agent.

Return type:

ToolListResponse

User data management — purge endpoints.

async veupath_chatbot.transport.http.routers.user_data.purge_user_data(user_id, stream_repo, site_id=Query(None), delete_wdk=Query(False))[source]

Purge user data from all local stores.

When deleteWdk=false (default): non-WDK streams are hard-deleted, WDK-linked projections are dismissed so WDK sync won’t re-import them. The strategies remain on VEuPathDB but PathFinder ignores them.

When deleteWdk=true: everything is hard-deleted locally AND all WDK strategies are deleted from VEuPathDB.

Always deletes: gene sets, experiments, control sets, Redis streams.

Pass ?siteId=X to limit to one site, or omit for everything.

Return type:

JSONObject

Strategy CRUD endpoints — CQRS only (streams + stream_projections).

async veupath_chatbot.transport.http.routers.strategies.crud.list_strategies(stream_repo, user_id, site_id=None)[source]

List user’s conversation streams (projections).

Return type:

list[StrategyResponse]

async veupath_chatbot.transport.http.routers.strategies.crud.list_dismissed_strategies(stream_repo, user_id, site_id=None)[source]

List user’s dismissed (soft-deleted) strategies.

Return type:

list[StrategyResponse]

async veupath_chatbot.transport.http.routers.strategies.crud.create_strategy(request, stream_repo, user_id)[source]

Create a new strategy (CQRS only).

Return type:

StrategyResponse

async veupath_chatbot.transport.http.routers.strategies.crud.get_strategy(strategyId, stream_repo, user_id)[source]

Get a strategy/stream by ID from the CQRS projection + Redis.

Return type:

StrategyResponse

async veupath_chatbot.transport.http.routers.strategies.crud.update_strategy(strategyId, request, stream_repo, user_id)[source]

Update a strategy (CQRS only).

Return type:

StrategyResponse

async veupath_chatbot.transport.http.routers.strategies.crud.delete_strategy(strategyId, stream_repo, user_id, delete_from_wdk=False)[source]

Delete a strategy: cancel ops, clean Redis stream, delete CQRS records.

For WDK-linked strategies with deleteFromWdk=false (default), the strategy is soft-deleted (dismissed) instead of hard-deleted. This prevents WDK sync from re-importing it. Use the restore endpoint to un-dismiss.

Pass deleteFromWdk=true to hard-delete from both PathFinder and WDK. Non-WDK strategies are always hard-deleted.

Return type:

Response

async veupath_chatbot.transport.http.routers.strategies.crud.get_strategy_ast(strategyId, stream_repo, user_id)[source]

Return the raw plan AST from a strategy’s projection.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.strategies.crud.restore_strategy(strategyId, stream_repo, user_id)[source]

Restore a dismissed (soft-deleted) strategy.

Clears dismissed_at, resets plan to empty (triggers lazy WDK re-fetch), and wipes message history. The strategy reappears as if freshly imported.

Return type:

StrategyResponse

Plan normalization endpoints (frontend-consumer alignment).

async veupath_chatbot.transport.http.routers.strategies.plan.normalize_plan(payload)[source]

Normalize/coerce plan parameters using backend-owned rules.

This endpoint exists so the frontend can be a consumer of backend canonicalization (and avoid re-implementing CSV/JSON parsing and WDK quirks).

Return type:

PlanNormalizeResponse

Strategy counts endpoints (WDK-backed).

async veupath_chatbot.transport.http.routers.strategies.counts.compute_step_counts(request, user_id)[source]

Compute step counts by executing the plan in WDK.

Return type:

StepCountsResponse

WDK-backed strategy endpoints (open/import/sync/list).

async veupath_chatbot.transport.http.routers.strategies.wdk_import.open_strategy(request, stream_repo, user_id)[source]

Open a strategy by local or WDK strategy.

Return type:

OpenStrategyResponse

async veupath_chatbot.transport.http.routers.strategies.wdk_import.sync_all_wdk_strategies(site_id, stream_repo, user_id, background_tasks)[source]

Batch-sync all WDK strategies into the CQRS layer and return the full list.

Return type:

list[StrategyResponse]

CRUD endpoints for experiments: list, get, update, delete.

class veupath_chatbot.transport.http.routers.experiments.crud.PatchExperimentRequest(*, notes=None)[source]

Bases: BaseModel

Request body for PATCH /experiments/{experiment_id}.

notes: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

async veupath_chatbot.transport.http.routers.experiments.crud.list_experiments(user_id, siteId=None)[source]

List experiments owned by the current user, optionally filtered by site.

Return type:

list[JSONObject]

async veupath_chatbot.transport.http.routers.experiments.crud.get_experiment(exp, user_id)[source]

Get full experiment details including all results.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.experiments.crud.update_experiment(exp, body, user_id)[source]

Update experiment metadata (e.g. notes).

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.experiments.crud.delete_experiment(exp, user_id)[source]

Delete an experiment and clean up its WDK strategy.

Return type:

Response

Experiment execution endpoints: create, batch, benchmark.

async veupath_chatbot.transport.http.routers.experiments.execution.create_experiment(request, body, user_id)[source]

Create and run an experiment as a background task.

Return type:

JSONResponse

async veupath_chatbot.transport.http.routers.experiments.execution.create_batch_experiment(request, body, user_id)[source]

Run the same search across multiple organisms as a background task.

Return type:

JSONResponse

async veupath_chatbot.transport.http.routers.experiments.execution.create_benchmark(request, body, user_id)[source]

Run the same strategy against multiple control sets as a background task.

Return type:

JSONResponse

async veupath_chatbot.transport.http.routers.experiments.execution.seed_strategies(user_id, stream_repo, control_set_repo, site_id=None)[source]

Seed demo strategies and control sets across VEuPathDB sites.

If site_id is provided, only seeds for that database are created.

Return type:

StreamingResponse

Evaluation endpoints: re-evaluate, threshold-sweep, export.

async veupath_chatbot.transport.http.routers.experiments.evaluation.re_evaluate_experiment(exp, user_id)[source]

Re-run control evaluation against the (possibly modified) strategy.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.experiments.evaluation.threshold_sweep(exp, request, user_id)[source]

Sweep a parameter across a range and stream metrics as they complete.

Return type:

StreamingResponse

async veupath_chatbot.transport.http.routers.experiments.evaluation.get_experiment_report(exp, user_id)[source]

Generate and return a self-contained HTML report for an experiment.

Return type:

StreamingResponse

Analysis endpoints: cross-validate, enrich, re-evaluate, threshold-sweep, etc.

Mounts sub-routers for each analysis domain. Non-parametric routes (overlap, enrichment-compare) are included first so they don’t get shadowed by /{experiment_id} parametric routes.

Cross-validation endpoint for experiments.

async veupath_chatbot.transport.http.routers.experiments.cross_validation.run_cv(exp, request, user_id)[source]

Run cross-validation on an existing experiment.

Return type:

JSONObject

Enrichment analysis endpoints for experiments.

async veupath_chatbot.transport.http.routers.experiments.enrichment.run_enrichment(exp, request, user_id)[source]

Run enrichment analysis on an existing experiment’s results.

Return type:

list[JSONObject]

async veupath_chatbot.transport.http.routers.experiments.enrichment.custom_enrichment(exp, request, user_id)[source]

Test enrichment of a custom gene set against the experiment results.

Return type:

CustomEnrichmentResult

Cross-experiment comparison endpoints: overlap and enrichment comparison.

async veupath_chatbot.transport.http.routers.experiments.comparison.compute_overlap(body, user_id)[source]

Compute pairwise gene set overlap between experiments.

Return type:

OverlapResult

async veupath_chatbot.transport.http.routers.experiments.comparison.compare_enrichment(body, user_id)[source]

Compare enrichment results across experiments.

Return type:

EnrichmentCompareResult

Workbench chat endpoints — conversational AI per experiment.

async veupath_chatbot.transport.http.routers.experiments.chat.workbench_chat(experiment_id, body, user_repo, stream_repo, user_id)[source]

Start a conversational AI chat for an experiment.

Returns operation ID for SSE subscription via GET /operations/{operationId}/subscribe.

Return type:

WorkbenchChatResponse

async veupath_chatbot.transport.http.routers.experiments.chat.get_workbench_chat_messages(experiment_id, user_id, stream_repo, user_repo)[source]

Get conversation history for an experiment’s chat.

Return type:

list[JSONObject]

Results endpoints: records, record detail, attributes, distributions, refine.

async veupath_chatbot.transport.http.routers.experiments.results.get_experiment_attributes(exp, user_id)[source]

Get available attributes for an experiment’s record type.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.experiments.results.get_experiment_records(exp, user_id, offset=Query(0), limit=Query(50), sort=None, dir='ASC', attributes=None, filter_attribute=Query(None), filter_value=Query(None))[source]

Get paginated result records for an experiment.

Requires a persisted WDK strategy (wdkStepId must be set).

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.experiments.results.get_experiment_record_detail(exp, body, user_id)[source]

Get a single record’s full details by primary key.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.experiments.results.get_experiment_distribution(exp, attribute_name, user_id)[source]

Get distribution data for an attribute using the byValue column reporter.

Return type:

JSONObject

async veupath_chatbot.transport.http.routers.experiments.results.refine_experiment(exp, request, user_id)[source]

Add a step to the experiment’s strategy (combine, transform, etc.).

Return type:

JSONObject

Workbench Chat

Purpose: Workbench chat orchestration. Mirrors the main chat orchestrator but scoped to (user_id, experiment_id) pairs for experiment-context conversations.

Workbench chat orchestration entrypoint (service layer).

Mirrors services/chat/orchestrator.py but scoped to experiment-bound workbench conversations. Streams are keyed by (user_id, experiment_id) instead of an explicit strategy UUID.

AI-layer dependencies (workbench agent factory, model resolver) are injected at startup via configure() — the transport layer calls this once to wire the concrete implementations so that the services layer never imports from veupath_chatbot.ai.

veupath_chatbot.services.workbench_chat.orchestrator.configure(*, create_workbench_agent_fn, resolve_model_id_fn)[source]

Wire AI-layer implementations into the workbench chat orchestrator.

Called once at application startup from the composition root.

Parameters

create_workbench_agent_fn:

Factory that builds a Kani workbench agent for a chat turn.

resolve_model_id_fn:

Resolves the effective model ID from overrides and persisted state.

async veupath_chatbot.services.workbench_chat.orchestrator.start_workbench_chat_stream(*, message, site_id, experiment_id, user_id, user_repo, stream_repo, provider_override=None, model_override=None, reasoning_effort=None)[source]

Start a background workbench chat operation and return its identifiers.

Returns (operation_id, stream_id) so the caller can hand them to the client. The client subscribes to GET /operations/{operation_id}/subscribe for SSE events.

Only fast, essential work runs synchronously (user lookup, stream resolution, operation registration, user_message emission). All heavy lifting is deferred into the background producer.

Return type:

tuple[str, str]

async veupath_chatbot.services.workbench_chat.orchestrator.cancel_workbench_chat_operation(operation_id)[source]

Cancel a running workbench chat operation.

Returns True if the operation was found and cancelled, False otherwise.

Return type:

bool

Schemas

Pydantic request/response models (DTOs) for the HTTP API.

Chat request/response DTOs.

class veupath_chatbot.transport.http.schemas.chat.ChatMention(*, type, id, displayName)[source]

Bases: BaseModel

A reference to a strategy or experiment included via @-mention.

type: Literal['strategy', 'experiment']
id: str
display_name: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.ChatRequest(*, strategyId=None, siteId, message, provider=None, model=None, reasoningEffort=None, disableRag=False, temperature=None, seed=None, contextSize=None, responseTokens=None, reasoningBudget=None, disabledTools=<factory>, mentions=<factory>)[source]

Bases: BaseModel

Request to send a chat message.

strategy_id: UUID | None
site_id: str
message: str
provider: Literal['openai', 'anthropic', 'google', 'ollama', 'mock'] | None
model_id: str | None
reasoning_effort: Literal['none', 'low', 'medium', 'high'] | None
disable_rag: bool
temperature: float | None
seed: int | None
context_size: int | None
response_tokens: int | None
reasoning_budget: int | None
disabled_tools: list[str]
mentions: list[ChatMention]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.ToolCallResponse(*, id, name, arguments, result=None)[source]

Bases: BaseModel

Tool call information.

id: str
name: str
arguments: JSONObject
result: str | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.SubKaniTokenUsageResponse(*, promptTokens, completionTokens, llmCallCount=0, estimatedCostUsd=0.0)[source]

Bases: BaseModel

Token usage for a single sub-kani agent.

prompt_tokens: int
completion_tokens: int
llm_call_count: int
estimated_cost_usd: float
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.SubKaniActivityResponse(*, calls, status, models=None, tokenUsage=None)[source]

Bases: BaseModel

Sub-kani tool call activity.

calls: dict[str, list[ToolCallResponse]]
status: dict[str, str]
models: dict[str, str] | None
token_usage: dict[str, SubKaniTokenUsageResponse] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.ThinkingResponse(*, toolCalls=None, lastToolCalls=None, subKaniCalls=None, subKaniStatus=None, reasoning=None, updatedAt=None)[source]

Bases: BaseModel

In-progress tool call state.

tool_calls: list[ToolCallResponse] | None
last_tool_calls: list[ToolCallResponse] | None
sub_kani_calls: dict[str, list[ToolCallResponse]] | None
sub_kani_status: dict[str, str] | None
reasoning: str | None
updated_at: datetime | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.TokenUsageResponse(*, promptTokens, completionTokens, totalTokens, cachedTokens=0, toolCallCount, registeredToolCount, llmCallCount=0, subKaniPromptTokens=0, subKaniCompletionTokens=0, subKaniCallCount=0, estimatedCostUsd=0.0, modelId='')[source]

Bases: BaseModel

Token usage statistics for a message turn.

prompt_tokens: int
completion_tokens: int
total_tokens: int
cached_tokens: int
tool_call_count: int
registered_tool_count: int
llm_call_count: int
sub_kani_prompt_tokens: int
sub_kani_completion_tokens: int
sub_kani_call_count: int
estimated_cost_usd: float
model_id: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.CitationResponse(*, id, source, tag=None, title, url=None, authors=None, year=None, doi=None, pmid=None, snippet=None, accessedAt=None)[source]

Bases: BaseModel

Citation from research tools.

id: str
source: str
tag: str | None
title: str
url: str | None
authors: list[str] | None
year: int | None
doi: str | None
pmid: str | None
snippet: str | None
accessed_at: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.PlanningArtifactResponse(*, id, title, summaryMarkdown, assumptions=<factory>, parameters=<factory>, proposedStrategyPlan=None, createdAt)[source]

Bases: BaseModel

Strategy planning artifact.

id: str
title: str
summary_markdown: str
assumptions: list[str]
parameters: dict[str, JSONValue]
proposed_strategy_plan: JSONObject | None
created_at: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.chat.MessageResponse(*, role, content, modelId=None, toolCalls=None, subKaniActivity=None, citations=None, planningArtifacts=None, reasoning=None, optimizationProgress=None, tokenUsage=None, timestamp)[source]

Bases: BaseModel

Chat message.

role: str
content: str
model_id: str | None
tool_calls: list[ToolCallResponse] | None
sub_kani_activity: SubKaniActivityResponse | None
citations: list[CitationResponse] | None
planning_artifacts: list[PlanningArtifactResponse] | None
reasoning: str | None
optimization_progress: OptimizationProgressEventData | None
token_usage: TokenUsageResponse | None
timestamp: datetime
model_config = {'extra': 'ignore', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Strategy request/response DTOs.

class veupath_chatbot.transport.http.schemas.strategies.StepCountsRequest(*, siteId, plan)[source]

Bases: BaseModel

Request to compute step counts from a plan.

site_id: str
plan: StrategyPlan
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.strategies.StepCountsResponse(*, counts)[source]

Bases: BaseModel

Step counts keyed by local step ID.

counts: dict[str, int | None]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.strategies.WdkStrategySummaryResponse(*, wdkStrategyId, name, siteId, wdkUrl=None, rootStepId=None, isSaved=None, isInternal=False)[source]

Bases: BaseModel

WDK strategy summary for list views (backend-only).

wdk_strategy_id: int
name: str
site_id: str
wdk_url: str | None
root_step_id: int | None
is_saved: bool | None
is_internal: bool
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.strategies.OpenStrategyRequest(*, strategyId=None, wdkStrategyId=None, siteId=None)[source]

Bases: BaseModel

Request to open a strategy.

strategy_id: UUID | None
wdk_strategy_id: int | None
site_id: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.strategies.OpenStrategyResponse(*, strategyId)[source]

Bases: BaseModel

Open strategy response.

strategy_id: UUID
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.strategies.StrategyResponse(*, id, name, title=None, description=None, siteId, recordType, steps=<factory>, rootStepId=None, wdkStrategyId=None, isSaved=False, messages=None, thinking=None, modelId=None, createdAt, updatedAt, stepCount=None, resultCount=None, wdkUrl=None, geneSetId=None, dismissedAt=None)[source]

Bases: BaseModel

Unified strategy response — used for both list and detail views.

List views: steps is [], stepCount/resultCount are populated. Detail views: steps is populated, summary fields may also be set.

id: UUID
name: str
title: str | None
description: str | None
site_id: str
record_type: str | None
steps: list[StepResponse]
root_step_id: str | None
wdk_strategy_id: int | None
is_saved: bool
messages: list[MessageResponse] | None
thinking: ThinkingResponse | None
model_id: str | None
created_at: datetime
updated_at: datetime
step_count: int | None
result_count: int | None
wdk_url: str | None
gene_set_id: str | None
dismissed_at: datetime | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.strategies.CreateStrategyRequest(*, name, siteId, plan)[source]

Bases: BaseModel

Request to create a strategy.

name: str
site_id: str
plan: StrategyPlan
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.strategies.UpdateStrategyRequest(*, name=None, plan=None, wdkStrategyId=None, isSaved=None)[source]

Bases: BaseModel

Request to update a strategy.

name: str | None
plan: StrategyPlan | None
wdk_strategy_id: int | None
is_saved: bool | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Strategy plan (DSL) request/response DTOs.

These models make the plan contract explicit in OpenAPI instead of using dict[str, Any], which is a major source of drift.

class veupath_chatbot.transport.http.schemas.plan.PlanMetadata(*, name=None, description=None, siteId=None, createdAt=None)[source]

Bases: BaseModel

name: str | None
description: str | None
siteId: str | None
createdAt: str | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.StepFilterSpec(*, name, value, disabled=False)[source]

Bases: BaseModel

name: str
value: JSONValue
disabled: bool
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.StepAnalysisSpec(*, analysisType, parameters=<factory>, customName=None)[source]

Bases: BaseModel

analysisType: str
parameters: JSONObject
customName: str | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.StepReportSpec(*, reportName='standard', config=<factory>)[source]

Bases: BaseModel

reportName: str
config: JSONObject
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.BasePlanNode(*, id=None, displayName=None, filters=None, analyses=None, reports=None, **extra_data)[source]

Bases: BaseModel

id: str | None
displayName: str | None
filters: list[StepFilterSpec] | None
analyses: list[StepAnalysisSpec] | None
reports: list[StepReportSpec] | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.ColocationParams(*, upstream, downstream, strand='both')[source]

Bases: BaseModel

upstream: int
downstream: int
strand: Literal['same', 'opposite', 'both']
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.PlanNode(*, id=None, displayName=None, filters=None, analyses=None, reports=None, searchName, parameters=<factory>, primaryInput=None, secondaryInput=None, operator=None, colocationParams=None, **extra_data)[source]

Bases: BasePlanNode

Untyped recursive plan node (WDK-aligned).

Kind is inferred from structure: - combine: primaryInput + secondaryInput - transform: primaryInput only - search: no inputs

searchName: str
parameters: JSONObject
primaryInput: PlanNode | None
secondaryInput: PlanNode | None
operator: str | None
colocationParams: ColocationParams | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.StrategyPlan(*, recordType, root, metadata=None, **extra_data)[source]

Bases: BaseModel

recordType: str
root: PlanNode
metadata: PlanMetadata | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.PlanNormalizeRequest(*, siteId, plan)[source]

Bases: BaseModel

siteId: str
plan: StrategyPlan
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.plan.PlanNormalizeResponse(*, plan, warnings=None)[source]

Bases: BaseModel

plan: StrategyPlan
warnings: JSONArray | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Sites request/response DTOs.

class veupath_chatbot.transport.http.schemas.sites.SiteResponse(*, id, name, displayName, baseUrl, projectId, isPortal)[source]

Bases: BaseModel

VEuPathDB site information.

id: str
name: str
display_name: str
base_url: str
project_id: str
is_portal: bool
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.RecordTypeResponse(*, name, displayName, description=None)[source]

Bases: BaseModel

Record type information.

name: str
display_name: str
description: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.SearchResponse(*, name, displayName, description=None, recordType)[source]

Bases: BaseModel

Search information.

name: str
display_name: str
description: str | None
record_type: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.DependentParamsRequest(*, parameterName, contextValues=<factory>)[source]

Bases: BaseModel

Dependent parameter values request.

parameter_name: str
context_values: JSONObject
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.SearchDetailsResponse(*, searchData=None, validation=None, searchConfig=None, parameters=None, paramMap=None, question=None, **extra_data)[source]

Bases: BaseModel

Search details payload (UI-facing).

search_data: JSONObject | None
validation: JSONObject | None
search_config: JSONObject | None
parameters: JSONArray | None
param_map: JSONObject | None
question: JSONObject | None
model_config = {'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.DependentParamsResponse(root=PydanticUndefined)[source]

Bases: RootModel[JSONArray]

Dependent parameter values response.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.SearchValidationRequest(*, contextValues=<factory>)[source]

Bases: BaseModel

Search parameter validation request.

context_values: JSONObject
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.ParamSpecsRequest(*, contextValues=<factory>)[source]

Bases: BaseModel

Parameter specs request (optionally contextual).

context_values: JSONObject
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.SearchValidationErrors(*, general=<factory>, byKey=<factory>)[source]

Bases: BaseModel

general: list[str]
by_key: dict[str, list[str]]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.SearchValidationPayload(*, isValid, normalizedContextValues=<factory>, errors=<factory>)[source]

Bases: BaseModel

is_valid: bool
normalized_context_values: JSONObject
errors: SearchValidationErrors
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.SearchValidationResponse(*, validation)[source]

Bases: BaseModel

Stable validation response for UI consumption.

validation: SearchValidationPayload
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sites.ParamSpecResponse(*, name, displayName=None, type, allowEmptyValue=False, allowMultipleValues=None, multiPick=None, minSelectedCount=None, maxSelectedCount=None, countOnlyLeaves=False, initialDisplayValue=None, vocabulary=None, min=None, max=None, isNumber=False, increment=None, displayType=None, isVisible=True, group=None, dependentParams=<factory>, help=None)[source]

Bases: BaseModel

Normalized parameter spec (UI-friendly).

name: str
display_name: str | None
type: str
allow_empty_value: bool
allow_multiple_values: bool | None
multi_pick: bool | None
min_selected_count: int | None
max_selected_count: int | None
count_only_leaves: bool
initial_display_value: JSONValue | None
vocabulary: JSONValue | None
min_value: float | None
max_value: float | None
is_number: bool
increment: float | None
display_type: str | None
is_visible: bool
group: str | None
dependent_params: list[str]
help: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Step request/response DTOs.

class veupath_chatbot.transport.http.schemas.steps.StepFilterResponse(*, name, value, disabled=False)[source]

Bases: BaseModel

Filter attached to a step.

name: str
value: JSONValue
disabled: bool
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepFiltersResponse(*, filters)[source]

Bases: BaseModel

Container for step filters.

filters: list[StepFilterResponse]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepAnalysisResponse(*, analysisType, parameters=<factory>, customName=None)[source]

Bases: BaseModel

Analysis configuration attached to a step.

analysis_type: str
parameters: JSONObject
custom_name: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepReportResponse(*, reportName='standard', config=<factory>)[source]

Bases: BaseModel

Report configuration attached to a step.

report_name: str
config: JSONObject
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepAnalysisRunResponse(*, analysis, wdk=None)[source]

Bases: BaseModel

Result of running a step analysis.

analysis: StepAnalysisResponse
wdk: JSONObject | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepReportRunResponse(*, report, wdk=None)[source]

Bases: BaseModel

Result of running a step report.

report: StepReportResponse
wdk: JSONObject | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepResponse(*, id, kind=None, displayName, searchName=None, recordType=None, parameters=None, operator=None, colocationParams=None, primaryInputStepId=None, secondaryInputStepId=None, resultCount=None, wdkStepId=None, filters=None, analyses=None, reports=None, validationError=None)[source]

Bases: BaseModel

Strategy step.

id: str
kind: str | None
display_name: str
search_name: str | None
record_type: str | None
parameters: JSONObject | None
operator: str | None
colocation_params: ColocationParams | None
primary_input_step_id: str | None
secondary_input_step_id: str | None
result_count: int | None
wdk_step_id: int | None
filters: list[StepFilterResponse] | None
analyses: list[StepAnalysisResponse] | None
reports: list[StepReportResponse] | None
validation_error: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepFilterRequest(*, value, disabled=False)[source]

Bases: BaseModel

Request to set or update a step filter.

value: JSONValue
disabled: bool
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepAnalysisRequest(*, analysisType, parameters=<factory>, customName=None)[source]

Bases: BaseModel

Request to run a step analysis.

analysis_type: str
parameters: JSONObject
custom_name: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.StepReportRequest(*, reportName='standard', config=<factory>)[source]

Bases: BaseModel

Request to run a step report.

report_name: str
config: JSONObject
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.PrimaryKeyPart(*, name, value)[source]

Bases: BaseModel

A single part of a composite WDK primary key.

name: str
value: str
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.steps.RecordDetailRequest(*, primaryKey)[source]

Bases: BaseModel

Request to fetch a single record by primary key.

primary_key: list[PrimaryKeyPart]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Experiment Lab request/response DTOs.

class veupath_chatbot.transport.http.schemas.experiments.ThresholdKnobRequest(*, stepId, paramName, minVal=0, maxVal=1, stepSize=None)[source]

Bases: BaseModel

A numeric parameter knob for tree optimization.

step_id: str
param_name: str
min_val: float
max_val: float
step_size: float | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.OperatorKnobRequest(*, combineNodeId, options=<factory>)[source]

Bases: BaseModel

A boolean-operator knob for tree optimization.

combine_node_id: str
options: list[str]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.OptimizationSpecRequest(*, name, type, min=None, max=None, step=None, choices=None)[source]

Bases: BaseModel

Describes a single parameter to optimise.

name: str
type: Literal['numeric', 'integer', 'categorical']
min: float | None
max: float | None
step: float | None
choices: list[str] | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.CreateExperimentRequest(*, siteId, recordType, mode='single', searchName='', parameters=<factory>, stepTree=None, sourceStrategyId=None, optimizationTargetStep=None, positiveControls, negativeControls, controlsSearchName, controlsParamName, controlsValueFormat='newline', enableCrossValidation=False, kFolds=5, enrichmentTypes=<factory>, name='Untitled Experiment', description='', optimizationSpecs=None, optimizationBudget=30, optimizationObjective=None, parameterDisplayValues=None, enableStepAnalysis=False, stepAnalysisPhases=None, controlSetId=None, thresholdKnobs=None, operatorKnobs=None, treeOptimizationObjective='precision_at_50', treeOptimizationBudget=50, maxListSize=None, sortAttribute=None, sortDirection='ASC', parentExperimentId=None, targetGeneIds=None)[source]

Bases: BaseModel

Request to create and run an experiment.

Supports three modes: single (default), multi-step, and import.

site_id: str
record_type: str
mode: Literal['single', 'multi-step', 'import']
search_name: str
parameters: JSONObject
step_tree: JSONValue
source_strategy_id: str | None
optimization_target_step: str | None
positive_controls: list[str]
negative_controls: list[str]
controls_search_name: str
controls_param_name: str
controls_value_format: Literal['newline', 'json_list', 'comma']
enable_cross_validation: bool
k_folds: int
enrichment_types: list[Literal['go_function', 'go_component', 'go_process', 'pathway', 'word']]
name: str
description: str
optimization_specs: list[OptimizationSpecRequest] | None
optimization_budget: int
optimization_objective: Literal['f1', 'f_beta', 'recall', 'precision', 'specificity', 'balanced_accuracy', 'mcc', 'youdens_j', 'custom'] | None
parameter_display_values: JSONObject | None
enable_step_analysis: bool
step_analysis_phases: list[str] | None
control_set_id: str | None
threshold_knobs: list[ThresholdKnobRequest] | None
operator_knobs: list[OperatorKnobRequest] | None
tree_optimization_objective: str
tree_optimization_budget: int
max_list_size: int | None
sort_attribute: str | None
sort_direction: Literal['ASC', 'DESC']
parent_experiment_id: str | None
target_gene_ids: list[str] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.BatchOrganismTargetRequest(*, organism, positiveControls=None, negativeControls=None)[source]

Bases: BaseModel

Per-organism override for a cross-organism batch experiment.

organism: str
positive_controls: list[str] | None
negative_controls: list[str] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.CreateBatchExperimentRequest(*, base, organismParamName, targetOrganisms)[source]

Bases: BaseModel

Request to run the same search across multiple organisms.

base: CreateExperimentRequest
organism_param_name: str
target_organisms: list[BatchOrganismTargetRequest]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.RunCrossValidationRequest(*, kFolds=5)[source]

Bases: BaseModel

Request to run cross-validation on an existing experiment.

k_folds: int
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.RunEnrichmentRequest(*, enrichmentTypes)[source]

Bases: BaseModel

Request to run enrichment on an existing experiment.

enrichment_types: list[Literal['go_function', 'go_component', 'go_process', 'pathway', 'word']]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.ThresholdSweepRequest(*, parameterName, sweepType='numeric', minValue=None, maxValue=None, steps=10, values=None)[source]

Bases: BaseModel

Request to sweep a parameter across a range (numeric) or set of values (categorical).

parameter_name: str
sweep_type: Literal['numeric', 'categorical']
min_value: float | None
max_value: float | None
steps: int
values: list[str] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.RunAnalysisRequest(*, analysisName, parameters=<factory>)[source]

Bases: BaseModel

Request to run a WDK step analysis.

analysis_name: str
parameters: JSONObject
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.RefineRequest(*, action, searchName='', parameters=<factory>, operator='INTERSECT', transformName='')[source]

Bases: BaseModel

Request to refine an experiment’s strategy.

action: Literal['combine', 'transform']
search_name: str
parameters: JSONObject
operator: str
transform_name: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.CustomEnrichRequest(*, geneSetName, geneIds)[source]

Bases: BaseModel

Request to run a custom gene-set enrichment test.

gene_set_name: str
gene_ids: list[str]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.BenchmarkControlSet(*, label, positiveControls, negativeControls, controlSetId=None, isPrimary=False)[source]

Bases: BaseModel

A single control set within a benchmark suite.

label: str
positive_controls: list[str]
negative_controls: list[str]
control_set_id: str | None
is_primary: bool
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.CreateBenchmarkRequest(*, base, controlSets)[source]

Bases: BaseModel

Request to run a benchmark suite across multiple control sets.

base: CreateExperimentRequest
control_sets: list[BenchmarkControlSet]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.OverlapRequest(*, experimentIds)[source]

Bases: BaseModel

Request to compute pairwise gene set overlap between experiments.

experiment_ids: list[str]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.EnrichmentCompareRequest(*, experimentIds, analysisType=None)[source]

Bases: BaseModel

Request to compare enrichment results across experiments.

experiment_ids: list[str]
analysis_type: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiments.AiAssistRequest(*, siteId, step, message, context=<factory>, history=<factory>, model=None)[source]

Bases: BaseModel

Request for the experiment wizard AI assistant.

site_id: str
step: Literal['search', 'parameters', 'controls', 'run', 'results', 'analysis']
message: str
context: JSONObject
history: JSONArray
model: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Health request/response DTOs.

class veupath_chatbot.transport.http.schemas.health.HealthResponse(*, status, version, timestamp)[source]

Bases: BaseModel

Health check response.

status: str
version: str
timestamp: datetime
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.health.ProviderStatus(*, openai, anthropic, google, ollama)[source]

Bases: BaseModel

Per-provider API-key availability.

openai: bool
anthropic: bool
google: bool
ollama: bool
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.health.SystemConfigResponse(*, chat_provider, llm_configured, providers)[source]

Bases: BaseModel

System configuration status (unauthenticated).

chat_provider: str
llm_configured: bool
providers: ProviderStatus
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

VEuPathDB auth request/response DTOs.

class veupath_chatbot.transport.http.schemas.veupathdb_auth.AuthSuccessResponse(*, success)[source]

Bases: BaseModel

Success response. Auth token is set via httpOnly cookie only.

success: bool
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.veupathdb_auth.AuthStatusResponse(*, signedIn, name=None, email=None)[source]

Bases: BaseModel

Current auth status response.

signedIn: bool
name: str | None
email: str | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

HTTP request/response schemas for gene sets.

class veupath_chatbot.transport.http.schemas.gene_sets.CreateGeneSetRequest(*, name, siteId, geneIds, source='paste', wdkStrategyId=None, wdkStepId=None, searchName=None, recordType=None, parameters=None)[source]

Bases: BaseModel

Create a gene set from IDs, strategy, or upload.

name: str
site_id: str
gene_ids: list[str]
source: Literal['strategy', 'paste', 'upload', 'derived', 'saved']
wdk_strategy_id: int | None
wdk_step_id: int | None
search_name: str | None
record_type: str | None
parameters: dict[str, str] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.GeneSetResponse(*, id, name, siteId, geneIds, source, geneCount, wdkStrategyId=None, wdkStepId=None, searchName=None, recordType=None, parameters=None, parentSetIds=<factory>, operation=None, createdAt, stepCount=1)[source]

Bases: BaseModel

Gene set response DTO.

id: str
name: str
site_id: str
gene_ids: list[str]
source: Literal['strategy', 'paste', 'upload', 'derived', 'saved']
gene_count: int
wdk_strategy_id: int | None
wdk_step_id: int | None
search_name: str | None
record_type: str | None
parameters: dict[str, str] | None
parent_set_ids: list[str]
operation: Literal['intersect', 'union', 'minus'] | None
created_at: str
step_count: int
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.SetOperationRequest(*, setAId, setBId, operation, name)[source]

Bases: BaseModel

Perform set operations between two gene sets.

set_a_id: str
set_b_id: str
operation: Literal['intersect', 'union', 'minus']
name: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.GeneSetEnrichRequest(*, enrichmentTypes)[source]

Bases: BaseModel

Run enrichment on a gene set.

enrichment_types: list[Literal['go_function', 'go_component', 'go_process', 'pathway', 'word']]
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.EnsembleScoringRequest(*, geneSetIds, positiveControls=None)[source]

Bases: BaseModel

Compute ensemble frequency scores across multiple gene sets.

gene_set_ids: list[str]
positive_controls: list[str] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.ReverseSearchRequest(*, positiveGeneIds, negativeGeneIds=None, siteId)[source]

Bases: BaseModel

Rank user’s gene sets by recall of given positive genes.

positive_gene_ids: list[str]
negative_gene_ids: list[str] | None
site_id: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.ReverseSearchResultItem(*, geneSetId, name, searchName=None, recall, precision, f1, resultCount, overlapCount)[source]

Bases: BaseModel

A single ranked gene set in reverse search results.

gene_set_id: str
name: str
search_name: str | None
recall: float
precision: float
f1: float
result_count: int
overlap_count: int
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.RunGeneSetAnalysisRequest(*, analysisName, parameters=<factory>)[source]

Bases: BaseModel

Run a WDK step analysis on a gene set.

analysis_name: str
parameters: JSONObject
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.GeneConfidenceRequest(*, tpIds, fpIds, fnIds, tnIds, ensembleScores=None, enrichmentGeneCounts=None, maxEnrichmentTerms=1)[source]

Bases: BaseModel

Compute per-gene confidence scores from classification data.

tp_ids: list[str]
fp_ids: list[str]
fn_ids: list[str]
tn_ids: list[str]
ensemble_scores: dict[str, float] | None
enrichment_gene_counts: dict[str, int] | None
max_enrichment_terms: int
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.gene_sets.GeneConfidenceScoreResponse(*, geneId, compositeScore, classificationScore, ensembleScore, enrichmentScore)[source]

Bases: BaseModel

Single gene confidence score in the response.

gene_id: str
composite_score: float
classification_score: float
ensemble_score: float
enrichment_score: float
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Schemas for workbench chat endpoints.

class veupath_chatbot.transport.http.schemas.workbench_chat.WorkbenchChatRequest(*, message, siteId, provider=None, model=None, reasoningEffort=None)[source]

Bases: BaseModel

message: str
site_id: str
provider: Literal['openai', 'anthropic', 'google', 'ollama', 'mock'] | None
model_id: str | None
reasoning_effort: Literal['none', 'low', 'medium', 'high'] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.workbench_chat.WorkbenchChatResponse(*, operationId, streamId)[source]

Bases: BaseModel

operation_id: str
stream_id: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Optimization event/response models shared by chat and SSE schemas.

class veupath_chatbot.transport.http.schemas.optimization.OptimizationTrialData(*, trialNumber, parameters=<factory>, score=0.0, recall=None, falsePositiveRate=None, resultCount=None, positiveHits=None, negativeHits=None, totalPositives=None, totalNegatives=None)[source]

Bases: BaseModel

A single optimization trial result.

trial_number: int
parameters: dict[str, JSONValue]
score: float
recall: float | None
false_positive_rate: float | None
result_count: int | None
positive_hits: int | None
negative_hits: int | None
total_positives: int | None
total_negatives: int | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.optimization.OptimizationParameterSpecData(*, name, type, minValue=None, maxValue=None, logScale=None, choices=None)[source]

Bases: BaseModel

Specification for one optimization parameter.

name: str
type: str
min_value: float | None
max_value: float | None
log_scale: bool | None
choices: list[str] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.optimization.OptimizationProgressEventData(*, optimizationId, status='', searchName=None, recordType=None, budget=None, objective=None, currentTrial=None, totalTrials=None, parameterSpecs=None, trial=None, bestTrial=None, recentTrials=None, allTrials=None, paretoFrontier=None, sensitivity=None, totalTimeSeconds=None, error=None)[source]

Bases: BaseModel

Payload for optimization_progress SSE events.

optimization_id: str
status: str
search_name: str | None
record_type: str | None
budget: int | None
objective: str | None
current_trial: int | None
total_trials: int | None
parameter_specs: list[OptimizationParameterSpecData] | None
trial: OptimizationTrialData | None
best_trial: OptimizationTrialData | None
recent_trials: list[OptimizationTrialData] | None
all_trials: list[OptimizationTrialData] | None
pareto_frontier: list[OptimizationTrialData] | None
sensitivity: dict[str, float] | None
total_time_seconds: float | None
error: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

SSE event payload schemas — typed Pydantic models for every SSE event.

class veupath_chatbot.transport.http.schemas.sse.MessageStartEventData(*, strategyId=None, strategy=None)[source]

Bases: BaseModel

Payload for message_start SSE events.

strategy_id: str | None
strategy: JSONObject | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.UserMessageEventData(*, messageId=None, content=None)[source]

Bases: BaseModel

Payload for user_message SSE events.

message_id: str | None
content: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.AssistantDeltaEventData(*, messageId=None, delta=None)[source]

Bases: BaseModel

Payload for assistant_delta SSE events (streaming tokens).

message_id: str | None
delta: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.AssistantMessageEventData(*, messageId=None, content=None)[source]

Bases: BaseModel

Payload for assistant_message SSE events (complete message).

message_id: str | None
content: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.MessageEndEventData(*, modelId=None, promptTokens=None, completionTokens=None, totalTokens=None, cachedTokens=None, toolCallCount=None, registeredToolCount=None, llmCallCount=None, subKaniPromptTokens=None, subKaniCompletionTokens=None, subKaniCallCount=None, estimatedCostUsd=None)[source]

Bases: BaseModel

Payload for message_end SSE events — mirrors TokenUsageResponse.

model_id: str | None
prompt_tokens: int | None
completion_tokens: int | None
total_tokens: int | None
cached_tokens: int | None
tool_call_count: int | None
registered_tool_count: int | None
llm_call_count: int | None
sub_kani_prompt_tokens: int | None
sub_kani_completion_tokens: int | None
sub_kani_call_count: int | None
estimated_cost_usd: float | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.ToolCallStartEventData(*, id, name, arguments=None)[source]

Bases: BaseModel

Payload for tool_call_start SSE events.

id: str
name: str
arguments: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.ToolCallEndEventData(*, id, result=None)[source]

Bases: BaseModel

Payload for tool_call_end SSE events.

id: str
result: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.SubKaniTaskStartEventData(*, task=None, modelId=None)[source]

Bases: BaseModel

Payload for subkani_task_start SSE events.

task: str | None
model_id: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.SubKaniToolCallStartEventData(*, task=None, id, name, arguments=None)[source]

Bases: BaseModel

Payload for subkani_tool_call_start SSE events.

task: str | None
id: str
name: str
arguments: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.SubKaniToolCallEndEventData(*, task=None, id, result=None)[source]

Bases: BaseModel

Payload for subkani_tool_call_end SSE events.

task: str | None
id: str
result: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.SubKaniTaskEndEventData(*, task=None, status=None, modelId=None, promptTokens=None, completionTokens=None, llmCallCount=None, estimatedCostUsd=None)[source]

Bases: BaseModel

Payload for subkani_task_end SSE events.

task: str | None
status: str | None
model_id: str | None
prompt_tokens: int | None
completion_tokens: int | None
llm_call_count: int | None
estimated_cost_usd: float | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.TokenUsagePartialEventData(*, promptTokens=None, registeredToolCount=None)[source]

Bases: BaseModel

Payload for token_usage_partial SSE events.

prompt_tokens: int | None
registered_tool_count: int | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.ModelSelectedEventData(*, modelId)[source]

Bases: BaseModel

Payload for model_selected SSE events.

model_id: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.ErrorEventData(*, error)[source]

Bases: BaseModel

Payload for error SSE events.

error: str
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.GraphSnapshotEventData(*, graphSnapshot=None)[source]

Bases: BaseModel

Payload for graph_snapshot SSE events.

graph_snapshot: JSONObject | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.StrategyMetaEventData(*, graphId=None, graphName=None, name=None, description=None, recordType=None)[source]

Bases: BaseModel

Payload for strategy_meta SSE events.

graph_id: str | None
graph_name: str | None
name: str | None
description: str | None
record_type: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.GraphPlanEventData(*, graphId=None, plan=None, name=None, recordType=None, description=None)[source]

Bases: BaseModel

Payload for graph_plan SSE events.

graph_id: str | None
plan: JSONObject | None
name: str | None
record_type: str | None
description: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.StrategyUpdateEventData(*, graphId=None, step=None)[source]

Bases: BaseModel

Payload for strategy_update SSE events.

graph_id: str | None
step: JSONObject | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.StrategyLinkEventData(*, graphId=None, wdkStrategyId=None, wdkUrl=None, name=None, description=None, isSaved=None)[source]

Bases: BaseModel

Payload for strategy_link SSE events.

graph_id: str | None
wdk_strategy_id: int | None
wdk_url: str | None
name: str | None
description: str | None
is_saved: bool | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.GraphClearedEventData(*, graphId=None)[source]

Bases: BaseModel

Payload for graph_cleared SSE events.

graph_id: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.ExecutorBuildRequestEventData(*, executorBuildRequest=None)[source]

Bases: BaseModel

Payload for executor_build_request SSE events.

executor_build_request: JSONObject | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.GeneSetSummary(*, id=None, name=None, geneCount=None, source=None, siteId=None)[source]

Bases: BaseModel

Summary of a gene set — nested model, not a top-level event.

id: str | None
name: str | None
gene_count: int | None
source: str | None
site_id: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.WorkbenchGeneSetEventData(*, geneSet=None)[source]

Bases: BaseModel

Payload for workbench_gene_set SSE events.

gene_set: GeneSetSummary | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.CitationsEventData(*, citations=None)[source]

Bases: BaseModel

Payload for citations SSE events.

citations: list[CitationResponse] | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.PlanningArtifactEventData(*, planningArtifact=None)[source]

Bases: BaseModel

Payload for planning_artifact SSE events.

planning_artifact: PlanningArtifactResponse | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.sse.ReasoningEventData(*, reasoning=None)[source]

Bases: BaseModel

Payload for reasoning SSE events.

reasoning: str | None
model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Pydantic response models for experiment types.

These models mirror the dataclasses in services.experiment.types but exist in the transport layer so they appear in the OpenAPI schema and get auto-generated as TypeScript types.

All field aliases use camelCase to match the existing to_json codec output.

class veupath_chatbot.transport.http.schemas.experiment_responses.ConfusionMatrixResponse(*, truePositives, falsePositives, trueNegatives, falseNegatives)[source]

Bases: BaseModel

2x2 confusion matrix counts.

true_positives: int
false_positives: int
true_negatives: int
false_negatives: int
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ExperimentMetricsResponse(*, confusionMatrix, sensitivity, specificity, precision, f1Score, mcc, balancedAccuracy, negativePredictiveValue=0.0, falsePositiveRate=0.0, falseNegativeRate=0.0, youdensJ=0.0, totalResults=0, totalPositives=0, totalNegatives=0)[source]

Bases: BaseModel

Full classification metrics derived from a confusion matrix.

confusion_matrix: ConfusionMatrixResponse
sensitivity: float
specificity: float
precision: float
f1_score: float
mcc: float
balanced_accuracy: float
negative_predictive_value: float
false_positive_rate: float
false_negative_rate: float
youdens_j: float
total_results: int
total_positives: int
total_negatives: int
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.GeneInfoResponse(*, id, name=None, organism=None, product=None)[source]

Bases: BaseModel

Minimal gene metadata.

id: str
name: str | None
organism: str | None
product: str | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.FoldMetricsResponse(*, foldIndex, metrics, positiveControlIds=<factory>, negativeControlIds=<factory>)[source]

Bases: BaseModel

Metrics for a single cross-validation fold.

fold_index: int
metrics: ExperimentMetricsResponse
positive_control_ids: list[str]
negative_control_ids: list[str]
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.CrossValidationResultResponse(*, k, folds, meanMetrics, stdMetrics=<factory>, overfittingScore=0.0, overfittingLevel='low')[source]

Bases: BaseModel

Aggregated cross-validation result.

k: int
folds: list[FoldMetricsResponse]
mean_metrics: ExperimentMetricsResponse
std_metrics: dict[str, float]
overfitting_score: float
overfitting_level: str
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.EnrichmentTermResponse(*, termId, termName, geneCount, backgroundCount, foldEnrichment, oddsRatio, pValue, fdr, bonferroni, genes=<factory>)[source]

Bases: BaseModel

Single enriched term from WDK analysis.

term_id: str
term_name: str
gene_count: int
background_count: int
fold_enrichment: float
odds_ratio: float
p_value: float
fdr: float
bonferroni: float
genes: list[str]
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.EnrichmentResultResponse(*, analysisType, terms, totalGenesAnalyzed=0, backgroundSize=0, error=None)[source]

Bases: BaseModel

Results for a single enrichment analysis type.

analysis_type: Literal['go_function', 'go_component', 'go_process', 'pathway', 'word']
terms: list[EnrichmentTermResponse]
total_genes_analyzed: int
background_size: int
error: str | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.RankMetricsResponse(*, precisionAtK=<factory>, recallAtK=<factory>, enrichmentAtK=<factory>, prCurve=<factory>, listSizeVsRecall=<factory>, totalResults=0)[source]

Bases: BaseModel

Rank-based evaluation metrics computed over an ordered result list.

precision_at_k: dict[int, float]
recall_at_k: dict[int, float]
enrichment_at_k: dict[int, float]
pr_curve: list[tuple[float, float]]
list_size_vs_recall: list[tuple[int, float]]
total_results: int
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ConfidenceIntervalResponse(*, lower=0.0, mean=0.0, upper=0.0, std=0.0)[source]

Bases: BaseModel

Bootstrap confidence interval for a single metric.

lower: float
mean: float
upper: float
std: float
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.NegativeSetVariantResponse(*, label, rankMetrics, negativeCount=0)[source]

Bases: BaseModel

Rank metrics evaluated with an alternative negative control set.

label: str
rank_metrics: RankMetricsResponse
negative_count: int
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.BootstrapResultResponse(*, nIterations=0, metricCis=<factory>, rankMetricCis=<factory>, topKStability=0.0, negativeSetSensitivity=<factory>)[source]

Bases: BaseModel

Robustness assessment via bootstrap resampling.

n_iterations: int
metric_cis: dict[str, ConfidenceIntervalResponse]
rank_metric_cis: dict[str, ConfidenceIntervalResponse]
top_k_stability: float
negative_set_sensitivity: list[NegativeSetVariantResponse]
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.StepEvaluationResponse(*, stepId, searchName, displayName, resultCount, positiveHits, positiveTotal, negativeHits, negativeTotal, recall, falsePositiveRate, capturedPositiveIds=<factory>, capturedNegativeIds=<factory>, tpMovement=0, fpMovement=0, fnMovement=0)[source]

Bases: BaseModel

Per-leaf-step evaluation against controls.

step_id: str
search_name: str
display_name: str
result_count: int
positive_hits: int
positive_total: int
negative_hits: int
negative_total: int
recall: float
false_positive_rate: float
captured_positive_ids: list[str]
captured_negative_ids: list[str]
tp_movement: int
fp_movement: int
fn_movement: int
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.OperatorVariantResponse(*, operator, positiveHits, negativeHits, totalResults, recall, falsePositiveRate, f1Score)[source]

Bases: BaseModel

Metrics for one boolean operator at a combine node.

operator: str
positive_hits: int
negative_hits: int
total_results: int
recall: float
false_positive_rate: float
f1_score: float
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.OperatorComparisonResponse(*, combineNodeId, currentOperator, variants=<factory>, recommendation='', recommendedOperator='', precisionAtKDelta=<factory>)[source]

Bases: BaseModel

Comparison of operators at a single combine node.

combine_node_id: str
current_operator: str
variants: list[OperatorVariantResponse]
recommendation: str
recommended_operator: str
precision_at_k_delta: dict[int, float]
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.StepContributionResponse(*, stepId, searchName, baselineRecall, ablatedRecall, recallDelta, baselineFpr, ablatedFpr, fprDelta, verdict, enrichmentDelta=0.0, narrative='')[source]

Bases: BaseModel

Ablation analysis for one leaf step.

step_id: str
search_name: str
baseline_recall: float
ablated_recall: float
recall_delta: float
baseline_fpr: float
ablated_fpr: float
fpr_delta: float
verdict: Literal['essential', 'helpful', 'neutral', 'harmful']
enrichment_delta: float
narrative: str
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ParameterSweepPointResponse(*, value, positiveHits, negativeHits, totalResults, recall, fpr, f1)[source]

Bases: BaseModel

One data point in a parameter sensitivity sweep.

value: float
positive_hits: int
negative_hits: int
total_results: int
recall: float
fpr: float
f1: float
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ParameterSensitivityResponse(*, stepId, paramName, currentValue, sweepPoints=<factory>, recommendedValue=0.0, recommendation='')[source]

Bases: BaseModel

Sensitivity sweep for one numeric parameter on one leaf step.

step_id: str
param_name: str
current_value: float
sweep_points: list[ParameterSweepPointResponse]
recommended_value: float
recommendation: str
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.StepAnalysisResultResponse(*, stepEvaluations=<factory>, operatorComparisons=<factory>, stepContributions=<factory>, parameterSensitivities=<factory>)[source]

Bases: BaseModel

Container for all deterministic step analysis results.

step_evaluations: list[StepEvaluationResponse]
operator_comparisons: list[OperatorComparisonResponse]
step_contributions: list[StepContributionResponse]
parameter_sensitivities: list[ParameterSensitivityResponse]
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.OptimizationSpecResponse(*, name, type, min=None, max=None, step=None, choices=None)[source]

Bases: BaseModel

Describes a single parameter to optimise.

name: str
type: Literal['numeric', 'integer', 'categorical']
min: float | None
max: float | None
step: float | None
choices: list[str] | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ThresholdKnobResponse(*, stepId, paramName, minVal, maxVal, stepSize=None)[source]

Bases: BaseModel

A numeric parameter on a leaf step that can be tuned.

step_id: str
param_name: str
min_val: float
max_val: float
step_size: float | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.OperatorKnobResponse(*, combineNodeId, options=<factory>)[source]

Bases: BaseModel

A combine-node operator that can be switched during optimization.

combine_node_id: str
options: list[str]
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.TreeOptimizationTrialResponse(*, trialNumber, parameters=<factory>, score=0.0, rankMetrics=None, listSize=0)[source]

Bases: BaseModel

One trial during tree-knob optimization.

trial_number: int
parameters: dict[str, float | str]
score: float
rank_metrics: RankMetricsResponse | None
list_size: int
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.TreeOptimizationResultResponse(*, bestTrial=None, allTrials=<factory>, totalTimeSeconds=0.0, objective='')[source]

Bases: BaseModel

Result of multi-step tree-knob optimization.

best_trial: TreeOptimizationTrialResponse | None
all_trials: list[TreeOptimizationTrialResponse]
total_time_seconds: float
objective: str
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ExperimentConfigResponse(*, siteId, recordType, searchName, parameters, positiveControls, negativeControls, controlsSearchName, controlsParamName, controlsValueFormat='newline', enableCrossValidation=False, kFolds=5, enrichmentTypes=<factory>, name='', description='', optimizationSpecs=None, optimizationBudget=30, optimizationObjective='balanced_accuracy', parameterDisplayValues=None, mode='single', stepTree=None, sourceStrategyId=None, optimizationTargetStep=None, enableStepAnalysis=False, stepAnalysisPhases=<factory>, controlSetId=None, thresholdKnobs=None, operatorKnobs=None, treeOptimizationObjective='precision_at_50', treeOptimizationBudget=50, maxListSize=None, sortAttribute=None, sortDirection='ASC', parentExperimentId=None, targetGeneIds=None)[source]

Bases: BaseModel

Full configuration for an experiment run.

site_id: str
record_type: str
search_name: str
parameters: JSONObject
positive_controls: list[str]
negative_controls: list[str]
controls_search_name: str
controls_param_name: str
controls_value_format: Literal['newline', 'json_list', 'comma']
enable_cross_validation: bool
k_folds: int
enrichment_types: list[Literal['go_function', 'go_component', 'go_process', 'pathway', 'word']]
name: str
description: str
optimization_specs: list[OptimizationSpecResponse] | None
optimization_budget: int
optimization_objective: Literal['f1', 'f_beta', 'recall', 'precision', 'specificity', 'balanced_accuracy', 'mcc', 'youdens_j', 'custom']
parameter_display_values: dict[str, str] | None
mode: Literal['single', 'multi-step', 'import']
step_tree: JSONValue
source_strategy_id: str | None
optimization_target_step: str | None
enable_step_analysis: bool
step_analysis_phases: list[str]
control_set_id: str | None
threshold_knobs: list[ThresholdKnobResponse] | None
operator_knobs: list[OperatorKnobResponse] | None
tree_optimization_objective: str
tree_optimization_budget: int
max_list_size: int | None
sort_attribute: str | None
sort_direction: str
parent_experiment_id: str | None
target_gene_ids: list[str] | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ExperimentResponse(*, id, config, userId=None, status='pending', metrics=None, crossValidation=None, enrichmentResults=<factory>, truePositiveGenes=<factory>, falseNegativeGenes=<factory>, falsePositiveGenes=<factory>, trueNegativeGenes=<factory>, error=None, totalTimeSeconds=None, createdAt='', completedAt=None, batchId=None, benchmarkId=None, controlSetLabel=None, isPrimaryBenchmark=False, optimizationResult=None, wdkStrategyId=None, wdkStepId=None, notes=None, stepAnalysis=None, rankMetrics=None, robustness=None, treeOptimization=None)[source]

Bases: BaseModel

Full experiment with config and results.

id: str
config: ExperimentConfigResponse
user_id: str | None
status: Literal['pending', 'running', 'completed', 'error', 'cancelled']
metrics: ExperimentMetricsResponse | None
cross_validation: CrossValidationResultResponse | None
enrichment_results: list[EnrichmentResultResponse]
true_positive_genes: list[GeneInfoResponse]
false_negative_genes: list[GeneInfoResponse]
false_positive_genes: list[GeneInfoResponse]
true_negative_genes: list[GeneInfoResponse]
error: str | None
total_time_seconds: float | None
created_at: str
completed_at: str | None
batch_id: str | None
benchmark_id: str | None
control_set_label: str | None
is_primary_benchmark: bool
optimization_result: JSONObject | None
wdk_strategy_id: int | None
wdk_step_id: int | None
notes: str | None
step_analysis: StepAnalysisResultResponse | None
rank_metrics: RankMetricsResponse | None
robustness: BootstrapResultResponse | None
tree_optimization: TreeOptimizationResultResponse | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ExperimentSummaryResponse(*, id, name, siteId, searchName, recordType, mode, status, f1Score=None, sensitivity=None, specificity=None, totalPositives, totalNegatives, createdAt, batchId=None, benchmarkId=None, controlSetLabel=None, isPrimaryBenchmark=False)[source]

Bases: BaseModel

Lightweight experiment summary for list views.

id: str
name: str
site_id: str
search_name: str
record_type: str
mode: Literal['single', 'multi-step', 'import']
status: Literal['pending', 'running', 'completed', 'error', 'cancelled']
f1_score: float | None
sensitivity: float | None
specificity: float | None
total_positives: int
total_negatives: int
created_at: str
batch_id: str | None
benchmark_id: str | None
control_set_label: str | None
is_primary_benchmark: bool
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.TrialProgressDataResponse(*, trialNumber, totalTrials, status, score=None, recall=None, falsePositiveRate=None, resultCount=None, parameters=None)[source]

Bases: BaseModel

Progress data for a single optimization trial.

trial_number: int
total_trials: int
status: str
score: float | None
recall: float | None
false_positive_rate: float | None
result_count: int | None
parameters: dict[str, JSONValue] | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.StepAnalysisProgressDataResponse(*, phase, currentStep=None, totalSteps=None, stepId=None, searchName=None, message=None)[source]

Bases: BaseModel

Progress data for step analysis.

phase: str
current_step: int | None
total_steps: int | None
step_id: str | None
search_name: str | None
message: str | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ExperimentProgressDataResponse(*, phase, message=None, trialProgress=None, stepAnalysisProgress=None)[source]

Bases: BaseModel

Progress data for experiment execution.

phase: str
message: str | None
trial_progress: TrialProgressDataResponse | None
step_analysis_progress: StepAnalysisProgressDataResponse | None
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.OptimizationResultResponse(*, optimizationId, status, bestTrial=None, allTrials=<factory>, paretoFrontier=<factory>, sensitivity=<factory>, totalTimeSeconds=0, totalTrials=0)[source]

Bases: BaseModel

Complete optimization result.

optimization_id: str
status: str
best_trial: OptimizationTrialData | None
all_trials: list[OptimizationTrialData]
pareto_frontier: list[OptimizationTrialData]
sensitivity: dict[str, float]
total_time_seconds: float
total_trials: int
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class veupath_chatbot.transport.http.schemas.experiment_responses.ControlSetSummaryResponse(*, id, name, source, organism=None, positiveCount, negativeCount)[source]

Bases: BaseModel

Control set summary for listing.

id: str
name: str
source: str
organism: str | None
positive_count: int
negative_count: int
model_config = {'from_attributes': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].