Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 10
Unified API: Add support for Kaapi Abstracted LLM Call#498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
6980bbe2847d5063a3bceb3393d8f2484950840c510a21c4ef5ab6851399f2278c20adFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,44 @@ | ||
| from typing import Any, Literal | ||
| from typing import Annotated, Any, Literal, Union | ||
| from uuid import UUID | ||
| from sqlmodel import Field, SQLModel | ||
| from pydantic import model_validator, HttpUrl | ||
| from pydantic import Discriminator, model_validator, HttpUrl | ||
| class KaapiLLMParams(SQLModel): | ||
| """ | ||
| Kaapi-abstracted parameters for LLM providers. | ||
| These parameters are mapped internally to provider-specific API parameters. | ||
| Provides a unified contract across all LLM providers (OpenAI, Claude, Gemini, etc.). | ||
| Provider-specific mappings are handled at the mapper level. | ||
| """ | ||
| model: str = Field( | ||
| description="Model identifier to use for completion (e.g., 'gpt-4o', 'gpt-5')", | ||
| ) | ||
avirajsingh7 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| instructions: str | None = Field( | ||
| default=None, | ||
| description="System instructions to guide the model's behavior", | ||
| ) | ||
| knowledge_base_ids: list[str] | None = Field( | ||
| default=None, | ||
| description="List of vector store IDs to use for knowledge retrieval", | ||
| ) | ||
| reasoning: Literal["low", "medium", "high"] | None = Field( | ||
| default=None, | ||
| description="Reasoning configuration or instructions", | ||
| ) | ||
| temperature: float | None = Field( | ||
| default=None, | ||
| ge=0.0, | ||
| le=2.0, | ||
| description="Sampling temperature between 0 and 2", | ||
| ) | ||
| max_num_results: int | None = Field( | ||
| default=None, | ||
| ge=1, | ||
| description="Maximum number of results to return", | ||
| ) | ||
avirajsingh7 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| class ConversationConfig(SQLModel): | ||
| @@ -46,18 +82,44 @@ class QueryParams(SQLModel): | ||
| ) | ||
| class CompletionConfig(SQLModel): | ||
| """Completion configuration with provider and parameters.""" | ||
| class NativeCompletionConfig(SQLModel): | ||
| """ | ||
| Native provider configuration (pass-through). | ||
| All parameters are forwarded as-is to the provider's API without transformation. | ||
| Supports any LLM provider's native API format. | ||
| """ | ||
| provider: Literal["openai"] = Field( | ||
| default="openai", description="LLM provider to use" | ||
| provider: Literal["openai-native"] = Field( | ||
| default="openai-native", | ||
| description="Native provider type (e.g., openai-native)", | ||
| ) | ||
| params: dict[str, Any] = Field( | ||
| ..., | ||
| description="Provider-specific parameters (schema varies by provider), should exactly match the provider's endpoint params structure", | ||
| ) | ||
| class KaapiCompletionConfig(SQLModel): | ||
| """ | ||
| Kaapi abstraction for LLM completion providers. | ||
| Uses standardized Kaapi parameters that are mapped to provider-specific APIs internally. | ||
| Supports multiple providers: OpenAI, Claude, Gemini, etc. | ||
| """ | ||
| provider: Literal["openai"] = Field(..., description="LLM provider (openai)") | ||
| params: KaapiLLMParams = Field( | ||
| ..., | ||
| description="Kaapi-standardized parameters mapped to provider-specific API", | ||
| ) | ||
| # Discriminated union for completion configs based on provider field | ||
| CompletionConfig = Annotated[ | ||
| Union[NativeCompletionConfig, KaapiCompletionConfig], | ||
| Field(discriminator="provider"), | ||
| ] | ||
| class ConfigBlob(SQLModel): | ||
| """Raw JSON blob of config.""" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -10,11 +10,12 @@ | ||
| from app.crud.credentials import get_provider_credential | ||
| from app.crud.jobs import JobCrud | ||
| from app.models import JobStatus, JobType, JobUpdate, LLMCallRequest | ||
| from app.models.llm.request import ConfigBlob, LLMCallConfig | ||
| from app.models.llm.request import ConfigBlob, LLMCallConfig, KaapiCompletionConfig | ||
| from app.utils import APIResponse, send_callback | ||
| from app.celery.utils import start_high_priority_job | ||
| from app.core.langfuse.langfuse import observe_llm_execution | ||
| from app.services.llm.providers.registry import get_llm_provider | ||
| from app.services.llm.mappers import transform_kaapi_config_to_native | ||
| logger = logging.getLogger(__name__) | ||
| @@ -170,10 +171,27 @@ def execute_job( | ||
| else: | ||
| config_blob = config.blob | ||
| try: | ||
| # Transform Kaapi config to native config if needed (before getting provider) | ||
| completion_config = config_blob.completion | ||
| if isinstance(completion_config, KaapiCompletionConfig): | ||
| completion_config, warnings = transform_kaapi_config_to_native( | ||
| completion_config | ||
| ) | ||
| if request.request_metadata is None: | ||
| request.request_metadata = {} | ||
| request.request_metadata.setdefault("warnings", []).extend(warnings) | ||
| except Exception as e: | ||
| callback_response = APIResponse.failure_response( | ||
| error=f"Error processing configuration: {str(e)}", | ||
| metadata=request.request_metadata, | ||
| ) | ||
| return handle_job_error(job_id, request.callback_url, callback_response) | ||
avirajsingh7 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| try: | ||
| provider_instance = get_llm_provider( | ||
| session=session, | ||
| provider_type=config_blob.completion.provider, | ||
| provider_type=completion_config.provider, # Now always native provider type | ||
| project_id=project_id, | ||
| organization_id=organization_id, | ||
| ) | ||
| @@ -203,7 +221,7 @@ def execute_job( | ||
| )(provider_instance.execute) | ||
| response, error = decorated_execute( | ||
| completion_config=config_blob.completion, | ||
| completion_config=completion_config, | ||
| query=request.query, | ||
| include_provider_raw_response=request.include_provider_raw_response, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| """Parameter mappers for converting Kaapi-abstracted parameters to provider-specific formats.""" | ||
| import litellm | ||
| from app.models.llm import KaapiLLMParams, KaapiCompletionConfig, NativeCompletionConfig | ||
| def map_kaapi_to_openai_params(kaapi_params: KaapiLLMParams) -> tuple[dict, list[str]]: | ||
| """Map Kaapi-abstracted parameters to OpenAI API parameters. | ||
| This mapper transforms standardized Kaapi parameters into OpenAI-specific | ||
| parameter format, enabling provider-agnostic interface design. | ||
| Args: | ||
| kaapi_params: KaapiLLMParams instance with standardized parameters | ||
| Supported Mapping: | ||
| - model → model | ||
| - instructions → instructions | ||
| - knowledge_base_ids → tools[file_search].vector_store_ids | ||
| - max_num_results → tools[file_search].max_num_results (fallback default) | ||
| - reasoning → reasoning.effort (if reasoning supported by model else suppressed) | ||
| - temperature → temperature (if reasoning not supported by model else suppressed) | ||
| Returns: | ||
| Tuple of: | ||
| - Dictionary of OpenAI API parameters ready to be passed to the API | ||
| - List of warnings describing suppressed or ignored parameters | ||
| """ | ||
| openai_params = {} | ||
| warnings = [] | ||
| support_reasoning = litellm.supports_reasoning( | ||
| model="openai/" + f"{kaapi_params.model}" | ||
| ) | ||
| # Handle reasoning vs temperature mutual exclusivity | ||
| if support_reasoning: | ||
| if kaapi_params.reasoning is not None: | ||
| openai_params["reasoning"] = {"effort": kaapi_params.reasoning} | ||
| if kaapi_params.temperature is not None: | ||
| warnings.append( | ||
| "Parameter 'temperature' was suppressed because the selected model " | ||
| "supports reasoning, and temperature is ignored when reasoning is enabled." | ||
| ) | ||
| else: | ||
| if kaapi_params.reasoning is not None: | ||
| warnings.append( | ||
| "Parameter 'reasoning' was suppressed because the selected model " | ||
| "does not support reasoning." | ||
| ) | ||
| if kaapi_params.temperature is not None: | ||
| openai_params["temperature"] = kaapi_params.temperature | ||
| if kaapi_params.model: | ||
| openai_params["model"] = kaapi_params.model | ||
| if kaapi_params.instructions: | ||
| openai_params["instructions"] = kaapi_params.instructions | ||
| if kaapi_params.knowledge_base_ids: | ||
| openai_params["tools"] = [ | ||
| { | ||
| "type": "file_search", | ||
| "vector_store_ids": kaapi_params.knowledge_base_ids, | ||
| "max_num_results": kaapi_params.max_num_results or 20, | ||
| } | ||
| ] | ||
| return openai_params, warnings | ||
| def transform_kaapi_config_to_native( | ||
| kaapi_config: KaapiCompletionConfig, | ||
| ) -> tuple[NativeCompletionConfig, list[str]]: | ||
| """Transform Kaapi completion config to native provider config with mapped parameters. | ||
| Currently supports OpenAI. Future: Claude, Gemini mappers. | ||
| Args: | ||
| kaapi_config: KaapiCompletionConfig with abstracted parameters | ||
| Returns: | ||
| NativeCompletionConfig with provider-native parameters ready for API | ||
| """ | ||
| if kaapi_config.provider == "openai": | ||
| mapped_params, warnings = map_kaapi_to_openai_params(kaapi_config.params) | ||
| return ( | ||
| NativeCompletionConfig(provider="openai-native", params=mapped_params), | ||
| warnings, | ||
| ) | ||
| raise ValueError(f"Unsupported provider: {kaapi_config.provider}") |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.