Pada tahun 2021, Microsoft, OpenAI dan Github bersama-sama mencipta alat pelengkap kod dan cadangan yang berguna-Copilot.
Ia akan mengesyorkan baris kod dalam editor kod pembangun, seperti apabila pembangun memasukkan kod dalam persekitaran pembangunan bersepadu seperti Kod Visual Studio, Neovim dan JetBrains IDE baris kod seterusnya. Selain itu, Copilot juga boleh memberikan nasihat tentang kaedah lengkap dan algoritma kompleks, serta bantuan dengan kod templat dan ujian unit.
Lebih daripada setahun kemudian, alat ini telah menjadi "rakan kongsi pengaturcaraan" yang tidak dapat dipisahkan untuk ramai pengaturcara. Andrej Karpathy, bekas pengarah kecerdasan buatan di Tesla, berkata, "Copilot telah sangat mempercepatkan kelajuan pengaturcaraan saya, dan sukar untuk membayangkan bagaimana untuk kembali kepada 'pengaturcaraan manual'. Pada masa ini, saya masih belajar cara menggunakannya, dan ia telah memprogramkan hampir 80% daripada saya Ketepatan kod adalah hampir 80%. apakah rupa gesaan Copilot? Bagaimanakah ia memanggil model? Bagaimanakah kadar kejayaan pengesyorannya diukur? Adakah ia akan mengumpul coretan kod pengguna dan menghantarnya ke pelayannya sendiri? Adakah model di belakang Copilot model besar atau model kecil?
Untuk menjawab soalan-soalan ini, seorang penyelidik dari University of Illinois di Urbana-Champaign secara kasarnya telah membuat kejuruteraan terbalik Copilot dan menulis blog tentang pemerhatiannya.
Andrej Karpathy mengesyorkan blog ini dalam tweetnya.
Berikut ialah teks asal blog tersebut.
Reverse Engineering Copilot
Github Copilot telah sangat berguna kepada saya. Ia sering secara ajaib membaca fikiran saya dan membuat cadangan yang berguna. Apa yang paling mengejutkan saya ialah keupayaannya untuk "meneka" fungsi/pembolehubah dengan betul daripada kod sekeliling (termasuk kod dalam fail lain). Ini hanya berlaku apabila sambungan Copilot menghantar maklumat berharga daripada kod sekeliling kepada model Codex. Saya ingin tahu tentang cara ia berfungsi, jadi saya memutuskan untuk melihat kod sumber.Dalam siaran ini saya cuba menjawab soalan khusus tentang dalaman Copilot, sambil turut menerangkan beberapa pemerhatian menarik yang saya buat semasa menyisir kod.
Kod untuk projek ini boleh didapati di sini:
Alamat kod: https : //github.com/thakkarparth007/copilot-explorer
Keseluruhan artikel disusun seperti berikut:
Gambaran Keseluruhan Kejuruteraan Terbalik Beberapa bulan yang lalu saya telah melakukan "kejuruteraan terbalik" yang sangat dangkal bagi sambungan Copilot, dan saya telah mahu menyelidiki lebih mendalam sejak itu. Saya akhirnya dapat melakukan ini dalam beberapa minggu yang lalu. Pada asasnya, dengan menggunakan fail extension.js yang disertakan dengan Copilot, saya membuat beberapa perubahan manual kecil untuk memudahkan pengekstrakan automatik modul, dan menulis sekumpulan transformasi AST untuk "mencantikkan" setiap modul, menamakan modul, Juga mengelaskan dan memberi anotasi secara manual beberapa bahagian yang paling menarik.
Anda boleh meneroka pangkalan kod kopilot kejuruteraan terbalik melalui alatan yang saya bina. Ia mungkin tidak menyeluruh dan halus, tetapi anda masih boleh menggunakannya untuk meneroka kod Copilot.
Pautan alat: https://thakkarparth007.github.io/copilot-explorer/
Copilot: Gambaran Keseluruhan
Github Copilot terdiri daripada dua bahagian utama berikut:
Sekarang Codex telah dilatih mengenai sejumlah besar kod Github awam, masuk akal bahawa ia boleh membuat cadangan yang berguna . Tetapi Codex tidak mempunyai cara untuk mengetahui ciri yang wujud dalam projek semasa anda Walaupun begitu, ia masih boleh membuat cadangan yang melibatkan ciri projek.
Mari kita jawab ini dalam dua bahagian: mula-mula mari kita lihat contoh segera sebenar yang dijana oleh copilot, dan kemudian kita akan melihat cara ia dijana.
Apakah rupa gesaan
Pelanjutan Copilot mengodkan banyak maklumat yang berkaitan dengan projek anda dalam gesaan. Copilot mempunyai saluran paip kejuruteraan segera yang agak kompleks. Berikut ialah contoh gesaan:
{"prefix": "# Path: codeviz\app.pyn# Compare this snippet from codeviz\predictions.py:n# import jsonn# import sysn# import timen# from manifest import Manifestn# n# sys.path.append(__file__ + "/..")n# from common import module_codes, module_deps, module_categories, data_dir, cur_dirn# n# gold_annots = json.loads(open(data_dir / "gold_annotations.js").read().replace("let gold_annotations = ", ""))n# n# M = Manifest(n# client_name = "openai",n# client_connection = open(cur_dir / ".openai-api-key").read().strip(),n# cache_name = "sqlite",n# cache_connection = "codeviz_openai_cache.db",n# engine = "code-davinci-002",n# )n# n# def predict_with_retries(*args, **kwargs):n# for _ in range(5):n# try:n# return M.run(*args, **kwargs)n# except Exception as e:n# if "too many requests" in str(e).lower():n# print("Too many requests, waiting 30 seconds...")n# time.sleep(30)n# continuen# else:n# raise en# raise Exception("Too many retries")n# n# def collect_module_prediction_context(module_id):n# module_exports = module_deps[module_id]["exports"]n# module_exports = [m for m in module_exports if m != "default" and "complex-export" not in m]n# if len(module_exports) == 0:n# module_exports = ""n# else:n# module_exports = "It exports the following symbols: " + ", ".join(module_exports)n# n# # get module snippetn# module_code_snippet = module_codes[module_id]n# # snip to first 50 lines:n# module_code_snippet = module_code_snippet.split("\n")n# if len(module_code_snippet) > 50:n# module_code_snippet = "\n".join(module_code_snippet[:50]) + "\n..."n# else:n# module_code_snippet = "\n".join(module_code_snippet)n# n# return {"exports": module_exports, "snippet": module_code_snippet}n# n# #### Name prediction ####n# n# def _get_prompt_for_module_name_prediction(module_id):n# context = collect_module_prediction_context(module_id)n# module_exports = context["exports"]n# module_code_snippet = context["snippet"]n# n# prompt = f"""\n# Consider the code snippet of an unmodule named.n# nimport jsonnfrom flask import Flask, render_template, request, send_from_directorynfrom common import *nfrom predictions import predict_snippet_description, predict_module_namennapp = Flask(__name__)nn@app.route('/')ndef home():nreturn render_template('code-viz.html')nn@app.route('/data/<filename>')ndef get_data_files(filename):nreturn send_from_directory(data_dir, filename)nn@app.route('/api/describe_snippet', methods=['POST'])ndef describe_snippet():nmodule_id = request.json['module_id']nmodule_name = request.json['module_name']nsnippet = request.json['snippet']ndescription = predict_snippet_description(nmodule_id,nmodule_name,nsnippet,n)nreturn json.dumps({'description': description})nn# predict name of a module given its idn@app.route('/api/predict_module_name', methods=['POST'])ndef suggest_module_name():nmodule_id = request.json['module_id']nmodule_name = predict_module_name(module_id)n","suffix": "if __name__ == '__main__':rnapp.run(debug=True)","isFimEnabled": true,"promptElementRanges": [{ "kind": "PathMarker", "start": 0, "end": 23 },{ "kind": "SimilarFile", "start": 23, "end": 2219 },{ "kind": "BeforeCursor", "start": 2219, "end": 3142 }]}</filename>
Seperti yang anda lihat, gesaan di atas termasuk awalan dan akhiran. Copilot kemudian menghantar gesaan ini (selepas beberapa pemformatan) kepada model. Dalam kes ini, kerana akhiran tidak kosong, Copilot akan memanggil Codex dalam "mod sisip", iaitu mod isi-dalam-tengah (FIM).
Jika anda melihat awalan, anda akan melihat bahawa ia mengandungi beberapa kod daripada fail lain dalam projek. Lihat # Bandingkan coretan ini daripada codevizpredictions.py: Bagaimanakah baris kod dan baris berikut
gesaan disediakan?
Secara kasarnya, urutan langkah berikut dilaksanakan untuk menjana gesaan:
Secara umumnya, gesaan melepasi siri Langkah berikut penjanaan mengikut langkah:
1. Titik masuk: pengekstrakan segera berlaku pada dokumen dan kedudukan kursor yang diberikan. Titik masuk utama yang dijana ialah extractPrompt (ctx, doc, insertPos)
2. Tanya laluan relatif dan ID bahasa dokumen daripada VSCode. Lihat: getPromptForRegularDoc (ctx, doc, insertPos)
3 Dokumen berkaitan: Kemudian, tanya 20 fail yang paling baru diakses dalam bahasa yang sama daripada VSCode. Lihat getPromptHelper (ctx, docText, insertOffset, docRelPath, docUri, docLangId) . Fail ini kemudiannya digunakan untuk mengekstrak coretan yang serupa untuk disertakan dalam gesaan. Saya secara peribadi berpendapat adalah pelik untuk menggunakan bahasa yang sama sebagai penapis kerana pembangunan berbilang bahasa adalah perkara biasa. Tetapi saya rasa itu masih meliputi kebanyakan kes.
4. Khususnya termasuk:
5. Pengiraan awalan: Sekarang, buat "Senarai Hajat Prompt" untuk mengira bahagian awalan gesaan. Di sini, kami menambah "elemen" yang berbeza dan keutamaannya. Contohnya, elemen boleh jadi seperti "Bandingkan serpihan ini daripada ", atau konteks import tempatan, atau ID bahasa dan/atau laluan setiap fail. Ini semua berlaku dalam getPrompt (fs, curFile, promptOpts = {}, relevantDocs = []) .
6. Pengiraan akhiran: Langkah sebelumnya adalah untuk awalan, tetapi logik akhiran agak mudah - cuma isikan belanjawan token dengan sebarang akhiran yang tersedia daripada kursor . Ini ialah lalai, tetapi kedudukan permulaan akhiran akan berbeza sedikit bergantung pada pilihan SuffixStartMode, yang juga dikawal oleh rangka kerja percubaan AB. Sebagai contoh, jika SuffixStartMode ialah SiblingBlock, Copilot akan mula-mula mencari adik beradik berfungsi yang paling hampir dengan fungsi yang sedang diedit dan menulis akhiran dari sana.
Melihat lebih dekat pada pengekstrakan serpihan
Bagi saya bahagian paling lengkap daripada generasi segera nampaknya mengekstrak daripada yang lain serpihan fail. Ia dipanggil di sini dan ditakrifkan oleh jiran-snippet-selector.getNeighbourSnippets. Bergantung pada pilihan, ini akan menggunakan "Penjodoh Jaccard tetingkap tetap" atau "Penjodoh Jaccard berasaskan lekukan". Saya tidak pasti 100%, tetapi ia tidak kelihatan seperti Jaccard Matcher berasaskan Indentasi sebenarnya digunakan.
Secara lalai, kami menggunakan tetingkap tetap Jaccard Matcher. Dalam kes ini, fail yang diberikan (dari mana serpihan akan diekstrak) dibahagikan kepada tetingkap gelongsor bersaiz tetap. Kemudian hitung persamaan Jaccard antara setiap tetingkap dan fail rujukan (fail yang anda taipkan). Hanya tetingkap optimum dikembalikan untuk setiap "fail berkaitan" (walaupun terdapat keperluan untuk mengembalikan serpihan K teratas, ini tidak pernah diikuti). Secara lalai, FixedWindowJaccardMatcher akan digunakan dalam "mod bersemangat" (iaitu, saiz tetingkap ialah 60 baris). Walau bagaimanapun, mod ini dikawal oleh rangka kerja Percubaan AB, jadi kami mungkin menggunakan mod lain.
Copilot menyediakan penyelesaian melalui dua UI: Inline/GhostText dan Panel Copilot. Dalam kedua-dua kes, terdapat beberapa perbezaan dalam cara model dipanggil.
Inline/GhostText
Modul utama: https://thakkarparth007.github.io/copilot-explorer/ codeviz/templates/code-viz.html#m9334&pos=301:14
Di dalamnya, sambungan Copilot memerlukan model memberikan sedikit cadangan (1-3 item) untuk mempercepatkan . Ia juga secara aktif menyimpan hasil model. Selain itu, ia perlu melaraskan cadangan jika pengguna terus menaip. Jika pengguna menaip sangat pantas, ia juga akan meminta model untuk menghidupkan fungsi nyahlantun.
UI ini juga menetapkan beberapa logik untuk menghalang permintaan daripada dihantar dalam keadaan tertentu. Contohnya, jika kursor pengguna berada di tengah-tengah baris, permintaan hanya akan dihantar jika aksara di sebelah kanannya ialah ruang, pendakap penutup, dsb.
1 Sekat permintaan buruk melalui penapis kontekstual
Apa yang lebih menarik ialah selepas menjana gesaan, modul menyemak sama ada gesaan itu "cukup baik" untuk memanggil model Ini dicapai dengan mengira "skor penapisan konteks". Skor ini nampaknya berdasarkan model regresi logistik mudah, yang mengandungi 11 ciri seperti bahasa, sama ada cadangan sebelumnya diterima/ditolak, tempoh antara penerimaan/penolakan sebelumnya, panjang baris terakhir dalam gesaan, yang terakhir watak dll. Berat model ini terkandung dalam kod sambungan itu sendiri.
Jika markah berada di bawah ambang (lalai 15%), permintaan tidak akan dibuat. Adalah menarik untuk meneroka model ini, saya telah melihat bahawa sesetengah bahasa mempunyai berat yang lebih tinggi daripada yang lain (cth. php > js > python > rust > dart…php). Pemerhatian intuitif lain ialah jika gesaan berakhir dengan ) atau ], skor adalah lebih rendah daripada jika ia berakhir dengan (atau [. Ini masuk akal, kerana yang pertama lebih berkemungkinan menunjukkan bahawa ia telah "selesai", manakala yang terakhir jelas menunjukkan bahawa pengguna akan Mendapat Manfaat daripada pelengkapan automatik
Panel Salinan
Modul utama: https://thakkarparth007 .github. io/copilot-explorer/codedeviz/templates/code-viz.html#m2990&pos=12:1
Logik teras 1: https://thakkarparth007.github.io/ copilot-explorer /codeviz/templates/code-viz.html#m893&pos=9:1
Logik teras 2: https://thakkarparth007.github.io/copilot-explorer/codedeviz /templates/ code-viz.html#m2388&pos=67:1
UI ini meminta lebih banyak sampel daripada model (10 secara lalai) daripada UI Sebaris nampaknya tiada konteks logik penapisan (masuk akal, anda tidak mahu tidak menggesa model jika pengguna memanggilnya secara jelas. Terdapat dua perkara menarik utama di sini:
Ia meminta logprob daripada model dan senarai penyelesaian diisih mengikut kategori logprobs min
Jika output ialah Duplikat (seperti: foo = foo = foo = foo...), yang merupakan mod kegagalan biasa model bahasa, maka cadangan ini akan dibuang dalam pelayan proksi Copilot atau klien 🎜>
Jika pengguna telah sudah menaip cadangan, cadangan itu juga akan dibuang.Petua 3: telemetri
Github mendakwa dalam blog sebelum ini bahawa 40% daripada kod yang ditulis oleh pengaturcara ditulis oleh Copilot (untuk Python dan bahasa popular lain). Saya ingin tahu bagaimana mereka mengukur nombor ini, jadi ingin memasukkan sesuatu ke dalam kod telemetri.
Saya juga ingin mengetahui data telemetri yang dikumpulnya, terutamanya jika ia mengumpul coretan kod. Saya tertanya-tanya tentang perkara ini kerana walaupun kita boleh dengan mudah mengarahkan sambungan Copilot ke bahagian belakang FauxPilot sumber terbuka dan bukannya bahagian belakang Github, sambungan itu mungkin masih menghantar coretan kod ke Github melalui telemetri, yang tidak menggalakkan sesetengah orang yang mempunyai kebimbangan tentang privasi kod daripada menggunakannya. Copilot. Saya tertanya-tanya jika ini berlaku.
Soalan 1: Bagaimanakah angka 40% diukur?
Mengukur kejayaan Copilot bukan sekadar soal mengira penerimaan/penolakan, kerana orang sering menerima cadangan dengan beberapa pengubahsuaian. Oleh itu, kakitangan Github menyemak sama ada cadangan yang diterima masih wujud dalam kod. Secara khusus, mereka menyemak pada 15 saat, 30 saat, 2 minit, 5 minit dan 10 minit selepas kod yang dicadangkan dimasukkan.
Carian tepat untuk cadangan yang diterima kini terlalu terhad, jadi mereka mengukur jarak edit antara teks yang dicadangkan dan tetingkap di sekitar titik sisipan (pada peringkat aksara dan peringkat perkataan ). Cadangan dianggap "masih dalam kod" jika jarak edit peringkat perkataan antara sisipan dan tetingkap kurang daripada 50% (dinormalkan kepada saiz cadangan). Sudah tentu, ini hanya terpakai pada kod yang diterima. Soalan 2: Adakah data telemetri mengandungi coretan kod? Ya, termasuk. 30 saat selepas menerima atau menolak cadangan, copilot akan "menangkap" syot kilat berhampiran titik sisipan. Secara khusus, sambungan memanggil mekanisme pengekstrakan segera untuk mengumpulkan "gesaan hipotesis" yang boleh digunakan untuk membuat cadangan pada titik sisipan itu. copilot juga menangkap "penyelesaian hipotesis" dengan menangkap kod antara titik sisipan dan titik akhir "tekaan". Saya tidak begitu faham bagaimana ia meneka titik akhir ini. Seperti yang dinyatakan sebelum ini, ini berlaku selepas penerimaan atau penolakan. Saya mengesyaki syot kilat ini boleh digunakan sebagai data latihan untuk menambah baik lagi model. Walau bagaimanapun, 30 saat nampaknya masa yang terlalu singkat untuk menganggap bahawa kod telah "selesai." Tetapi saya rasa, memandangkan telemetri mengandungi repo github yang sepadan dengan projek pengguna, walaupun jika tempoh 30 saat menghasilkan titik data yang bising, kakitangan GitHub boleh membersihkan data yang agak bising ini di luar talian. Sudah tentu, semua ini hanyalah spekulasi di pihak saya. Perhatikan bahawa GitHub akan membenarkan anda memilih sama ada bersetuju untuk menggunakan coretan kod anda untuk "memperbaiki produk jika anda tidak bersetuju, telemetri yang mengandungi coretan ini tidak akan dihantar ke". pelayan (Sekurang-kurangnya itu yang berlaku dalam v1.57 saya periksa, tetapi saya juga mengesahkan v1.65). Saya menyemak ini dengan melihat kod dan mengelog titik data telemetri sebelum ia dihantar melalui rangkaian. Saya mengubah suai kod sambungan sedikit untuk mendayakan pengelogan verbose (tidak dapat mencari parameter boleh dikonfigurasikan). Saya mendapati bahawa model ini dipanggil "cushman-ml", yang sangat mencadangkan bahawa Copilot mungkin menggunakan model parameter 12B dan bukannya model parameter 175B. Bagi pekerja sumber terbuka, ini sangat menggalakkan, bermakna model bersaiz sederhana boleh memberikan nasihat yang begitu baik. Sudah tentu, sejumlah besar data yang dipegang oleh Github masih tidak boleh diakses oleh pekerja sumber terbuka. Dalam artikel ini saya tidak menutup fail worker.js yang dihantar bersama sambungan. Pada pandangan pertama, ia nampaknya pada asasnya hanya menyediakan versi selari logik pengekstrakan segera, tetapi ia mungkin mempunyai lebih banyak keupayaan. Alamat fail: https://thakkarparth007.github.io/copilot-explorer/muse/github.copilot-1.57.7193/dist/worker_expanded.js Dayakan pengelogan bertele-tele Jika anda ingin mendayakan pengelogan verbose, anda boleh berbuat demikian dengan mengubah suai kod sambungan: Jika anda mahukan tampalan siap sedia , hanya salin kod sambungan: https://thakkarparth007.github.io/copilot-explorer/muse/github.copilot-1.57.7193/dist/extension.js Nota , ini untuk versi 1.57 .7193 Terdapat pautan yang lebih terperinci dalam teks asal, pembaca yang berminat boleh menyemak teks asal.Pemerhatian Lain
Atas ialah kandungan terperinci Selepas Copilot kejuruteraan terbalik, saya mendapati bahawa ia mungkin hanya menggunakan model kecil dengan parameter 12B.. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!