فایلی را پیدا کنید که پاسخ در آن است
zjm-rag یعنی RAG روی فایلهای خودتان. zg پوشههایتان را میگردد، Jev نتیجهها را میخواند و میسنجد کدام فایلها واقعاً پاسخ را در خود دارند، و بعد یک LLM فقط از روی همان فایلها جواب میدهد و مسیرشان را هم میآورد.
کتابخانهٔ zjm_rag و فرمان zjm آمادهاند، با خروجی --json برای اسکریپتها. API روی HTTP و سرور MCP مشخصاتشان نوشته شده و قدم بعدی ساختن آنهاست.
>>> zjm_rag.ask("which linter checks CSS files")
- 0.96
agent-linters/README.md - 0.81
agent-linters/bin/lintp - 0.58
agent-linters/llms.txt - آستانه ۰٫۵: فایلهای زیر آن بهعنوان ردشده برمیگردند. سه فایل برتر از میان پذیرفتهها به LLM میرسند.
- 0.22
agent-linters/shell/linters.fish - 0.14
agent-linters/website/index.html - 0.09
agent-linters/install.sh - 0.03
message-test-plugin/CONTRIBUTING.md - 0.02
message-test-plugin/scripts/validate-plugin.py
Biome checks .css and .scss files. It is listed in the linter table in agent-linters/README.md.
سه مرحله، هر کدام باریکتر از قبلی
جستوجو تور را پهن میاندازد و یک داور صید را سوا میکند. فقط فایلهایی که داور میپذیرد به مدل میرسند، پس مدل خود فایلها را میخواند، از هر کدام تا ۲۰٬۰۰۰ نویسه، نه انبوهی از تکههای پراکنده.
۴۰ نتیجه، در حداکثر ۸ فایل
zg پیدا میکند
یک جستوجوی ترکیبی، هم کلیدواژهای و هم معنایی، روی نمایهٔ محلی zg. find تا ۴۰ نتیجه برمیدارد، آنها را بر اساس فایل گروه میکند و از هر فایل دو تکهٔ کوتاه نگه میدارد.
۸ فایل، هر کدام با یک احتمال
Jev داوری میکند
یک درخواست به Jev، یعنی OpenRouter Decisions API، از همهٔ فایلها یک سؤال را میپرسد: آیا این فایل چیزی را که پاسخ لازم دارد در خود دارد؟ Jev هر فایل را از روی مسیر و تکههایش میسنجد و یک احتمال برمیگرداند. فایلهایی با ۰٫۵ یا بیشتر پذیرفته میشوند. بقیه بهعنوان ردشده برمیگردند، پس هیچ فایلی بیسروصدا گم نمیشود.
حداکثر ۳ فایل پذیرفته، یک پاسخ
LLM جواب میدهد
ask سه فایل پذیرفتهٔ برتر را با یک دستور به claude CLI میدهد: فقط از روی همین فایلها جواب بده، مسیر فایل را بیاور، و اگر پاسخ در آنها نیست همین را بگو. اگر هیچ فایلی به آستانه نرسد، سراغ LLM نمیرود.
چه چیزی از رایانهٔ شما بیرون میرود
جستوجو محلی است، اما داوری و پاسخ نه. فقط پوشههایی را به آن بدهید که حاضرید محتوایشان را در گفتوگو با همین سرویسها بچسبانید.
| zg | روی رایانهٔ خودتان اجرا میشود، روی نمایهٔ یک کپی از پوشههایتان. |
|---|---|
| Jev | سؤال، همراه با مسیر و حداکثر دو تکه از هر فایل، از حداکثر ۸ فایل، به OpenRouter میرود. |
claude | سؤال، همراه با مسیر و ۲۰٬۰۰۰ نویسهٔ اول هر فایلی که پاسخ از آن میآید، حداکثر سه فایل، به Anthropic میرود. |
آنچه امروز هست و آنچه در برنامه است
امروز
- کتابخانهٔ
zjm_rag، فقط با کتابخانهٔ استاندارد پایتون:index،findوask. - فرمان
zjmهمین کارها را از خط فرمان انجام میدهد، بهعلاوهٔzjm doctor. با--jsonنتیجه به شکل یک شیء JSON چاپ میشود. مشخصات خط فرمان indexپوشههایتان را در یک پوشهٔ جدا (بهطور پیشفرض در پوشهٔ موقت سیستم) کپی میکند و از کپی نمایه میسازد، پس به پروژههایتان دست نمیزند.multilingual=Trueمدلی برای محتوای غیرانگلیسی انتخاب میکند.findفایلها را با یک آستانه به پذیرفته و ردشده تقسیم میکند و بر اساس امتیاز، رتبهٔ zg، زمان تغییر یا مسیر مرتب میکند.- تستها با نسخههای ساختگی کار میکنند و هیچوقت zg، Jev یا LLM را صدا نمیزنند.
در برنامه، برای هر مشخصه یک pull request
zjm serve، یک API از نوع JSON روی127.0.0.1برای برنامههایی به هر زبانی. مشخصات HTTPzjm mcp، یک سرور MCP برای عاملهای هوش مصنوعی، و یک اسکریپت نصب یکخطی. مشخصات MCP و نصب
نصب کنید و امتحانش کنید
- پایتون ۳٫۱۰ یا جدیدتر. بسته هیچ وابستگیای ندارد.
zgرویPATH:npm install -g @zvec/zvec-grepOPENROUTER_API_KEYدر محیط شما، برای رتبهبندی Jev.claudeCLI، برای پاسخها.
از یک کلون مخزن نصبش کنید
git clone https://github.com/cocodedk/zjm-rag.git && cd zjm-rag pip install .
یک پوشه را نمایه کنید، بعد بپرسید، از خط فرمان یا از پایتون
zjm index ~/projects/some-repo # copy, then index the copy zjm find "which linter checks CSS files" # accepted and rejected files zjm ask "which linter checks CSS files" # the answer and its sources zjm doctor # checks zg, claude and the API key
import os, zjm_rag
zjm_rag.index([os.path.expanduser("~/projects/some-repo")]) # copy, then index the copy
hits = zjm_rag.find("which linter checks CSS files") # accepted and rejected files
reply = zjm_rag.ask("which linter checks CSS files")
print(reply["answer"], reply["files"])