AI qualify round 2: strip gender/seniority from roles, aide synonyms, more tag noise
Re-checked live data and found cases the first pass missed: - Gender baked into roles («پرستار آقا», «کمک بهیار آقا») → StripRoleModifiers removes آقا/خانم/مرد/زن/کارآموز/ارشد… from role names (none of the real roles contain these), collapsing the sprawl; gender still lives on the Gender field. - «کمکیار» vs «کمک بهیار» forking → alias maps them to one role. - Personality words («خوشاخلاق», «دلسوز», «منظم»…) added to the tag stop-list. - Prompt: gender goes to the gender field, not the role. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -155,9 +155,10 @@ public class AppSetting
|
||||
نقش (role) و گروه (category):
|
||||
اول سعی کن نقش را با یکی از نقشهای رایج تطبیق دهی: پزشک عمومی، پزشک متخصص، پرستار،
|
||||
پرستار سالمندان، ماما، تکنسین اتاق عمل، تکنسین فوریتهای پزشکی، کارشناس آزمایشگاه، دندانپزشک.
|
||||
نقش را به «حرفهٔ پایه» بنویس، نه با پیشوند/پسوندِ توصیفی. گروهِ سنی، بخش، یا سطح را در نقش
|
||||
نیاور و بهجایش در tags بگذار:
|
||||
نقش را به «حرفهٔ پایه» بنویس، نه با پیشوند/پسوندِ توصیفی. گروهِ سنی، بخش، سطح، یا جنسیت را در
|
||||
نقش نیاور و بهجایش در tags (و جنسیت را در فیلد gender) بگذار:
|
||||
«پرستار کودک» → نقش «پرستار» + تگ «کودک»
|
||||
«پرستار آقا» → نقش «پرستار» + جنسیت «آقا»
|
||||
«پرستار اورژانس» → نقش «پرستار» + تگ «اورژانس»
|
||||
«کارآموز تکنسین داروخانه» → نقش «تکنسین داروخانه» + تگ «کارآموز»
|
||||
فقط وقتی نقشِ جدید بساز که یک «حرفهٔ پایهٔ متفاوت» باشد که در فهرست نیست (مثل «تکنسین داروخانه»،
|
||||
|
||||
@@ -438,6 +438,8 @@ public class IngestionService
|
||||
{
|
||||
"توافقی", "پرداخت", "پرداخت توافقی", "حقوق", "دستمزد", "تماس", "شماره", "شماره تماس",
|
||||
"مراقبت از", "مراقبت", "همکاری", "آماده", "آماده به کار", "نیرو", "استخدام", "جذب",
|
||||
// personality / filler — not clinical skills
|
||||
"خوشاخلاق", "خوش اخلاق", "خوشاخلاق", "دلسوز", "منظم", "مسئولیتپذیر", "مسئولیت پذیر", "باتجربه", "مجرب",
|
||||
};
|
||||
|
||||
private static bool IsNoiseTag(string tag)
|
||||
@@ -454,6 +456,10 @@ public class IngestionService
|
||||
/// sub-specialties («پرستار ICU») stay distinct on purpose.</summary>
|
||||
private Role ResolveOrCreateRole(List<Role> roles, string name, string? category)
|
||||
{
|
||||
// Drop gender/seniority modifiers baked into the role («پرستار آقا»→«پرستار»,
|
||||
// «کارآموز تکنسین داروخانه»→«تکنسین داروخانه»). None of the real roles contain these tokens,
|
||||
// so it only collapses sprawl — the modifier still lives on as a tag / the Gender field.
|
||||
name = StripRoleModifiers(name);
|
||||
var norm = NormalizeFa(name);
|
||||
|
||||
// (1) Already a known role (same word or spelling variant).
|
||||
@@ -504,6 +510,7 @@ public class IngestionService
|
||||
["تکنسین فوریتهای پزشکی"] = new[] { "فوریت پزشکی", "تکنسین اورژانس", "پارامدیک", "paramedic", "emt", "اورژانس ۱۱۵" },
|
||||
["کارشناس آزمایشگاه"] = new[] { "علوم آزمایشگاهی", "تکنسین آزمایشگاه", "آزمایشگاهی", "لابراتوار", "lab", "laboratory" },
|
||||
["دندانپزشک"] = new[] { "دندان پزشک", "دندون پزشک", "dentist" },
|
||||
["کمک بهیار"] = new[] { "کمکیار", "کمکیار", "کمک یار", "کمکبهیار", "کمک بیمار" },
|
||||
});
|
||||
|
||||
// Synonyms → canonical CATEGORY (the role-group used for filters/chips).
|
||||
@@ -537,6 +544,19 @@ public class IngestionService
|
||||
|
||||
private static string Clamp(string s, int max) => s.Length <= max ? s : s[..max].Trim();
|
||||
|
||||
// Gender/seniority tokens that don't belong in a role name (they go to tags / the Gender field).
|
||||
private static readonly string[] RoleModifierWords =
|
||||
{ "آقا", "خانم", "خانوم", "بانو", "مرد", "زن", "کارآموز", "کارورز", "ارشد", "مبتدی" };
|
||||
|
||||
/// <summary>Remove modifier tokens from a role name, keeping the base profession. Never strips to
|
||||
/// empty (falls back to the original).</summary>
|
||||
private static string StripRoleModifiers(string name)
|
||||
{
|
||||
var kept = NormalizeFa(name).Split(' ', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Where(t => !RoleModifierWords.Any(m => NormalizeFa(m) == t)).ToList();
|
||||
return kept.Count > 0 ? string.Join(" ", kept) : name.Trim();
|
||||
}
|
||||
|
||||
/// <summary>Fresh ContactMethod rows for one talent listing (parser contacts + AI phone).</summary>
|
||||
private static List<ContactMethod> BuildContacts(AiStructured? d, ParsedListing parsed)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user