كيف أقوم بإنشاء خدمة توصية مجتمع VKontakte

كان الصيف ينتهي ، وكان أغسطس الباردة خاصة. بدأ الصف الحادي عشر وأدركت الآن أن الفرصة الأخيرة (المفسد: لا) لتحسين كفاءتي المهنية بطريقة أو بأخرى. منذ عدة سنوات ، كنت أقوم بعمل العديد من مشاريع تكنولوجيا المعلومات ، بعضها بمفردي ، بعضها في الفريق. ولكن الآن جميع أبناء صديقة أمي يفعلون شيئًا جميلًا بالفعل. ربما عديمة الفائدة ، ولكن جميلة في المظهر. يقوم شخص ما بإجراء محاكاة لزجة للجسيمات في شكل صور متحركة ، يغرق شخص ما في التعلم الآلي ويقوم بكل أنواع عمليات نقل الأسلوب. وما أنا أسوأ؟ أنا أيضا أريد أن!

مثال على المحاكاة هو أيضا تحت القط.


مثال محاكاة الجسيمات من صديق لي

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

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

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

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



والآن ، نعود إلى شهر أغسطس ، الذي أصبح أكثر دفئًا قليلاً مما كان عليه في بداية المقال. عندما أدركت أن لدي الآن مصدر ضخم للمعلومات ، أدركت أن الوقت قد حان. لقد حان الوقت لنظامنا الوحشي. لكن السؤال الرئيسي ظل بعد بضعة أيام - ماذا أفعل بكل هذا؟ ماذا تقدم للمستخدم؟ لن أعذب القارئ ، سأخبرك فقط أنه ، مثل بعض أصدقائي ، صعب للغاية بالنسبة لي للبحث عن مجموعات VKontakte جديدة قد أرغب فيها. الآن كل جمهور أول لديه اسم - مجموعة عشوائية من الكلمات. يحاول المسؤولون جعله أكثر سخافة ، وربما هذا هو نوع من العرق ، يكون مفهومًا لهم فقط.

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

المقدمة لم تكن طويلة بالصدفة ، كان من المفترض أن أنقل مشاعري وأظهر أن الفكرة لم تظهر من اللون الأزرق. في الواقع ، مثل أي أفكار أخرى عن حبري.

لا تزال خدمتي قيد التشغيل ، فهي مستمرة منذ أكثر من أربعة أشهر (إذا كنت تعول من لحظة أول تجربة ناجحة). لكن لديّ بالفعل خبرة أرغب في مشاركتها معك. الآن سيكون هناك وصف قصير وموجز للمشروع. بعد ذلك ، سأوضح بعض النقاط الرئيسية. وإذا كانت المقالة سوف تروق بشكل خاص للرعاة ، فسيظهر استمرارها ، حيث سيكون هناك المزيد من المعلومات والرموز الفنية البحتة.

كل شيء يتكون من ثلاثة أجزاء:

  • البحث بوت (إذا كنت تستطيع أن نسميها ذلك)
  • محرك معالجة البيانات
  • موقع للمستخدمين (مع لوحة تحكم ومراقبة للمسؤولين)

تتضمن وظيفة الروبوت البحث عن مجموعات جديدة ونص "تجريد" وغيرها من المعلومات في قاعدة البيانات. يشارك المحرك في مزيد من المعالجة لهذه البيانات ، والتي سأكتب عنها أدناه. ويتيح الموقع للمستخدمين ببساطة استخدام كل هذا.

البحث بوت


لا جديد هنا أنا فقط أخذ ملف تعريف الشخص على VK وأحصل على قائمة بالمجموعات وأصدقائه منه. كل هذا يحدث مع VK API. وإذا تمكنت IPA من الحصول على قائمة بمجموعات المستخدمين وأصدقائه ، فلن يتمكن من الحصول على محتويات المجموعات ... لقد واجهت قيودًا وهذا كل شيء. ثم تذكرت أنه منذ بعض الوقت ، كان فكونتاكتي يروج لنظامهم الرائع لمثل هذه الأشياء. واسم هذا النظام هو الجري API.
تدفق API - أداة للحصول على اختيار عشوائي للسجلات من VK. إنه مكتوب على صفحة الوصف أنه يمكنك فقط الحصول على ما يصل إلى 1 ٪ من جميع المعلومات ، من أجل الحصول على ما يصل إلى مائة تحتاج إلى الكتابة إلى الدعم وشرح نواياك لهم.
يبدو أن كل شيء رائع. لكن لا. أنا ، مثل الكثيرين على الأرجح ، فاتتهم الكلمة الأكثر أهمية في الوصف أعلاه. وهذا هو حرف الجر "قبل". لا أحد سوف يعطيك 100 ٪ من البيانات. هذا مجرد شريط علوي جميل وهذا كل شيء. في الواقع ، نحصل على مثل هذا:


أمل العامل # 365 لن يكرهني كل 365 يومًا في هذه الصورة

وهذا يعني أنه لا يمكنني سوى الحصول على 30 ألف حدث يوميًا. وهذا الرقم يتضمن تعليقات و reposts فقط. من الضروري أيضًا الإشارة إلى بعض الكلمات الوسم ، حيث ستظهر الرسائل فقط. بعض المنشورات المتبقية فقط لا تهمني ، لأنها على حائط المستخدمين. لا يزال قليلا جدا. كمرجع ، في تطبيقي الحالي ، يمكنني الحصول على ما يصل إلى 8.5 مليون سجل في بضعة أيام من وقت التشغيل غير المكتمل (في المجموع - حوالي 10 ساعات ، ولكن لم تكن هناك قياسات دقيقة).

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

قررت ذلك وقتا طويلا وذهبت في الاتجاه الآخر. نظرًا لأنني لا أستطيع الحصول على إجابة دقيقة من VKontakte بتنسيق JSON ، فسأقوم بتحليل جدران المجتمعات. نعم ، المهمة معقدة بعض الشيء ، ويبطئ حلها ، لكن ليس لدي بديل. هكذا بدأت في كتابة الكتلة الأولى من نظامي. لقد كتبت ذلك ، بالمناسبة ، في Java باستخدام Jsoup ، وهي مكتبة تجعل من السهل للغاية استخراج المحتوى من نص HTML. لم أنس معالجة معالجة تاريخ نشر آخر مشاركة ، ولا أحتاج إلى مجتمعات ميتة ، فأنا ببساطة لا أفهرسها. يتم أيضًا تجاهل المشاركات الموسومة بالإعلانات. ليس كل المسؤولين يقومون بإصدار مثل هذه الملاحظات ، لكن هذه المشكلة ليست بسيطة في حلها ، لم أتمكن من إنشاء فلتر إعلان مناسب ، ولهذا السبب ، في الوقت الحالي ، أرفض هذا التصفية.

المحرك


ربما هذا هو الجزء الأكثر إثارة للاهتمام من المشروع ، لكنني لن أصف كل شيء بالتفصيل في هذا المنشور. إذا كان شخص ما مهتمًا بالتفاصيل ، فاطلب منهم ذلك بكل الطرق الممكنة.

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



عملية النقل والمزيد عن BOW
أعدد قاموسًا لكل الكلمات الشائعة مسبقًا (دون أن أنسى استبعاد الكلمات الشائعة بشكل مباشر ، مثل "a" و "what" و "which" وغيرها ، ولا يميزون نصهم عن خلفية الآخرين) ، كل كلمة لها رقمها الخاص بها. بعد ذلك ، عندما أحتاج إلى معالجة النص باستخدام شبكة عصبية ، أحصل على رقم كل كلمة من القاموس (إذا كانت موجودة) وأحصل على متجه (ويعرف أيضًا باسم المصفوفة في البرمجة). هذه مجموعة من الأرقام مرتبة ، حيث توجد وحدة في مكان كل رقم كلمة من النص (انظر الصورة أعلاه). اتضح نوع البيانات مفهومة تماما للشبكة. لدي طول كل متجه 30،000 ، أي حول الكثير من الكلمات التي جمعتها في المراحل الأولى من التطوير.

من المهم أيضًا ألا ننسى أن عبارة "habr" و "(c) habr" ، على سبيل المثال ، تكاد تكون متطابقة مع الفهم. ولكن بالنسبة للخوارزمية الموضحة أعلاه ، فهذه كلمات مختلفة تمامًا. من أجل إصلاح هذا ، يمكنني استخدام محلل المورفولوجية JMorphy2 . هذا هو منفذ PyMorphy2 الأصلي لجافا. يمكنه القيام بالعديد من الأشياء الرائعة ، على سبيل المثال ، تغيير شكل الكلمة (الحالة أو الجنس أو الرقم أو ما إلى ذلك). أحتاجه للحصول على الشكل الأولي للكلمة. كما تعلمون ، الأشكال الأولية للكلمات "متطابقة" هي نفسها. وهذا يحل المشكلة أعلاه.

 6929  21903  25126  11441  7374  1925  1626  23128  6241  25584 

مثال لقائمة الكلمات في القاموس وأرقامها (مفصولة بمسافة)

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

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

لكنني سأستمر من اللحظة التي تحولت فيها أي مشاركة من فكونتاكتي بالفعل إلى متجه (أسميها vectorization). هنا الرابط التالي متصل: شبكة عصبية. قررت استخدامه لأنه كان مثيراً للاهتمام بالنسبة لي وتمكنت من إيجاد بنية مناسبة لمهمتي. ساعدني المقال الأول من سلسلة "Auto Encoders in Keras" في ذلك. ونعم ، قررت استخدام أكثر برامج الترميز التلقائي شيوعًا ، حيث إنها مفيدة من حيث السرعة والتدريب. ولكن دعونا نتحدث عن كل شيء بالترتيب.

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

 from keras.layers import Input, Dense, Flatten, Reshape from keras.models import Model #    encoding_dim = 64 #  inp = Input(shape=(30000, )) # 30000 -  #     encoded = Dense(encoding_dim, activation='linear')(inp) #  #     input_encoded = Input(shape=(encoding_dim,)) decoded = Dense(30000, activation='sigmoid')(input_encoded) #          encoder = Model(inp, encoded, name="encoder") decoder = Model(input_encoded, decoded, name="decoder") autoencoder = Model(inp, decoder(encoder(inp)), name="autoencoder") 

ولكن لماذا نحتاج إلى شبكتين؟ على أي حال ، يا صاحب البلاغ ، أنت لم تصف لماذا كل هذا!

الهدوء ، والآن كل شيء سيكون. لتدريب ، على سبيل المثال ، فقط من المستحيل التشفير - ببساطة لن يكون من الواضح مدى صحة التنبؤ الذي أدلى به. ولهذا ، نقوم بتدريب الشبكة الثانية ، والتي ستقوم على الفور بفك تشفير ناتج الأول (وحدة فك الترميز). وتستخدم أيضا نفس المدخلات والمخرجات البيانات. تتعلم مجموعة من شبكتين (يطلق عليها الرمز التلقائي) الحصول على نفس الشيء من بيانات الإدخال. ولكن جميع البيانات تمر "عنق الزجاجة" الضيقة في شكل 64 الخلايا العصبية. هذا يتجاهل معظم المعلومات غير الضرورية. وبالتالي ، تتعلم الشبكات العصبية نقل المعلومات الهامة حول النص بأعلى جودة وإلقاء كل الضوضاء. ثم أنا فقط إزالة فك التشفير وهذا كل شيء. يمكنك الحصول على نتيجة أفضل ، ولكن بعد ذلك تحتاج إلى زيادة بُعد طبقة إخراج وحدة فك التشفير / الإدخال. بعد ذلك ، سيكون من الضروري تخزين المزيد من القيم في قاعدة البيانات ، وستزن أكثر + جميع العمليات على المتجهات الطويلة ستكون أطول (أكثر على ذلك لاحقًا). أو يمكنك إضافة طبقات / خلايا عصبية ، ولكن بعد ذلك سوف يكون التدريب والتوجه أطول.

يسمح لك المشفر نفسه بـ "ضغط بُعد المتجه". تذكر أن ناقلات الأصفار وتلك؟ لذلك ، يسمح لك المشفر بتغيير حجمه من 30 ك إلى 64 دون فقدان الكثير من المعلومات الهامة. بعد هذه الخطوة ، يمكنك عادةً مقارنة المتجهين لتحديد تشابههما ...

لكننا ننظر إلى عمل الخدمة بناءً على توصية من مجتمعات VK ، وليس السجلات الفردية. هذا يعني أننا نحتاج إلى الحصول على ناقل للجمهور بطريقة أو بأخرى. يتم ذلك بسهولة ، الرياضيات في مستوى الصف الخامس. هذه هي الطريقة الخام بعض الشيء ، لكنها تعمل. أنا فقط أحذف وأضيف كل متجهات السجلات من مجتمع واحد (على سبيل المثال ، استخدم ثلاثة متجهات صغيرة {1 ، 2 ، 3} ، {2 ، 3 ، 4} ، {0 ، 4 ، 2} ، نحصل على المتجه {3 ، 9 ، 9 }). وأقسم كل عنصر من عناصره على عدد المتجهات (نحصل على المتجه {1 ، 3 ، 3}). هذا كل شيء ، لقد جمعنا جميع سجلات المجموعة في سجل واحد. في المستقبل ، تحتاج إلى التوصل إلى شيء أكثر صعوبة ، بحيث يمكنك إلقاء ضوضاء في شكل منشورات مع الإعلان ، على سبيل المثال. ولكن الآن هذا يكفي.

ننتقل إلى الجزء الرياضي نفسه ، لكن بما أن الجميع يخافون منه لسبب ما ، فسأوقعه قدر الإمكان. لنبدأ مع المتجهات بالمعنى الرياضي. المتجه هو الجزء الموجه. هذا شيء له إحداثيات البداية (من الأنسب أخذها مع الأصفار) وإحداثيات النهاية. هذا هو الأخير الذي يتم تسجيله في الأقواس. على سبيل المثال ، تعد إحداثيات نهاية المتجه {1 ، 0 ، 1} youtube نقطة ذات إحداثيات (1 ، 0 ، 1). ولكن سننظر في ناقلات ثنائية الأبعاد ، {5 ، 2} و {5 ، 0}. دعونا نبنيها في نظام إحداثي واحد:



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

المنتج العددية < ، > يساوي مجموع منتجات العناصر المقابلة ، لدينا ،.

تم العثور على الوحدة النمطية للناقلات بواسطة الصيغة التالية:


أين و هذه هي القيمة الأولى والثانية للمتجه a ، على التوالي. لذلك:
أ
ب

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

ماذا تعطي هذه المعلومات؟ كما اتضح ، كلما كانت قيمة جيب التمام أكبر (كلما كانت الزاوية أصغر) ، كانت النصوص التي تتوافق مع المتجهات أكثر تشابهًا. وبالتالي ، فإن مهمة العثور على المجموعة الأكثر تشابهاً مع المجموعة "أ" تكمن في إيجاد جيب التمام للزاوية بين متجه هذه المجموعة وكل المجموعات الأخرى. ثم يترك المحرك جميع المجموعات التي تكون فيها قيمة جيب التمام مع A أكبر من ، على سبيل المثال ، 0.99. في هذه المرحلة ، يمكنك ببساطة عرض النتيجة ، كما كان من قبل. لكن هذه العملية طويلة جدًا بالفعل في 100 ألف مجتمع ، وما الذي سيحدث ، على سبيل المثال ، في 1 مليون؟

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

الموقع


لن أرسم كل شيء عن الموقع ، لأن هذا هو الجزء الأسهل والأكثر مملة. لم أقم مطلقًا بكتابة مواقع من الصفر ، وكنت دائمًا ما أستخدم العديد من المحركات الجاهزة. لكن في هذا المشروع ، أدركت أنه سيكون من الأسهل صنع samopis. لذلك ، يتم كتابة محرك الموقع في Python 3 باستخدام Flask. ويتم استخدام محرك القالب Ninja2 ، مما يجعله أكثر ملاءمة لاستبدال القيم الديناميكية في كود HTML (و js) الثابت. لم أنس التفويض من خلال فكونتاكتي ، لأن هذا هو الخيار الأمثل. المصمم ، مثل مصمم التخطيط ، سيئ جدًا ، إذا كان هناك من يريد الانضمام إلى المشروع - مرحبًا بك.


السطر الأول من النتائج من الموقع

المشاكل


لقد واجهت بعض المواقف غير السارة التي نجحت في حلها. تمت كتابة مشكلة VK API أعلاه وحلها كان مزعجًا بشكل خاص للخدمة ، نظرًا لأن السرعة انخفضت كثيرًا. إذا كنت قد تلقيت قبل ذلك مائة منشور في طلب واحد ، فأنا بحاجة الآن إلى إجراء عدد قليل من التنزيلات لرمز HTML الكبير ، وتحليله ، وفقط بعد هذه العملية. هناك الآن مشكلة في التقييد الذي يُفرض على المستخدمين وأصدقائهم ومجموعاتهم ، ولكن هذا الحد لا يتداخل في هذه المرحلة. ثم عليك حلها بنفس طريقة حلها.

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



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

لا يزال هناك سؤال آخر لم يُحل بشأن عدد الطلبات إلى موقع VKontakte الذي يمكنني تقديمه لكل وحدة زمنية. أو في يوم واحد. الآن لم أواجه هذا التقييد ، لكن يمكن أن يحدث في أكثر اللحظات غير المناسبة.

الخطط المستقبلية


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

الخاتمة


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

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

Source: https://habr.com/ru/post/ar436636/


All Articles