Feature: Add configurable LLM endpoint for Claude-compatible alternatives

This commit is contained in:
WLTBAgent
2026-02-16 16:35:42 +00:00
parent 8b5c8826e2
commit 3c2d356eb0
5 changed files with 45 additions and 12 deletions

View File

@@ -33,6 +33,7 @@ class AdminController {
public function load(): JSONResponse {
$clientId = $this->config->getAppValue('google_client_id', 'analyticshub', '');
$apiKey = $this->config->getAppValue('anthropic_api_key', 'analyticshub', '');
$llmEndpoint = $this->config->getAppValue('llm_api_endpoint', 'analyticshub', '');
$refreshToken = $this->config->getAppValue('google_refresh_token', 'analyticshub', '');
// Check if configured
@@ -54,6 +55,7 @@ class AdminController {
'data' => [
'google_client_id' => $clientId,
'google_refresh_token' => $maskedRefreshToken,
'llm_api_endpoint' => $llmEndpoint,
'anthropic_api_key' => $maskedApiKey,
'is_configured' => $isConfigured,
],
@@ -77,6 +79,7 @@ class AdminController {
$clientSecret = $data['google_client_secret'] ?? '';
$refreshToken = $data['google_refresh_token'] ?? '';
$apiKey = $data['anthropic_api_key'] ?? '';
$llmEndpoint = $data['llm_api_endpoint'] ?? '';
if (empty($clientId) || empty($clientSecret) || empty($apiKey)) {
return new JSONResponse([
@@ -93,6 +96,10 @@ class AdminController {
$this->config->setAppValue('google_refresh_token', 'analyticshub', $refreshToken);
}
if (!empty($llmEndpoint)) {
$this->config->setAppValue('llm_api_endpoint', 'analyticshub', $llmEndpoint);
}
$this->config->setAppValue('anthropic_api_key', 'analyticshub', $apiKey);
// Check if fully configured

View File

@@ -61,6 +61,7 @@ class PageController extends \OCP\AppFramework\Controller {
// Get configuration values (masked for secrets)
$clientId = $this->config->getAppValue('google_client_id', 'analyticshub', '');
$apiKey = $this->config->getAppValue('anthropic_api_key', 'analyticshub', '');
$llmEndpoint = $this->config->getAppValue('llm_api_endpoint', 'analyticshub', '');
// Mask API key for display
$maskedApiKey = '';
@@ -76,6 +77,7 @@ class PageController extends \OCP\AppFramework\Controller {
'is_ga_configured' => $isGAConfigured,
'is_llm_configured' => $isLLMConfigured,
'google_client_id' => $clientId,
'llm_api_endpoint' => $llmEndpoint,
'anthropic_api_key_masked' => $maskedApiKey,
'request' => $this->request,
]);

View File

@@ -17,8 +17,8 @@ class LLMService {
private IConfig $config;
private ?ILogger $logger;
// Anthropic API endpoint
private const ANTHROPIC_API = 'https://api.anthropic.com/v1/messages';
// Anthropic API endpoint (default)
private const DEFAULT_API_ENDPOINT = 'https://api.anthropic.com/v1/messages';
private const MAX_RETRIES = 3;
private const RATE_LIMIT_DELAY = 12; // Seconds to wait between retries
private const TIMEOUT_SECONDS = 30;
@@ -44,17 +44,21 @@ class LLMService {
try {
$apiKey = $this->config->getAppValue('anthropic_api_key', 'analyticshub');
$apiEndpoint = $this->config->getAppValue('llm_api_endpoint', 'analyticshub', '');
if (empty($apiKey)) {
throw new \Exception('Anthropic API key not configured');
throw new \Exception('API key not configured');
}
// Use configured endpoint or default to Anthropic
$endpoint = !empty($apiEndpoint) ? $apiEndpoint : self::DEFAULT_API_ENDPOINT;
// Build prompt
$systemPrompt = $this->buildSystemPrompt($client);
$userPrompt = $this->buildUserPrompt($processedData);
// Call with retry
$response = $this->callWithRetry($systemPrompt, $userPrompt, $apiKey);
$response = $this->callWithRetry($systemPrompt, $userPrompt, $apiKey, $endpoint);
return $response;
@@ -120,12 +124,12 @@ PROMPT;
/**
* Call Claude API with retry logic
*/
private function callWithRetry(string $systemPrompt, string $userPrompt, string $apiKey): string {
private function callWithRetry(string $systemPrompt, string $userPrompt, string $apiKey, string $endpoint): string {
for ($attempt = 0; $attempt < self::MAX_RETRIES; $attempt++) {
$this->logger->info("LLM API call attempt {$attempt}/" . self::MAX_RETRIES);
try {
$response = $this->makeLLMRequest($systemPrompt, $userPrompt, $apiKey);
$response = $this->makeLLMRequest($systemPrompt, $userPrompt, $apiKey, $endpoint);
// Validate response
$this->validateResponse($response);
@@ -180,9 +184,9 @@ PROMPT;
}
/**
* Make HTTP request to Anthropic API
* Make HTTP request to LLM API
*/
private function makeLLMRequest(string $systemPrompt, string $userPrompt, string $apiKey): string {
private function makeLLMRequest(string $systemPrompt, string $userPrompt, string $apiKey, string $endpoint): string {
$ch = curl_init();
$payload = [
@@ -197,7 +201,7 @@ PROMPT;
]
];
curl_setopt($ch, CURLOPT_URL, self::ANTHROPIC_API);
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));