AI ingestion: dynamic role/category creation + tags, hardcoded read-only prompt
CI/CD / CI · dotnet build (push) Successful in 2m19s
CI/CD / Deploy · hamkadr (push) Successful in 2m12s

- Unknown roles from the AI are now resolved-or-CREATED (Persian-normalized dedupe) instead of dropped/fallback; new role gets the AI's category, assigned to the applicant.
- AI output gains category + tags; AI-detected skills/requirements (ICU, MMT, پروانه‌دار…) now fold into the applicant's searchable Tags.
- System prompt is hardcoded in AppSetting.DefaultPrompt and used directly by the auditor; admin sees it read-only (cannot edit/break it).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-09 19:04:24 +03:30
parent 59fb30ac77
commit cf5e0011c4
6 changed files with 123 additions and 43 deletions
@@ -71,9 +71,10 @@
<div style="flex:1;"><label>نام مدل</label><input type="text" name="AiModel" value="@Model.AiModel" dir="ltr" /></div>
</div>
<div class="filter-group">
<label>دستور و چارچوب هوش مصنوعی (Prompt / Framework)</label>
<textarea name="AiSystemPrompt" rows="8" dir="rtl">@Model.AiSystemPrompt</textarea>
<p class="muted" style="font-size:12px; margin:4px 0 0;">به مدل بگو چطور تأیید/رد کند و چه فیلدهایی را استخراج کند. خروجی باید JSON باشد.</p>
<label>دستور و چارچوب هوش مصنوعی (Prompt / Framework) — ثابت 🔒</label>
<textarea rows="14" dir="rtl" readonly
style="background:var(--bg); color:var(--muted); cursor:not-allowed;">@JobsMedical.Web.Models.AppSetting.DefaultPrompt</textarea>
<p class="muted" style="font-size:12px; margin:4px 0 0;">این دستور در کد ثابت شده و قابل ویرایش نیست تا دسته‌بندی و استخراج همیشه درست بماند. یک «اسکیمای خروجی JSON» هم به‌صورت خودکار به انتهای آن افزوده می‌شود.</p>
</div>
<label class="toggle-row">
<input type="checkbox" name="AiAutoApprove" value="true" checked="@Model.AiAutoApprove" />
@@ -32,7 +32,7 @@ public class SettingsModel : PageModel
[BindProperty] public string? AiEndpoint { get; set; }
[BindProperty] public string? AiApiKey { get; set; }
[BindProperty] public string? AiModel { get; set; }
[BindProperty] public string AiSystemPrompt { get; set; } = "";
// AiSystemPrompt is hardcoded (AppSetting.DefaultPrompt) and shown read-only — not bound/editable.
[BindProperty] public bool AiAutoApprove { get; set; }
[BindProperty] public bool AiUseProxy { get; set; }
// Channel scraping sources
@@ -82,7 +82,6 @@ public class SettingsModel : PageModel
AiEndpoint = s.AiEndpoint;
AiApiKey = s.AiApiKey;
AiModel = s.AiModel;
AiSystemPrompt = s.AiSystemPrompt;
AiAutoApprove = s.AiAutoApprove;
AiUseProxy = s.AiUseProxy;
AutoIngestEnabled = s.AutoIngestEnabled;
@@ -127,7 +126,7 @@ public class SettingsModel : PageModel
AiEndpoint = AiEndpoint,
AiApiKey = AiApiKey,
AiModel = AiModel,
AiSystemPrompt = AiSystemPrompt,
// AiSystemPrompt intentionally omitted — AppSetting defaults it to DefaultPrompt (hardcoded).
AiAutoApprove = AiAutoApprove,
AiUseProxy = AiUseProxy,
AutoIngestEnabled = AutoIngestEnabled,