استخدام الذكاء الاصطناعي لوضع العلامات وتصنيف منشورات المنتدى

لقد أنشأت شخصية لمحاولة التصنيف ووضع العلامات تلقائيًا على المواضيع الجديدة. هذا هو الموجه الذي أستخدمه لهذا التصنيف والمُصنِّف.

أنت مساعد ذكاء اصطناعي لمنتدى Discourse الخاص بي. وظيفتك هي تصنيف المواضيع الجديدة إلى واحدة من الفئات المحددة مسبقًا وتطبيق ما يصل إلى 5 علامات ذات صلة.

الفئات:

  • الفئة 1
  • الفئة 2
  • الفئة 3
  • الفئة 4
  • الفئة 5

العلامات:

يجب أن يأتي اختيارك من هذه القائمة المحددة مسبقًا (اختر ما يصل إلى 5):
tag1, tag2, tag3, tag4, tag5

المهمة:

  • اختر فئة واحدة بالضبط من القائمة أعلاه والتي تناسب الموضوع بشكل أفضل.
  • اختر ما يصل إلى 5 علامات من القائمة أعلاه بناءً على الصلة.
  • قم بتنسيق استجابتك بتنسيق JSON تمامًا مثل هذا:
{
  "category": "اسم الفئة المختارة",
  "tags": ["tag1", "tag2", "tag3"]
}

عند تحديد هذه الشخصية لاستخدامها في الأتمتة وإنشاء المنشور، يتعرف الذكاء الاصطناعي على الفئات والعلامات بدقة بهذه النتيجة في منشور.

قائمة الفئات
{
  "category": "الفئة المحددة بشكل صحيح",
  "tags": ["الكل", "صالح", "علامات"]
}

السؤال هو، هل من الممكن بالفعل استخدام الذكاء الاصطناعي والأتمتة لنقل المنشورات الجديدة وتصنيفها وتعيين العلامات للموضوع. إذا كان الأمر كذلك، فأنا متأكد من أنه يمكن تعديل الموجه لتحسين مدى فعاليته.

شكرا،
إعجاب واحد (1)

Getting there… it is a bit tricky we are missing 2 little pieces:

  1. Custom tools now support lots of stuff, but they do not support categorizing and tagging, we can easily add that.
  2. I need a responder that works in “silent” mode, so it does not actually respond to the topic.

Once both of those are in place you would give access to 2 custom tools

  1. tag topic
  2. categorize topic

(or a single tool that does both)

5 إعجابات

في الواقع، طالما أنك موافق على الهمس، يمكنك فعل شيء الآن.

الفكرة هي أنك ستحدد أداة مخصصة لتصنيف موضوع (أو وضع علامة على موضوع) ثم ستجعل الشخصية تستدعيها.

من المثير للاهتمام أن نرى كيف تعمل هذه الطريقة معك، ستحتاج إلى اختبار الأداة، يجب أن تكون واضحة جدًا من واجهة المستخدم للأداة.

من الصعب جدًا تنفيذ كل هذا، ولكنه أيضًا :exploding_head: أنه يمكن القيام به. الهمس مفيد بشكل معقول لأنه يمنحك “عملية تفكير” قليلاً حول كيفية توصل المستجيب إلى العلامات/الفئات.

3 إعجابات

شكراً سام،

أسهل للبعض من الآخرين. أنا في الفئة الأخيرة :joy:

أنا أعبث بهذا ولم أتمكن من جعله يعمل. ليس لدي أي خبرة في الأدوات، لذا أتطلع حقًا إلى جعله يعمل للتفكير في طرق أخرى لاستخدام الأدوات.

لقد حاولت استخدام الكود من مدونتك مع مفتاح API ولم ينجح الأمر. اقترح الذكاء الاصطناعي استخدام عنوان URL ثابت، لذا جربت ذلك دون نجاح.

لم يتم استدعاء مفتاح API ولم يتم إنشاء أي سجلات بها أخطاء.

يُستخدم هذا لتصنيف المواضيع تلقائيًا عند إنشائها

سأقوم بتصنيف الموضوع “رؤى من سنوات يسوع المبكرة والمعجزات” ضمن فئة العهد الجديد، حيث يتعلق بحياة وتعاليم يسوع.
جاري نقل الموضوع الآن…

هذا ما جربته.

/**

  • مرجع سريع لواجهة برمجة تطبيقات الأداة
  • وظائف الدخول
  • invoke(parameters): الوظيفة الرئيسية. تستقبل المعلمات (كائن). يجب أن تُرجع قيمة قابلة للتسلسل JSON.
  • مثال:
  • function invoke(parameters) { return “result”; }
  • details(): اختياري. تُرجع سلسلة تصف الأداة.
  • مثال:
  • function details() { return “وصف الأداة.”; }
  • الكائنات المتوفرة
    1. http
  • http.get(url, options?): يقوم بطلب HTTP GET.
  • المعلمات:
  •  url (string): عنوان URL للطلب.
    
  •  options (Object, اختياري):
    
  •    headers (Object): رؤوس الطلب.
    
  • يُرجع:
  •  { status: number, body: string }
    
  • http.post(url, options?): يقوم بطلب HTTP POST.
  • المعلمات:
  •  url (string): عنوان URL للطلب.
    
  •  options (Object, اختياري):
    
  •    headers (Object): رؤوس الطلب.
    
  •    body (string): نص الطلب.
    
  • يُرجع:
  •  { status: number, body: string }
    
  • (متوفر أيضًا: http.put, http.patch, http.delete)
  • ملاحظة: بحد أقصى 20 طلب HTTP لكل تنفيذ.
    1. llm
  • llm.truncate(text, length): يقتطع النص إلى طول رمز محدد.
  • المعلمات:
  •  text (string): النص المراد اقتطاعه.
    
  •  length (number): الحد الأقصى للرموز.
    
  • يُرجع:
  •  سلسلة مقتطعة.
    
    1. index
  • index.search(query, options?): يبحث في المستندات المفهرسة.
  • المعلمات:
  •  query (string): استعلام البحث.
    
  •  options (Object, اختياري):
    
  •    filenames (Array): تحديد البحث لملفات معينة.
    
  •    limit (number): الحد الأقصى للأجزاء (حتى 200).
    
  • يُرجع:
  •  مصفوفة من { fragment: string, metadata: string }
    
    1. upload
  • upload.create(filename, base_64_content): يقوم بتحميل ملف.
  • المعلمات:
  •  filename (string): اسم الملف.
    
  •  base_64_content (string): محتوى الملف مشفر بـ Base64.
    
  • يُرجع:
  •  { id: number, short_url: string }
    
    1. chain
  • chain.setCustomRaw(raw): يضبط نص المنشور ويخرج السلسلة.
  • المعلمات:
  •  raw (string): المحتوى الخام المراد إضافته إلى المنشور.
    
  • القيود
  • وقت التنفيذ: ≤ 2000 مللي ثانية
  • الذاكرة: ≤ 10 ميجابايت
  • طلبات HTTP: ≤ 20 لكل تنفيذ
  • تجاوز الحدود سيؤدي إلى أخطاء أو إنهاء.
  • الأمان
  • بيئة معزولة: لا يمكن الوصول إلى كائنات النظام أو الكائنات العامة.
  • لا يوجد وصول إلى نظام الملفات: لا يمكن قراءة أو كتابة الملفات.
    */

/**

  • مصنف مواضيع Discourse
  • تتيح لك هذه الأداة تغيير فئة موضوع Discourse
  • باستخدام واجهة برمجة تطبيقات Discourse.
    */

/**

  • مصنف مواضيع Discourse
  • تتيح لك هذه الأداة تغيير فئة موضوع Discourse
  • باستخدام واجهة برمجة تطبيقات Discourse.
    */

/**

  • مصنف مواضيع Discourse
  • تتيح لك هذه الأداة تغيير فئة موضوع Discourse
  • باستخدام واجهة برمجة تطبيقات Discourse.
    */

function invoke(params) {
// التحقق من صحة المعلمات المطلوبة
if (!params.topic_id) {
return { error: “المعلمة المطلوبة مفقودة: topic_id” };
}

if (!params.category_id) {
return { error: “المعلمة المطلوبة مفقودة: category_id” };
}

// عنوان URL الأساسي لمثيل Discourse الخاص بك
const baseUrl = “https://community.mysite.com”;

// عنوان URL الكامل لنقطة نهاية واجهة برمجة التطبيقات لتحديث موضوع
const apiUrl = ${baseUrl}/t/${params.topic_id}.json;

// إعداد نص الطلب
const requestBody = {
category_id: params.category_id
};

// معلمة اختيارية: تحديث العنوان إذا تم توفيره
if (params.title) {
requestBody.title = params.title;
}

// استخدم مفتاح API الخاص بك
const apiKey = “Discourse-API-Key”;

try {
// إجراء طلب PUT لتحديث الموضوع
const response = http.put(apiUrl, {
headers: {
“Content-Type”: “application/json”,
“Api-Key”: apiKey,
“Api-Username”: params.api_username || “system”
},
body: JSON.stringify(requestBody)
});

if (response.status >= 200 && response.status < 300) {
  return {
    success: true,
    topic_id: params.topic_id,
    category_id: params.category_id,
    response: JSON.parse(response.body)
  };
} else {
  return {
    error: `فشل تحديث فئة الموضوع. الحالة: ${response.status}`,
    details: response.body
  };
}

} catch (error) {
return {
error: “حدث خطأ أثناء تحديث فئة الموضوع”,
details: error.toString()
};
}
}

function details() {
return “يقوم بتصنيف موضوع عن طريق نقله إلى فئة محددة”;
}

إعجابَين (2)

هل تمكنت من حل هذا يا براين C؟

إعجاب واحد (1)

Discourse AI Tagger Category Quick Start.pdf|مرفق (147.1 كيلوبايت)

Discourse AI Tagger Category.pdf|مرفق (506.0 كيلوبايت)

@سام،

شكرًا للتواصل. حاولت ولكن لم أتمكن من جعله يعمل، لذا توقفت. لقد قمت بتشغيل اختبار السيناريو من خلال Gemini 2.5 وحفظت الناتج كملفات PDF.

سأحاول مرة أخرى. الأدوات ليست قوتي بعد، ولكن أحتاج إلى أن أكون أكثر دراية بها. ملفات PDF مرفقة—ربما يوجد فيها شيء مفيد.

3 إعجابات

لقد أضفنا أتمتة للوسوم بالذكاء الاصطناعي قد تكون مهتمًا بتجربتها: FEATURE: create AI tagging automation (#34587) · discourse/discourse@e470f3d · GitHub

الموجه الذي كنت أستخدمه لاختباره
 أنت مصنف محتوى خبير ومساعد وسوم لهذا المنتدى.

 مهمتك هي تحليل المشاركات واقتراح وسوم مناسبة بناءً على المحتوى والصور وقائمة الوسوم المتاحة المقدمة.

 الإرشادات:
 - اقترح فقط وسومًا من قائمة الوسوم المتاحة المقدمة
 - كن متحفظًا - قم بوضع الوسوم فقط عندما تكون واثقًا
 - ضع في اعتبارك موضوع المحتوى وقصد المشاركة

 يجب عليك دائمًا الرد بتنسيق JSON صالح بهذا التنسيق المحدد:
 {"tags": ["tag1", "tag2"], "confidence": 85}

 - tags: مصفوفة بأسماء الوسوم من القائمة المتاحة
 - confidence: عدد صحيح من 0 إلى 100 يمثل مستوى ثقتك

 إذا لم تكن هناك وسوم مناسبة، استخدم: {"tags": [], "confidence": 0}

تنسيق استجابة JSON للشخصية:

{
  "tags": "[string]",
  "confidence": "[integer]"
}

أدوات الشخصية الممكّنة: الوسوم (اختياري، هذا إذا كنت تريدها أن تستخدم الوسوم الموجودة على الموقع)
تحتوي الأتمتة على وضعين:

  • استخدام وسوم الموقع الحالية
  • استخدام قائمة الوسوم المقدمة

تحتوي الأتمتة أيضًا على مستوى ثقة قابل للتكوين، يمكنك تمكين/تعطيل الوسوم المقيدة، وضبط عدد المشاركات التي تستخدمها في موضوع للسياق

6 إعجابات

شكرا لهذه الميزة الرائعة، لم أتمكن من تشغيلها فقط، الخطأ الذي تلقيته هو:

llm_tagger: فشل في معالجة المنشور 30550 /t/gecici-baslik-1756753838814/17361/1 : NoMethodError : تم استدعاء الطريقة الخاصة select’ على مثيل من String`

رسالة

llm_tagger: فشل في معالجة المنشور 30550 /t/gecici-baslik-1756753838814/17361/1 : NoMethodError : تم استدعاء الطريقة الخاصة `select' على مثيل من String

تتبع الأخطاء

/var/www/discourse/plugins/discourse-ai/lib/automation/llm_tagger.rb:140:in `handle'
/var/www/discourse/plugins/discourse-ai/discourse_automation/llm_tagger.rb:110:in `block (2 levels) in <main>'
/var/www/discourse/plugins/automation/app/models/discourse_automation/automation.rb:158:in `block in trigger!'
/var/www/discourse/plugins/automation/app/models/discourse_automation/stat.rb:11:in `log'
/var/www/discourse/plugins/automation/app/models/discourse_automation/automation.rb:156:in `trigger!'
/var/www/discourse/plugins/automation/app/jobs/regular/discourse_automation/trigger.rb:29:in `execute'
/var/www/discourse/app/jobs/base.rb:318:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-7.0.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-7.0.0/lib/rails_multisite/connection_management.rb:17:in `with_connection'
/var/www/discourse/app/jobs/base.rb:305:in `block in perform'
/var/www/discourse/app/jobs/base.rb:301:in `each'
/var/www/discourse/app/jobs/base.rb:301:in `perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:220:in `execute_job'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:185:in `block (4 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:180:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/lib/sidekiq/discourse_event.rb:6:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/lib/sidekiq/pausable.rb:131:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_interrupt_handler.rb:9:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/metrics/tracking.rb:26:in `track'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/metrics/tracking.rb:134:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:173:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:183:in `block (3 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:145:in `block (6 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_retry.rb:118:in `local'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:144:in `block (5 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/config.rb:39:in `block in <class:Config>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:139:in `block (4 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:281:in `stats'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:134:in `block (3 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_logger.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:133:in `block (2 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_retry.rb:85:in `global'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:132:in `block in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_logger.rb:40:in `prepare'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:131:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:183:in `block (2 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:182:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:182:in `block in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:181:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:181:in `process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:86:in `process_one'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:76:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/component.rb:10:in `watchdog'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/component.rb:19:in `block in safe_thread'

هل تستخدم ميتا ذلك؟ اعتقدت أنني رأيت @system يصنف موضوعًا قبل بضعة أيام.

إعجاب واحد (1)

قد يكون الإعداد صعبًا، ولكن إذا كان Discourse يقوم بالفعل بإنشاء تضمينات (للبحث الدلالي) للمواضيع الجديدة، فيمكنك على الأرجح إنشاء تضمينات لأوصاف العلامات، ثم استخدام التشابه الدلالي لاقتراح علامات للمواضيع الجديدة، أو وضع علامات تلقائية على المواضيع الموجودة.

3 إعجابات

نعم، لقد قمت بتشغيله لبضعة أيام على ميتا للحصول على المزيد من الاختبارات… إنه يعمل بشكل جيد ولكن بدون أوصاف العلامات كان يسيء استخدام how-to لبعض الأسئلة من نوع “كيف أفعل” وكان يطبق moderator على المشاركات التي تستخدم فيها الكلمة ولكنها لم تكن ذات صلة تمامًا بالموضوع. قد تساعد بعض تعديلات المطالبات، وتبدو أفكار @simon وكأنها تحسينات مستقبلية رائعة.

إعجابَين (2)

تخميني هو أن التضمينات (embeddings) يمكن أن تعمل بشكل أفضل وتكون أسرع/أرخص. اهتمامي الفعلي بهذا الأمر يكمن أكثر في نظام علامات ديناميكي يمكنه استبدال الترميز الثابت للعلامات في قاعدة البيانات. على سبيل المثال، “كيفية” (how-to) + “تسجيل الدخول الموحد” (sso) سيكون قائمة بالمواضيع ذات التضمينات التي كانت قريبة دلاليًا من تضمينات وصف العلامة “كيفية” و"تسجيل الدخول الموحد".

إعجابَين (2)