litellm/litellm/integrations/gitlab
Alexsander Hamir 5de9bfde53
[Fix] CI/CD - mypy & check_code_and_doc_quality & mcp_testing (#17920)
* Fix duplicate imports in SAP embedding transformation

* fix: add missing prompt_spec parameter to HumanloopLogger.get_chat_completion_prompt

- Add prompt_spec: Optional[PromptSpec] = None parameter to match base class signature
- Import PromptSpec from litellm.types.prompts.init_prompts
- Pass prompt_spec to super().get_chat_completion_prompt() call
- Fixes mypy type error: Signature incompatible with supertype CustomLogger

* fix: add missing parameters to AnthropicCacheControlHook.async_get_chat_completion_prompt

- Add ignore_prompt_manager_model and ignore_prompt_manager_optional_params parameters
- Change litellm_logging_obj type from Any to LiteLLMLoggingObj using TYPE_CHECKING pattern
- Pass all parameters including prompt_spec to get_chat_completion_prompt call
- Fixes mypy type errors: Signature incompatible with supertype CustomLogger and PromptManagementBase

* fix: add missing parameters to DotpromptManager.async_get_chat_completion_prompt

- Add ignore_prompt_manager_model and ignore_prompt_manager_optional_params parameters
- Change litellm_logging_obj type from Any to LiteLLMLoggingObj using TYPE_CHECKING pattern
- Pass all parameters including ignore flags to PromptManagementBase.async_get_chat_completion_prompt
- Fixes mypy type errors: Signature incompatible with supertype CustomLogger and PromptManagementBase

* fix: document envs

* fix: add missing parameters to LangfusePromptManagement.async_get_chat_completion_prompt

- Add ignore_prompt_manager_model and ignore_prompt_manager_optional_params parameters
- Pass all parameters including prompt_spec and ignore flags to get_chat_completion_prompt
- Fixes mypy type errors: Signature incompatible with supertype CustomLogger and PromptManagementBase

* fix: add missing parameters to prompt management async methods (Category 1)

- vector_store_pre_call_hook: add ignore_prompt_manager_model, ignore_prompt_manager_optional_params, prompt_spec
- gitlab_prompt_manager: add ignore parameters, fix litellm_logging_obj type
- bitbucket_prompt_manager: add ignore parameters, fix litellm_logging_obj type
- proxy/custom_prompt_management: add prompt_spec parameter
- Fixes mypy type errors: Signature incompatible with supertype

* fix: fix arize_phoenix_prompt_manager and custom_prompt_management (Category 2)

- arize_phoenix_prompt_manager: add prompt_spec to all methods, fix prompt_id types, implement async_compile_prompt_helper
- custom_prompt_management: implement async_compile_prompt_helper abstract method
- Fixes mypy type errors: Signature incompatible with supertype and abstract method errors

* fix: fix obvious type errors (Category 3 - Quick Wins)

- langfuse: change 'callable' to 'Callable' type annotation
- presidio: add type narrowing check for Choices vs StreamingChoices
  - StreamingChoices doesn't have .message attribute, only Choices does
  - Add hasattr check before accessing choice.message
- Fixes mypy type errors: callable? not callable and union-attr errors

* fix: handle expires_after None in Azure files handler (Todo 14)

- Extract logic to _prepare_create_file_data helper method
- Remove expires_after from dict if None to match SDK's Omit pattern
- Add type ignore for FileExpiresAfter -> file_create_params.ExpiresAfter mismatch
- Fixes mypy error: Argument expires_after has incompatible type

* fix: change purpose parameter type to OpenAIFilesPurpose (Todo 18)

- Import OpenAIFilesPurpose in storage_backend_service.py
- Change upload_file_to_storage_backend purpose parameter from str to OpenAIFilesPurpose
- Change _create_file_object_with_storage_metadata purpose parameter from str to OpenAIFilesPurpose
- Fixes mypy error: Argument purpose has incompatible type str; expected Literal type
- Purpose is already validated in files_endpoints.py before reaching these functions

* fix: handle UploadFile | str type for expires_after form fields (Todo 19)

- Validate expires_after[anchor] and expires_after[seconds] are strings, not UploadFiles
- Validate anchor equals 'created_at' before using literal in TypedDict
- Use literal 'created_at' (not variable) in FileExpiresAfter to satisfy Literal type
- Add proper error handling for invalid anchor values and int conversion
- Fixes mypy errors: Incompatible types for anchor and seconds in FileExpiresAfter

* fix: add type narrowing for expires_after_seconds_str to fix mypy error

- Add assert statement after UploadFile validation to help mypy narrow type
- Use validated variable with explicit str type annotation
- Fixes: Argument of type 'UploadFile | str' cannot be assigned to int()

* fix: trigger async_success_handler for MCP tool calls to enable cost tracking and logging

- Set call_type to CallTypes.call_mcp_tool.value before calling async_success_handler
- Update mcp_tool_call_metadata with cost info when server is found
- Call async_success_handler to build standard_logging_object and trigger callbacks
- Fixes test_mcp_cost_tracking by ensuring standard_logging_payload is populated

* refactor: use positive isinstance check for safer type narrowing

- Replace assert with positive isinstance(..., str) check
- Matches codebase pattern (see pass_through_endpoints.py)
- Safer than assert: assertions can be disabled with -O flag
- Mypy properly narrows type after positive isinstance check
- More explicit and readable than assert statement

* fix: add missing REDIS_DAILY_AGENT_SPEND_UPDATE_QUEUE to ServiceTypes enum (Todo 17)

- Add REDIS_DAILY_AGENT_SPEND_UPDATE_QUEUE enum value following the pattern of other daily spend queues
- Add corresponding entry to DEFAULT_SERVICE_CONFIGS with GAUGE metrics
- Fixes mypy error: 'type[ServiceTypes]' has no attribute 'REDIS_DAILY_AGENT_SPEND_UPDATE_QUEUE'
- This enum value is already used in redis_update_buffer.py for agent spend tracking
2025-12-13 08:18:43 -08:00
..
__init__.py Add GitlabPromptCache and enable subfolder access (#15712) 2025-10-28 14:46:50 -07:00
gitlab_client.py Gitlab based Prompt manager (#14988) 2025-10-01 18:13:11 -07:00
gitlab_prompt_manager.py [Fix] CI/CD - mypy & check_code_and_doc_quality & mcp_testing (#17920) 2025-12-13 08:18:43 -08:00
README.md Gitlab based Prompt manager (#14988) 2025-10-01 18:13:11 -07:00

LiteLLM gitlab Prompt Management

A powerful prompt management system for LiteLLM that fetches .prompt files from gitlab repositories. This enables team-based prompt management with gitlab's built-in access control and version control capabilities.

Features

  • 🏢 Team-based access control: Leverage gitlab's workspace and repository permissions
  • 📁 Repository-based prompt storage: Store prompts in gitlab repositories
  • 🔐 Multiple authentication methods: Support for access tokens and basic auth
  • 🎯 YAML frontmatter: Define model, parameters, and schemas in file headers
  • 🔧 Handlebars templating: Use {{variable}} syntax with Jinja2 backend
  • Input validation: Automatic validation against defined schemas
  • 🔗 LiteLLM integration: Works seamlessly with litellm.completion()
  • 💬 Smart message parsing: Converts prompts to proper chat messages
  • ⚙️ Parameter extraction: Automatically applies model settings from prompts

Quick Start

1. Set up gitlab Repository

Create a repository in your gitlab workspace and add .prompt files:

your-repo/
├── prompts/
│   ├── chat_assistant.prompt
│   ├── code_reviewer.prompt
│   └── data_analyst.prompt

2. Create a .prompt file

Create a file called prompts/chat_assistant.prompt:

---
model: gpt-4
temperature: 0.7
max_tokens: 150
input:
  schema:
    user_message: string
    system_context?: string
---

{% if system_context %}System: {{system_context}}

{% endif %}User: {{user_message}}

3. Configure gitlab Access

import litellm

# Configure gitlab access
gitlab_config = {
    "project": "a/b/<repo_name>",
    "access_token": "your-access-token",
    "base_url": "gitlab url",
    "prompts_path": "src/prompts", # folder to point to, defaults to root
    "branch":"main"  # optional, defaults to main
}

# Set global gitlab configuration
litellm.set_global_gitlab_config(gitlab_config)

Option B: Basic Authentication

import litellm

# Configure gitlab access with basic auth
gitlab_config = {
    "project": "a/b/<repo_name>",
    "base_url": "base url",
    "access_token": "your-app-password",  # Use app password for basic auth
    "branch": "main",
    "prompts_path": "src/prompts", # folder to point to, defaults to root
}

litellm.set_global_gitlab_config(gitlab_config)

4. Use with LiteLLM

# Use with completion - the model prefix 'gitlab/' tells LiteLLM to use gitlab prompt management
response = litellm.completion(
    model="gitlab/gpt-4",  # The actual model comes from the .prompt file
    prompt_id="prompts/chat_assistant", # Location of the prompt file
    prompt_variables={
        "user_message": "What is machine learning?",
        "system_context": "You are a helpful AI tutor."
    },
    # Any additional messages will be appended after the prompt
    messages=[{"role": "user", "content": "Please explain it simply."}]
)

print(response.choices[0].message.content)

Proxy Server Configuration

1. Create a .prompt file

Create prompts/hello.prompt:

---
model: gpt-4
temperature: 0.7
---
System: You are a helpful assistant.

User: {{user_message}}

2. Setup config.yaml

model_list:
  - model_name: my-gitlab-model
    litellm_params:
      model: gitlab/gpt-4
      prompt_id: "prompts/hello"
      api_key: os.environ/OPENAI_API_KEY

litellm_settings:
  global_gitlab_config:
    workspace: "your-workspace"
    repository: "your-repo"
    access_token: "your-access-token"
    branch: "main"

3. Start the proxy

litellm --config config.yaml --detailed_debug

4. Test it!

curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer sk-1234' \
-d '{
    "model": "my-gitlab-model",
    "messages": [{"role": "user", "content": "IGNORED"}],
    "prompt_variables": {
        "user_message": "What is the capital of France?"
    }
}'

Prompt File Format

Basic Structure

---
# Model configuration
model: gpt-4
temperature: 0.7
max_tokens: 500

# Input schema (optional)
input:
  schema:
    user_message: string
    system_context?: string
---

System: You are a helpful {{role}} assistant.

User: {{user_message}}

Advanced Features

Multi-role conversations:

---
model: gpt-4
temperature: 0.3
---
System: You are a helpful coding assistant.

User: {{user_question}}

Dynamic model selection:

---
model: "{{preferred_model}}"  # Model can be a variable
temperature: 0.7
---
System: You are a helpful assistant specialized in {{domain}}.

User: {{user_message}}

Team-Based Access Control

gitlab's built-in permission system provides team-based access control:

  1. Workspace-level permissions: Control access to entire workspaces
  2. Repository-level permissions: Control access to specific repositories
  3. Branch-level permissions: Control access to specific branches
  4. User and group management: Manage team members and their access levels

Setting up Team Access

  1. Create workspaces for each team:

    team-a-prompts/
    team-b-prompts/
    team-c-prompts/
    
  2. Configure repository permissions:

    • Grant read access to team members
    • Grant write access to prompt maintainers
    • Use branch protection rules for production prompts
  3. Use different access tokens:

    • Each team can have their own access token
    • Tokens can be scoped to specific repositories
    • Use app passwords for additional security

API Reference

gitlab Configuration

gitlab_config = {
    "workspace": str,           # Required: gitlab workspace name
    "repository": str,          # Required: Repository name
    "access_token": str,        # Required: gitlab access token or app password
    "branch": str,              # Optional: Branch to fetch from (default: "main")
    "base_url": str,            # Optional: Custom gitlab API URL
    "auth_method": str,         # Optional: "token" or "basic" (default: "token")
    "username": str,            # Optional: Username for basic auth
    "base_url" : str            # Optional: Incase where the base url is not https://api.gitlab.org/2.0
}

LiteLLM Integration

response = litellm.completion(
    model="gitlab/<base_model>",  # required (e.g., gitlab/gpt-4)
    prompt_id=str,                   # required - the .prompt filename without extension
    prompt_variables=dict,           # optional - variables for template rendering
    gitlab_config=dict,           # optional - gitlab configuration (if not set globally)
    messages=list,                   # optional - additional messages
)

Error Handling

The gitlab integration provides detailed error messages for common issues:

  • Authentication errors: Invalid access tokens or credentials
  • Permission errors: Insufficient access to workspace/repository
  • File not found: Missing .prompt files
  • Network errors: Connection issues with gitlab API

Security Considerations

  1. Access Token Security: Store access tokens securely using environment variables or secret management systems
  2. Repository Permissions: Use gitlab's permission system to control access
  3. Branch Protection: Protect main branches from unauthorized changes
  4. Audit Logging: gitlab provides audit logs for all repository access

Troubleshooting

Common Issues

  1. "Access denied" errors: Check your gitlab permissions for the workspace and repository
  2. "Authentication failed" errors: Verify your access token or credentials
  3. "File not found" errors: Ensure the .prompt file exists in the specified branch
  4. Template rendering errors: Check your Handlebars syntax in the .prompt file

Debug Mode

Enable debug logging to troubleshoot issues:

import litellm
litellm.set_verbose = True

# Your gitlab prompt calls will now show detailed logs
response = litellm.completion(
    model="gitlab/gpt-4",
    prompt_id="your_prompt",
    prompt_variables={"key": "value"}
)

Migration from File-Based Prompts

If you're currently using file-based prompts with the dotprompt integration, you can easily migrate to gitlab:

  1. Upload your .prompt files to a gitlab repository
  2. Update your configuration to use gitlab instead of local files
  3. Set up team access using gitlab's permission system
  4. Update your code to use gitlab/ model prefix instead of dotprompt/

This provides better collaboration, version control, and team-based access control for your prompts.