Custom AI adapter in P4 Code Review

Use a custom AI adapter in P4 Code Review to integrate AI services that are not directly compatible with the built-in AI integration format.

A custom AI adapter allows you to define how requests are sent to your AI service and how responses are processed before being returned to P4 Code Review.

When to use a custom AI adapter

Use a custom AI adapter if:

  • Your AI service does not support the required request and response format.

  • You need to transform requests before sending them to the AI service.

  • You need to process or modify responses returned from the AI service.

  • You want to integrate a proprietary or internal AI system.

How a custom AI adapter works

A custom adapter acts as a translation layer between P4 Code Review and your AI service:

  1. P4 Code Review sends a request to the adapter.

  2. The adapter transforms the request into the format expected by your AI service.

  3. The adapter sends the request to the AI service.

  4. The adapter processes the response.

  5. The adapter returns a formatted response to P4 Code Review.

 

You can write and integrate a Custom AI Adapter for your in-house or on-premise AI vendor with P4 Code Review.

Compatibility

The Custom AI Adapter feature has been tested with the following AI vendors and models:

  • Anthropic Claude:

    • claude-opus-4-6
    • claude-sonnet-4-6
  • Google Gemini:

    • gemini-1.0-pro
    • gemini-2.5-flash
    • gemini-3.1-flash-lite-preview
  • OpenAI:

    • gpt-4

  • LM Studio:

    • lmstudio-community/gemma-3-1B-it-qat-GGUF
    • lmstudio-community/Qwen3-1.7B-GGUF
    • lmstudio-community/DeepSeek-R1-Distill-Llama-8B-GGUF
    • lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGU

If you are developing a Custom AI Adapter for a different vendor or model, additional configuration might be required. For specific configuration details, see the vendor's documentation.

We strongly recommend implementing and testing it first in a sandbox environment, test account, or a new instance of P4 Code Review before integrating it into your production environment.

Create a Custom AI Adapter

There are two ways to configure AI in P4 Code Review:

  • Use AI configuration in System Information (Recommended)

  • Use ai_review block config.php (Not recommended)

The following steps outline how to configure a Custom AI Adapter using the ai_review block in config.php.

To write a Custom AI Adapter in P4 Code Review, start by copying the GenericAIAdapter.php file from your installation and then complete these three stages:

  1. Copy and modify GenericAIAdapter

  2. Validate the response

  3. Add custom AI adapter to config files

To review the terms for using your own API keys, download the API Key Usage Agreement for Perforce P4 Code Review.

Copy and modify GenericAIAdapter

  1. Go to the folder module/AiAnalysis/src/Service/

  2. Create the copy of file GenericAIAdapter.php within the same folder.

  3. Rename the copied file. For example: CustomAIAdapter.php.

  4. Use the copied file as the starting point for your custom adapter implementation.

    Always copy the GenericAIAdapter.php file from your P4 Code Review installation rather than recreating it from a documentation example.

    The installed file contains all methods required by the version of P4 Code Review that you are running. Future releases can add new methods that are required by AI features. Copying the file directly from your installation helps ensure that your custom adapter remains compatible with your P4 Code Review version.

  5. Update the class name from:

    class GenericAIAdapter

    To

    class CustomAIAdapter
  6. Modify the implementation to communicate with your AI provider.

AI Checklist compatibility

Custom AI adapters must implement all methods provided by the version of GenericAIAdapter.php included with your P4 Code Review installation.

For example, P4 Code Review 2026.2 introduced the AI Checklist feature, which requires the executeCheckListAIRequest() method. If your custom adapter does not implement this method, AI Checklist requests cannot be processed correctly.

To avoid compatibility issues, always create custom adapters by copying the current GenericAIAdapter.php file from your installation and then modifying it for your AI provider.

Validate the response

  1. Go to the folder module/AiAnalysis/src/Service/, open the AbstractAiAdapter.php file, and copy the validateResult function.

  2. Open CustomAIAdapter.php and overwrite validateResult with the copied function.

  3. Modify the copied function in CustomAIAdapter.php with your AI model’s response format.
    An example of an unmodified validateResult function is as follows:

    Copy
    protected function validateResult(object $result): bool
    {
        if (!property_exists($result, 'error') &&
            property_exists($result, 'choices') &&
            isset($result->choices[0]) && is_object($result->choices[0]) &&
            property_exists($result->choices[0], 'message') &&
            is_object($result->choices[0]->message) &&
            property_exists($result->choices[0]->message, 'content')) {
            return true;
        }
        return false;
    }

    If your AI model response is not a object, modify the validateResult function in CustomAIAdapter.php so that it can handle the response.

    For example, if the AI vendor returns the response as an array, update the validateResult function to parse the response.

    An example of an updated validateResult function that can handle the response as an array:

    Copy
    protected function validateAIResponse(array $result): bool
    {
        if (is_array($result) && isset($result[0]) && is_object($result[0]) &&
            property_exists($result[0], 'embedding'))
        {
            return true;
        }
        return false;
    }
  4. If your AI model’s response format is different from the example above, modify the format accordingly.
    Also update IAiAnalysisHelper within the CustomAIAdapter.php file.
    An example of different AI response format is shown below:

    Copy
    {
      "id": "chatcmpl-B9MBs8CjcvOU2jLn4n570S5qMJKcT",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "Hello! How can I assist you today?",
            "refusal": null,
            "annotations": []
          },
        }
      ],
    }
  5. Update the Services.php file located in module/Application/src/Config/ to include an entry for CustomAIAdapter alongside the other AI adapters.
    An example for the AI adapter entries in this file:

    Copy
    const LM_STUDIO_AI = 'lmStudioAI';
    const CUSTOM_AI = 'customAI';
  6. Update the AiServiceFactory.php file located in module/AiAnalysis/src/Factory/ to include an entry for CustomAIAdapter alongside the other AI adapters.
    An example for the AI adapter entries in this file:

    Copy
        const OPENAIADAPTER     = 'openAI';
        const GENERICAIADAPTER  = 'genericAI';
        const LMSTUDIOAIADAPTER = 'lmStudioAI';
        const CUSTOMAIADAPTER = 'customAI';

Add custom AI adapter to config files

Two config files require updating with entries for the custom AI adapter:

  • module/AiAnalysis/config/module.config.php

  • SWARM_ROOT/data.config.php

To update the files:

  1. Open the module.config.php file found in module/AiAnalysis/config/.

  2. At the top of the module.config.php file, add a use statement for the CustomAIAdapter above the current use statement for the GenericAIAdapter. Below is an example of these use statements:

    Copy
    use AiAnalysis\Service\CustomAIAdapter;
    use AiAnalysis\Service\GenericAIAdapter;
  3. Inside the same module.config.php file, find the service_manager array, and add the following entries.

    In the aliases array, add:

    • AiServiceFactory::CUSTOMAIADAPTER => CustomAIAdapter::class

    In the factories array, add:

    • CustomAIAdapter::class => AiServiceFactory::class
    • Services::CUSTOM_AI => CustomAIAdapter::class

    An example of the updated service_manager array in the module.config.php file.

    Copy
    'service_manager' => [
        'aliases' => [
            IDao::AI_ANALYSIS_DAO  => AiAnalysisDAO::class,
            AiServiceFactory::OPENAIADAPTER => OpenAIAdapter::class,
            AiServiceFactory::GENERICAIADAPTER => GenericAIAdapter::class,
            AiServiceFactory::LMSTUDIOAIADAPTER => LMStudioAIAdapter::class,
            IAiAnalysis::NAME => AiAnalysis::class,
            IAiAnalysis::DISCARD_ANALYSIS_FILTER => DiscardAnalysis::class,
            AiServiceFactory::CUSTOMAIADAPTER => CustomAIAdapter::class
        ],
        'factories' => [
                AiAnalysisDAO::class => InvokableServiceFactory::class,
                OpenAIAdapter::class => AiServiceFactory::class,
                Services::OPEN_AI => OpenAIAdapter::class,
                GenericAIAdapter::class => AiServiceFactory::class,
                Services::GENERIC_AI => GenericAIAdapter::class,
                LMStudioAIAdapter::class => AiServiceFactory::class,
                Services::LM_STUDIO_AI => LMStudioAIAdapter::class,
                AiAnalysis::class => InvokableServiceFactory::class,
                AiAnalysisChecker::class => InvokableServiceFactory::class,
                AiAnalysisCharLimitChecker::class => InvokableServiceFactory::class,
                AiAnalysisDataRetentionLifetimeChecker::class => InvokableServiceFactory::class,
                DiscardAnalysis::class => InvokableServiceFactory::class,
                CustomAIAdapter::class => AiServiceFactory::class,
                Services::CUSTOM_AI => CustomAIAdapter::class,
        ],
    ],
  4. Open config.php file found in SWARM_ROOT/data/.

  5. Update the ai_review module with the values for the custom AI Adapter.

    Make sure you update api_end_point with your AI vendor end point .

    Below is an example of a modified ai_review module:

    Copy
    'ai_review' => array(
        // Please read through the https://www.perforce.com/generative-ai-policy before you enable this feature
        'enabled'    => true,
        'data_retention_lifetime' => '150 days',
        'timeout' => 500,
        'ai_vendors' => array(
            'ai_model1' => array(
                'ai_vendor' => 'customAI',
                'ai_package_id' => '1', // id should be one & should not modify it
                'ai_package_key' => 'CustomAIPackage', // This is for future purposes when we will be supporting multiple models & will have an AI configuration page on UI
                'ai_package_value' => 'Custom AI', // This is used for displaying the model type on the AI vendor response summary
                'ai_package_type' => "Explain the following code ", // This is prompt type
                'api_key' => '$SECRET_KEY', // Add in the API-key for you AI vendor
                'api_end_point' => 'http://myAIVendorAPI/chat/completion', //Add an optional API endpoint
                'ai_min_char_limit' => 10,
                'ai_max_char_limit' => 70000
            ),
        ),
    ),

After completing these steps, a custom AI adapter has been added to P4 Code Review that supports your in-house AI model.