π€ ΠΠ΅Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΡ: ΠΊΠ°ΠΊ OpenAI ΠΈ FastAPI ΡΠΏΠ°ΡΡΡ Habr ΠΎΡ Π΄ΡΠ±Π»Π΅ΠΈΜ
Π ΡΡΠ°ΡΡΠ΅ ΡΠ°ΡΡΠΊΠ°Π·ΡΠ²Π°Π΅ΡΡΡ ΠΎ ΡΠΎΠΌ, ΠΊΠ°ΠΊ ΠΌΠΎΠ΄Π΅Π»ΠΈ OpenAI ΠΏΠΎΠΌΠΎΠ³Π°ΡΡ Π² Π·Π°Π΄Π°ΡΠ΅ Π΄Π΅Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ ΡΠ΅ΠΊΡΡΠΎΠ² ΠΈ similarity search. Π Π°ΡΡΠΌΠΎΡΡΠ΅Π½Ρ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Ρ ΠΊ ΡΠ΅ΡΠ΅Π½ΠΈΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ: ΠΎΡ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΠΈ MinHash Π΄ΠΎ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Π½Π° ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³Π°Ρ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ΅Π½Π½ΡΡ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ. Π ΡΡΠ°ΡΡΠ΅ ΡΠ°ΠΊΠΆΠ΅ ΠΎΠΏΠΈΡΠ°Π½ ΠΏΡΠΈΠΌΠ΅Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠ° Π½Π° FastAPI Π΄Π»Ρ ΠΏΠΎΠΈΡΠΊΠ° Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΎΠ² ΠΏΠΎΡΡΠΎΠ².

OpenAI ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅Ρ Π½Π°Π²ΠΎΠ΄ΠΈΡΡ ΡΡΠ΅ΡΡ. ΠΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ ChatGPT ΠΏΠ΅ΡΠ΅Π²Π°Π»ΠΈΠ»ΠΎ Π·Π° 100 ΠΌΠΈΠ»Π»ΠΈΠΎΠ½ΠΎΠ², Π½ΠΎ Ρ Π°ΠΉΠΏ Π΄Π°ΠΆΠ΅ ΠΈ Π½Π΅ Π΄ΡΠΌΠ°Π΅Ρ ΡΡΠΈΡ Π°ΡΡ β ΠΊΠ°ΠΆΠ΅ΡΡΡ, Π΄Π°ΠΆΠ΅ Π±Π°Π±ΡΡΠΊΠΈ Ρ ΠΏΠΎΠ΄ΡΠ΅Π·Π΄Π° ΡΠ»ΡΡ ΠΠ ΡΠ²ΠΎΠΈ Π²ΠΎΠΏΡΠΎΡΡ ΠΏΡΠΎ ΠΏΠΎΠ²ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΠ΅Π½ΡΠΈΠΈ. ΠΠΎ ΡΠ΅Π³ΠΎΠ΄Π½Ρ ΠΏΠΎΠΉΠ΄Π΅Ρ ΡΠ΅ΡΡ Π½Π΅ ΠΎ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΡ Π²ΠΎΠΏΡΠΎΡΠ°Ρ , Π° ΠΎ ΡΠΎΠΌ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΌΠΎΠ΄Π΅Π»ΠΈ OpenAI Π΄Π»Ρ Π·Π°Π΄Π°ΡΠΈ Π΄Π΅Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ.
ΠΠ΅Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΡ (Deduplication), similarity search ΡΠ²Π»ΡΡΡΡΡ Π²ΠΎΡΡΡΠ΅Π±ΠΎΠ²Π°Π½Π½ΡΠΌΠΈ Π΄ΠΎΠΌΠ΅Π½Π°ΠΌΠΈ ΠΌΠ°ΡΠΈΠ½Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ. Π ΠΊΠΎΠΌΠ°Π½Π΄Π΅ Π½ΠΎΠ²ΠΎΡΡΠ½ΠΎΠ³ΠΎ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³Π° Π‘Π±Π΅ΡΠ° Ρ ΡΠ΅ΡΠ°Π» ΡΡΠΈ Π·Π°Π΄Π°ΡΠΈ Π΄Π»Ρ ΠΏΠΎΡΠΎΠΊΠ° Π½ΠΎΠ²ΠΎΡΡΠ΅ΠΉ. Π‘Π΅ΠΉΡΠ°Ρ Ρ ΡΠ°Π±ΠΎΡΠ°Ρ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π΅ Data Science Π‘Π°ΠΌΠΎΠ»Π΅ΡΠ° (ΡΡΠΎ ΡΠ°ΠΊΠΎΠΉ Π·Π°ΡΡΡΠΎΠΉΡΠΈΠΊ Π·Π΄ΠΎΡΠΎΠ²ΠΎΠ³ΠΎ ΡΠ΅Π»ΠΎΠ²Π΅ΠΊΠ°) ΠΈ ΠΎΠΊΠ°Π·Π°Π»ΠΎΡΡ, ΡΡΠΎ Π·Π΄Π΅ΡΡ ΡΠΎΡΠ΅ΠΊ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π΄Π»Ρ NLP Π΄Π°ΠΆΠ΅ Π±ΠΎΠ»ΡΡΠ΅ ΡΠ΅ΠΌ Π² Π±Π°Π½ΠΊΠ΅, Π² ΡΠΎΠΌ ΡΠΈΡΠ»Π΅ ΠΈ Π΄Π»Ρ ΠΌΡΡΡΠΈΠ½Π³Π°.
Π ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ Ρ ΠΏΠΎΡΡΠ°ΡΠ°ΡΡΡ ΡΠ°ΡΡΠΊΠ°Π·Π°ΡΡ ΠΎ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Π°Ρ ΠΊ Π΄Π΅Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ ΡΠ΅ΠΊΡΡΠΎΠ², ΠΊΠ°ΠΊ Π² ΡΡΠΎΠΌ ΠΏΠΎΠΌΠΎΠ³Π°ΡΡ ΠΌΠΎΠ΄Π΅Π»ΠΈ OpenAI, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΏΡΠΈΠ²Π΅Π΄Ρ ΠΏΡΠΈΠΌΠ΅Ρ Π±ΠΎΠ΅Π²ΠΎΠ³ΠΎ ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠ° Π½Π° FastAPI, ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅Ρ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡ Π½Π΅ ΠΎΡΠ΅Π½Ρ ΡΠ²Π΅ΠΆΠΈΠ΅ ΠΏΠΎ ΡΠΎΠ΄Π΅ΡΠΆΠ°Π½ΠΈΡ ΠΏΠΎΡΡΡ Π½Π° Π₯Π°Π±ΡΠ΅. ΠΠ½Π΅ ΠΈΠΌΠΏΠΎΠ½ΠΈΡΡΠ΅Ρ ΠΈΡΡΠΎΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΏΠΎΠ΄Ρ ΠΎΠ΄, ΠΏΠΎΡΡΠΎΠΌΡ Ρ ΡΠ½Π°ΡΠ°Π»Π° ΡΠ°ΡΡΠΊΠ°ΠΆΡ ΠΏΡΠΎ ΡΠ΅ΠΌΠ½ΠΎΠ΅ ΠΏΡΠΎΡΠ»ΠΎΠ΅, ΠΈ ΠΏΠΎΡΡΠ΅ΠΏΠ΅Π½Π½ΠΎ Π΄ΠΎΠ±Π΅ΡΠ΅ΠΌΡΡ Π΄ΠΎ Π·ΠΎΠ»ΠΎΡΠΎΠ³ΠΎ Π²Π΅ΠΊΠ° ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΡΠ·ΡΠΊΠΎΠ²ΡΡ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ.
Π‘ΡΠ°ΡΠΎΠ΅, Π΄ΠΎΠ±ΡΠΎΠ΅, Π²Π΅ΡΠ½ΠΎΠ΅
ΠΠ°Π²Π°ΠΉΡΠ΅ ΡΠ½Π°ΡΠ°Π»Π° ΡΠ°Π·Π±Π΅ΡΠ΅ΠΌΡΡ, ΠΊΠ°ΠΊ Π²ΠΎΠΎΠ±ΡΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡΠ΅Π½ΠΈΡΡ, ΡΡΠΎ Π΄Π²Π° ΡΠ΅ΠΊΡΡΠ° ΡΠ²Π»ΡΡΡΡΡ ΠΏΠΎΡ ΠΎΠΆΠΈΠΌΠΈ. ΠΡ, ΡΠ°ΠΌΠΎΠ΅ ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΠΎΠ΅ β ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ Π½Π° ΠΎΠ±ΡΠΈΠ΅ ΡΠ»ΠΎΠ²Π°, ΡΠ΅ΠΌ ΠΈΡ Π±ΠΎΠ»ΡΡΠ΅, ΡΠ΅ΠΌ Π±Π»ΠΈΠΆΠ΅ Π΄Π²Π° ΡΠ΅ΠΊΡΡΠ°. Π‘ΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ ΡΡΡ ΠΈΠ΄Π΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΠΌΠ΅ΡΠ° ΠΠ°ΠΊΠΊΠ°ΡΠ°.

ΠΠ΄Π½Π°ΠΊΠΎ Π² ΡΠ°ΠΊΠΎΠΌ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Π΅ Π΅ΡΡΡ ΡΠ²ΠΎΠΈ ΠΌΠΈΠ½ΡΡΡ. ΠΠΎ-ΠΏΠ΅ΡΠ²ΡΡ , ΠΎΠ½ Π½Π΅ ΠΎΠΏΡΠΈΠΌΠ°Π»Π΅Π½ Ρ Π²ΡΡΠΈΡΠ»ΠΈΡΠ΅Π»ΡΠ½ΠΎΠΉ ΡΠΎΡΠΊΠΈ Π·ΡΠ΅Π½ΠΈΡ. ΠΡΠ»ΠΈ Ρ Π²Π°Ρ Π±ΠΎΠ»ΡΡΠΎΠΉ ΠΊΠΎΡΠΏΡΡ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΎΠ², Π° Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΡ ΡΠΎΡΡΠΎΡΡ ΠΈΠ· ΡΡΡΡΡ ΡΠ»ΠΎΠ², ΡΠΎ ΠΊΠ²Π°Π΄ΡΠ°ΡΠΈΡΠ½Π°Ρ ΡΠ»ΠΎΠΆΠ½ΠΎΡΡΡ ΠΌΠΎΠΆΠ΅Ρ ΠΏΠΎΡ ΠΎΡΠΎΠ½ΠΈΡΡ Π²Π°ΡΠΈ ΡΠ΅ΡΡΡΡΡ. ΠΠΎ-Π²ΡΠΎΡΡΡ , ΠΎΡΡΡΡΡΡΠ²ΠΈΠ΅ ΠΎΠ±ΡΠΈΡ ΡΠ»ΠΎΠ² Π΅ΡΠ΅ Π½Π΅ ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ ΡΠΌΡΡΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΎΡΠ»ΠΈΡΠΈΡ.
doc Π = 'Π¦Π΅Π½Π° Π½Π΅ΡΡΠΈ Π±ΡΠ΅Π½Π΄ Π²ΡΡΠΎΡΠ»Π° ΠΈΠ·-Π·Π° ΠΎΠΏΠ°ΡΠ΅Π½ΠΈΠΉ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ ΡΡΠΎΠ»ΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρ Π‘Π¨Π ΠΈ ΠΡΠ°Π½ΠΎΠΌ' doc B = 'Π‘ΡΠΎΠΈΠΌΠΎΡΡΡ ΡΠ΅Π²Π΅ΡΠΎΠΌΠΎΡΡΠΊΠΎΠΉ Π½Π΅ΡΡΠΈ ΡΠ°ΡΡΠ΅Ρ Π½Π° ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ ΠΎΠ±ΠΎΡΡΡΠ΅Π½ΠΈΡ ΠΊΠΎΠ½ΡΠ»ΠΈΠΊΡΠ° ΠΠ΅Π½ΡΠ°Π³ΠΎΠ½Π° ΠΈ ΠΡΠ°Π½Π°β Π Π΄Π°Π½Π½ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΠΌΠ΅ΡΠ° ΠΠ°ΠΊΠΊΠ°ΡΠ° Π±ΡΠ΄Π΅Ρ ΠΎΠΊΠΎΠ»ΠΎ 0.1
ΠΠ±ΠΎΠΉΡΠΈ ΠΏΠ΅ΡΠ²ΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ ΡΠ²ΡΠ·ΠΊΠ° minhash + lsh. Minhash-ΠΏΠΎΠ΄Ρ ΠΎΠ΄ Π·Π°ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ Π² ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎΠΉ ΠΏΠ΅ΡΠ΅ΡΡΠ°Π½ΠΎΠ²ΠΊΠ΅ ΡΠ»ΠΎΠ² (Π½Π° ΡΠ°ΠΌΠΎΠΌ Π΄Π΅Π»Π΅ ΠΊΡΡΠΎΡΠΊΠΎΠ² ΡΠ»ΠΎΠ² β ΡΠΈΠ½Π³Π»ΠΎΠ²) ΠΈ Ρ Π΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠΈ. Π’ΠΎ Π΅ΡΡΡ ΡΠ΅ΠΊΡΡ Π»ΡΠ±ΠΎΠΉ Π΄Π»ΠΈΠ½Ρ ΠΏΡΠ΅Π²ΡΠ°ΡΠ°Π΅ΡΡΡ Π² Π½Π°Π±ΠΎΡ ΡΠ°ΠΊΠΈΡ Ρ Π΅ΡΠ΅ΠΉ (ΡΠΈΠ³Π½Π°ΡΡΡΠ°): Π±ΡΠ»ΠΎ 10 ΡΡΡ. ΡΠ»ΠΎΠ², Π° Π»Π΅Π³ΠΊΠΈΠΌ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ΠΌ ΡΡΠΊΠΈ Ρ Π΅Ρ-ΡΡΠ½ΠΊΡΠΈΠΈ Π²ΡΠ΅ ΠΏΡΠ΅Π²ΡΠ°ΡΠΈΡΡΡ Π² ΡΠΈΠ³Π½Π°ΡΡΡΡ Π΄Π»ΠΈΠ½Ρ 200. ΠΡ Π° Π΄Π°Π»ΡΡΠ΅ Π²Ρ ΡΠΆΠ΅ ΡΡΠ°Π²Π½ΠΈΠ²Π°Π΅ΡΠ΅ ΡΠ°ΠΊΠΈΠ΅ ΡΠΈΠ³Π½Π°ΡΡΡΡ. ΠΡΠΎ ΠΏΠΎΠΊΠ° Π½Π΅ ΠΈΠ·Π±Π°Π²Π»ΡΠ΅Ρ ΠΎΡ ΠΊΠ²Π°Π΄ΡΠ°ΡΠΈΡΠ½ΠΎΠΉ ΡΠ»ΠΎΠΆΠ½ΠΎΡΡΠΈ, Π½ΠΎ Π·Π°ΡΠΎ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡΡΠ΅Π΅ ΠΏΡΠΎΡΡΠΈΡΡΠ²Π°ΡΡ Π±Π»ΠΈΠ·ΠΎΡΡΡ. Π Π²ΠΎΡ LSH (local sensitive hashing) ΠΊΠ°ΠΊ ΡΠ°Π· ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ ΠΈΡΠΊΠ°ΡΡ Π΄ΡΠ±Π»ΠΈ Π½Π΅ ΠΏΠΎ Π²ΡΠ΅ΠΌΡ ΠΊΠΎΡΠΏΡΡΡ, Π° ΠΏΠΎ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½Π½ΠΎΠΌΡ ΠΏΠΎΠ΄ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²Ρ. Π ΠΏΠΈΡΠΎΠ½Π΅ Π΅ΡΡΡ ΡΠΆΠ΅ Π³ΠΎΡΠΎΠ²Π°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΡΠΎΠ³ΠΎ ΠΌΠ΅ΡΠΎΠ΄Π° Π² Π²ΠΈΠ΄Π΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ datasketch. Π§ΡΠΎ ΠΊΠ°ΡΠ°Π΅ΡΡΡ Π²ΡΠΎΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ, ΡΠΎβ¦ ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΡΠΈΡΠ°ΡΡ Π΄Π°Π»ΡΡΠ΅.
Π Π°ΡΡΠΊΠ°ΠΆΠΈ ΠΌΠ½Π΅ ΠΏΡΠΎ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΈ
ΠΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΊΡΠ°Π΅ΡΠ³ΠΎΠ»ΡΠ½ΡΠΌ ΠΊΠ°ΠΌΠ½Π΅ΠΌ Π²ΡΠ΅Π³ΠΎ NLP, Π΄Π°, ΠΏΡΡΠΌΠΎ ΠΊΠ°ΠΊ ΡΠ΅ΡΠ²Π΅ΡΡΡΡΡΠ½ΡΠΎΠ²ΡΠΉ ΡΠΈΠ·Π±ΡΡΠ³Π΅Ρ Π² ΠΏΠΈΡΠ°Π½ΠΈΠΈ. ΠΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ β ΡΡΠΎ Π²Π΅ΠΊΡΠΎΡΠ½ΠΎΠ΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊΠ°ΠΊΠΎΠΉ-ΡΠΎ ΡΡΡΠ½ΠΎΡΡΠΈ: ΡΠ»ΠΎΠ²Π°, ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΡ, Π°Π±Π·Π°ΡΠ° ΠΈ Π΄Π°ΠΆΠ΅ Π²ΡΠ΅Π³ΠΎ ΡΠ΅ΠΊΡΡΠ°. ΠΠ° ΡΠ°ΠΌΠΎΠΌ Π΄Π΅Π»Π΅ Π²Π΅ΠΊΡΠΎΡΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΌΠΎΠΆΠ½ΠΎ Π²ΡΠ΅ ΡΡΠΎ ΡΠ³ΠΎΠ΄Π½ΠΎ. Π‘ΠΈΠ³Π½Π°ΡΡΡΠ° Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ° ΠΈΠ· ΡΠ΅ΠΊΡΡΠ° Π²ΡΡΠ΅ ΡΠΎΠΆΠ΅, ΠΏΠΎ ΡΡΡΠΈ, ΡΠ²Π»ΡΠ΅ΡΡΡ Π²Π΅ΠΊΡΠΎΡΠΎΠΌ, Π½ΠΎ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΎΠΌ Π»ΡΡΡΠ΅ ΡΡΠΎ Π½Π΅ Π½Π°Π·ΡΠ²Π°ΡΡ, Ρ. ΠΊ. ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ ΡΡΠΎ Β«Ρ ΠΎΡΠΎΡΠΈΠΉΒ» Π²Π΅ΠΊΡΠΎΡ, Π΄Π»Ρ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ (ΡΡΠΌΠΌΠ°, ΡΠ°Π·Π½ΠΎΡΡΡ, ΡΠΊΠ°Π»ΡΡΠ½ΠΎΠ΅ ΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅) ΡΠ²Π»ΡΡΡΡΡ ΠΎΡΠΌΡΡΠ»Π΅Π½Π½ΡΠΌΠΈ. ΠΠ°ΡΡΠΈΠ½ΠΊΠ° Π½ΠΈΠΆΠ΅ ΡΠΆΠ΅ Π½Π°Π±ΠΈΠ»Π° ΠΎΡΠΊΠΎΠΌΠΈΠ½Ρ, Π½ΠΎ ΠΎΠ½Π° Ρ ΠΎΡΠΎΡΠΎ ΠΈΠ»Π»ΡΡΡΡΠΈΡΡΠ΅Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π½Π°Π΄ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³Π°ΠΌΠΈ. ΠΠ°ΡΡΠΈΠ½ΠΊΠ° ΠΈΠ»Π»ΡΡΡΡΠΈΡΡΠ΅Ρ ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΈΠΉ word2vec ΠΈΠ· Π΄Π°Π»Π΅ΠΊΠΎΠ³ΠΎ 2013 Π³ΠΎΠ΄Π°.
Π’Π΅ΠΊΡΡΠΈΠ΅ Π²Π΅ΠΊΡΠΎΡΠ½ΡΠ΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΠΆΠ΅ Π½Π°ΡΡΠΎΠ»ΡΠΊΠΎ ΠΊΡΡΡΡ, ΡΡΠΎ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ· Π²Π΅ΠΊΡΠΎΡΠ° ΡΡΡΠ±ΠΎΠ»ΠΊΠΈ Ρ ΠΊΠΎΡΠΎΡΠΊΠΈΠΌΠΈ ΡΡΠΊΠ°Π²Π°ΠΌΠΈ Π²ΡΡΠ΅ΡΡΡ Π²Π΅ΠΊΡΠΎΡ ΠΊΠΎΡΠΎΡΠΊΠΎΠ³ΠΎ ΡΡΠΊΠ°Π²Π°, ΠΏΠΎΡΠΎΠΌ ΠΏΡΠΈΠ±Π°Π²ΠΈΡΡ Π²Π΅ΠΊΡΠΎΡ Π΄Π»ΠΈΠ½Π½ΠΎΠ³ΠΎ ΡΡΠΊΠ°Π²Π° ΠΈ Π½Π°ΠΊΠΎΠ½Π΅Ρ β ΠΏΠΎΠ»ΡΡΠΈΡΡ ΠΊΠ°ΡΡΠΈΠ½ΠΊΡ ΡΡΡΠ±ΠΎΠ»ΠΊΠΈ Ρ Π΄Π»ΠΈΠ½Π½ΡΠΌΠΈ ΡΡΠΊΠ°Π²Π°ΠΌΠΈ.
Π word2vec Π²Ρ ΠΏΠΎΠ»ΡΡΠ°Π΅ΡΠ΅ Π²Π΅ΠΊΡΠΎΡΠ° Π΄Π»Ρ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ ΡΠ»ΠΎΠ², ΠΈ ΠΎΠ½ΠΈ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅. Π ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΡΡ Β«ΠΠ»ΡΡ Π΄Π»Ρ Π·Π°ΠΌΠΊΠ°Β» ΠΈ Β«ΠΡΠΈ ΠΌΠ΅ΡΠ·Π°Π²ΡΡ Π»ΠΈΡΠΈΠ»ΠΈ ΠΌΠ΅Π½Ρ ΡΠΎΠ΄ΠΎΠ²ΠΎΠ³ΠΎ Π·Π°ΠΌΠΊΠ°Β», ΡΠ»ΠΎΠ²ΠΎ Β«Π·Π°ΠΌΠΎΠΊΒ» Π±ΡΠ΄Π΅Ρ ΠΈΠΌΠ΅ΡΡ ΠΎΠ΄Π½ΠΎ ΠΈ ΡΠΎ ΠΆΠ΅ Π²Π΅ΠΊΡΠΎΡΠ½ΠΎΠ΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΠ΅.
ΠΠ»Ρ ΡΡΠ°Π²Π½Π΅Π½ΠΈΡ ΡΠ΅ΠΊΡΡΠΎΠ² ΠΈΠ· ΡΠΎΡΠ΅Π½ ΠΈ ΡΡΡΡΡ ΡΠ»ΠΎΠ² Π²Π°ΠΌ ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΠΏΡΠΈΠ΄ΡΠΌΠ°ΡΡ ΡΠΏΠΎΡΠΎΠ± ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π²Π΅ΠΊΡΠΎΡΠΎΠ² Π² ΠΎΠ΄ΠΈΠ½. ΠΠΎΠΆΠ½ΠΎ, ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ, ΠΏΡΠΎΡΡΠΎ ΡΡΡΠ΅Π΄Π½ΠΈΡΡ, Π½ΠΎ ΡΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠ΅ΡΡΡΡ ΠΎΡΠ΅Π½Ρ ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ. ΠΡΡΠ³ΠΎΠΉ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ β ΡΡΠΎ ΡΠΊΠ»Π°Π΄ΡΠ²Π°ΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ Π²Π΅ΠΊΡΠΎΡΠ° Ρ Π²Π΅ΡΠ°ΠΌΠΈ, Π° Π²Π΅ΡΠ° Π²Π·ΡΡΡ ΠΈΠ· ΠΌΠ°ΡΡΠΈΡΡ TF-IDF.
ΠΠΎΠ³Π΄Π° Ρ Π²Π°Ρ Π΅ΡΡΡ Π²Π΅ΠΊΡΠΎΡΠ° Π΄Π»Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΎΠ², ΡΠΎ Π½Π°ΠΉΡΠΈ ΠΈΡ ΠΏΠΎΡ ΠΎΠΆΠ΅ΡΡΡ ΠΌΠΎΠΆΠ½ΠΎ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΊΠΎΡΠΈΠ½ΡΡΠ½ΠΎΠΉ Π±Π»ΠΈΠ·ΠΎΡΡΠΈ. ΠΠΎΠ³Π΄Π° Π² 8 ΠΊΠ»Π°ΡΡΠ΅ Π²Ρ ΡΠ΅ΡΠ°Π»ΠΈ ΠΏΡΠΈΠΌΠ΅ΡΡ Π½Π° ΡΠΊΠ°Π»ΡΡΠ½ΠΎΠ΅ ΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅, ΡΠΎ ΠΊΠ°ΠΊ ΡΠ°Π· ΠΈ Π²ΡΡΡΠΈΡΡΠ²Π°Π»ΠΈ ΡΡΡ ΠΌΠ΅ΡΡΠΈΠΊΡ. Π§Π΅ΠΌ ΠΎΠ½Π° ΠΌΠ΅Π½ΡΡΠ΅, ΡΠ΅ΠΌ Π±ΠΎΠ»ΡΡΠ΅ ΠΏΠΎΡ ΠΎΠΆΠ΅ΡΡΡ.
ΠΠΎΡΡ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ΅ΡΠΎΠ²
ΠΠ΅ΠΊΡΠΎΡΠ° word2vec ΠΈΠ»ΠΈ ΠΈΡ Π±ΠΎΠ»Π΅Π΅ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ Π°Π½Π°Π»ΠΎΠ³ΠΈ ΡΠΈΠΏΠ° fasttext ΡΡΡΠ°Π΄Π°ΡΡ ΠΎΡΡΡΡΡΡΠ²ΠΈΠ΅ΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΡΠ°Π»ΡΠ½ΠΎΡΡΠΈ. Π’Π°ΠΊΠΆΠ΅ ΡΡΠΈ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΈ ΡΡΡΠ΅ΡΡΠ²ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π½Π° ΡΡΠΎΠ²Π½Π΅ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ ΡΠ»ΠΎΠ² (ΡΠΎΠΊΠ΅Π½ΠΎΠ²), Π° Π½Π°ΠΌ Π½ΡΠΆΠ΅Π½ ΡΠΌΠ±Π΅Π΄ΠΈΠ½Π³ Π²ΡΠ΅Π³ΠΎ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°.
ΠΠΎΡ ΡΡΡ ΠΈ ΠΏΡΠΈΡ ΠΎΠ΄ΡΡ Π½Π° ΠΏΠΎΠΌΠΎΡΡ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ΅ΡΡ. Π― Π½Π΅ Π±ΡΠ΄Ρ ΡΠ°ΡΡΠΊΠ°Π·ΡΠ²Π°ΡΡ ΠΏΡΠΎ ΠΈΡ ΠΊΡΡΡΠΎΡΡΡ ΠΈ ΠΌΠ°Π³ΠΈΡ, ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΡΡΡΡ ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡΠΎΠΌ, ΡΠ΅ΠΌ Π±ΠΎΠ»Π΅Π΅ ΡΠΈΡΠ°ΡΠ΅Π»Ρ Π½Π΅Π΄ΠΎΡΠΌΠ΅Π²Π°Π΅Ρ ΠΈ Π½Π°Π²Π΅ΡΠ½ΡΠΊΠ° ΠΆΠ΄Π΅Ρ, ΠΊΠΎΠ³Π΄Π° ΠΆΠ΅ Ρ Π²ΡΠ΅-ΡΠ°ΠΊΠΈ Π½Π°ΡΠ½Ρ ΡΠ°ΡΡΠΊΠ°Π·ΡΠ²Π°ΡΡ ΠΏΡΠΎ ChatGPT.
Π‘Π°ΠΌΠΎΠ΅ Π³Π»Π°Π²Π½ΠΎΠ΅, ΡΡΠΎ ΠΈΠ· ΡΠ½ΠΊΠΎΠ΄Π΅ΡΠ° ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ΅ΡΠ° ΠΌΠΎΠΆΠ½ΠΎ Π²ΡΡΠ°ΡΠΈΡΡ ΠΊΠ°ΠΊ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΈ ΡΠ»ΠΎΠ² (ΠΏΡΠΈ ΡΠ΅ΠΌ Π·Π΄Π΅ΡΡ ΠΎΠ½ΠΈ Π±ΡΠ΄ΡΡ ΡΠΆΠ΅ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ½ΠΎ-Π·Π°Π²ΠΈΡΠΈΠΌΡΠΌΠΈ), ΡΠ°ΠΊ ΠΈ Π²Π΅ΠΊΡΠΎΡΠ½ΠΎΠ΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΡ.
ΠΠ° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅ ΠΎΡΠ΅Π½Ρ Ρ ΠΎΡΠΎΡΠΎ ΡΠ΅Π±Ρ ΠΏΠΎΠΊΠ°Π·Π°Π» ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊ SentenceTransformers. Π‘ Π΅Π³ΠΎ ΠΏΠΎΠΌΠΎΡΡΡ ΠΌΠΎΠΆΠ½ΠΎ Π²Π΅ΠΊΡΠΎΡΠΈΠ·ΠΎΠ²Π°ΡΡ Π²Π°Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌΠΈ ΡΡΡΠΎΡΠΊΠ°ΠΌΠΈ ΠΊΠΎΠ΄Π°:
from sentence_transformers import SentenceTransformer # ΠΈΠΌΠΏΠΎΡΡΠΈΡΡΠ΅ΠΌ ΠΌΡΠ»ΡΡΠΈΡΠ·ΡΡΠ½ΡΡ ΠΌΠΎΠ΄Π΅Π»Ρ model = SentenceTransformer('distiluse-base-multilingual-cased-v2') sentence = 'ΠΠ°ΠΌΠ° ΠΌΡΠ»Π° ΡΠ°ΠΌΡ' # ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ embedding = model.encode(sentence)
SentenceTransformers ΠΎΡΠ»ΠΈΡΠ½Π°Ρ ΡΡΡΠΊΠ°, Π½ΠΎ, ΠΊΠ°ΠΊ ΠΈ Π²ΡΠ΅ Ρ ΠΎΡΠΎΡΠ΅Π΅, ΠΈΠΌΠ΅Π΅Ρ ΡΠ²ΠΎΠΈ ΠΈΠ·ΡΡΠ½Ρ. ΠΠ»Π°Π²Π½ΡΠΉ ΠΈΠ· Π½ΠΈΡ β ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠ΅ Π½Π° Π΄Π»ΠΈΠ½Ρ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ. ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΡΡΠΎ 128 ΡΠΎΠΊΠ΅Π½ΠΎΠ². ΠΠΎΠΆΠ½ΠΎ Π² ΠΏΡΠΈΠ½ΡΠΈΠΏΠ΅ ΡΠ²Π΅Π»ΠΈΡΠΈΡΡ ΡΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π²ΠΏΠ»ΠΎΡΡ Π΄ΠΎ 512, Π½ΠΎ ΡΡΠΎΠ³ΠΎ Π²ΡΠ΅ ΡΠ°Π²Π½ΠΎ Π½Π΅ Ρ Π²Π°ΡΠΈΡ, ΡΡΠΎΠ±Ρ Π²Π΅ΠΊΡΠΎΡΠΈΠ·ΠΎΠ²Π°ΡΡ Π±ΠΎΠ»ΡΡΠΎΠΉ ΡΠ΅ΠΊΡΡ. ΠΡΠΈΠΌΠ΅Ρ Π½ΠΈΠΆΠ΅ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΡΡΠΎ ΠΏΡΠΈ ΡΡΠΎΠΌ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ.
sentence_1 = 'ΠΠ°ΠΌΠ° ΠΌΡΠ»Π° ΡΠ°ΠΌΡ' * 64 sentence_2 = 'ΠΠ°ΠΌΠ° ΠΌΡΠ»Π° ΡΠ°ΠΌΡ' * 128 embeddings = model.encode([sentence_1, sentence_2]) print((embeddings[0] == embeddings[1]).all()) True
ΠΠ° ΡΡΠ΅Π½Ρ Π²ΡΡ ΠΎΠ΄ΠΈΡ OpenAI
ΠΠ°ΠΊΠΎΠ½Π΅Ρ-ΡΠΎ ΠΌΡ Π΄ΠΎΠ±ΡΠ°Π»ΠΈΡΡ Π΄ΠΎ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠ³ΠΎ Π±Π»ΡΠ΄Π°. ΠΠΎΠΌΠ°Π½Π΄Π° OpenAI ΠΏΠΎΠΌΠΈΠΌΠΎ web-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°, ΡΠ°ΠΊΠΆΠ΅ ΠΎΡΠΊΡΡΠ»Π° Π΄ΠΎΡΡΡΠΏ ΠΊ API ΡΠ²ΠΎΠΈΡ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΊ. Π ΡΠΎΠΌ ΡΠΈΡΠ»Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π΅ΠΉΡΡΠ²ΠΎΠ²Π°ΡΡ ΠΈ ΡΠ΅, ΡΡΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠ΅ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΈ. ΠΠΎΠ³ΠΈΠΊΠ° ΡΡΡ ΡΠ°ΠΊΠ°Ρ ΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ Π² SentenceTransformers, Π½ΠΎ ΠΌΡ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌ, ΡΡΠΎ ΡΠ°ΠΊΠΈΠ΅ Π²Π΅ΠΊΡΠΎΡΠ°ΠΉΠ·Π΅ΡΡ Π·Π°Π΄Π΅ΠΉΡΡΠ²ΡΠ΅Ρ Π³ΠΎΡΠ°Π·Π΄ΠΎ Π±ΠΎΠ»ΡΡΠΈΠΉ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ.
ΠΡΠ»ΠΈ ΠΎΠ±ΡΠ°ΡΠΈΡΡΡΡ ΠΊ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ, ΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ²ΠΈΠ΄Π΅ΡΡ, ΡΡΠΎ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½Π°Ρ Π΄Π»ΠΈΠ½Π° Π²Ρ ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ ΡΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΠΎ Π²ΡΡΠ΅, ΡΠ΅ΠΌ Ρ SentenceTransformers.
ΠΠΎΡΠ° ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ, ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ ΡΠΏΡΠ°Π²ΡΡΡΡ Ρ Π·Π°Π΄Π°ΡΠ΅ΠΉ ΠΏΠΎΠΈΡΠΊΠ° Π΄ΡΠ±Π»Π΅ΠΉ.
- Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ ΡΡΠΎΡ ΠΏΡΠΎΠ΅ΠΊΡ
conda create --name open_ai conda activate open_ai
- Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ
pip install openai tiktoken juputer scipy pandas fastapi uvicorn
ΠΠ»Ρ ΡΠ°Π±ΠΎΡΡ Ρ openai Π½Π°ΠΌ ΠΏΠΎΠ½Π°Π΄ΠΎΠ±ΠΈΡΡΡ ΡΠΎΠΊΠ΅Π½ Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΠΈ.
- Π Π΅Π³ΠΈΡΡΡΠΈΡΡΠ΅ΠΌΡΡ Π½Π° ΡΠ°ΠΉΡΠ΅.
- ΠΠ΅Π½Π΅ΡΠΈΡΡΠ΅ΠΌ ΠΊΠ»ΡΡ.
- Π’Π΅ΠΏΠ΅ΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡΠΎΡΠ΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ.
import tiktoken import openai from scipy.spatial.distance import cosine # Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΊΠ»ΡΡΠ° openai.api_key = 'sk-7FUL3uCuviG7F...Kc08xiSoFidB9Us' # ΠΡΠΈΠΌΠ΅ΡΡ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠΉ sentence_1 = 'ΠΌΠ°ΠΌΠ° ΠΌΡΠ»Π° ΡΠ°ΠΌΡ' sentence_2 = 'ΠΌΠ°ΠΌΠ° ΠΌΠΎΠ΅Ρ ΠΎΠΊΠ½ΠΎ' # ΠΠ΅ΡΡΠΈΡ ΠΌΠΎΠ΄Π΅Π»ΠΈ(ΡΡΠΎ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ) model = 'text-embedding-ada-002' # Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΈ embedding_1 = openai.Embedding.create( input=sentence_1, model=model) embedding_2 = openai.Embedding.create( input=sentence_2, model=model) # Π‘ΠΌΠΎΡΡΠΈΠΌ Π½Π° Π±Π»ΠΈΠ·ΠΎΡΡΡ, Π² Π΄Π°Π½Π½ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΡΡΠΈΡΠ°Π΅ΡΡΡ ΠΊΠ°ΠΊ 1-cos distance = cosine(embedding_1['data'][0]['embedding'], embedding_2['data'][0]['embedding']) print(distance) 0.11193540954120007
ΠΠΎΡΠΌΠΎΡΡΠΈΠΌ, ΠΊΠ°ΠΊ ΠΎΠ½Π° ΡΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ Ρ Π΄Π»ΠΈΠ½Π½ΡΠΌΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΡΠΌΠΈ.
sentence_1 = ''' Π ΡΠ½Π²Π°ΡΠ΅ ΠΠ΅Π½Π΅ΡΠ°Π»ΡΠ½Π°Ρ ΠΏΡΠΎΠΊΡΡΠ°ΡΡΡΠ° ΠΠ΅ΡΠΌΠ°Π½ΠΈΠΈ Π² ΡΠ°ΠΌΠΊΠ°Ρ ΡΠ°ΡΡΠ»Π΅Π΄ΠΎΠ²Π°Π½ΠΈΡ Π΄ΠΈΠ²Π΅ΡΡΠΈΠΈ Π½Π° Π³Π°Π·ΠΎΠΏΡΠΎΠ²ΠΎΠ΄Π°Ρ Β«Π‘Π΅Π²Π΅ΡΠ½ΡΠΉ ΠΏΠΎΡΠΎΠΊΒ» ΠΏΡΠΎΠ²ΠΎΠ΄ΠΈΠ»Π° ΠΎΠ±ΡΡΠΊ Π½Π° ΠΏΠΎΠ΄ΠΎΠ·ΡΠΈΡΠ΅Π»ΡΠ½ΠΎΠΌ ΡΡΠ΄Π½Π΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ·ΠΈΠ»ΠΎ Π²Π·ΡΡΠ²ΡΠ°ΡΠΊΡ, ΠΏΠΈΡΠ΅Ρ Die Welt ΡΠΎ ΡΡΡΠ»ΠΊΠΎΠΉ Π½Π° Π·Π°ΡΠ²Π»Π΅Π½ΠΈΠ΅ Π²Π΅Π΄ΠΎΠΌΡΡΠ²Π°. ΠΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΠ΅ΠΉ, ΠΊΡΠΎ ΠΈ Π·Π°ΡΠ΅ΠΌ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ·ΠΈΠ» Π΅Π΅, Π²Π΅Π΄ΠΎΠΌΡΡΠ²ΠΎ Π½Π΅ ΠΏΡΠΈΠ²ΠΎΠ΄ΠΈΡ. Π ΠΎΡΠ²Π΅Ρ Π½Π° Π·Π°ΠΏΡΠΎΡ Π’ΠΠ‘Π‘ Π² ΠΠ΅Π½ΠΏΡΠΎΠΊΡΡΠ°ΡΡΡΠ΅ ΡΠΊΠ°Π·Π°Π»ΠΈ, ΡΡΠΎ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°ΡΡ Π°Π½Π°Π»ΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ ΡΠ»ΠΈΠΊΠΈ ΠΈ Π½Π΅ ΠΌΠΎΠ³ΡΡ Π³ΠΎΠ²ΠΎΡΠΈΡΡ ΠΎ ΠΏΡΠΈΡΠ°ΡΡΠ½ΠΎΡΡΠΈ ΠΊ ΠΏΠΎΠ΄ΡΡΠ²Ρ ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π»ΠΈΠ±ΠΎ Π³ΠΎΡΡΠ΄Π°ΡΡΡΠ²Π°. Π‘ΡΠ΄Π½ΠΎ, ΠΏΠΎ Π΄Π°Π½Π½ΡΠΌ Π²Π΅Π΄ΠΎΠΌΡΡΠ²Π°, Π±ΡΠ»ΠΎ Π°ΡΠ΅Π½Π΄ΠΎΠ²Π°Π½ΠΎ Ρ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ ΠΈΠ· Π€Π Π, Π½ΠΎ Π΅Π΅ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠΈ Π²Π½Π΅ ΠΏΠΎΠ΄ΠΎΠ·ΡΠ΅Π½ΠΈΠΉ. Π Π°Π½Π΅Π΅ Π³Π°Π·Π΅ΡΠ° Die Zeit ΡΠΎΠΎΠ±ΡΠΈΠ»Π°, ΡΡΠΎ Π½Π΅ΠΌΠ΅ΡΠΊΠΈΠ΅ ΡΠ»Π΅Π΄ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΠΎΡΠ³Π°Π½Ρ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΡΠΈΡΠΎΠ²Π°Π»ΠΈ ΡΡ ΡΡ, ΠΊΠΎΡΠΎΡΠ°Ρ, Π²Π΅ΡΠΎΡΡΠ½ΠΎ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»Π°ΡΡ ΠΏΡΠΈ ΡΠΎΠ²Π΅ΡΡΠ΅Π½ΠΈΠΈ Π²Π·ΡΡΠ²Π° Π½Π° Β«Π‘Π΅Π²Π΅ΡΠ½ΡΡ ΠΏΠΎΡΠΎΠΊΠ°Ρ Β» 26 ΡΠ΅Π½ΡΡΠ±ΡΡ ΠΏΡΠΎΡΠ»ΠΎΠ³ΠΎ Π³ΠΎΠ΄Π°. ''' sentence_2 = ''' ΠΠ»Π°ΡΡΠΈ Π€Π Π ΠΈΠ½ΠΈΡΠΈΠΈΡΠΎΠ²Π°Π»ΠΈ ΠΎΠ±ΡΡΠΊ ΠΊΠΎΡΠ°Π±Π»Ρ, ΠΏΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΈΠΌΠ΅ΡΡΠ΅Π³ΠΎ ΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΠ΅ ΠΊ Π΄ΠΈΠ²Π΅ΡΡΠΈΡΠΌ Π½Π° Π³Π°Π·ΠΎΠΏΡΠΎΠ²ΠΎΠ΄Π°Ρ Β«Π‘Π΅Π²Π΅ΡΠ½ΡΠΉ ΠΏΠΎΡΠΎΠΊΒ» ΠΈ Β«Π‘Π΅Π²Π΅ΡΠ½ΡΠΉ ΠΏΠΎΡΠΎΠΊ β 2Β». ΠΠ± ΡΡΠΎΠΌ 8 ΠΌΠ°ΡΡΠ° ΡΠΎΠΎΠ±ΡΠ°Π΅Ρ Π°Π³Π΅Π½ΡΡΡΠ²ΠΎ DPA ΡΠΎ ΡΡΡΠ»ΠΊΠΎΠΉ Π½Π° ΠΠ΅Π½Π΅ΡΠ°Π»ΡΠ½ΡΡ ΠΏΡΠΎΠΊΡΡΠ°ΡΡΡΡ Π² ΠΠ°ΡΠ»ΡΡΡΡ. Π‘ΠΎΠ³Π»Π°ΡΠ½ΠΎ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ Π²Π΅Π΄ΠΎΠΌΡΡΠ²Π°, ΡΡΠ΄Π½ΠΎ ΠΌΠΎΠ³Π»ΠΎ Π±ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΎ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ·ΠΊΠΈ Π²Π·ΡΡΠ²ΡΠ°ΡΡΡ Π²Π΅ΡΠ΅ΡΡΠ². Β«Π‘ 18 ΠΏΠΎ 20 ΡΠ½Π²Π°ΡΡ 2023 Π³ΠΎΠ΄Π° ΡΠ΅Π΄Π΅ΡΠ°Π»ΡΠ½Π°Ρ ΠΏΡΠΎΠΊΡΡΠ°ΡΡΡΠ° ΠΎΠ±ΡΡΠΊΠ°Π»Π° ΡΡΠ΄Π½ΠΎ Π² ΡΠ²ΡΠ·ΠΈ Ρ ΠΏΠΎΠ΄ΠΎΠ·ΡΠΈΡΠ΅Π»ΡΠ½ΠΎΠΉ Π΅Π³ΠΎ Π°ΡΠ΅Π½Π΄ΠΎΠΉ. ΠΡΡΡ ΠΏΠΎΠ΄ΠΎΠ·ΡΠ΅Π½ΠΈΠ΅, ΡΡΠΎ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°Π΅ΠΌΠΎΠ΅ ΡΡΠ΄Π½ΠΎ ΠΌΠΎΠ³Π»ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ·ΠΊΠΈ Π²Π·ΡΡΠ²Π½ΡΡ ΡΡΡΡΠΎΠΉΡΡΠ², Π²Π·ΠΎΡΠ²Π°Π²ΡΠΈΡ ΡΡ 26 ΡΠ΅Π½ΡΡΠ±ΡΡ 2022 Π³ΠΎΠ΄Π° Π½Π° Π³Π°Π·ΠΎΠΏΡΠΎΠ²ΠΎΠ΄Π°Ρ Β«Π‘Π΅Π²Π΅ΡΠ½ΡΠΉ ΠΏΠΎΡΠΎΠΊΒ» 1 ΠΈ 2 Π² ΠΠ°Π»ΡΠΈΠΉΡΠΊΠΎΠΌ ΠΌΠΎΡΠ΅Β», β ΡΠΎΠΎΠ±ΡΠΈΠ»ΠΈ Π² ΠΏΡΠΎΠΊΡΡΠ°ΡΡΡΠ΅ Π°Π³Π΅Π½ΡΡΡΠ²Ρ Β«Π ΠΠ ΠΠΎΠ²ΠΎΡΡΠΈΒ». ΠΡΠΌΠ΅ΡΠ°Π΅ΡΡΡ, ΡΡΠΎ Π½Π° Π΄Π°Π½Π½ΡΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ ΠΈΠ·ΡΡΡ ΡΡΠ΄ Π²Π΅ΡΠ΄ΠΎΠΊΠΎΠ², ΠΏΡΠΎΠ²ΠΎΠ΄ΠΈΡΡΡ ΠΈΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ°. ΠΠΈΡΠ½ΠΎΡΡΠΈ ΠΏΡΠ΅ΡΡΡΠΏΠ½ΠΈΠΊΠΎΠ² ΠΈ ΠΈΡ ΠΌΠΎΡΠΈΠ²Ρ ΡΠ²Π»ΡΡΡΡΡ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠΎΠΌ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°ΡΡΠΈΡ ΡΡ ΡΠ°ΡΡΠ»Π΅Π΄ΠΎΠ²Π°Π½ΠΈΠΉ. Β«ΠΠΎΡΡΠΎΠ²Π΅ΡΠ½ΡΡ Π΄ΠΎΠΊΠ°Π·Π°ΡΠ΅Π»ΡΡΡΠ² ΠΏΠΎ ΡΡΠΎΠΌΡ ΠΏΠΎΠ²ΠΎΠ΄Ρ, ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎ ΠΏΠΎ Π²ΠΎΠΏΡΠΎΡΡ Π³ΠΎΡΡΠ΄Π°ΡΡΡΠ²Π΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ, Π² Π½Π°ΡΡΠΎΡΡΠ΅Π΅ Π²ΡΠ΅ΠΌΡ Π½Π΅Ρ. ΠΠΈΠΊΠ°ΠΊΠΈΡ ΠΏΠΎΠ΄ΠΎΠ·ΡΠ΅Π½ΠΈΠΉ Π² ΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΠΈ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠΎΠ² Π½Π΅ΠΌΠ΅ΡΠΊΠΎΠΉ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ, ΡΠ΄Π°Π²ΡΠ΅ΠΉ ΡΡΠ΄Π½ΠΎ Π² Π°ΡΠ΅Π½Π΄Ρ, Π½Π΅ΡΒ», β Π·Π°ΠΊΠ»ΡΡΠΈΠ»ΠΈ Π² ΠΏΡΠΎΠΊΡΡΠ°ΡΡΡΠ΅. ''' # ΠΠ½ΠΊΠΎΠ΄Π΅Ρ Π΄Π»Ρ ΠΏΠΎΠ΄ΡΡΠ΅ΡΠ° ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΡΠΎΠΊΠ΅Π½ΠΎΠ² encoding = tiktoken.get_encoding('cl100k_base') num_tokens_1 = len(encoding.encode(sentence_1)) num_tokens_2 = len(encoding.encode(sentence_2)) embedding_1 = openai.Embedding.create( input=sentence_1, model=model ) embedding_2 = openai.Embedding.create( input=sentence_2, model=model ) distance = cosine( embedding_1['data'][0]['embedding'], embedding_2['data'][0]['embedding'] ) print( f'sentence_1 num tokens: {num_tokens_1}\\n' f'sentence_2 num tokens: {num_tokens_2}\\n' f'cos distance: {distance}' ) sentence_1 num tokens: 347 sentence_2 num tokens: 492 cos distance: 0.06688715737425832
ΠΠ»Ρ ΠΏΠΎΡ ΠΎΠΆΠΈΡ ΠΏΠΎ ΡΠΌΡΡΠ»Ρ Π½ΠΎΠ²ΠΎΡΡΠ΅ΠΉ, Π½ΠΎ Ρ ΡΠ°Π·Π½ΠΎΠΉ Π»Π΅ΠΊΡΠΈΠΊΠΎΠΉ ΠΈ ΡΠ°Π·Π½ΡΠΌ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠΌ, ΠΌΠΎΠ΄Π΅Π»Ρ Π²ΡΠ΄Π°Π΅Ρ Π°Π΄Π΅ΠΊΠ²Π°ΡΠ½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΡΠΈΠ½ΡΡΠ½ΠΎΠ³ΠΎ ΡΠ°ΡΡΡΠΎΡΠ½ΠΈΡ. Π§ΡΠΎ ΠΆ, Π²ΠΈΠ΄ΠΈΠΌΠΎ, ΡΠ΅Π±ΡΡΠ° ΠΈΠ· ΠΠ°Π»ΠΈΡΠΎΡΠ½ΠΈΠΈ Π²ΡΠ΅-ΡΠ°ΠΊΠΈ Π½Π΅ Π·ΡΡ Π΅Π΄ΡΡ ΡΠ²ΠΎΠΉ Ρ Π»Π΅Π± ΡΠΎ ΡΠΌΡΠ·ΠΈ.
ΠΠΎ ΠΊΠΎΠ½ΡΠΌ
ΠΠΎΡΠ° ΡΠΎΠ±ΠΈΡΠ°ΡΡ ΡΠ°Π±ΠΎΡΠ°ΡΡΠΈΠΉ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½. ΠΠ΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡΠ΅ ΠΈΠ½Π³ΡΠΈΠ΄ΠΈΠ΅Π½ΡΡ:
- ΠΠΎΡΠΏΡΡ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΡ ΡΠ΅ΠΊΡΡΠΎΠ². Π§ΡΠΎΠ±Ρ ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ Π½Π°Ρ ΠΏΡΠΈΠΌΠ΅Ρ Π½Π° ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΠΎΡΡΡ, ΠΌΡ Π±ΡΠ΄Π΅ΠΌ ΡΡΠ°Π²Π½ΠΈΠ²Π°ΡΡ Π΅Π³ΠΎ Ρ ΠΊΠ°ΠΆΠ΄ΡΠΌ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΎΠΌ ΠΈΠ· ΠΊΠΎΡΠΏΡΡΠ°. ΠΠ°ΡΡΠΈΡΡ Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅ Π±ΡΠ΄Π΅ΠΌ, Π²ΠΎΠ·ΡΠΌΠ΅ΠΌ Π³ΠΎΡΠΎΠ²ΡΠΉ Π΄Π°ΡΠ°ΡΠ΅Ρ Ρ huggingface.
- ΠΠΎΠ΄ Π΄Π»Ρ ΠΏΠΎΠΈΡΠΊΠ° ΠΏΠΎΡΠ΅Π½ΡΠΈΠ°Π»ΡΠ½ΡΡ Π΄ΡΠ±Π»Π΅ΠΉ.
- API-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π½Π°ΡΠΈΠΌ ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠΎΠΌ.
ΠΠ° Π²Ρ ΠΎΠ΄ ΠΌΡ Π±ΡΠ΄Π΅ΠΌ ΠΏΠΎΠ΄Π°Π²Π°ΡΡ ΡΠΏΠΈΡΠΎΠΊ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ², Π½Π° Π²ΡΡ ΠΎΠ΄Π΅ ΠΎΡΠ΅Π½ΠΊΠ° ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΠΎΡΡΠΈ:
api_input = { "ITEMS": [ doc1, doc2, doc3 ] } api_output = [ { "estimation": 1, "score": 0.3, "duplicates": [] }, { "estimation": 0, "score": 0.03, "duplicates": [original1, original2] }, { "estimation": 1, "score": 0.41, "duplicates": [] }, ]
ΠΠ°ΡΠ°ΡΠ΅Ρ
Π‘ΠΊΠ°ΡΠ°Π½Π½ΡΠΉ Π°ΡΡ ΠΈΠ² Π²Π΅ΡΠΈΡ 3.5 ΠΠ. ΠΡΠΎ ΠΌΠΎΠΆΠ΅Ρ ΠΎΠΊΠ°Π·Π°ΡΡΡΡ ΡΠ΅ΡΡΠ΅Π·Π½ΡΠΌ Π²ΡΠ·ΠΎΠ²ΠΎΠΌ Π΄Π»Ρ Π²Π°ΡΠ΅ΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²ΠΊΠΈ, ΠΊΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, ΠΏΠΎΠΈΡΠΊ Π² Π±ΠΎΠ»ΡΡΠΎΠΌ ΠΊΠΎΡΠΏΡΡΠ΅ Π±ΡΠ΄Π΅Ρ Π·Π°Π½ΠΈΠΌΠ°ΡΡ ΡΠ»ΠΈΡΠΊΠΎΠΌ ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ (ΡΠ΅ΠΉΡΠ°Ρ ΠΏΠΎΠΊΠ° ΠΏΡΠΎΠΏΡΡΡΠΈΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΠ΅ ΡΠΏΠΎΡΠΎΠ±Ρ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ ΡΡΠΎΠ³ΠΎ ΠΏΡΠΎΡΠ΅ΡΡΠ°). Π‘Π΅ΠΉΡΠ°Ρ Π½Π°ΡΠ° Π·Π°Π΄Π°ΡΠ° Π²ΡΠΊΠ°ΡΠΈΡΡ MVP (minimal viable product), ΠΏΠΎΡΡΠΎΠΌΡ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠΌΡΡ Π±Π°ΡΡΠ΅ΠΌ Π² 10ΠΊ ΠΏΠΎΡΡΠΎΠ².
import pandas as pd import pickle # Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΈΡΠ΅ΡΠ°ΡΠΎΡ Π΄Π»Ρ ΠΏΠΎΠ±Π°ΡΡΠ΅Π²ΠΎΠΉ Π·Π°Π³ΡΡΠ·ΠΊΠΈ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΡΠ°Π½Π΄Π°ΡΡΠ° zstd(pip install zstandard) habr = pd.read_json( 'habr.jsonl.zst', lines=True, chunksize=10**4, compression='zstd' ) # ΠΠ°Π±ΠΈΡΠ°Π΅ΠΌ ΠΏΠ΅ΡΠ²ΡΠΉ Π±Π°ΡΡ habr_chunk = next(habr) print(habr_chunk.shape) (10000, 22)
Π ΡΠ΅ΡΠ΅ 22 ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ, Π½ΠΎ Π½Π°ΠΌ ΡΡΠΎΠ»ΡΠΊΠΎ Π½Π΅ ΠΏΠΎΠ½Π°Π΄ΠΎΠ±ΠΈΡΡΡ. ΠΠ°ΠΈΠ±ΠΎΠ»Π΅Π΅ Π²Π°ΠΆΠ½ΡΠ΅ Π΄Π»Ρ Π½Π°Ρ:
text_markdown
β ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ ΡΠ°ΠΌ ΡΠ΅ΠΊΡΡ ΠΏΠΎΡΡΠ°.lead_markdown
β Ρ Π΅Π΄Π΅Ρ ΠΏΠΎΡΡΠ° (ΠΏΠ΅ΡΠ²ΡΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠΉ).title
β Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ.
ΠΠ»Ρ ΠΏΠΎΠΈΡΠΊΠ° Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΎΠ² ΠΏΠΎΠΊΠ° ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΡΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ text_markdown
, Π² Π΄Π°Π»ΡΠ½Π΅ΠΉΡΠ΅ΠΌ ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ΄Π΅Ρ Π·Π°Π΄Π΅ΠΉΡΡΠ²ΠΎΠ²Π°ΡΡ ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΠΏΠΎΠ»Ρ.
ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΎΠ²
ΠΡΡΠ΅ Ρ ΡΠΊΠ°Π·ΡΠ²Π°Π», ΡΡΠΎ ΠΌΠΎΠ΄Π΅Π»Ρ ΡΠΏΠΎΡΠΎΠ±Π½Π° ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡ Π½Π° Π²Ρ ΠΎΠ΄ ΡΠ²ΡΡΠ΅ 8k ΡΠΎΠΊΠ΅Π½ΠΎΠ², ΠΎΠ΄Π½Π°ΠΊΠΎ Π΅ΡΠ»ΠΈ Π²Π°Ρ ΡΠ΅ΠΊΡΡ ΠΏΡΠ΅Π²ΡΡΠΈΡ ΡΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅, ΡΠΎ API ΡΠΏΠ°Π΄Π΅Ρ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ. ΠΠ΅ΡΠ΅Π΄ ΠΎΡΠΏΡΠ°Π²ΠΊΠΎΠΉ Π±ΡΠ΄Π΅ΠΌ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΡ ΠΏΠΎΠ΄ΡΡΠ΅Ρ ΠΈ ΠΎΠ±ΡΠ΅Π·Π°ΡΡ Π½Π°ΡΠΈ ΡΠ΅ΠΊΡΡΡ.
def get_embeddings( texts: list, model: str = 'text-embedding-ada-002', chunksize: int = 100, max_tokens: int = 8192, cut_coef: float = 0.8 ) -> list: """ Π€ΡΠ½ΠΊΡΠΈΡ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ ΡΠΏΠΈΡΠΎΠΊ ΡΠ΅ΠΊΡΡΠΎΠ² ΠΈ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠΏΠΈΡΠΎΠΊ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΎΠ², ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΠΌΠΎΠ΄Π΅Π»Ρ ΠΎΡ OpenAI. Π‘ΠΏΠΈΡΠΎΠΊ ΡΠ°Π·Π±ΠΈΠ²Π°Π΅ΡΡΡ Π½Π° ΠΊΡΡΠΊΠΈ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠΌ chunksize, Π° Π·Π°ΡΠ΅ΠΌ ΡΡΠ½ΠΊΡΠΈΡ Π²ΡΡΠΈΡΠ»ΡΠ΅Ρ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΎΠΊΠ΅Π½ΠΎΠ² ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡΠ΅ΠΊΡΡΠ°, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΡΠ½ΠΊΠΎΠ΄Π΅Ρ cl100k_base. ΠΡΠ»ΠΈ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΎΠΊΠ΅Π½ΠΎΠ² ΠΏΡΠ΅Π²ΡΡΠ°Π΅Ρ max_tokens,ΡΠ΅ΠΊΡΡ ΡΠΊΠΎΡΠ°ΡΠΈΠ²Π°Π΅ΡΡΡ Π½Π° cut_coef. ΠΡΠ³ΡΠΌΠ΅Π½ΡΡ: df (pd.DataFrame): pandas DataFrame, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΠΉ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ model (str ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ text-embedding-ada-002): ΠΌΠΎΠ΄Π΅Π»Ρ Π²Π΅ΠΊΡΠΎΡΠΈΠ·Π°ΡΠΈΠΈ chunksize(int ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 100): ΡΠ°Π·ΠΌΠ΅Ρ ΠΊΡΡΠΊΠΎΠ², Π½Π° ΠΊΠΎΡΠΎΡΡΠ΅ ΡΠ°Π·Π±ΠΈΠ²Π°ΡΡΡΡ Π²Ρ ΠΎΠ΄Π½ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ max_tokens (int ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 8192): ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΎΠΊΠ΅Π½ΠΎΠ², ΡΠ°Π·ΡΠ΅ΡΠ΅Π½Π½ΠΎΠ΅ Π½Π° ΠΎΠ΄ΠΈΠ½ ΡΠ΅ΠΊΡΡ cut_coef (float ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 0.8): ΠΊΠΎΡΡΡΠΈΡΠΈΠ΅Π½Ρ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠΉ Π΄Π»Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΡΠ΅ΠΊΡΡΠ° Π΄Π»Ρ ΠΎΠ±ΡΠ΅Π·ΠΊΠΈ, Π΅ΡΠ»ΠΈ ΠΎΠ½ΠΎ ΠΏΡΠ΅Π²ΡΡΠ°Π΅Ρ max_tokens ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ: ΡΠΏΠΈΡΠΎΠΊ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΎΠ² """ embeddings_all = [] encoding = tiktoken.get_encoding('cl100k_base') @retry(wait=wait_random_exponential(min=1, max=10), stop=stop_after_attempt(5)) # ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ Π·Π°ΠΏΡΠΎΡΠΎΠ² def api_request(texts, model): return openai.Embedding.create(input=texts, model=model) for i in range(0, len(texts), chunksize): processed_texts = [] texts_chunk = texts[i:i + chunksize] for text in texts_chunk: if not text: text = 'default' num_tokens = len(encoding.encode(text)) if num_tokens > max_tokens: len_text = len(text) cut_trh = int(max_tokens / num_tokens * len_text * cut_coef) text = text[:cut_trh] processed_texts.append(text) embeddings = api_request(processed_texts, model) for embedding in embeddings['data']: embeddings_all.append(embedding['embedding']) if (i % 1000 == 0) & (i != 0): print(f'processed {i} texts') return embeddings_all
ΠΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΈ Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΠΌ Π² Π΄Π°ΡΠ°ΡΠ΅Ρ ΠΈ ΡΠΎΡ ΡΠ°Π½ΡΠ΅ΠΌ.
embeddings_all = get_embeddings(habr_chunk.text_markdown.values.tolist()) habr_chunk['embedding'] = embeddings_all with open('habr_chunk.pickle', 'wb') as f: pickle.dump(habr_chunk[['text_markdown', 'embedding']], f
ΠΠ°Π·Π° Π΄Π°Π½Π½ΡΡ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΡ ΠΏΠΎΡΡΠΎΠ² Ρ Π½Π°Ρ Π΅ΡΡΡ. ΠΡΠ°Π²Π΄Π°, ΠΌΡ Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ ΠΏΡΠΎΠ²Π΅ΡΠΈΠ»ΠΈ ΠΈΡ Π½Π° ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΠΎΡΡΡ. ΠΠΎΠΊΠ° ΠΎΡΠΏΡΠ°Π²ΠΈΠΌ ΡΡΡ Π·Π°Π΄Π°ΡΡ Π² Π±ΡΠΊΠ»ΠΎΠ³.
ΠΠΎΠΈΡΠΊ Π΄ΡΠ±Π»Π΅ΠΉ
def find_duplicates(candidates: list, df: pd.DataFrame, n_similar: int = 5, thrh: float = 0.1) -> list: ''' Π€ΡΠ½ΠΊΡΠΈΡ Π½Π°Ρ ΠΎΠ΄ΠΈΡ Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΡ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΡ ΡΡΠ°Π³ΠΌΠ΅Π½ΡΠΎΠ² Π΄Π»Ρ ΡΠΏΠΈΡΠΊΠ° candidates Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ ΡΡ ΠΎΠ΄ΡΡΠ²Π° ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΎΠ², Π²ΡΡΠΈΡΠ»Π΅Π½Π½ΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ get_embeddings, ΠΈ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ Π² Π²ΠΈΠ΄Π΅ pandas.DataFrame. Π€ΡΠ½ΠΊΡΠΈΡ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠΏΠΈΡΠΎΠΊ, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΠΉ ΠΎΡΠ΅Π½ΠΊΡ, Π±Π»ΠΈΠ·ΠΎΡΡΡ ΠΈ ΡΠΏΠΈΡΠΎΠΊ ΠΏΠΎΡ ΠΎΠΆΠΈΡ ΡΡΠ°Π³ΠΌΠ΅Π½ΡΠΎΠ² Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡΠ΅ΠΊΡΡΠΎΠ²ΠΎΠ³ΠΎ ΡΡΠ°Π³ΠΌΠ΅Π½ΡΠ° ΠΈΠ· candidates. ΠΡΠ³ΡΠΌΠ΅Π½ΡΡ: candidates (list): ΡΠΏΠΈΡΠΎΠΊ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΡ ΡΡΠ°Π³ΠΌΠ΅Π½ΡΠΎΠ² Π΄Π»Ρ ΠΏΠΎΠΈΡΠΊΠ° Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΎΠ² df (pd.DataFrame): Π±Π°Π·Π° Π΄Π°Π½Π½ΡΡ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ pandas.DataFrame, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠ°Ρ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΈ ΠΈ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠ΅ ΡΡΠ°Π³ΠΌΠ΅Π½ΡΡ Π΄Π»Ρ ΡΡΠ°Π²Π½Π΅Π½ΠΈΡ Ρ candidates n_similar (int, ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 5): ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠΎΡ ΠΎΠΆΠΈΡ ΡΡΠ°Π³ΠΌΠ΅Π½ΡΠΎΠ², ΠΊΠΎΡΠΎΡΡΠ΅ Π±ΡΠ΄ΡΡ Π²ΠΎΠ·Π²ΡΠ°ΡΠ΅Π½Ρ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡΠ΅ΠΊΡΡΠ° candidates thrh (float, ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 0.1): ΠΏΠΎΡΠΎΠ³ΠΎΠ²ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΠΎΠ΅ Π΄Π»Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΡΠΎΠ³ΠΎ, ΡΡΠΎ Π΄Π²Π° ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³Π° Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΠΏΠΎΡ ΠΎΠΆΠΈ. ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ: ΡΠΏΠΈΡΠΎΠΊ ΡΠ»ΠΎΠ²Π°ΡΠ΅ΠΉ Ρ ΠΎΡΠ΅Π½ΠΊΠΎΠΉ, ΠΊΠΎΡΠΈΠ½ΡΡΠ½ΠΎΠΉ Π±Π»ΠΈΠ·ΠΎΡΡΡΡ ΠΈ ΡΠΏΠΈΡΠΊΠΎΠΌ Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΎΠ². ''' embeddings = get_embeddings(candidates) processed_candidates = [] for embedding in embeddings: checked_candidat = { "estimation": 0, "score": None, "duplicates": [] } distances = np.array( [cosine(embedding, e) for e in df.embedding.values] ) under_treshold = distances < thrh if under_treshold.sum() == 0: processed_candidates.append(checked_candidat) else: checked_candidat["estimation"] = 1 checked_candidat["score"] = min(distances) checked_candidat["duplicates"] = df.iloc[ under_treshold ].text_markdown.values[:n_similar].tolist() processed_candidates.append(checked_candidat) return processed_candidates
ΠΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡ ΠΊΡΡΡΠΈΡΡΡ
ΠΡΠ΅ Π΄Π΅ΡΠ°Π»ΡΠΊΠΈ ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠ° Π³ΠΎΡΠΎΠ²Ρ, ΠΎΡΡΠ°Π»ΠΎΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡΡ ΠΈΡ
Π²ΠΌΠ΅ΡΡΠ΅ ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ FastAPI. ΠΠ»Ρ ΡΠ΄ΠΎΠ±ΡΡΠ²Π° ΡΠΎΠ·Π΄Π°Π΄ΠΈΠΌ ΠΏΠ°ΠΊΠ΅Ρ utils
, Π² Π½Π΅Π³ΠΎ ΠΏΠΎΠΌΠ΅ΡΡΠΈΠΌ ΠΊΠΎΠ΄ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π²Π΅ΠΊΡΠΎΡΠΎΠ² ΠΈ ΠΏΠΎΠΈΡΠΊΠ° ΠΏΠΎ ΠΏΠΎΡΡΠ°ΠΌ.
mkdir utils touch utils/__init__.py utils/search.py app.py
Π search.py
ΡΠΊΠΎΠΏΠΈΡΡΠ΅ΠΌ ΠΊΠΎΠ΄ Π΄Π»Ρ ΡΠΌΠ±Π΅Π΄Π΄ΠΈΠ½Π³ΠΎΠ² ΠΈ ΠΏΠΎΠΈΡΠΊΠ°, Π² app.py
ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ FastAPI, ΠΎΠ½ΠΎ ΠΏΡΠ΅Π΄Π΅Π»ΡΠ½ΠΎ ΠΏΡΠΎΡΡΠΎΠ΅.
import os import pickle from fastapi import FastAPI from pydantic import BaseModel import openai from utils.search import find_duplicates # Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΊΠ»ΡΡΠ°(ΡΠ°ΠΊ Π»ΡΡΡΠ΅ Π½Π΅ Ρ ΡΠ°Π½ΠΈΡΡ!!!) openai.api_key = 'sk-7F...idB9Us' # ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π° Ρ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΌΠΈ ΠΏΠΎΡΡΠ°ΠΌΠΈ habr_masters_path = 'habr_chunk.pickle' # Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ fastapi app = FastAPI(title='Deduplication App') # ΠΠ»Ρ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΈ Π΄Π°Π½Π½ΡΡ ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΠΌΠΎΠ΄Π΅Π»Ρ Π΄Π°Π½Π½ΡΡ class Candidat(BaseModel): ITEM: list # ΠΠΎΠ΄Π³ΡΡΠΆΠ°Π΅ΠΌ Π΄Π°ΡΠ°ΡΡΠ΅ΠΉΠΌ Ρ ΠΏΠΎΡΡΠ°ΠΌΠΈ with open(os.path.join(os.path.dirname(__file__), habr_masters_path), 'rb') as f: df = pickle.load(f) # ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ Π΄Π»Ρ Π²Ρ ΠΎΠ΄ΡΡΠΈΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ @app.post('/predict') async def make_predictions(request: Candidat): if not request.ITEM: request.ITEM.append('dafault') processed_candidates = find_duplicates(request.ITEM, df) return processed_candidates
Done!
Π§ΡΠΎΠ±Ρ Π·Π°ΠΏΡΡΡΠΈΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΡΠ΅ΡΠ²Π΅Ρ uvicorn.
uvicorn app:app --reload
Π ΡΠ»ΡΡΠ°Π΅ ΡΡΠΏΠ΅Ρ Π° Π²Ρ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠ²ΠΈΠ΄Π΅ΡΡ ΡΡΠΎ-ΡΠΎ ΠΏΠΎΡ ΠΎΠΆΠ΅Π΅ Π½Π° ΡΡΠΎ:
INFO: Will watch for changes in these directories: ['/Users/m.konakov/Desktop/search_duplicates'] INFO: Uvicorn running on <http://127.0.0.1:8000> (Press CTRL+C to quit) INFO: Started reloader process [24198] using StatReload INFO: Started server process [24200] INFO: Waiting for application startup. INFO: Application startup complete.
ΠΡΡΡΠΎΡΡΡ FastAPI Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ Π² Π±ΡΡΡΡΠΎΡΠ΅, Π½ΠΎ ΠΈ Π² ΡΠ΄ΠΎΠ±ΡΡΠ²Π΅ ΠΎΡΠ»Π°Π΄ΠΊΠΈ. ΠΠ΅ΡΠ΅ΠΉΠ΄Ρ ΠΏΠΎ Π°Π΄ΡΠ΅ΡΡ http://127.0.0.1:8000/docs, Π²Ρ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΏΠΎΠΏΠ°ΡΡΡ Π² swagger. Swagger β ΡΡΠΎ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊ, ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡΠΈΠΉ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΎΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡ ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ RESTful API ΠΈΠ½ΡΠ΅ΡΠ°ΠΊΡΠΈΠ²Π½ΠΎ, Π½ΠΎ ΠΈ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ Π·Π°ΠΏΡΠΎΡΡ ΠΈ ΠΏΡΠΎΠ²Π΅ΡΡΡΡ ΠΎΡΠ²Π΅ΡΡ.
Π ΡΠΏΠΈΡΠΎΠΊ ITEM ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠΌΠ΅ΡΠ°ΡΡ ΡΠ²ΠΎΠΈΡ ΠΊΠ°Π½Π΄ΠΈΠ΄Π°ΡΠΎΠ² Π½Π° Π΄ΡΠ±Π»ΠΈ. ΠΠΎΠ·ΡΠΌΠ΅ΠΌ, Π΄Π»Ρ ΠΏΡΠΈΠΌΠ΅ΡΠ°, Ρ Π΅Π΄Π΅Ρ ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π½ΠΈΠ±ΡΠ΄Ρ ΠΏΠΎΡΡΠ°. ΠΠΎ-Ρ ΠΎΡΠΎΡΠ΅ΠΌΡ, ΡΡΠΎΠΈΡ ΠΆΠ΄Π°ΡΡ, ΡΡΠΎ ΠΌΠΎΠ΄Π΅Π»Ρ Π΄ΠΎΠ»ΠΆΠ½Π° Π½Π°ΠΌ Π²Π΅ΡΠ½ΡΡΡ ΠΏΠΎΠ»Π½ΡΠΉ ΡΠ΅ΠΊΡΡ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠ°.
Π ΡΡΠ°ΡΡΡΡ, Π½Π°ΡΠΈ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ Π½Π΅ ΠΎΠΊΠ°Π·Π°Π»ΠΈΡΡ Π½Π°ΡΠΈΠΌΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°ΠΌΠΈ.
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
ΠΠ΅Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΡ ΠΏΠΎΠ½ΡΡΠ½Π°Ρ ΠΈ Π½Π° ΠΏΠ΅ΡΠ²ΡΠΉ Π²Π·Π³Π»ΡΠ΄ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΠΏΡΠΎΡΡΠ°Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°. ΠΠΎ ΡΠ΅ΡΠ°Ρ Π΅Π΅, ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡΠΊΡΡΡΡ Π΄Π»Ρ ΡΠ΅Π±Ρ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ ΠΊΡΡΡΡΡ ΠΈ ΡΠ΅Π½Π½ΡΡ ΠΈΠ΄Π΅ΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅ Π±ΡΠ΄ΡΡ ΠΏΠΎΠ»Π΅Π·Π½Ρ Π²ΠΎ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²Π΅ Π΄ΡΡΠ³ΠΈΡ Π·Π°Π΄Π°Ρ. Π ΡΡΠ°ΡΡΠ΅ Ρ ΠΏΠΎΡΡΠ°ΡΠ°Π»ΡΡ ΡΠ°ΡΠΊΡΡΡΡ Π±Π°Π·ΠΎΠ²ΡΠ΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Ρ, Π±Π΅Π· ΡΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ³ΡΡΠΆΠ΅Π½ΠΈΡ Π² Π΄Π΅ΡΠ°Π»ΠΈ, Π½ΠΎ Π½Π°Π΄Π΅ΡΡΡ, ΡΡΠΎ ΠΊΠΎΠ³ΠΎ-ΡΠΎ ΡΡΠΎ Π²Π΄ΠΎΡ Π½ΠΎΠ²ΠΈΡ ΠΊ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΌ ΠΏΠΎΠΈΡΠΊΠ°ΠΌ. Π‘ΠΏΠ°ΡΠΈΠ±ΠΎ Π·Π° Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅!