* OpenAI-compatible provider adapter * OpenAI support * LM Studio support * Ollama OpenAI-compatible support * Encrypted API-key storage * Default provider and model selection * Provider connection testing * Reusable prompt library * Prompt variables and templates * Prompt version field * AI execution history * Token-usage storage * Duration and failure tracking * Manual knowledge sources * Knowledge-source chunking * Knowledge indexing status * Authenticated AI REST endpoint * AI administration dashboard * AI permissions * Module registration and boot test
47 lines
2.9 KiB
PHP
47 lines
2.9 KiB
PHP
<?php
|
|
namespace Modules\AI\Http\Controllers;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\View\View;
|
|
use Modules\AI\Contracts\AIManager;
|
|
use Modules\AI\Models\AIExecution;
|
|
use Modules\AI\Models\AIKnowledgeSource;
|
|
use Modules\AI\Models\AIPrompt;
|
|
use Modules\AI\Models\AIProvider;
|
|
use Modules\AI\Services\KnowledgeIndexer;
|
|
final class AIController extends Controller
|
|
{
|
|
public function index(): View
|
|
{
|
|
return view('ai::admin.index',['providers'=>AIProvider::latest()->get(),'prompts'=>AIPrompt::latest()->paginate(15,'*','prompts'),'executions'=>AIExecution::latest()->limit(15)->get(),'sources'=>AIKnowledgeSource::latest()->limit(15)->get()]);
|
|
}
|
|
public function storeProvider(Request $request): RedirectResponse
|
|
{
|
|
$data=$request->validate(['name'=>'required|string|max:100','driver'=>'required|in:openai_compatible,openai,lm_studio,ollama','base_url'=>'nullable|url','api_key'=>'nullable|string','default_model'=>'required|string|max:150','is_default'=>'nullable|boolean']);
|
|
if($request->boolean('is_default')) AIProvider::query()->update(['is_default'=>false]);
|
|
$data['is_default']=$request->boolean('is_default'); AIProvider::create($data); return back()->with('status','AI provider created.');
|
|
}
|
|
public function testProvider(AIProvider $provider,AIManager $manager): RedirectResponse
|
|
{
|
|
$result=$manager->testProvider($provider->id); return back()->with($result['ok']?'status':'error',$result['message']);
|
|
}
|
|
public function storePrompt(Request $request): RedirectResponse
|
|
{
|
|
$data=$request->validate(['name'=>'required|string|max:120','slug'=>'nullable|alpha_dash|max:140','purpose'=>'nullable|string|max:100','system_prompt'=>'nullable|string','user_template'=>'required|string']);
|
|
$data['slug']=$data['slug']?:Str::slug($data['name']); $data['created_by']=auth()->id(); AIPrompt::create($data); return back()->with('status','Prompt created.');
|
|
}
|
|
public function execute(Request $request,AIPrompt $prompt,AIManager $manager): RedirectResponse
|
|
{
|
|
$data=$request->validate(['input'=>'required|string|max:50000','provider_id'=>'nullable|exists:ai_providers,id']);
|
|
$execution=$manager->execute($prompt,['input'=>$data['input']],['provider_id'=>$data['provider_id']??null]);
|
|
return back()->with($execution->status==='completed'?'status':'error',$execution->status==='completed'?'AI execution completed.':$execution->error);
|
|
}
|
|
public function storeSource(Request $request,KnowledgeIndexer $indexer): RedirectResponse
|
|
{
|
|
$data=$request->validate(['name'=>'required|string|max:150','content'=>'required|string|max:1000000']);
|
|
$source=AIKnowledgeSource::create(['name'=>$data['name'],'source_kind'=>'manual','content'=>$data['content'],'status'=>'pending']); $indexer->index($source); return back()->with('status','Knowledge source indexed.');
|
|
}
|
|
}
|