Skip to content

Add LiteLLM provider for pentestgpt-legacy - #479

Open
RheagalFire wants to merge 4 commits into
GreyDGL:mainfrom
RheagalFire:feat/litellm-provider
Open

RheagalFire wants to merge 4 commits into
GreyDGL:mainfrom
RheagalFire:feat/litellm-provider

Conversation

@RheagalFire

@RheagalFire RheagalFire commented Jun 29, 2026

Copy link
Copy Markdown

Add LiteLLM provider for pentestgpt-legacy

LiteLLM is an open-source gateway that provides a unified completion() interface for 100+ LLM providers. Adding it as a provider gives pentestgpt-legacy users access to Azure, AWS Bedrock, Google Vertex, HuggingFace, vLLM, and any OpenAI-compatible endpoint, all through a single litellm:<model> prefix, without per-provider code.

Changes

File Change
llm/providers/litellm_provider.py New LiteLLMProvider(BaseProvider) using litellm.acompletion() with drop_params=True
llm/registry.py Added litellm ProviderInfo + litellm: dynamic prefix resolver
llm/factory.py Registered LiteLLMProvider in _PROVIDER_CLASSES
llm/providers/__init__.py Export LiteLLMProvider
llm/config.py Added LITELLM_API_KEY and LITELLM_BASE_URL settings
pyproject.toml Added litellm>=1.80.0 as optional dependency
.env.example Documented LiteLLM configuration
tests/legacy/test_litellm_provider.py 6 unit tests covering registry, resolve, factory, and proxy config

Usage

# Install with the litellm extra
uv sync --extra litellm

# Use any LiteLLM-supported model
pentestgpt-legacy --reasoning-model litellm:azure/gpt-4 --parsing-model litellm:bedrock/anthropic.claude-v2

# With a LiteLLM proxy
LITELLM_API_KEY=sk-proxy LITELLM_BASE_URL=http://proxy:4000 \
  pentestgpt-legacy --reasoning-model litellm:gpt-4

Tests

Live E2E - full LLMClient stack via Azure Foundry (anthropic/claude-sonnet-4-6):

from pentestgpt_legacy.llm.factory import get_client

# Factory resolves litellm: prefix -> LiteLLMProvider -> litellm.acompletion()
client = get_client('litellm:anthropic/claude-sonnet-4-6')

# Test 1: New conversation
response, cid = client.send_new_message('Say hello in 5 words.')
print(f"Response: {response}")
print(f"Conversation ID: {cid}")
# Response: Hello there, how are you?
# Conversation ID: <uuid>

# Test 2: Multi-turn (same conversation)
response2 = client.send_message('Now say goodbye in 3 words.', cid)
print(f"Follow-up: {response2}")
# Follow-up: Goodbye for now!

Full chain verified: get_client('litellm:...') -> LLMClientFactory -> LiteLLMProvider.acompletion() -> litellm.acompletion(drop_params=True) -> Azure Foundry -> response parsed correctly. Multi-turn conversation state maintained across calls.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces integration with LiteLLM as an optional multi-provider gateway, adding configuration options, a dedicated LiteLLMProvider class, and corresponding unit tests. The feedback suggests two improvements: updating the installation error message to recommend installing the optional dependency via 'uv sync --extra litellm' instead of 'uv add litellm', and safely guarding against an empty response.choices list to prevent a potential IndexError.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +35 to +37
raise RuntimeError(
"The 'litellm' package is required. Install with: uv add litellm"
) from exc

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message suggests installing litellm using uv add litellm. However, litellm is defined as an optional dependency (extra) in pyproject.toml. Running uv add litellm would add it as a direct dependency. To keep it as an optional dependency, the error message should recommend using uv sync --extra litellm (consistent with the instructions in .env.example).

Suggested change
raise RuntimeError(
"The 'litellm' package is required. Install with: uv add litellm"
) from exc
raise RuntimeError(
"The 'litellm' package is required. Install with: uv sync --extra litellm"
) from exc

Comment on lines +58 to +59
response = await litellm.acompletion(**kwargs)
return response.choices[0].message.content or ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the API response is empty or blocked (e.g., due to content filtering), response.choices might be empty. Accessing response.choices[0] directly without checking can raise an IndexError. It is safer to guard against empty choices.

Suggested change
response = await litellm.acompletion(**kwargs)
return response.choices[0].message.content or ""
response = await litellm.acompletion(**kwargs)
if not response.choices:
return ""
return response.choices[0].message.content or ""

RheagalFire and others added 3 commits June 29, 2026 22:37
- Change error message from 'uv add litellm' to 'uv sync --extra litellm'
  since litellm is declared as an optional dependency group
- Add guard against empty response.choices before indexing to prevent
  IndexError when the API returns no completions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant