Anda dan Brad Pitt 99%

Besok sedang liburan


Kami di departemen analitik sinema daring Okko senang mengotomatiskan perhitungan biaya film Alexander Nevsky sebanyak mungkin, dan di waktu luang untuk mempelajari hal-hal baru dan menerapkan hal-hal keren yang karena alasan tertentu biasanya diterjemahkan menjadi bot untuk Telegram. Misalnya, sebelum dimulainya Piala Dunia FIFA 2018, kami meluncurkan bot untuk obrolan yang berfungsi, yang mengumpulkan taruhan pada distribusi tempat terakhir, dan setelah final, kami menghitung hasil berdasarkan metrik yang telah ditemukan sebelumnya dan menentukan pemenang. Kroasia belum menempatkan empat di empat besar.


Waktu luang terakhir dari menyusun komedi TOP-10 Rusia yang kami persembahkan untuk membuat bot yang menemukan selebriti yang paling mirip dengan pengguna. Dalam obrolan yang berhasil, semua orang sangat menghargai gagasan itu sehingga kami memutuskan untuk membuat bot tersedia untuk umum. Pada artikel ini, kami mengingat teori secara singkat, berbicara tentang pembuatan bot kami dan bagaimana melakukannya sendiri.


Sedikit teori (kebanyakan dalam gambar)


Secara rinci tentang bagaimana sistem pengenalan wajah diatur, saya bicarakan di salah satu artikel saya sebelumnya . Pembaca yang tertarik dapat mengikuti tautan, dan saya akan menguraikan di bawah ini hanya poin utama.


Jadi, Anda memiliki foto di mana, mungkin, bahkan wajah ditampilkan dan Anda ingin memahami siapa itu. Untuk melakukan ini, Anda harus mengikuti 4 langkah sederhana:


  1. Pilih persegi panjang yang membatasi wajah.
  2. Sorot titik-titik kunci wajah.
  3. Sejajarkan dan potong wajah Anda.
  4. Ubah gambar wajah menjadi representasi yang diinterpretasikan dengan mesin.
  5. Bandingkan tampilan ini dengan yang lain yang Anda miliki.

Seleksi wajah


Meskipun jaringan saraf convolutional baru-baru ini belajar bagaimana menemukan wajah dalam gambar tidak lebih buruk dari metode klasik, mereka masih kalah dengan HOG klasik dalam kecepatan dan kemudahan penggunaan.


HOG - Histogram Gradien Berorientasi. Orang ini mengaitkan setiap piksel dari gambar sumber dengan gradiennya - vektor ke arah yang paling banyak mengubah kecerahan piksel. Keuntungan dari pendekatan ini adalah bahwa ia tidak peduli dengan nilai absolut dari kecerahan piksel, hanya rasio mereka cukup. Oleh karena itu, wajah normal, dan gelap, dan kurang terang, dan berisik akan ditampilkan dalam kira-kira histogram gradien yang sama.


Histogram gradien wajah Arah


Tidak perlu menghitung gradien untuk setiap piksel, cukup untuk menghitung gradien rata-rata untuk setiap kotak kecil n oleh n . Menggunakan bidang vektor yang diterima, Anda kemudian dapat pergi melalui beberapa detektor dengan jendela dan menentukan untuk setiap jendela seberapa besar kemungkinan wajah di dalamnya. Detektor dapat berupa SVM, hutan acak, atau apa pun.


Deteksi wajah


Sorot Poin-Poin Utama


Poin-poin penting dari wajah


Poin kunci adalah poin yang membantu mengidentifikasi seseorang di luar angkasa. Lemah dan tidak aman Para ilmuwan biasanya membutuhkan 68 poin utama, dan terutama dalam kasus yang diabaikan, bahkan lebih. Anak laki-laki normal dan percaya diri, berpenghasilan 300rb per detik, selalu punya cukup lima: sudut dalam dan luar mata dan hidung.


Meme tua


Poin-poin seperti itu dapat diekstraksi, misalnya, dengan kaskade regressor .


Perataan wajah


Aplikasi terpaku di masa kecil? Di sini semuanya persis sama: Anda membangun transformasi affine yang menerjemahkan tiga titik arbitrer ke posisi standar mereka. Hidung bisa dibiarkan apa adanya, tetapi agar mata menghitung pusatnya - ini adalah tiga poin yang siap.


Putar muka


Ubah gambar wajah menjadi vektor


Meme kurang tua


Tiga tahun telah berlalu sejak penerbitan artikel tentang FaceNet , selama ini banyak skema pelatihan yang menarik dan fungsi kerugian muncul, tetapi dialah yang mendominasi di antara solusi OpenSource yang tersedia. Tampaknya, semuanya adalah kombinasi dari kemudahan pemahaman, implementasi dan hasil yang layak. Terima kasih setidaknya untuk fakta bahwa selama tiga tahun terakhir arsitektur telah diubah menjadi ResNet.


Meme baru


FaceNet belajar dari tiga kali lipat contoh: (jangkar, positif, negatif). Anchor dan contoh positif adalah milik satu orang, sedangkan negatif dipilih sebagai wajah orang lain, yang karena beberapa alasan jaringan terlalu dekat dengan yang pertama. Fungsi kerugian dirancang sedemikian rupa untuk memperbaiki kesalahpahaman ini, menyatukan contoh-contoh yang diperlukan dan memindahkan yang tidak perlu dari mereka.


Guccinet


Wajah wajah dan Dmitry Malikov


Output dari lapisan terakhir dari jaringan disebut embedding - representasi representatif dari seseorang dalam ruang tertentu dari dimensi kecil (biasanya 128 dimensi).


Perbandingan wajah


Keindahan embeddings terlatih adalah bahwa wajah satu orang ditampilkan di beberapa lingkungan kecil ruang, jauh dari embed wajah orang lain. Jadi, untuk ruang ini Anda dapat memasukkan ukuran kesamaan, kebalikan dari jarak: Euclidean atau cosinus, tergantung pada jarak yang dilatih jaringan.


Contoh embedding yang sepenuhnya buatan


Jadi, sebelumnya kita perlu membuat embed untuk semua orang di antaranya pencarian akan dilakukan, dan kemudian, untuk setiap permintaan, temukan vektor terdekat di antara mereka. Atau, dengan cara lain, selesaikan masalah menemukan k tetangga terdekat, di mana k mungkin sama dengan satu, atau mungkin tidak, jika kita ingin menggunakan beberapa logika bisnis yang lebih maju. Orang yang memiliki vektor hasil akan paling mirip dengan orang yang meminta.


Kesamaan tatap muka tidak dengan tatap muka


Perpustakaan mana yang digunakan?


Pilihan perpustakaan terbuka yang menerapkan berbagai bagian pipa sangat bagus. dlib dan OpenCV dapat menemukan wajah dan titik kunci, dan versi jaringan yang sudah dilatih sebelumnya dapat ditemukan untuk kerangka kerja jaringan saraf besar. Ada proyek OpenFace di mana Anda dapat memilih arsitektur untuk kebutuhan kecepatan dan kualitas Anda. Tetapi hanya satu perpustakaan yang memungkinkan Anda untuk menerapkan semua 5 poin pengenalan wajah dalam panggilan ke tiga fungsi tingkat tinggi: dlib . Pada saat yang sama, ini ditulis dalam C ++ modern, menggunakan BLAS, memiliki pembungkus untuk Python, tidak memerlukan GPU, dan bekerja cukup cepat pada CPU. Pilihan kita jatuh padanya.


Membuat bot Anda sendiri


Bagian ini telah dijelaskan dalam setiap panduan untuk membuat bot, tetapi setelah kami menulisnya, kami harus mengulanginya. Kami menulis @BotFather dan meminta tanda untuk bot baru kami.


Mengaburkan tanda xs Fakta


643075690:AAFC8ola8WRdhGbJtzjmkOhne1FGfu1BFg terlihat seperti ini: 643075690:AAFC8ola8WRdhGbJtzjmkOhne1FGfu1BFg . Diperlukan otorisasi pada setiap permintaan ke API bot Telegram.


Saya harap tidak ada seorang pun di tahap ini yang memiliki keraguan ketika memilih bahasa pemrograman. Tentu saja, Anda harus menulis di Haskell. Mari kita mulai dengan modul utama.


 import System.Process main :: IO () main = do (_, _, _, handle) <- createProcess (shell "python bot.py") _ <- waitForProcess handle putStrLn "Done!" 

Seperti yang dapat Anda lihat dari kode, di masa depan kita akan menggunakan DSL khusus untuk menulis bot telegram. Kode pada DSL ini ditulis dalam file terpisah. Instal bahasa domain dan semua yang diperlukan.


 python -m venv .env source .env/bin/activate pip install python-telegram-bot 

python-telegram-bot saat ini merupakan kerangka kerja yang paling nyaman untuk membuat bot. Mudah dipelajari, fleksibel, dapat diskalakan, mendukung multithreading. Sayangnya, saat ini tidak ada kerangka asinkron normal tunggal dan utas kuno harus digunakan sebagai pengganti coroutine ilahi.


asyncio adalah satu-satunya tuhan saya


Memulai bot dengan python-telegram-bot mudah. Tambahkan kode berikut ke bot.py


 from telegram.ext import Updater from telegram.ext import MessageHandler, Filters #      TOKEN = '<TOKEN>' def echo(bot, update): bot.send_message(chat_id=update.message.chat_id, text=update.message.text) updater = Updater(token=TOKEN) dispatcher = updater.dispatcher echo_handler = MessageHandler(Filters.text, echo) dispatcher.add_handler(echo_handler) 

Jalankan bot. Untuk keperluan debugging, ini bisa dilakukan dengan perintah python bot.py tanpa menjalankan kode Haskell.


Bot sederhana semacam itu mampu mempertahankan percakapan minimum, dan karenanya, dapat dengan mudah diatur untuk berfungsi sebagai pengembang front-end.


Dialog khas dengan pengembang front-end


Tetapi ujung depan pengembang sudah terlalu banyak, jadi kami akan membunuhnya sesegera mungkin dan melanjutkan untuk mengimplementasikan fungsi utama. Demi kesederhanaan, bot kami hanya akan membalas pesan yang berisi foto dan mengabaikan yang lainnya. Ubah kode menjadi yang berikut.


 from telegram.ext import Updater from telegram.ext import MessageHandler, Filters #      TOKEN = '<TOKEN>' def handle_photo(bot, update): bot.send_message(chat_id=update.message.chat_id, text='nice') updater = Updater(token=TOKEN) dispatcher = updater.dispatcher photo_handler = MessageHandler(Filters.photo, handle_photo) dispatcher.add_handler(photo_handler) updater.start_polling() updater.idle() 

Sudah bukan pengembang front-end


Ketika gambar memasuki server Telegram, gambar itu secara otomatis disesuaikan ke beberapa ukuran yang telah ditentukan. Bot, pada gilirannya, dapat mengunduh gambar dalam berbagai ukuran dari yang ada di daftar message.photo diurutkan dalam urutan menaik. Opsi termudah: ambil gambar terbesar. Tentu saja, di lingkungan toko bahan makanan, Anda perlu memikirkan tentang beban jaringan dan waktu muat serta memilih gambar dengan ukuran minimum yang sesuai. Tambahkan kode unduhan gambar ke bagian atas fungsi handle_photo .


 import io 

 message = update.message photo = message.photo[~0] with io.BytesIO() as fd: file_id = bot.get_file(photo.file_id) file_id.download(out=fd) fd.seek(0) 

Gambar telah diunduh dan ada di memori. Untuk menafsirkannya dan menyajikannya dalam bentuk matriks intensitas piksel, kami menggunakan perpustakaan Pillow dan numpy .


 from PIL import Image import numpy as np 

Kode berikut perlu ditambahkan ke blok with .


 image = Image.open(fd) image.load() image = np.asarray(image) 

Waktunya telah tiba dlib. Di luar fungsinya, buat pendeteksi wajah.


 import dlib 

 face_detector = dlib.get_frontal_face_detector() 

Dan di dalam fungsi kita menggunakannya.


 face_detects = face_detector(image, 1) 

Parameter kedua dari fungsi berarti perbesaran yang harus diterapkan sebelum mencoba untuk mendeteksi wajah. Semakin besar, semakin kecil dan kompleks wajah detektor akan dapat dideteksi, tetapi semakin lama akan berfungsi. face_detects - daftar wajah yang diurutkan dalam urutan menurun dari kepercayaan detektor bahwa wajah ada di depannya. Dalam aplikasi nyata, Anda kemungkinan besar akan ingin menerapkan beberapa logika memilih orang utama, dan dalam studi kasus kami akan membatasi diri untuk memilih yang pertama.


 if not face_detects: bot.send_message(chat_id=update.message.chat_id, text='no faces') face = face_detects[0] 

Kami melanjutkan ke tahap berikutnya - mencari poin-poin penting. Unduh model yang terlatih dan pindahkan muatannya ke luar fungsi.


 shape_predictor = dlib.shape_predictor('path/to/shape_predictor_5_face_landmarks.dat') 

Temukan poin kunci.


 landmarks = shape_predictor(image, face) 

Satu-satunya yang tersisa adalah kecil: untuk meluruskan wajah, mengendarainya melalui ResNet dan mendapatkan embedding 128 dimensi. Untungnya, dlib memungkinkan Anda melakukan semua ini dengan satu panggilan. Anda hanya perlu mengunduh model pra-terlatih .


 face_recognition_model = dlib.face_recognition_model_v1('path/to/dlib_face_recognition_resnet_model_v1.dat') 

 embedding = face_recognition_model.compute_face_descriptor(image, landmarks) embedding = np.asarray(embedding) 

Lihat saja betapa indahnya waktu kita hidup. Seluruh kerumitan jaringan saraf convolutional, metode vektor dukungan, dan transformasi affine yang diterapkan untuk pengenalan wajah dirangkum dalam tiga panggilan perpustakaan.


Karena kita belum tahu bagaimana melakukan sesuatu yang berarti, mari kembali kepada pengguna nilai rata-rata penanamannya, dikalikan dengan seribu.


 bot.send_message( chat_id=update.message.chat_id, text=f'yours embedding mean: {embedding.mean() * 1e3:.2f}' ) 

Saya tidak tahu apa yang harus saya lakukan


Agar bot kami dapat menentukan selebriti mana yang disukai pengguna, kami sekarang perlu menemukan setidaknya satu foto dari setiap selebriti, membuat embedding di atasnya dan menyimpannya di suatu tempat. Kami hanya akan menambahkan 10 selebritas ke bot pelatihan kami, menemukan foto-foto mereka dengan tangan dan meletakkannya di direktori photos . Seperti inilah seharusnya tampilannya:


Dengar, aku tidak punya cukup uang untuk MacBook.


Jika Anda ingin memiliki satu juta selebritas dalam basis data, semuanya akan terlihat sama persis, hanya ada lebih banyak file dan tidak mungkin Anda bisa mencarinya dengan tangan Anda. Sekarang mari kita buat utilitas build_embeddings.py menggunakan panggilan dlib sudah kita ketahui dan menyimpan embeddings selebriti beserta nama mereka dalam format biner.


 import os import dlib import numpy as np import pickle from PIL import Image face_detector = dlib.get_frontal_face_detector() shape_predictor = dlib.shape_predictor('assets/shape_predictor_5_face_landmarks.dat') face_recognition_model = dlib.face_recognition_model_v1('assets/dlib_face_recognition_resnet_model_v1.dat') fs = os.listdir('photos') es = [] for f in fs: print(f) image = np.asarray(Image.open(os.path.join('photos', f))) face_detects = face_detector(image, 1) face = face_detects[0] landmarks = shape_predictor(image, face) embedding = face_recognition_model.compute_face_descriptor(image, landmarks, num_jitters=10) embedding = np.asarray(embedding) name, _ = os.path.splitext(f) es.append((name, embedding)) with open('assets/embeddings.pickle', 'wb') as f: pickle.dump(es, f) 

Tambahkan pemuatan sematan ke kode bot kami.


 import pickle 

 with open('assets/embeddings.pickle', 'rb') as f: star_embeddings = pickle.load(f) 

Dan dengan pencarian lengkap kami akan menemukan siapa pengguna kami yang sama.


 ds = [] for name, emb in star_embeddings: distance = np.linalg.norm(embedding - emb) ds.append((name, distance)) best_match, best_distance = min(ds, key=itemgetter(1)) bot.send_message( chat_id=update.message.chat_id, text=f'your look exactly like *{best_match}*', parse_mode='Markdown' ) 

Harap dicatat bahwa kami menggunakan jarak Euclidean sebagai jarak, karena jaringan di dlib dilatih dengan tepat dengan bantuannya.


Saya kecewa dengan artikel itu


Itu saja, selamat! Kami telah membuat bot sederhana yang dapat menentukan selebriti yang disukai pengguna. Tetap menemukan lebih banyak foto, menambahkan branding, skalabilitas, sedikit logging dan semuanya dapat dirilis dalam produksi. Semua topik ini terlalu tebal untuk dibicarakan secara rinci dengan daftar kode besar, jadi saya hanya akan menguraikan poin utama dalam format tanya jawab di bagian berikutnya.


Kode bot pelatihan lengkap tersedia di GitHub .


Kami berbicara tentang bot kami


Berapa banyak selebriti yang Anda miliki di basis data Anda? Di mana Anda menemukannya?


Keputusan paling logis saat membuat bot sepertinya mengambil data selebritas dari basis konten internal kami. Dia dalam format grafik menyimpan film dan semua entitas yang terkait dengan film, termasuk aktor dan sutradara. Untuk setiap orang, kami tahu namanya, login dan kata sandi dari iCloud, film terkait dan alias, yang dapat digunakan untuk menghasilkan tautan ke situs. Setelah membersihkan dan mengekstraksi hanya informasi yang diperlukan, file json tetap sebagai berikut:


 [ { "name": " ", "alias": "tilda-swinton", "role": "actor", "n_movies": 14 }, { "name": " ", "alias": "michael-shannon", "role": "actor", "n_movies": 22 }, ... ] 

Ada 22.000 entri seperti itu di katalog. Ngomong-ngomong, bukan katalog, tapi katalog.


Di mana menemukan foto untuk semua orang ini?


Di masa-masa berbahaya kita hidup


Ya, Anda tahu, di sana-sini . Misalnya, ada perpustakaan yang luar biasa yang memungkinkan Anda untuk mengunggah hasil permintaan gambar dari Google. 22 ribu orang - tidak banyak, menggunakan 56 aliran kami berhasil mengunduh foto untuk mereka dalam waktu kurang dari satu jam.


Di antara foto yang diunduh, Anda harus membuang foto yang rusak, berisik, dalam format yang salah. Kemudian tinggalkan hanya yang ada wajah dan yang memenuhi kondisi tertentu: jarak minimum antara mata, kemiringan kepala. Semua ini memberi kita 12.000 foto.


Dari 12 ribu selebritas, pengguna hanya menemukan 2 saat ini, yaitu ada sekitar 8 ribu selebritas yang masih belum seperti orang lain. Jangan biarkan begitu saja! Buka telegram dan temukan semuanya.


Bagaimana cara menentukan persentase kesamaan untuk jarak Euclidean?


Pertanyaan bagus! Memang, jarak Euclidean, berbeda dengan cosinus, tidak dibatasi di atas. Oleh karena itu, muncul pertanyaan yang masuk akal, bagaimana menunjukkan kepada pengguna sesuatu yang lebih bermakna daripada "Selamat, jarak antara penyematan Anda dan penyematan Angelina Jolie adalah 0,27635462738"? Salah satu anggota tim kami mengusulkan solusi sederhana dan cerdik berikut ini. Jika Anda membangun distribusi jarak antara embed, itu akan menjadi normal. Jadi, baginya, Anda dapat menghitung rata-rata dan standar deviasi, dan kemudian untuk setiap pengguna, menurut parameter ini, pertimbangkan berapa persen orang yang kurang seperti selebritas mereka daripada dirinya . Ini sama dengan mengintegrasikan fungsi kerapatan probabilitas dari d hingga plus tak terhingga, di mana d adalah jarak antara pengguna dan demonstrasi selebriti.


Ini bukan seaborn


Berikut adalah fungsi persis yang kami gunakan:


 def _transform_dist_to_sim(self, dist): p = 0.5 * (1 + erf((dist - self._dist_mean) / (self._dist_std * 1.4142135623730951))) return max(min(1 - p, 1.0), self._min_similarity) 

Apakah benar-benar perlu untuk mengulangi daftar semua serikat pekerja untuk menemukan kecocokan?


Tentu saja tidak, ini tidak optimal dan membutuhkan banyak waktu. Cara termudah untuk mengoptimalkan perhitungan adalah dengan menggunakan operasi matriks. Alih-alih mengurangi vektor dari satu sama lain, Anda dapat menyusun matriks dari mereka dan mengurangi vektor dari matriks, dan kemudian menghitung norma L2 dalam baris.


 scores = np.linalg.norm(emb - embeddings, axis=1) best_idx = scores.argmax() 

Ini sudah memberi peningkatan besar dalam produktivitas, tetapi, ternyata, Anda bahkan bisa lebih cepat. Pencarian dapat dipercepat secara signifikan dengan kehilangan sedikit dalam akurasinya menggunakan pustaka nmslib . Ia menggunakan metode HNSW untuk memperkirakan pencarian k tetangga terdekat. Untuk semua vektor yang tersedia, indeks yang disebut harus dibangun, di mana kemudian pencarian akan dilakukan. Anda dapat membuat dan menyimpan indeks untuk jarak Euclidean sebagai berikut:


 import nmslib index = nmslib.init(method='hnsw', space='l2', data_type=nmslib.DataType.DENSE_VECTOR) for idx, emb in enumerate(embeddings): index.addDataPoint(idx, emb) index_time_params = { 'indexThreadQty': 4, 'skip_optimized_index': 0, 'post': 2, 'delaunay_type': 1, 'M': 100, 'efConstruction': 2000 } index.createIndex(index_time_params, print_progress=True) index.saveIndex('./assets/embeddings.bin') 

Parameter M dan efConstruction dijelaskan secara rinci dalam dokumentasi dan dipilih secara eksperimental berdasarkan akurasi yang diperlukan, waktu konstruksi indeks dan kecepatan pencarian. Sebelum menggunakan indeks, Anda harus mengunduh:


 index = nmslib.init(method='hnsw', space='l2', data_type=nmslib.DataType.DENSE_VECTOR) index.loadIndex('./assets/embeddings.bin') query_time_params = {'efSearch': 400} index.setQueryTimeParams(query_time_params) 

Parameter efSearch memengaruhi keakuratan dan kecepatan kueri dan mungkin tidak cocok dengan efConstruction . Sekarang Anda dapat membuat permintaan.


 ids, dists = index.knnQuery(embedding, k=1) best_dx = ids[0] best_dist = dists[0] 

Dalam kasus kami, nmslib adalah 20 kali lebih cepat dari versi linier vektor, dan satu permintaan diproses rata-rata 0.005 detik.


Bagaimana cara membuat bot saya siap untuk produksi?


1. Asynchrony

Pertama, Anda perlu membuat fungsi handle_photo asinkron. Seperti yang sudah saya katakan, python-telegram-bot menawarkan multithreading untuk ini dan mengimplementasikan dekorator yang nyaman.


 from telegram.ext.dispatcher import run_async @run_async def handle_photo(bot, update): ... 

Sekarang framework itu sendiri akan meluncurkan handler Anda di utas terpisah di kumpulannya. Ukuran kumpulan diatur saat membuat Updater . "Tapi dengan python tidak ada multithreading!" yang paling tidak sabar dari Anda sudah berseru. Dan ini tidak sepenuhnya benar. Karena GIL, kode Python biasa benar-benar tidak dapat dieksekusi secara paralel, tetapi GIL dirilis untuk menunggu semua operasi IO, dan itu juga dapat dirilis oleh perpustakaan yang menggunakan ekstensi C.


Sekarang menganalisis fungsi handle_photo kami: itu hanya terdiri dari menunggu operasi IO (mengunggah foto, mengirim respons, membaca foto dari disk, dll.) Dan memanggil fungsi dari perpustakaan numpy , nmslib dan Pillow .


Saya tidak menyebutkan dlib karena suatu alasan. Perpustakaan yang memanggil kode asli tidak diperlukan untuk merilis GIL dan dlib hak ini. Dia tidak membutuhkan kunci ini, dia hanya tidak membiarkannya pergi. Penulis mengatakan bahwa ia akan dengan senang hati menerima Permintaan Tarik yang sesuai, tetapi saya terlalu malas.


2. Multiprocessing

Cara termudah untuk berurusan dengan dlib adalah merangkum model dalam entitas terpisah dan menjalankannya dalam proses terpisah. Dan lebih baik di pool proses.


 def _worker_initialize(config): global model model = Model(config) model.load_state() def _worker_do(image): return model.process_image(image) pool = multiprocessing.Pool(8, initializer=_worker_initialize, initargs=(config,)) 

 result = pool.apply(_worker_do, (image,)) 

3. Besi

Jika bot Anda perlu terus-menerus membaca foto dari disk, pastikan disk tersebut adalah SSD. Atau bahkan memasangnya ke RAM. Ping ke server telegram dan kualitas saluran juga penting.


4. Kontrol banjir

Telegram tidak mengizinkan bot mengirim lebih dari 30 pesan per detik. Jika bot Anda populer dan banyak orang menggunakannya pada saat yang bersamaan, maka sangat mudah untuk mendapatkan larangan selama beberapa detik, yang akan berubah menjadi kekecewaan dari harapan banyak pengguna. Untuk mengatasi masalah ini, python-telegram-bot menawarkan kepada kami antrian yang tidak dapat mengirim lebih dari batas pesan yang ditentukan per detik, mempertahankan interval yang sama antara pengiriman.


 from telegram.ext.messagequeue import MessageQueue 

Untuk menggunakannya, Anda perlu mendefinisikan bot Anda sendiri dan menggantinya saat membuat Updater .


 from telegram.utils.promise import Promise class MQBot(Bot): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._message_queue = MessageQueue( all_burst_limit=30, all_time_limit_ms=1000 ) def __del__(self): try: self._message_queue.stop() finally: super().__del__() def send_message(self, *args, **kwargs): is_group = kwargs.get('chat_id', 0) >= 0 return self._message_queue(Promise(super().send_message, args, kwargs), is_group) 

 bot = MQBot(token=TOKEN) updater = Updater(bot=bot) 

5. Kait web

Dalam lingkungan produk, Web Hooks harus selalu digunakan daripada Long Polling sebagai cara untuk menerima pembaruan dari server Telegram. Tentang apa semua ini dan bagaimana menggunakannya dapat dibaca di sini .


6. Trivia

json . , ultrajson .


IO-: , , . , .


6.

, . , , , . , .


, , BI-tool Splunk .


Papan Iklan (harap berikan kami lisensi)


, . , .


, . , : @OkkoFaceBot .


, . , .

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


All Articles