Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- .claude/settings.local.json +39 -0
- .env.backup +2 -0
- .gitignore +16 -0
- .gradio/certificate.pem +31 -0
- .gradio/flagged/dataset1.csv +4 -0
- README.md +8 -7
- ResearchRadar_Week1_Demo_ๆนๆก.md +1225 -0
- ResearchRadar_ไน_ไปปๅกไนฆ.md +1575 -0
- app.py +317 -0
- direction_analyzer.py +202 -0
- gradio_output.log +8 -0
- llm_utils.py +263 -0
- paper_fetcher.py +113 -0
- repo_evaluator.py +268 -0
- repo_fetcher.py +89 -0
- repo_searcher.py +69 -0
- requirements.txt +3 -0
- run.py +489 -0
- state.py +78 -0
- test_agents.py +294 -0
- ไน_ๅฎ็ฐๆป็ป.md +107 -0
- ไนโ็ฒ_ๅฏนๆฅๆๆกฃ.md +772 -0
- ๆต็จๆถๆๅพ.md +129 -0
.claude/settings.local.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"permissions": {
|
| 3 |
+
"allow": [
|
| 4 |
+
"Bash(pip install *)",
|
| 5 |
+
"Bash(python direction_analyzer.py)",
|
| 6 |
+
"Bash(python repo_evaluator.py)",
|
| 7 |
+
"Bash(python test_agents.py)",
|
| 8 |
+
"WebSearch",
|
| 9 |
+
"mcp__filesystem__read_media_file",
|
| 10 |
+
"Bash(python -c \"import run; print\\('run.py ๅฏผๅ
ฅๆๅ'\\)\")",
|
| 11 |
+
"Bash(python -c \"from app import format_report; print\\('app.py ๅฏผๅ
ฅๆๅ'\\)\")",
|
| 12 |
+
"Bash(python -c ' *)",
|
| 13 |
+
"Bash(ls -la *.txt *.md .gitignore)",
|
| 14 |
+
"Bash(cat requirements.txt)",
|
| 15 |
+
"Bash(python run.py https://arxiv.org/abs/2011.08785)",
|
| 16 |
+
"Bash(export GITHUB_TOKEN=\"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\")",
|
| 17 |
+
"Bash(timeout 15 python app.py.)",
|
| 18 |
+
"Bash(python -c \"import gradio; print\\(f'Gradio {gradio.__version__}'\\)\")",
|
| 19 |
+
"Bash(python run.py https://arxiv.org/abs/1706.03762)",
|
| 20 |
+
"Bash(python app.py)",
|
| 21 |
+
"Bash(taskkill //F //IM python.exe)",
|
| 22 |
+
"Read(//dev/**)",
|
| 23 |
+
"Bash(tasklist)",
|
| 24 |
+
"Bash(python -u app.py)",
|
| 25 |
+
"Bash(mkdir -p \"C:\\\\Users\\\\Yuan Xin\\\\.cache\\\\huggingface\\\\gradio\\\\frpc\")",
|
| 26 |
+
"Bash(curl -L -o \"C:\\\\Users\\\\Yuan Xin\\\\.cache\\\\huggingface\\\\gradio\\\\frpc\\\\frpc_windows_amd64_v0.3\" \"https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_windows_amd64.exe\")",
|
| 27 |
+
"Bash(where ngrok *)",
|
| 28 |
+
"Bash(export HF_ENDPOINT=https://hf-mirror.com)",
|
| 29 |
+
"Bash(curl -L -o \"C:\\\\Users\\\\Yuan Xin\\\\.cache\\\\huggingface\\\\gradio\\\\frpc\\\\frpc_windows_amd64_v0.3\" \"https://hf-mirror.com/frpc-gradio-0.3/resolve/main/frpc_windows_amd64.exe\")",
|
| 30 |
+
"Bash(python *)",
|
| 31 |
+
"Bash(curl -L -o \"C:\\\\Users\\\\Yuan Xin\\\\AppData\\\\Local\\\\Programs\\\\Python\\\\Python311\\\\Lib\\\\site-packages\\\\gradio\\\\frpc_windows_amd64_v0.3\" \"https://hf-mirror.com/frpc-gradio-0.3/resolve/main/frpc_windows_amd64.exe\")",
|
| 32 |
+
"Bash(curl *)",
|
| 33 |
+
"Bash(gradio deploy *)",
|
| 34 |
+
"Bash(pip freeze *)",
|
| 35 |
+
"Bash(huggingface-cli whoami *)",
|
| 36 |
+
"Bash(hf auth *)"
|
| 37 |
+
]
|
| 38 |
+
}
|
| 39 |
+
}
|
.env.backup
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
GITHUB_TOKEN=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
|
| 2 |
+
NGROK_AUTH_TOKEN=3DHp7jn8WuHK6PhtgOTTAcmptnT_5ZdsV7VpfD6WQTKDeYD9r
|
.gitignore
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*.pyo
|
| 5 |
+
*.egg-info/
|
| 6 |
+
|
| 7 |
+
# Environment
|
| 8 |
+
.env
|
| 9 |
+
|
| 10 |
+
# IDE
|
| 11 |
+
.vscode/
|
| 12 |
+
.idea/
|
| 13 |
+
|
| 14 |
+
# OS
|
| 15 |
+
.DS_Store
|
| 16 |
+
Thumbs.db
|
.gradio/certificate.pem
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN CERTIFICATE-----
|
| 2 |
+
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
|
| 3 |
+
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
| 4 |
+
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
|
| 5 |
+
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
|
| 6 |
+
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
|
| 7 |
+
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
|
| 8 |
+
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
|
| 9 |
+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
|
| 10 |
+
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
|
| 11 |
+
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
|
| 12 |
+
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
|
| 13 |
+
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
|
| 14 |
+
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
|
| 15 |
+
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
|
| 16 |
+
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
|
| 17 |
+
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
|
| 18 |
+
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
|
| 19 |
+
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
|
| 20 |
+
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
|
| 21 |
+
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
|
| 22 |
+
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
|
| 23 |
+
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
|
| 24 |
+
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
|
| 25 |
+
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
|
| 26 |
+
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
|
| 27 |
+
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
|
| 28 |
+
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
|
| 29 |
+
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
|
| 30 |
+
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
|
| 31 |
+
-----END CERTIFICATE-----
|
.gradio/flagged/dataset1.csv
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
่ฎบๆ arxiv ้พๆฅ,็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ,timestamp
|
| 2 |
+
,"## โ ๏ธ ่ฏท่พๅ
ฅ arxiv ่ฎบๆ้พๆฅ
|
| 3 |
+
|
| 4 |
+
็คบไพ: `https://arxiv.org/abs/2011.08785`",2026-05-05 10:05:48.041973
|
README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
| 1 |
---
|
| 2 |
title: ResearchRadar
|
| 3 |
-
|
| 4 |
-
colorFrom: yellow
|
| 5 |
-
colorTo: gray
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: 6.14.0
|
| 8 |
-
python_version: '3.13'
|
| 9 |
-
app_file: app.py
|
| 10 |
-
pinned: false
|
| 11 |
---
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: ResearchRadar
|
| 3 |
+
app_file: app.py
|
|
|
|
|
|
|
| 4 |
sdk: gradio
|
| 5 |
sdk_version: 6.14.0
|
|
|
|
|
|
|
|
|
|
| 6 |
---
|
| 7 |
|
| 8 |
+
# ResearchRadar โ ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ
|
| 9 |
+
|
| 10 |
+
่พๅ
ฅไธ็ฏ AI ่ฎบๆ็ arxiv ้พๆฅ๏ผ่ชๅจ็ๆ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ๏ผ
|
| 11 |
+
|
| 12 |
+
1. **็ ็ฉถๆนๅๅ
จๆฏ** โ ๅญ้ขๅๅฎไฝ + ๆนๆณๆ่ฐฑ็ณป + ๅผๆบ่ฆ็ๅบฆ
|
| 13 |
+
2. **ๅผๆบๅฎ็ฐ่ฏไผฐ** โ ๅ
ญ็ปดๅบฆๆๅ๏ผ็ฏๅข้
็ฝฎใๆๆกฃใไปฃ็ ใ็คพๅบใไพ่ตใๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผ
|
| 14 |
+
3. **ๅฏนๆฏๅฎ้ชๆจ่** โ ๆๅฐฑ็ปชๅบฆๅ็ป๏ผๅฏ็ดๆฅ็จ / ้ไฟฎๆน / ไป
ๅ่๏ผ
|
ResearchRadar_Week1_Demo_ๆนๆก.md
ADDED
|
@@ -0,0 +1,1225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ResearchRadar ้กน็ฎไปปๅกไนฆ
|
| 2 |
+
|
| 3 |
+
> ่ฏป่
๏ผ็ฒใไน๏ผ็ ไธ๏ผๅไธบ Python ๅ
ฅ้จๆฐดๅนณ๏ผ
|
| 4 |
+
> ็จ้๏ผ็ฌฌไธๅจๆผ็คบๆฑๆฅ + ๅ็ปญ 6 ๅจๅผๅ็ๆง่กไพๆฎ
|
| 5 |
+
> ๆฑๆฅๅฏน่ฑก๏ผๅฏผๅธ + ๆ่ตไบบ | ๆถ้ฟ๏ผ6 ๅ้
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## ไธใ้กน็ฎๅฎไน
|
| 10 |
+
|
| 11 |
+
### 1.1 ๆไปฌ่ฆ่งฃๅณไปไน้ฎ้ข
|
| 12 |
+
|
| 13 |
+
AI ็ ็ฉถ่
่ฏปๅฐไธ็ฏ่ฎบๆๅ๏ผๆณๅจ่ฏฅๆนๅๅผๅฑ็ ็ฉถใๅ่ฎบๆ่ทๅฏนๆฏๅฎ้ช๏ผ้ขไธดไธไธช้่ฟ็็็น๏ผ
|
| 14 |
+
|
| 15 |
+
| ็็น | ๅ
ทไฝๆ่ฟฐ | ไบบๅทฅ่ๆถ |
|
| 16 |
+
|------|----------|----------|
|
| 17 |
+
| **ๆธๆธ
ๆนๅ้พ** | ่ฏปๅฎไธ็ฏ่ฎบๆ๏ผๆณ็ฅ้่ฟไธช็ ็ฉถๆนๅๆๅชไบไธปๆตๆนๆณๆใๅ่ชๆไปไนๅผๆบๅฎ็ฐใ็ฎๅๅๆฒฟๅจๅช้โโไฟกๆฏๅๆฃๅจ GitHubใPapersWithCodeใ็ฅไนใๅๅฎ้ชๅฎคไธป้กต๏ผๆผๅๅ
จๆฏๅพๆ่ดนๆถ้ด | 1~2 ๅคฉ |
|
| 18 |
+
| **ๆพๅฏนไปฃ็ ้พ** | ๅณไพฟๆพๅฐไธๅ ไปๅบ๏ผไนๅไธๆธ
ๅชไธชๆฏ"ๅฎๆนๅฎ็ฐ"ใๅชไธชๆฏ"็คพๅบๆ็ญๅค็ฐ"ใๅชไธชๅชๆฏ"ๅชๆ README ็็ฉบๅฃณ" | ๅๅคฉ~1 ๅคฉ |
|
| 19 |
+
| **่ฏไผฐ่ฝไธ่ฝ่ท้พ** | ็ไธญไธไธชไปๅบๆณๆฟๆฅ่ทๅฏนๆฏๅฎ้ช๏ผ่ฃ
ไบไธคๅคฉ็ฏๅขๅ็ฐไพ่ตๅดฉไบใๆฐๆฎ้ๆฒกๅ
ฌๅผใ่ฎญ็ป่ๆฌ่ทไธ้ | ๅๅคฉ~1 ๅคฉ |
|
| 20 |
+
|
| 21 |
+
**ResearchRadar ๅ็ไบๆ
**๏ผ่พๅ
ฅไธ็ฏ่ฎบๆ็ arxiv ้พๆฅ๏ผ่ชๅจๅฎๆใๆธๆธ
็ ็ฉถๆนๅๅ
จๆฏ โ ๆพๅฐ้ซ่ดจ้ๅผๆบๅฎ็ฐ โ ่ฏไผฐๅฏๅค็ฐๆง โ ๆจ่ๆ้ๅๆฟๆฅๅๅฏนๆฏๅฎ้ช็ไปๅบใใ
|
| 22 |
+
|
| 23 |
+
### 1.2 ่พๅ
ฅไธ่พๅบ
|
| 24 |
+
|
| 25 |
+
```
|
| 26 |
+
่พๅ
ฅ๏ผไธ็ฏ่ฎบๆ็ arxiv URL๏ผๅฆ https://arxiv.org/abs/1706.03762๏ผ
|
| 27 |
+
โ
|
| 28 |
+
่พๅบ๏ผไธไปฝ"็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ"๏ผๅ
ๅซ๏ผ
|
| 29 |
+
1. ็ ็ฉถๆนๅ่งฃ่ฏป๏ผ่ฟ็ฏ่ฎบๆๅฑไบไปไนๅญ้ขๅใ่ฏฅ้ขๅๆๅชไบไธปๆตๆนๆณๆ
|
| 30 |
+
2. ๅผๆบๅฎ็ฐๅ
จๆฏๅพ๏ผๆฏไธชๆนๆณๆไธๆๅชไบ้ซ่ดจ้ไปๅบ๏ผๅซ starใ็ปดๆค็ถๆใๆนๆณ็ฑปๅ๏ผ
|
| 31 |
+
3. ๆฏไธชไปๅบ็ๅฏๅค็ฐๆง่ฏๅ๏ผ0-100๏ผ+ ไบ็ปดๅบฆๆ็ป + ๅคๅฎ็็ฑ
|
| 32 |
+
4. ๅฏนๆฏๅฎ้ชๆจ่๏ผๅชไบไปๅบๅฏไปฅ็ดๆฅๆฟๆฅ่ท baseline / ๅฏนๆฏๅฎ้ช๏ผไธบไปไน
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
### 1.3 ๆ ธๅฟไปทๅผ้พ๏ผไธๅฑ๏ผ
|
| 36 |
+
|
| 37 |
+
```
|
| 38 |
+
่ฎบๆ่พๅ
ฅ
|
| 39 |
+
โ
|
| 40 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 41 |
+
โ ็ฌฌไธๅฑ๏ผ็ ็ฉถๆนๅ่งฃๆ โ
|
| 42 |
+
โ LLM ็่งฃ่ฎบๆ โ ่ฏๅซๅญ้ขๅ โ ๆขณ็ๆนๆณๆ่ฐฑ็ณป โ
|
| 43 |
+
โ ่พๅบ๏ผ่ฏฅๆนๅ็"็ ็ฉถๅฐๅพ" โ
|
| 44 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
| 45 |
+
โ ็ฌฌไบๅฑ๏ผๅผๆบไปฃ็ ๅ็ฐ โ
|
| 46 |
+
โ ้ๅฏนๆฏไธชๆนๆณๆๆ็ดข GitHub โ ๅป้ โ ๅ็ญ โ
|
| 47 |
+
โ ่พๅบ๏ผๆๆนๆณๆๅ็ฑป็ๅ้ไปๅบๅ่กจ โ
|
| 48 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
| 49 |
+
โ ็ฌฌไธๅฑ๏ผๅฏๅค็ฐๆง่ฏไผฐ + ๅฏนๆฏๅฎ้ช้้
ๅบฆ โ
|
| 50 |
+
โ ๆ README + ไพ่ต โ LLM ๅค็ปดๅบฆ่ฏๅ โ
|
| 51 |
+
โ ่พๅบ๏ผๆๅ + ๆจ่ + ้ฃ้ฉๆ็คบ โ
|
| 52 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 53 |
+
โ
|
| 54 |
+
็ ๆฅ่พๅบ๏ผ็ ็ฉถๆนๅๅ
จๆฏ + ไปฃ็ ๆจ่ + ๅค็ฐ้ฃ้ฉ่ฏไผฐ๏ผ
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
**ไธๅฑ็ผบไธไธๅฏ**๏ผไธ่งฃๆๆนๅๅฐฑๆไธๅไปฃ็ ๏ผไธ่ฏไผฐๅฐฑไธ็ฅ้่ฝไธ่ฝ่ท๏ผๆ็ป็ฎๆ ๆฏไธบ็ ็ฉถ่
ๅ่ฎบๆ่ทๅฏนๆฏๅฎ้ชๆไพๅฏ้ ็ๅๅคไปฃ็ ๅบใ
|
| 58 |
+
|
| 59 |
+
---
|
| 60 |
+
|
| 61 |
+
## ไบใ็ณป็ปๆถๆ
|
| 62 |
+
|
| 63 |
+
### 2.1 ๆปไฝๆถๆๅพ
|
| 64 |
+
|
| 65 |
+
```
|
| 66 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 67 |
+
โ ResearchRadar ็ณป็ป โ
|
| 68 |
+
โ โ
|
| 69 |
+
็จๆท่พๅ
ฅ arxiv URL โโโ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
| 70 |
+
โ โ ็ฌฌไธๅฑ๏ผ็ ็ฉถๆนๅ่งฃๆ๏ผAgent๏ผ โ โ
|
| 71 |
+
โ โ โ โ
|
| 72 |
+
โ โ 1. arxiv API โ ่ฎบๆๅ
ไฟกๆฏ โ โ
|
| 73 |
+
โ โ 2. LLM โ ๅญ้ขๅ่ฏๅซ + ๆนๆณๆๆขณ็ โ โ
|
| 74 |
+
โ โ 3. LLM โ ไธบๆฏไธชๆนๆณๆ็ๆๆ็ดข่ฏ โ โ
|
| 75 |
+
โ โ ่พๅบ๏ผ็ ็ฉถๆนๅ "ๅฐๅพ" โ โ
|
| 76 |
+
โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโ โ
|
| 77 |
+
โ โ โ
|
| 78 |
+
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
| 79 |
+
โ โ ็ฌฌไบๅฑ๏ผๅผๆบไปฃ็ ๅ็ฐ๏ผWorkflow๏ผ โ โ
|
| 80 |
+
โ โ โ โ
|
| 81 |
+
โ โ 1. GitHub Search โ ๅคๅ
ณ้ฎ่ฏๆ็ดข โ โ
|
| 82 |
+
โ โ 2. ๅป้ + ๆๆนๆณๆๅฝ็ฑป โ โ
|
| 83 |
+
โ โ 3. ๅ็ญ๏ผstar/ๆดๆฐๆถ้ด/่ฏญ่จ๏ผ โ โ
|
| 84 |
+
โ โ ่พๅบ๏ผๆๆนๆณๆๅ็ฑป็ๅ้ไปๅบๅ่กจ โ โ
|
| 85 |
+
โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโ โ
|
| 86 |
+
โ โ โ
|
| 87 |
+
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
| 88 |
+
โ โ ็ฌฌไธๅฑ๏ผ่ฏไผฐไธๆจ่๏ผAgent๏ผ โ โ
|
| 89 |
+
โ โ โ โ
|
| 90 |
+
โ โ ๅฏนๆฏไธชๅ้ไปๅบ๏ผ โ โ
|
| 91 |
+
โ โ 1. ๆ README + ไพ่ตๆไปถ๏ผWorkflow๏ผโ โ
|
| 92 |
+
โ โ 2. LLM โ ๅฏๅค็ฐๆงไบ็ปดๅบฆ่ฏๅ โ โ
|
| 93 |
+
โ โ 3. LLM โ ๅฏนๆฏๅฎ้ช้้
ๅบฆ่ฏไผฐ โ โ
|
| 94 |
+
โ โ 4. ็ปผๅๆๅบ + ็ๆๆจ่็็ฑ โ โ
|
| 95 |
+
โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโ โ
|
| 96 |
+
โ โ โ
|
| 97 |
+
โ ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ๏ผMarkdown๏ผ โ
|
| 98 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
### 2.2 ๆถๆไธญ็ไธค็ฑป็ปไปถ
|
| 102 |
+
|
| 103 |
+
ๆ็
ง่ทฏ็บฟๅคง็บฒ็็บฆๅฎ๏ผๆดไธช็ณป็ปๅ
ๅซไธค็ฑป็ปไปถ๏ผ
|
| 104 |
+
|
| 105 |
+
| ็ฑปๅ | ๅฎไน | ๆฌ็ณป็ปไธญ็ๅฏนๅบ |
|
| 106 |
+
|------|------|---------------|
|
| 107 |
+
| **Workflow**๏ผ่ทฏๅพๅๆญป๏ผ | ็กฎๅฎๆงๆต็จ๏ผไธๆถๅ LLM ๅณ็ญ | ่ฎบๆไฟกๆฏๆๅใGitHub ๆ็ดขใไพ่ตๆไปถๆซๆใไปๅบๅ
ไฟกๆฏๆๅใๅป้ๅฝ็ฑป |
|
| 108 |
+
| **Agent**๏ผLLM ๅณ็ญ๏ผ | ้่ฆ LLM ็่งฃๅๅคๆญ็่็น | ็ ็ฉถๆนๅ่งฃๆใๆนๆณๆๆขณ็ใๆ็ดข่ฏ็ๆใๅฏๅค็ฐๆง่ฏๅใๅฏนๆฏๅฎ้ช้้
ๅบฆ่ฏไผฐ |
|
| 109 |
+
|
| 110 |
+
**Week 1 ๅชๅฎ็ฐ Workflow + ๆ็ฎๅ็ Agent**๏ผbaseline ๆนๆก๏ผๅๆฌก LLM ่ฐ็จๅบ่ฏๅ๏ผไธๆถๅๅ็ฏ๏ผใๅฏนไบไธๅฑๆถๆ๏ผWeek 1 ไธไธชๅฑ้ฝไผๅฎ็ฐไฝๆฏๅฑๅชไฟ็ๆ็ฎ็ๆฌ๏ผ
|
| 111 |
+
- ็ฌฌไธๅฑ๏ผ1 ๆฌก LLM ่ฐ็จๅฎๆๆนๅ่งฃๆ + ๅ
ณ้ฎ่ฏ็ๆ
|
| 112 |
+
- ็ฌฌไบๅฑ๏ผ็ดๆฅ็จๅ
ณ้ฎ่ฏๆ GitHub๏ผไธๅ ๆนๆณๆๅฝ็ฑป๏ผๅฝ็ฑป้ป่พ Week 3 ๅ ๏ผ
|
| 113 |
+
- ็ฌฌไธๅฑ๏ผ1 ๆฌก LLM ่ฐ็จๅฎๆๅฏๅค็ฐๆง่ฏๅ + ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผๅๅนถไธบไธไธช prompt๏ผ
|
| 114 |
+
|
| 115 |
+
---
|
| 116 |
+
|
| 117 |
+
## ไธใๆๆฏ้ๅ
|
| 118 |
+
|
| 119 |
+
| ้กน | ้ๅ | ็็ฑ |
|
| 120 |
+
|----|------|------|
|
| 121 |
+
| **็ผ็จ่ฏญ่จ** | Python 3.10+ | ไธคไบบ้ฝไผ๏ผ็ๆๆๅฅฝ |
|
| 122 |
+
| **LLM ่ฐ็จ** | DeepSeek API๏ผOpenAI SDK๏ผ | ไฝ ไปฌๆๆ ้้ขๅบฆ็ key๏ผไธญๆ่ฝๅๅผบ๏ผไพฟๅฎ |
|
| 123 |
+
| **่ฎบๆไฟกๆฏ** | arxiv REST API | ๅ
่ดนใๆ ้่ฎค่ฏใ่ฆ็ๆๆ AI ่ฎบๆ |
|
| 124 |
+
| **ไปฃ็ ๆ็ดข** | GitHub Search REST API | ๅ
่ดน๏ผๅธฆ token 30ๆฌก/ๅ้๏ผ๏ผๅฏๆๅ
ณ้ฎ่ฏใ่ฏญ่จใstar ็ญ้ |
|
| 125 |
+
| **ๆฐๆฎๆๅ** | `requests` + ๆ ๅๅบ | ไธๅผๅ
ฅ็ฌ่ซๆกๆถ |
|
| 126 |
+
| **UI** | Gradio | ่ทฏ็บฟๅคง็บฒๅทฒๅฎๆญป๏ผ่ฝป้ๅค็จ |
|
| 127 |
+
| **็ถๆ็ฎก็** | Python dict | ไธๅผๅ
ฅไปปไฝ็ถๆ็ฎก็ๆกๆถ |
|
| 128 |
+
| **ๅ
็ฎก็** | pip + requirements.txt | ไธคไบบ้ฝๅจ Windows ไธ๏ผ็ฎๅ็ฌฌไธ |
|
| 129 |
+
|
| 130 |
+
---
|
| 131 |
+
|
| 132 |
+
## ๅใ็ฌฌไธๅจ MVP ่ๅด
|
| 133 |
+
|
| 134 |
+
### 4.1 MVP ็ฎๆ
|
| 135 |
+
|
| 136 |
+
**ไธๅฅ่ฏ**๏ผ`python run.py <arxiv_url>` ่ฝ่ท้ๅฎๆด้พ่ทฏโโไป่ฎบๆๅฐๆจ่ไปๅบใ
|
| 137 |
+
|
| 138 |
+
### 4.2 MVP ๅ
ๅซไปไน๏ผ7 ไธชๆจกๅ๏ผ
|
| 139 |
+
|
| 140 |
+
```
|
| 141 |
+
ๆจกๅ 1: ่ฎบๆไฟกๆฏๆๅ arxiv API โ ๆ ้ขใๆ่ฆใไฝ่
ใๅ็ฑป
|
| 142 |
+
ๆจกๅ 2: ็ ็ฉถๆนๅ่งฃๆ + ๅ
ณ้ฎ่ฏ LLM โ ๅญ้ขๅ่ฏๅซ + ๆนๆณๆๆขณ็ + ๆ็ดข่ฏ็ๆ๏ผ1 ๆฌก่ฐ็จๅฎๆ๏ผ
|
| 143 |
+
ๆจกๅ 3: GitHub ไปฃ็ ๆ็ดข GitHub Search API โ ๅคๅ
ณ้ฎ่ฏๆ็ดข๏ผๅป้๏ผๆ star ๆๅบ
|
| 144 |
+
ๆจกๅ 4: ไปๅบ่ฏฆๆ
ๆๅ ๅฏน top 5 ๅ้ไปๅบ๏ผๆ README + ไพ่ตๆไปถ + ๅ
ไฟกๆฏ
|
| 145 |
+
ๆจกๅ 5: ๅฏๅค็ฐๆง + ้้
ๅบฆ่ฏไผฐ LLM โ ๅ
ญ็ปดๅบฆ่ฏๅ๏ผๅฏๅค็ฐๆง 5 ็ปด + ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผ
|
| 146 |
+
ๆจกๅ 6: ๆๅบๆจ่ ็ปผๅๅ ๆๆๅบ๏ผ็ๆๆจ่็็ฑ
|
| 147 |
+
ๆจกๅ 7: Gradio ็ ๆฅ่พๅบ ็ปๆๅ Markdown๏ผๆนๅๅ
จๆฏ + ไปๅบๆ่ก + ๆจ่ๅปบ่ฎฎ
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
### 4.3 MVP ไธๅ
ๅซไปไน
|
| 151 |
+
|
| 152 |
+
- โ Issue ๆๅไธๅๆ๏ผๆจกๅ่ฟๅคง๏ผWeek 2 ๅ ๏ผ
|
| 153 |
+
- โ Agent ๅ็ฏๆบๅถ๏ผWeek 4 ๅ ๏ผ
|
| 154 |
+
- โ ๆตๅผ่พๅบ๏ผWeek 5 ๅ ๏ผ
|
| 155 |
+
- โ ๅค่ฝฎๅนถๅ๏ผๅง็ปไธฒ่ก๏ผๅ
่ท้ๅไผๅ๏ผ
|
| 156 |
+
- โ ๅคๆ็้่ฏฏๆขๅค๏ผ็ฝ็ปๆไบๅฐฑๆฅ้๏ผไธๅๅผๅธธ๏ผ
|
| 157 |
+
|
| 158 |
+
---
|
| 159 |
+
|
| 160 |
+
## ไบใ็ฒ็ไปปๅก๏ผๆฐๆฎๅฑ๏ผ
|
| 161 |
+
|
| 162 |
+
็ฒ่ด่ดฃ **ๆๆไธๅค้จ API ๆไบค้** ็ๆจกๅ๏ผ่ฎบๆไฟกๆฏใไปฃ็ ๆ็ดขใไปๅบ่ฏฆๆ
ๆๅใ่ฏๆต้ๅปบ่ฎพใ
|
| 163 |
+
|
| 164 |
+
### 5.1 ๆจกๅ 1๏ผ่ฎบๆไฟกๆฏๆๅ `paper_fetcher.py`
|
| 165 |
+
|
| 166 |
+
**ๅไปไน**๏ผ่พๅ
ฅ arxiv URL โ ่พๅบ่ฎบๆๆ ้ขใๆ่ฆใไฝ่
ใๅ็ฑปๆ ็ญพใ
|
| 167 |
+
|
| 168 |
+
**ๆๆฏ่ฆ็น**๏ผ
|
| 169 |
+
- arxiv API ็ซฏ็น๏ผ`http://export.arxiv.org/api/query?id_list={arxiv_id}&max_results=1`
|
| 170 |
+
- ่ฟๅ Atom XML ๆ ผๅผ๏ผ็จๆ ๅๅบ `xml.etree.ElementTree` ่งฃๆ๏ผ**ไธๅผๅ
ฅ้ขๅคไพ่ต**
|
| 171 |
+
- **ๅฟ
้กปๅ User-Agent ่ฏทๆฑๅคด**๏ผๅฆๅ arxiv ๅฏ่ฝๆ็ป่ฏทๆฑ
|
| 172 |
+
- arxiv ID ไป URL ไธญๆๅ๏ผ`https://arxiv.org/abs/1706.03762` โ `1706.03762`๏ผๅ
ผๅฎน `abs`ใ`pdf` ็ญๅ็ผ
|
| 173 |
+
|
| 174 |
+
```python
|
| 175 |
+
# paper_fetcher.py
|
| 176 |
+
import urllib.request
|
| 177 |
+
import urllib.error
|
| 178 |
+
import xml.etree.ElementTree as ET
|
| 179 |
+
import re
|
| 180 |
+
|
| 181 |
+
def extract_arxiv_id(url: str) -> str:
|
| 182 |
+
"""ไป arxiv URL ๆๅ่ฎบๆ ID
|
| 183 |
+
ๆฏๆๆ ผๅผ:
|
| 184 |
+
- https://arxiv.org/abs/1706.03762
|
| 185 |
+
- https://arxiv.org/abs/1706.03762v2
|
| 186 |
+
- https://arxiv.org/pdf/1706.03762.pdf
|
| 187 |
+
- arxiv:1706.03762
|
| 188 |
+
- 1706.03762
|
| 189 |
+
"""
|
| 190 |
+
# ๅฐ่ฏๅน้
URL ๆ ผๅผ
|
| 191 |
+
match = re.search(r'arxiv\.org/(?:abs|pdf)/(\d{4}\.\d{4,5})(?:v\d+)?(?:\.pdf)?', url)
|
| 192 |
+
if match:
|
| 193 |
+
return match.group(1)
|
| 194 |
+
# ๅฐ่ฏๅน้
arxiv:ID ๆ็ดๆฅ ID ๆ ผๅผ
|
| 195 |
+
match = re.search(r'(?:arxiv:)?(\d{4}\.\d{4,5})', url)
|
| 196 |
+
if match:
|
| 197 |
+
return match.group(1)
|
| 198 |
+
raise ValueError(f"ๆ ๆณไป URL ๆๅ arxiv ID: {url}")
|
| 199 |
+
|
| 200 |
+
def fetch_paper_info(arxiv_url: str) -> dict:
|
| 201 |
+
"""ไป arxiv ่ทๅ่ฎบๆๅ
ไฟกๆฏ
|
| 202 |
+
่ฟๅ: {"arxiv_id": str, "title": str, "abstract": str,
|
| 203 |
+
"authors": [str, ...], "categories": [str, ...], "published": str}
|
| 204 |
+
"""
|
| 205 |
+
arxiv_id = extract_arxiv_id(arxiv_url)
|
| 206 |
+
api_url = f"http://export.arxiv.org/api/query?id_list={arxiv_id}&max_results=1"
|
| 207 |
+
|
| 208 |
+
req = urllib.request.Request(api_url, headers={"User-Agent": "ResearchRadar/1.0"})
|
| 209 |
+
try:
|
| 210 |
+
with urllib.request.urlopen(req, timeout=15) as resp:
|
| 211 |
+
xml_text = resp.read().decode("utf-8")
|
| 212 |
+
except urllib.error.HTTPError as e:
|
| 213 |
+
raise RuntimeError(f"arxiv API ่ฏทๆฑๅคฑ่ดฅ (HTTP {e.code})๏ผ่ฏทๆฃๆฅ่ฎบๆ ID ๆฏๅฆๆญฃ็กฎ")
|
| 214 |
+
except urllib.error.URLError as e:
|
| 215 |
+
raise RuntimeError(f"ๆ ๆณ่ฟๆฅ arxiv API๏ผ่ฏทๆฃๆฅ็ฝ็ป: {e.reason}")
|
| 216 |
+
|
| 217 |
+
root = ET.fromstring(xml_text)
|
| 218 |
+
ns = {
|
| 219 |
+
"atom": "http://www.w3.org/2005/Atom",
|
| 220 |
+
"arxiv": "http://arxiv.org/schemas/atom",
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
entry = root.find("atom:entry", ns)
|
| 224 |
+
if entry is None:
|
| 225 |
+
raise ValueError(f"arxiv ๆชๆพๅฐ่ฎบๆ {arxiv_id}๏ผ่ฏทๆฃๆฅ ID ๆฏๅฆๆญฃ็กฎ")
|
| 226 |
+
|
| 227 |
+
title_el = entry.find("atom:title", ns)
|
| 228 |
+
summary_el = entry.find("atom:summary", ns)
|
| 229 |
+
title = title_el.text.strip().replace("\n", " ") if title_el is not None and title_el.text else ""
|
| 230 |
+
abstract = summary_el.text.strip().replace("\n", " ") if summary_el is not None and summary_el.text else ""
|
| 231 |
+
|
| 232 |
+
authors = [
|
| 233 |
+
a.find("atom:name", ns).text
|
| 234 |
+
for a in entry.findall("atom:author", ns)
|
| 235 |
+
if a.find("atom:name", ns) is not None
|
| 236 |
+
]
|
| 237 |
+
categories = [
|
| 238 |
+
c.get("term", "") for c in entry.findall("atom:category", ns)
|
| 239 |
+
]
|
| 240 |
+
published_el = entry.find("atom:published", ns)
|
| 241 |
+
published = published_el.text if published_el is not None and published_el.text else ""
|
| 242 |
+
|
| 243 |
+
return {
|
| 244 |
+
"arxiv_id": arxiv_id,
|
| 245 |
+
"title": title,
|
| 246 |
+
"abstract": abstract,
|
| 247 |
+
"authors": authors,
|
| 248 |
+
"categories": categories,
|
| 249 |
+
"published": published,
|
| 250 |
+
}
|
| 251 |
+
```
|
| 252 |
+
|
| 253 |
+
### 5.2 ๆจกๅ 3๏ผGitHub ไปฃ็ ๆ็ดข `repo_searcher.py`
|
| 254 |
+
|
| 255 |
+
**ๅไปไน**๏ผ็ปๅฎไธไธชๅ
ณ้ฎ่ฏๅ่กจ โ ๆ็ดข GitHub ่ฟๅ็ธๅ
ณไปๅบๅ่กจใ
|
| 256 |
+
|
| 257 |
+
**ๆๆฏ่ฆ็น**๏ผ
|
| 258 |
+
- GitHub Search API๏ผ`GET /search/repositories?q={query}&sort=stars&order=desc&per_page=5`
|
| 259 |
+
- ๆ็ดข query ๆ้ ๏ผ็จๅ
ณ้ฎ่ฏ + ้ๅฎๆกไปถ๏ผlanguage:pythonใstars ้จๆง๏ผ
|
| 260 |
+
- **ๆ็ดขๆฅๅฃ้้ๆดไธฅ**๏ผๅธฆ token 30 ๆฌก/ๅ้๏ผไธๅธฆ token 10 ๆฌก/ๅ้ใไฝ ไปฌไธคไบบๅ็ณ่ฏทไธไธช token๏ผๅจไปฃ็ ้่ฝฎๆข
|
| 261 |
+
- ่ฟๅ็ปๆๅป้๏ผๅไธไธช repo ๅฏ่ฝ่ขซไธๅๅ
ณ้ฎ่ฏๆๅฐๅคๆฌก๏ผ
|
| 262 |
+
|
| 263 |
+
```python
|
| 264 |
+
# repo_searcher.py
|
| 265 |
+
import requests
|
| 266 |
+
import os
|
| 267 |
+
|
| 268 |
+
GITHUB_TOKENS = [
|
| 269 |
+
os.getenv("GITHUB_TOKEN_1", ""),
|
| 270 |
+
os.getenv("GITHUB_TOKEN_2", ""),
|
| 271 |
+
]
|
| 272 |
+
GITHUB_TOKENS = [t for t in GITHUB_TOKENS if t] # ่ฟๆปค็ฉบๅผ
|
| 273 |
+
_token_index = 0
|
| 274 |
+
|
| 275 |
+
def _get_token():
|
| 276 |
+
"""่ฝฎๆขไฝฟ็จไธคไธช token๏ผ้ไฝ้้้ฃ้ฉ"""
|
| 277 |
+
global _token_index
|
| 278 |
+
if not GITHUB_TOKENS:
|
| 279 |
+
return ""
|
| 280 |
+
token = GITHUB_TOKENS[_token_index]
|
| 281 |
+
_token_index = (_token_index + 1) % len(GITHUB_TOKENS)
|
| 282 |
+
return token
|
| 283 |
+
|
| 284 |
+
def _get_headers():
|
| 285 |
+
token = _get_token()
|
| 286 |
+
if token:
|
| 287 |
+
return {"Authorization": f"Bearer {token}", "Accept": "application/vnd.github.v3+json"}
|
| 288 |
+
return {"Accept": "application/vnd.github.v3+json"}
|
| 289 |
+
|
| 290 |
+
def search_repos(keywords: list[str], max_per_keyword: int = 5, language: str = "python") -> list[dict]:
|
| 291 |
+
"""็จๅ
ณ้ฎ่ฏๅ่กจๆ็ดข GitHub ไปๅบ
|
| 292 |
+
่ฟๅ: ๅป้ๅ็ไปๅบๅ่กจ๏ผๆ star ้ๅบๆๅ
|
| 293 |
+
"""
|
| 294 |
+
seen = set()
|
| 295 |
+
results = []
|
| 296 |
+
|
| 297 |
+
for kw in keywords:
|
| 298 |
+
# ๆ้ ๆฅ่ฏข๏ผๅ
ณ้ฎ่ฏ + Python + ่ณๅฐ 5 ไธช star๏ผ่ฟๆปค็ฉบๅฃณไปๅบ๏ผ
|
| 299 |
+
query = f"{kw} language:{language} stars:>=5"
|
| 300 |
+
url = "https://api.github.com/search/repositories"
|
| 301 |
+
params = {"q": query, "sort": "stars", "order": "desc", "per_page": max_per_keyword}
|
| 302 |
+
|
| 303 |
+
try:
|
| 304 |
+
resp = requests.get(url, headers=_get_headers(), params=params, timeout=15)
|
| 305 |
+
if resp.status_code == 403 and "rate limit" in resp.text.lower():
|
| 306 |
+
print(f"[่ญฆๅ] GitHub ๆ็ดข้้๏ผ่ทณ่ฟๅ
ณ้ฎ่ฏ: {kw}")
|
| 307 |
+
continue
|
| 308 |
+
resp.raise_for_status()
|
| 309 |
+
data = resp.json()
|
| 310 |
+
except Exception as e:
|
| 311 |
+
print(f"[่ญฆๅ] ๆ็ดขๅ
ณ้ฎ่ฏ '{kw}' ๅคฑ่ดฅ: {e}")
|
| 312 |
+
continue
|
| 313 |
+
|
| 314 |
+
for item in data.get("items", []):
|
| 315 |
+
full_name = item["full_name"]
|
| 316 |
+
if full_name not in seen:
|
| 317 |
+
seen.add(full_name)
|
| 318 |
+
results.append({
|
| 319 |
+
"full_name": full_name,
|
| 320 |
+
"html_url": item["html_url"],
|
| 321 |
+
"description": item.get("description", ""),
|
| 322 |
+
"stars": item.get("stargazers_count", 0),
|
| 323 |
+
"language": item.get("language", ""),
|
| 324 |
+
"topics": item.get("topics", []),
|
| 325 |
+
"updated_at": item.get("updated_at", ""),
|
| 326 |
+
"match_keyword": kw,
|
| 327 |
+
})
|
| 328 |
+
|
| 329 |
+
# ๆ star ้ๅบ
|
| 330 |
+
results.sort(key=lambda r: r["stars"], reverse=True)
|
| 331 |
+
return results
|
| 332 |
+
```
|
| 333 |
+
|
| 334 |
+
### 5.3 ๆจกๅ 5๏ผ็ไธ้จๅ๏ผ๏ผไปๅบ่ฏฆๆ
ๆๅ `repo_fetcher.py`
|
| 335 |
+
|
| 336 |
+
**ๅไปไน**๏ผ็ปๅฎไธไธช GitHub ไปๅบ็ owner/repo โ ๆ READMEใไพ่ตๆไปถใๅ
ไฟกๆฏใ
|
| 337 |
+
|
| 338 |
+
่ฟไธไนๅๆนๆก็ๅ
ๅฎนไธ่ด๏ผไฝ้่ฆๆณจๆ๏ผ็ฐๅจๆฏ**ๆน้ๆๅ**๏ผไธไธช่ฎบๆๅฏนๅบ 5 ไธชๅ้ไปๅบ๏ผ๏ผ้่ฆๅค็้จๅไปๅบๆๅๅคฑ่ดฅ็ๆ
ๅตโโไธ่ฝๅ ไธบไธไธชไปๅบๅคฑ่ดฅไบๅฐฑ่ฎฉๆดไธชๆต็จๅดฉๆบใ
|
| 339 |
+
|
| 340 |
+
```python
|
| 341 |
+
# repo_fetcher.py
|
| 342 |
+
import os
|
| 343 |
+
import base64
|
| 344 |
+
import requests
|
| 345 |
+
|
| 346 |
+
GITHUB_TOKENS = [
|
| 347 |
+
os.getenv("GITHUB_TOKEN_1", ""),
|
| 348 |
+
os.getenv("GITHUB_TOKEN_2", ""),
|
| 349 |
+
]
|
| 350 |
+
GITHUB_TOKENS = [t for t in GITHUB_TOKENS if t]
|
| 351 |
+
_token_index = 0
|
| 352 |
+
|
| 353 |
+
def _get_token():
|
| 354 |
+
global _token_index
|
| 355 |
+
if not GITHUB_TOKENS:
|
| 356 |
+
return ""
|
| 357 |
+
token = GITHUB_TOKENS[_token_index]
|
| 358 |
+
_token_index = (_token_index + 1) % len(GITHUB_TOKENS)
|
| 359 |
+
return token
|
| 360 |
+
|
| 361 |
+
API_BASE = "https://api.github.com"
|
| 362 |
+
|
| 363 |
+
DEPENDENCY_FILENAMES = [
|
| 364 |
+
"requirements.txt", "environment.yml", "environment.yaml",
|
| 365 |
+
"setup.py", "setup.cfg", "pyproject.toml",
|
| 366 |
+
"Pipfile", "Pipfile.lock", "Dockerfile", "Makefile", "CMakeLists.txt",
|
| 367 |
+
]
|
| 368 |
+
|
| 369 |
+
def _github_get(owner: str, repo: str, endpoint: str) -> dict | None:
|
| 370 |
+
"""็ปไธ็ GitHub API GET ่ฏทๆฑ"""
|
| 371 |
+
headers = {"Accept": "application/vnd.github.v3+json"}
|
| 372 |
+
token = _get_token()
|
| 373 |
+
if token:
|
| 374 |
+
headers["Authorization"] = f"Bearer {token}"
|
| 375 |
+
|
| 376 |
+
url = f"{API_BASE}/repos/{owner}/{repo}/{endpoint}" if endpoint else f"{API_BASE}/repos/{owner}/{repo}"
|
| 377 |
+
resp = requests.get(url, headers=headers, timeout=15)
|
| 378 |
+
if resp.status_code == 404:
|
| 379 |
+
return None
|
| 380 |
+
if resp.status_code in (403, 429):
|
| 381 |
+
raise RuntimeError(f"GitHub API ้้ๆๆ็ป่ฎฟ้ฎ: {resp.status_code}")
|
| 382 |
+
resp.raise_for_status()
|
| 383 |
+
return resp.json()
|
| 384 |
+
|
| 385 |
+
def fetch_readme(owner: str, repo: str) -> str | None:
|
| 386 |
+
"""ๆๅ README ๅ
ๅฎน๏ผๅทฒ่งฃ็ ็็บฏๆๆฌ๏ผ"""
|
| 387 |
+
data = _github_get(owner, repo, "readme")
|
| 388 |
+
if not data:
|
| 389 |
+
return None
|
| 390 |
+
content = data.get("content", "")
|
| 391 |
+
try:
|
| 392 |
+
return base64.b64decode(content).decode("utf-8", errors="replace")
|
| 393 |
+
except Exception:
|
| 394 |
+
return None
|
| 395 |
+
|
| 396 |
+
def fetch_dependencies(owner: str, repo: str) -> dict[str, str]:
|
| 397 |
+
"""ๆๅๆๆไพ่ตๆไปถ๏ผ่ฟๅ {ๆไปถๅ: ๅ
ๅฎน}"""
|
| 398 |
+
result = {}
|
| 399 |
+
contents = _github_get(owner, repo, "contents") or []
|
| 400 |
+
for item in contents:
|
| 401 |
+
name = item.get("name", "")
|
| 402 |
+
if name in DEPENDENCY_FILENAMES:
|
| 403 |
+
file_data = _github_get(owner, repo, f"contents/{name}")
|
| 404 |
+
if file_data and file_data.get("content"):
|
| 405 |
+
try:
|
| 406 |
+
decoded = base64.b64decode(file_data["content"]).decode("utf-8", errors="replace")
|
| 407 |
+
result[name] = decoded
|
| 408 |
+
except Exception:
|
| 409 |
+
pass
|
| 410 |
+
return result
|
| 411 |
+
|
| 412 |
+
def fetch_issues(owner: str, repo: str, max_count: int = 30) -> list[dict]:
|
| 413 |
+
"""ๆๅๆ่ฟ็ Issues๏ผไธบ Week 2 ้ข็ๆฅๅฃ๏ผWeek 1 ๅฏไปฅไธ่ฐ็จ๏ผ"""
|
| 414 |
+
issues = []
|
| 415 |
+
page = 1
|
| 416 |
+
while len(issues) < max_count:
|
| 417 |
+
params = {"state": "all", "sort": "created", "direction": "desc",
|
| 418 |
+
"per_page": min(30, max_count - len(issues)), "page": page}
|
| 419 |
+
resp = requests.get(
|
| 420 |
+
f"{API_BASE}/repos/{owner}/{repo}/issues",
|
| 421 |
+
headers=_get_headers(),
|
| 422 |
+
params=params,
|
| 423 |
+
timeout=15,
|
| 424 |
+
)
|
| 425 |
+
if resp.status_code != 200:
|
| 426 |
+
break
|
| 427 |
+
page_items = resp.json()
|
| 428 |
+
if not page_items:
|
| 429 |
+
break
|
| 430 |
+
for item in page_items:
|
| 431 |
+
if "pull_request" not in item: # GitHub Issues API ไผๆททๅ
ฅ PR๏ผ้่ฆ่ฟๆปค
|
| 432 |
+
issues.append({
|
| 433 |
+
"title": item.get("title", ""),
|
| 434 |
+
"state": item.get("state", ""),
|
| 435 |
+
"created_at": item.get("created_at", ""),
|
| 436 |
+
"body": (item.get("body") or "")[:500], # ๆชๆญ๏ผๅช่ฆๅ 500 ๅญ็ฌฆ
|
| 437 |
+
"comments": item.get("comments", 0),
|
| 438 |
+
})
|
| 439 |
+
page += 1
|
| 440 |
+
return issues
|
| 441 |
+
|
| 442 |
+
def _get_headers():
|
| 443 |
+
token = _get_token()
|
| 444 |
+
headers = {"Accept": "application/vnd.github.v3+json"}
|
| 445 |
+
if token:
|
| 446 |
+
headers["Authorization"] = f"Bearer {token}"
|
| 447 |
+
return headers
|
| 448 |
+
```
|
| 449 |
+
|
| 450 |
+
### 5.4 ่ฏๆต้ๅปบ่ฎพ
|
| 451 |
+
|
| 452 |
+
**่ฟๆฏๆดไธช้กน็ฎๆ้่ฆ็่ตไบง**ใ่ฏๆต้ๅไธค้จๅ๏ผ
|
| 453 |
+
|
| 454 |
+
**Part A๏ผไปฃ็ ๅ็ฐ่ฏๆต้๏ผ10 ็ฏ่ฎบๆ๏ผ**
|
| 455 |
+
|
| 456 |
+
ๆฏ็ฏ่ฎบๆๆ ๆณจ๏ผๅทฒ็ฅ็ๆไฝณๅผๆบๅฎ็ฐ๏ผground truth ไปๅบ๏ผใ
|
| 457 |
+
|
| 458 |
+
```json
|
| 459 |
+
{
|
| 460 |
+
"paper_arxiv_id": "1706.03762",
|
| 461 |
+
"paper_title": "Attention Is All You Need",
|
| 462 |
+
"paper_keywords_human": ["transformer", "attention mechanism", "seq2seq", "neural machine translation"],
|
| 463 |
+
"known_implementations": [
|
| 464 |
+
{"full_name": "huggingface/transformers", "relevance": "official"},
|
| 465 |
+
{"full_name": "tensorflow/tensor2tensor", "relevance": "official"},
|
| 466 |
+
{"full_name": "jadore801120/attention-is-all-you-need-pytorch", "relevance": "community"}
|
| 467 |
+
]
|
| 468 |
+
}
|
| 469 |
+
```
|
| 470 |
+
|
| 471 |
+
**Part B๏ผๅฏๅค็ฐๆง่ฏๆต้๏ผ20 ไธชไปๅบ๏ผ**
|
| 472 |
+
|
| 473 |
+
ๆฒฟ็จ่ทฏ็บฟๅคง็บฒ็ๆนๆก๏ผ10 ไธชๆญฃๆ ทๆฌ + 10 ไธช่ดๆ ทๆฌใ
|
| 474 |
+
|
| 475 |
+
```json
|
| 476 |
+
{
|
| 477 |
+
"repo_url": "https://github.com/xxx/yyy",
|
| 478 |
+
"ground_truth": "reproducible",
|
| 479 |
+
"evidence": ["่ฏๆฎ1", "่ฏๆฎ2"],
|
| 480 |
+
"rationale": "ไธบไปไน่ฟๆ ทๆ ๆณจ"
|
| 481 |
+
}
|
| 482 |
+
```
|
| 483 |
+
|
| 484 |
+
**Week 1 ๆไฝ่ฆๆฑ**๏ผPart A ๆ ๅฎ 3 ็ฏ่ฎบๆ๏ผ็จไบ demo๏ผ๏ผPart B ๆ ๅฎ 6-8 ไธชไปๅบใไธ้่ฆๅจ demo ๆถๅฑ็คบ่ฏๆต้๏ผไฝๆ ๆณจๅทฅไฝๆฏๆดไธช้กน็ฎ็ๅบๅใ
|
| 485 |
+
|
| 486 |
+
---
|
| 487 |
+
|
| 488 |
+
## ๅ
ญใไน็ไปปๅก๏ผLLM + ้ๆๅฑ๏ผ
|
| 489 |
+
|
| 490 |
+
ไน่ด่ดฃ **ๆๆไธ LLM ไบคไบ** ็ๆจกๅ๏ผๅ
ณ้ฎ่ฏๆๅใๅฏๅค็ฐๆง่ฏไผฐใไธปๆต็จ็ผๆใGradio ็้ขใ
|
| 491 |
+
|
| 492 |
+
### 6.1 ๆจกๅ 2๏ผ็ ็ฉถๆนๅ่งฃๆ + ๆ็ดข่ฏ็ๆ `direction_analyzer.py`
|
| 493 |
+
|
| 494 |
+
**ๅไปไน**๏ผ่พๅ
ฅ่ฎบๆๆ ้ข + ๆ่ฆ โ LLM ไธๆฌกๆงๅฎๆไธไปถไบ๏ผ(1) ่ฏๅซ่ฏฅ่ฎบๆๆๅฑๅญ้ขๅ๏ผ(2) ๆขณ็่ฏฅ้ขๅ็ไธปๆตๆนๆณๆ๏ผ(3) ็ๆ้ๅฏนๆฏไธชๆนๆณๆ็ GitHub ๆ็ดข่ฏใ
|
| 495 |
+
|
| 496 |
+
**ไธบไปไนๆฏๅ็บฏๆๅๅ
ณ้ฎ่ฏๆดๅฅฝ**๏ผ
|
| 497 |
+
- ็ ็ฉถ่
ไธๅช้่ฆ"ไธไธชๅฎๆนๅฎ็ฐ"๏ผไป่ฆ็ฅ้่ฟไธชๆนๅๆๅ ๆกๆๆฏ่ทฏ็บฟใๆฏๆก่ทฏ็บฟๆๅชไบไปฃ่กจๅฎ็ฐ
|
| 498 |
+
- ๆฏๅฆ่พๅ
ฅ Transformer ่ฎบๆ๏ผๅบ่ฏฅ่พๅบใvanilla Transformer / BERT ็ณป / GPT ็ณป / T5 ็ณป / ViT ็ณปใ็ญๆนๆณๆ
|
| 499 |
+
- ่ฟ็ดๆฅๅฏนๅบ็ ็ฉถ่
็ๅฎ้
้ๆฑโโๅ่ฎบๆ่ทๅฏนๆฏๅฎ้ชๆถ้่ฆ่ฆ็ๅคไธช baseline
|
| 500 |
+
|
| 501 |
+
```python
|
| 502 |
+
# direction_analyzer.py
|
| 503 |
+
import json
|
| 504 |
+
import re
|
| 505 |
+
from openai import OpenAI
|
| 506 |
+
|
| 507 |
+
client = OpenAI(
|
| 508 |
+
api_key="your-deepseek-api-key",
|
| 509 |
+
base_url="https://api.deepseek.com",
|
| 510 |
+
)
|
| 511 |
+
|
| 512 |
+
DIRECTION_SYSTEM_PROMPT = """ไฝ ๆฏไธไธช AI ็ ็ฉถ้ขๅ็ๅฏผ่ชไธๅฎถใไฝ ็ไปปๅกๆฏ๏ผ็ปๅฎไธ็ฏ่ฎบๆ๏ผๅธฎๅฉ็ ็ฉถ่
ๅฟซ้ไบ่งฃ่ฏฅๆนๅ็ๅๆฒฟๅผๆบ็ๆใ
|
| 513 |
+
|
| 514 |
+
## ไฝ ็ๅๆๆกๆถ
|
| 515 |
+
|
| 516 |
+
่ฏทๅฎๆไปฅไธไธไธชๅฑๆฌก็ๅๆ๏ผ
|
| 517 |
+
|
| 518 |
+
### ๅฑๆฌก 1๏ผๅญ้ขๅๅฎไฝ
|
| 519 |
+
- ่ฟ็ฏ่ฎบๆๅฑไบ AI/ML ็ๅชไธชๅ
ทไฝๅญ้ขๅ๏ผ๏ผๅฆ "Transformer-based Neural Machine Translation" ่้็ฌผ็ป็ "Deep Learning"๏ผ
|
| 520 |
+
- ่ฏฅๅญ้ขๅๅจ 2024-2025 ๅนด็ไธปๆต่ถๅฟๆฏไปไน๏ผ๏ผ1-2 ๅฅ่ฏ๏ผ
|
| 521 |
+
|
| 522 |
+
### ๅฑๆฌก 2๏ผๆนๆณๆ่ฐฑ็ณป
|
| 523 |
+
- ่ฏฅๅญ้ขๅ็ฎๅๆๅชไบไธปๆตๆนๆณๆ/ๅไฝ๏ผ
|
| 524 |
+
- ๆฏไธชๆนๆณๆ็ไปฃ่กจๅทฅไฝๆฏไปไน๏ผ
|
| 525 |
+
- ่พๅบ 3-6 ไธชๆนๆณๆ๏ผๆฏไธชๅ
ๅซๆนๆณๅ + ไธๅฅ่ฏ่ฏดๆ
|
| 526 |
+
|
| 527 |
+
### ๅฑๆฌก 3๏ผๆ็ดข็ญ็ฅ
|
| 528 |
+
- ไธบๆฏไธชๆนๆณๆ็ๆ 2-3 ไธช GitHub ๆ็ดขๆฅ่ฏข
|
| 529 |
+
- ๆฅ่ฏขๅบไฝฟ็จ่ฑๆ๏ผๅ
ๅซ๏ผๆนๆณๅ + ๅ
ณ้ฎ่ฏ + "implementation" ๆ "pytorch" ๆ "official"
|
| 530 |
+
- ้ขๅค็ๆ 2-3 ไธช่ฆ็ๅ
จ้ขๅ็ๅฎฝๆณๆ็ดข
|
| 531 |
+
|
| 532 |
+
## ่พๅบๆ ผๅผ๏ผไธฅๆ ผ JSON๏ผไธ่ฆไปปไฝ้ขๅคๆๅญ๏ผ
|
| 533 |
+
{
|
| 534 |
+
"subfield": "ๅญ้ขๅๅ็งฐ๏ผไธญ่ฑๆๅๅฏ๏ผ",
|
| 535 |
+
"subfield_trend": "่ฏฅๅญ้ขๅๅฝๅไธปๆต่ถๅฟ๏ผ1-2 ๅฅไธญๆ๏ผ",
|
| 536 |
+
"method_families": [
|
| 537 |
+
{
|
| 538 |
+
"family_name": "ๆนๆณๆๅ็งฐ",
|
| 539 |
+
"description": "ไธๅฅ่ฏ่ฏดๆ",
|
| 540 |
+
"representative_work": "ไปฃ่กจ่ฎบๆๆๅทฅไฝ",
|
| 541 |
+
"search_queries": ["ๆ็ดข่ฏ1", "ๆ็ดข่ฏ2"]
|
| 542 |
+
}
|
| 543 |
+
],
|
| 544 |
+
"broad_queries": ["ๅ
จ้ขๅๅฎฝๆณๆ็ดข่ฏ1", "ๅ
จ้ขๅๅฎฝๆณๆ็ดข่ฏ2"]
|
| 545 |
+
}
|
| 546 |
+
"""
|
| 547 |
+
|
| 548 |
+
def analyze_direction(title: str, abstract: str) -> dict:
|
| 549 |
+
"""ไป่ฎบๆๆ ้ขๅๆ่ฆไธญ่งฃๆ็ ็ฉถๆนๅๅนถ็ๆๆ็ดข็ญ็ฅ"""
|
| 550 |
+
user_prompt = f"""## ่ฎบๆๆ ้ข
|
| 551 |
+
{title}
|
| 552 |
+
|
| 553 |
+
## ่ฎบๆๆ่ฆ
|
| 554 |
+
{abstract[:2000]}
|
| 555 |
+
|
| 556 |
+
่ฏทๅๆ่ฏฅ่ฎบๆ็็ ็ฉถๆนๅๅนถ็ๆๆ็ดข็ญ็ฅใ"""
|
| 557 |
+
|
| 558 |
+
response = client.chat.completions.create(
|
| 559 |
+
model="deepseek-chat",
|
| 560 |
+
messages=[
|
| 561 |
+
{"role": "system", "content": DIRECTION_SYSTEM_PROMPT},
|
| 562 |
+
{"role": "user", "content": user_prompt},
|
| 563 |
+
],
|
| 564 |
+
temperature=0.4, # ็จ้ซๆธฉๅบฆ่ฎฉๆนๆณๆๆขณ็ๆดๆๅ้ ๅ
|
| 565 |
+
max_tokens=1500,
|
| 566 |
+
)
|
| 567 |
+
raw = response.choices[0].message.content.strip()
|
| 568 |
+
return _parse_json(raw)
|
| 569 |
+
|
| 570 |
+
def _parse_json(raw: str) -> dict:
|
| 571 |
+
"""ๅฎๅ
จ่งฃๆ JSON๏ผๅฎนๅฟ LLM ็ๆ ผๅผ้ฎ้ข"""
|
| 572 |
+
try:
|
| 573 |
+
return json.loads(raw)
|
| 574 |
+
except json.JSONDecodeError:
|
| 575 |
+
pass
|
| 576 |
+
match = re.search(r'```(?:json)?\s*([\s\S]*?)```', raw)
|
| 577 |
+
if match:
|
| 578 |
+
try:
|
| 579 |
+
return json.loads(match.group(1).strip())
|
| 580 |
+
except json.JSONDecodeError:
|
| 581 |
+
pass
|
| 582 |
+
match = re.search(r'\{[\s\S]*\}', raw)
|
| 583 |
+
if match:
|
| 584 |
+
try:
|
| 585 |
+
return json.loads(match.group(0))
|
| 586 |
+
except json.JSONDecodeError:
|
| 587 |
+
pass
|
| 588 |
+
raise ValueError(f"ๆนๅ่งฃๆ LLM ่ฟๅๆ ผๅผๆ ๆณ่งฃๆ: {raw[:300]}")
|
| 589 |
+
```
|
| 590 |
+
|
| 591 |
+
### 6.2 ๆจกๅ 5๏ผๅฏๅค็ฐๆง + ๅฏนๆฏๅฎ้ช้้
ๅบฆ่ฏไผฐ `repo_evaluator.py`
|
| 592 |
+
|
| 593 |
+
**ๅไปไน**๏ผ่พๅ
ฅไธไธชไปๅบ็ README + ไพ่ตๆไปถ + ๅ
ไฟกๆฏ + ๆๅฑๆนๆณๆ โ LLM ่พๅบๅ
ญ็ปดๅบฆ่ฏๅ๏ผๅฏๅค็ฐๆง 5 ็ปด + ๅฏนๆฏๅฎ้ช้้
ๅบฆ 1 ็ปด๏ผใ
|
| 594 |
+
|
| 595 |
+
**ไธบไปไนๆฐๅขใๅฏนๆฏๅฎ้ช้้
ๅบฆใ็ปดๅบฆ**๏ผๅพๅคไปๅบ่ฝ่ท๏ผๅฏๅค็ฐ๏ผ๏ผไฝไธ้ๅ็ดๆฅๆฟๆฅ่ทๅฏนๆฏๅฎ้ชโโๆฏๅฆๅฎๅชๅฎ็ฐไบๆจ็ๆฒกๆ่ฎญ็ปใๆฐๆฎ้็จ็ๆฏ็งๆๆฐๆฎใๆ่
benchmark ๆๆ ไธๆฏ้ขๅๆ ๅๆๆ ใ็ ็ฉถ่
้่ฆ็ๆฏ"่ฝ็ดๆฅๅ ๅ
ฅ่ฎบๆ experiment section ็ไปฃ็ "ใ
|
| 596 |
+
|
| 597 |
+
```python
|
| 598 |
+
# repo_evaluator.py
|
| 599 |
+
import json
|
| 600 |
+
import re
|
| 601 |
+
from openai import OpenAI
|
| 602 |
+
|
| 603 |
+
client = OpenAI(
|
| 604 |
+
api_key="your-deepseek-api-key",
|
| 605 |
+
base_url="https://api.deepseek.com",
|
| 606 |
+
)
|
| 607 |
+
|
| 608 |
+
EVAL_SYSTEM_PROMPT = """ไฝ ๆฏไธไธช AI ่ฎบๆไปฃ็ ๅฏๅค็ฐๆงไธๅฏนๆฏๅฎ้ช้้
ๅบฆ่ฏไผฐไธๅฎถใ
|
| 609 |
+
|
| 610 |
+
ไฝ ็ไปปๅกๆฏ่ฏไผฐไธไธช GitHub ไปๅบๅจไปฅไธไธคไธชๆน้ข็่กจ็ฐ๏ผ
|
| 611 |
+
- **ๅฏๅค็ฐๆง**๏ผ่ฟไธชไปๅบ็ไปฃ็ ่ฝๅฆ่ขซไปไบบๆๅ่ท้๏ผ
|
| 612 |
+
- **ๅฏนๆฏๅฎ้ช้้
ๅบฆ**๏ผ่ฟไธชไปๅบ้ไธ้ๅ็ดๆฅๆฟๆฅๅ่ฎบๆๅๅฏนๆฏๅฎ้ช๏ผbaseline / comparison๏ผ๏ผ
|
| 613 |
+
|
| 614 |
+
## ่ฏไผฐๆกๆถ๏ผๅ
ญ็ปดๅบฆ๏ผ
|
| 615 |
+
|
| 616 |
+
### ๅฏๅค็ฐๆง๏ผไบ็ปดๅบฆ๏ผๅ่ฎก 0-80 ๅ๏ผ
|
| 617 |
+
|
| 618 |
+
1. **็ฏๅข้
็ฝฎๅฎๆดๆง๏ผ0-15 ๅ๏ผ**
|
| 619 |
+
- 15 ๅ๏ผๆไพไบๅฎๆด็ไพ่ตๆไปถ๏ผrequirements.txt / environment.yml๏ผ๏ผ็ๆฌๅทๆ็กฎ
|
| 620 |
+
- 8-14 ๅ๏ผๆไพ่ตๆไปถไฝ้จๅ็ๆฌๅท็ผบๅคฑๆๆจก็ณ
|
| 621 |
+
- 0-7 ๅ๏ผๆฒกๆไพ่ตๆไปถๆไธฅ้ไธๅฎๆด
|
| 622 |
+
|
| 623 |
+
2. **ๆๆกฃ่ดจ้๏ผ0-20 ๅ๏ผ**
|
| 624 |
+
- 16-20 ๅ๏ผๆๆธ
ๆฐ็ๅฎ่ฃ
ๆญฅ้ชคใ่ฎญ็ป/ๆจ็ๅฝไปคใๆฐๆฎ้่ทๅๆนๅผ
|
| 625 |
+
- 8-15 ๅ๏ผๆๅบๆฌ่ฏดๆไฝๅ
ณ้ฎๆญฅ้ชค็ผบๅคฑ
|
| 626 |
+
- 0-7 ๅ๏ผREADME ็ฉบๆด๏ผๆฒกๆๅฏๆง่ก็ๅฝไปค
|
| 627 |
+
|
| 628 |
+
3. **ไปฃ็ ๅฏ็จๆง๏ผ0-20 ๅ๏ผ**
|
| 629 |
+
- 16-20 ๅ๏ผๆๅฎๆด็่ฎญ็ป/ๆจ็่ๆฌใ้
็ฝฎๆไปถ๏ผๅ
ฅๅฃๆธ
ๆฐ
|
| 630 |
+
- 8-15 ๅ๏ผๆๆ ธๅฟไปฃ็ ไฝ็ผบๅฐๅ
ณ้ฎ็ปไปถ๏ผๅฆๅชๆๆจ็ๆฒกๆ่ฎญ็ป๏ผ
|
| 631 |
+
- 0-7 ๅ๏ผไปฃ็ ๆฎ็ผบ
|
| 632 |
+
|
| 633 |
+
4. **็คพๅบๆดป่ทๅบฆ๏ผ0-10 ๅ๏ผ**
|
| 634 |
+
- 8-10 ๅ๏ผStar > 500๏ผๆ่ฟๅๅนดๆๆดๆฐ
|
| 635 |
+
- 4-7 ๅ๏ผๆไธๅฎๅ
ณๆณจๅบฆไฝๆดๆฐไธ้ข็น
|
| 636 |
+
- 0-3 ๅ๏ผ้ฟๆไธๆดๆฐ๏ผStar < 10
|
| 637 |
+
|
| 638 |
+
5. **ไพ่ตๅฅๅบทๅบฆ๏ผ0-15 ๅ๏ผ**
|
| 639 |
+
- 12-15 ๅ๏ผไพ่ตๅ
จๆฏไธปๆตๆดป่ทๅ
๏ผๆ ๅทฒ็ฅๅ
ผๅฎนๆง้ฎ้ข
|
| 640 |
+
- 6-11 ๅ๏ผๆๅฐ้่ฟๆถไพ่ตไฝๅฏๅ็บง
|
| 641 |
+
- 0-5 ๅ๏ผไพ่ตๅทฒๅๆญข็ปดๆค๏ผๅฆ TF 1.x๏ผๆๅทฒ็ฅๆ ๆณๅฎ่ฃ
|
| 642 |
+
|
| 643 |
+
### ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผไธ็ปดๅบฆ๏ผ0-20 ๅ๏ผ
|
| 644 |
+
|
| 645 |
+
6. **ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผ0-20 ๅ๏ผ**
|
| 646 |
+
- 16-20 ๅ๏ผๆไพๆ ๅ benchmark ่ฏไผฐ่ๆฌ + ้ข่ฎญ็ปๆ้ + ๅ
ฌๅผๆฐๆฎ้๏ผๅฏไปฅ็ดๆฅ่ทๅบ่ฎบๆๅธธ็จๆๆ
|
| 647 |
+
- 10-15 ๅ๏ผๆ่ฎญ็ป่ๆฌๅ่ฏไผฐไปฃ็ ๏ผไฝ้่ฆ่ชๅทฑๅๅคๆฐๆฎๆๅพฎ่ฐ้
ๆฅ
|
| 648 |
+
- 0-9 ๅ๏ผๅชๆๆจ็ใไฝฟ็จ็งๆๆฐๆฎ้ใๆฒกๆๆ ๅๅ่ฏไผฐๆต็จ
|
| 649 |
+
|
| 650 |
+
## ่พๅบๆ ผๅผ๏ผไธฅๆ ผ JSON๏ผไธ่ฆไปปไฝ้ขๅคๆๅญ๏ผ
|
| 651 |
+
{
|
| 652 |
+
"reproducibility_score": ๆดๆฐ๏ผ0-80๏ผๅฏๅค็ฐๆงไบ้กนๆฑๅ๏ผ,
|
| 653 |
+
"benchmark_fitness_score": ๆดๆฐ๏ผ0-20๏ผๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผ,
|
| 654 |
+
"overall_score": ๆดๆฐ๏ผ0-100๏ผๅ
ญ้กนๆปๅ๏ผ,
|
| 655 |
+
"verdict": "reproducible" | "partially" | "not_reproducible",
|
| 656 |
+
"env_score": ๆดๆฐ,
|
| 657 |
+
"doc_score": ๆดๆฐ,
|
| 658 |
+
"code_score": ๆดๆฐ,
|
| 659 |
+
"community_score": ๆดๆฐ,
|
| 660 |
+
"dep_score": ๆดๆฐ,
|
| 661 |
+
"benchmark_score": ๆดๆฐ,
|
| 662 |
+
"reasoning": "200ๅญไปฅๅ
็ไธญๆๅๆ๏ผๅฟ
้กปๅบๅ'่ฝไธ่ฝ่ท'ๅ'้ไธ้ๅ่ทๅฏนๆฏๅฎ้ช'ไธคไธชๅฑ้ข",
|
| 663 |
+
"risks": ["้ฃ้ฉ1", "้ฃ้ฉ2"],
|
| 664 |
+
"benchmark_readiness": "ready" | "partial" | "not_ready",
|
| 665 |
+
"suggested_use": "ๅฏไปฅ็ดๆฅไฝไธบๅฏนๆฏๅฎ้ช baseline" | "้่ฆๅฐ้ไฟฎๆนๅๅฏ็จไบๅฏนๆฏๅฎ้ช" | "ไป
้ๅๅ่ไปฃ็ ๅฎ็ฐ๏ผไธ้ๅ็ดๆฅ่ทๅฏนๆฏๅฎ้ช"
|
| 666 |
+
}
|
| 667 |
+
|
| 668 |
+
## ๅคๅฎ่งๅ
|
| 669 |
+
- overall_score >= 70 โ verdict = "reproducible"
|
| 670 |
+
- 40 <= overall_score < 70 โ verdict = "partially"
|
| 671 |
+
- overall_score < 40 โ verdict = "not_reproducible"
|
| 672 |
+
|
| 673 |
+
- benchmark_score >= 16 โ benchmark_readiness = "ready"
|
| 674 |
+
- 10 <= benchmark_score < 16 โ benchmark_readiness = "partial"
|
| 675 |
+
- benchmark_score < 10 โ benchmark_readiness = "not_ready"
|
| 676 |
+
"""
|
| 677 |
+
|
| 678 |
+
def evaluate_repo(repo: dict, readme: str | None, dependencies: dict[str, str],
|
| 679 |
+
method_family: str = "") -> dict:
|
| 680 |
+
"""่ฏไผฐๅไธชไปๅบ็ๅฏๅค็ฐๆงๅๅฏนๆฏๅฎ้ช้้
ๅบฆ"""
|
| 681 |
+
readme_text = (readme or "README ๆชๆพๅฐ")[:2500]
|
| 682 |
+
deps_text = "\n\n".join(
|
| 683 |
+
f"### {fname}\n```\n{content[:1000]}\n```"
|
| 684 |
+
for fname, content in dependencies.items()
|
| 685 |
+
) or "ๆชๆพๅฐไพ่ตๆไปถ"
|
| 686 |
+
|
| 687 |
+
family_hint = f"\n่ฏฅๆนๆณๅฑไบ: {method_family}" if method_family else ""
|
| 688 |
+
|
| 689 |
+
user_prompt = f"""## ไปๅบไฟกๆฏ
|
| 690 |
+
- ๅ็งฐ: {repo.get('full_name', '')}
|
| 691 |
+
- URL: {repo.get('html_url', '')}
|
| 692 |
+
- Stars: {repo.get('stars', 0)}
|
| 693 |
+
- ๆ่ฟฐ: {repo.get('description', '')}
|
| 694 |
+
- ๆๅๆดๆฐ: {repo.get('updated_at', '')}
|
| 695 |
+
- ่ฏญ่จ: {repo.get('language', '')}{family_hint}
|
| 696 |
+
|
| 697 |
+
## README
|
| 698 |
+
{readme_text}
|
| 699 |
+
|
| 700 |
+
## ไพ่ตๆไปถ
|
| 701 |
+
{deps_text}
|
| 702 |
+
|
| 703 |
+
่ฏท่ฏไผฐ่ฏฅไปๅบ็ๅฏๅค็ฐๆงๅๅฏนๆฏๅฎ้ช้้
ๅบฆใ"""
|
| 704 |
+
|
| 705 |
+
response = client.chat.completions.create(
|
| 706 |
+
model="deepseek-chat",
|
| 707 |
+
messages=[
|
| 708 |
+
{"role": "system", "content": EVAL_SYSTEM_PROMPT},
|
| 709 |
+
{"role": "user", "content": user_prompt},
|
| 710 |
+
],
|
| 711 |
+
temperature=0.3,
|
| 712 |
+
max_tokens=1500,
|
| 713 |
+
)
|
| 714 |
+
raw = response.choices[0].message.content.strip()
|
| 715 |
+
return _parse_json(raw)
|
| 716 |
+
|
| 717 |
+
def _parse_json(raw: str) -> dict:
|
| 718 |
+
"""ๅฎๅ
จ JSON ่งฃๆ"""
|
| 719 |
+
try:
|
| 720 |
+
return json.loads(raw)
|
| 721 |
+
except json.JSONDecodeError:
|
| 722 |
+
pass
|
| 723 |
+
match = re.search(r'```(?:json)?\s*([\s\S]*?)```', raw)
|
| 724 |
+
if match:
|
| 725 |
+
try:
|
| 726 |
+
return json.loads(match.group(1).strip())
|
| 727 |
+
except json.JSONDecodeError:
|
| 728 |
+
pass
|
| 729 |
+
match = re.search(r'\{[\s\S]*\}', raw)
|
| 730 |
+
if match:
|
| 731 |
+
try:
|
| 732 |
+
return json.loads(match.group(0))
|
| 733 |
+
except json.JSONDecodeError:
|
| 734 |
+
pass
|
| 735 |
+
raise ValueError(f"่ฏไผฐ LLM ่ฟๅๆ ผๅผๆ ๆณ่งฃๆ: {raw[:300]}")
|
| 736 |
+
```
|
| 737 |
+
|
| 738 |
+
def evaluate_repo(repo: dict, readme: str | None, dependencies: dict[str, str]) -> dict:
|
| 739 |
+
"""่ฏไผฐๅไธชไปๅบ็ๅฏๅค็ฐๆง"""
|
| 740 |
+
readme_text = (readme or "README ๆชๆพๅฐ")[:2500]
|
| 741 |
+
deps_text = "\n\n".join(
|
| 742 |
+
f"### {fname}\n```\n{content[:1000]}\n```"
|
| 743 |
+
for fname, content in dependencies.items()
|
| 744 |
+
) or "ๆชๆพๅฐไพ่ตๆไปถ"
|
| 745 |
+
|
| 746 |
+
user_prompt = f"""## ไปๅบไฟกๆฏ
|
| 747 |
+
- ๅ็งฐ: {repo.get('full_name', '')}
|
| 748 |
+
- URL: {repo.get('html_url', '')}
|
| 749 |
+
- Stars: {repo.get('stars', 0)}
|
| 750 |
+
- ๆ่ฟฐ: {repo.get('description', '')}
|
| 751 |
+
- ๆๅๆดๆฐ: {repo.get('updated_at', '')}
|
| 752 |
+
- ่ฏญ่จ: {repo.get('language', '')}
|
| 753 |
+
|
| 754 |
+
## README
|
| 755 |
+
{readme_text}
|
| 756 |
+
|
| 757 |
+
## ไพ่ตๆไปถ
|
| 758 |
+
{deps_text}
|
| 759 |
+
|
| 760 |
+
่ฏท่ฏไผฐ่ฏฅไปๅบ็ๅฏๅค็ฐๆงใ"""
|
| 761 |
+
|
| 762 |
+
response = client.chat.completions.create(
|
| 763 |
+
model="deepseek-chat",
|
| 764 |
+
messages=[
|
| 765 |
+
{"role": "system", "content": EVAL_SYSTEM_PROMPT},
|
| 766 |
+
{"role": "user", "content": user_prompt},
|
| 767 |
+
],
|
| 768 |
+
temperature=0.3,
|
| 769 |
+
max_tokens=1200,
|
| 770 |
+
)
|
| 771 |
+
raw = response.choices[0].message.content.strip()
|
| 772 |
+
return _parse_json(raw)
|
| 773 |
+
|
| 774 |
+
def _parse_json(raw: str) -> dict:
|
| 775 |
+
"""ๅฎๅ
จ JSON ่งฃๆ๏ผๅ direction_analyzer ไธญ็ๅฎ็ฐ"""
|
| 776 |
+
try:
|
| 777 |
+
return json.loads(raw)
|
| 778 |
+
except json.JSONDecodeError:
|
| 779 |
+
pass
|
| 780 |
+
match = re.search(r'```(?:json)?\s*([\s\S]*?)```', raw)
|
| 781 |
+
if match:
|
| 782 |
+
try:
|
| 783 |
+
return json.loads(match.group(1).strip())
|
| 784 |
+
except json.JSONDecodeError:
|
| 785 |
+
pass
|
| 786 |
+
match = re.search(r'\{[\s\S]*\}', raw)
|
| 787 |
+
if match:
|
| 788 |
+
try:
|
| 789 |
+
return json.loads(match.group(0))
|
| 790 |
+
except json.JSONDecodeError:
|
| 791 |
+
pass
|
| 792 |
+
raise ValueError(f"่ฏไผฐ LLM ่ฟๅๆ ผๅผๆ ๆณ่งฃๆ: {raw[:300]}")
|
| 793 |
+
```
|
| 794 |
+
|
| 795 |
+
### 6.3 ๆจกๅ 6๏ผไธปๆต็จ `run.py`
|
| 796 |
+
|
| 797 |
+
**่ฟๆฏๆดไธช้กน็ฎ็ไธญๅคฎ่ฐๅบฆๅจ**ใๆไธๅฑๆถๆไธฒ่ๆๆๆจกๅใ
|
| 798 |
+
|
| 799 |
+
```python
|
| 800 |
+
# run.py
|
| 801 |
+
import sys
|
| 802 |
+
from paper_fetcher import fetch_paper_info
|
| 803 |
+
from direction_analyzer import analyze_direction
|
| 804 |
+
from repo_searcher import search_repos
|
| 805 |
+
from repo_fetcher import fetch_readme, fetch_dependencies
|
| 806 |
+
from repo_evaluator import evaluate_repo
|
| 807 |
+
|
| 808 |
+
def run(arxiv_url: str, top_n: int = 5) -> dict:
|
| 809 |
+
"""ไธปๅ
ฅๅฃ๏ผไป่ฎบๆๅฐ"็ ็ฉถๆนๅๅ
จๆฏ + ไปฃ็ ๆจ่"็ๅฎๆด้พ่ทฏ
|
| 810 |
+
|
| 811 |
+
่ฟๅ dict:
|
| 812 |
+
- paper: ่ฎบๆไฟกๆฏ
|
| 813 |
+
- direction: ็ ็ฉถๆนๅ่งฃๆ็ปๆ๏ผๅญ้ขๅ + ๆนๆณๆ + ๆ็ดข่ฏ๏ผ
|
| 814 |
+
- repos: ่ฏไผฐๅ็ไปๅบๅ่กจ๏ผๆ overall_score ้ๅบ๏ผ
|
| 815 |
+
"""
|
| 816 |
+
# ===== ็ฌฌไธๅฑ๏ผ็ ็ฉถๆนๅ่งฃๆ =====
|
| 817 |
+
print(f"[1/5] ๆญฃๅจ่ทๅ่ฎบๆไฟกๆฏ...")
|
| 818 |
+
paper = fetch_paper_info(arxiv_url)
|
| 819 |
+
print(f" ่ฎบๆ: {paper['title'][:80]}...")
|
| 820 |
+
|
| 821 |
+
print(f"[2/5] ๆญฃๅจ่งฃๆ็ ็ฉถๆนๅ...")
|
| 822 |
+
direction = analyze_direction(paper["title"], paper["abstract"])
|
| 823 |
+
print(f" ๅญ้ขๅ: {direction.get('subfield', 'ๆช็ฅ')}")
|
| 824 |
+
print(f" ๆนๆณๆ: {len(direction.get('method_families', []))} ไธช")
|
| 825 |
+
|
| 826 |
+
# ๆฑๆปๆๆๆ็ดข่ฏ๏ผๆนๆณๆๆ็ดข + ๅฎฝๆณๆ็ดข๏ผ
|
| 827 |
+
all_queries = []
|
| 828 |
+
for mf in direction.get("method_families", []):
|
| 829 |
+
all_queries.extend(mf.get("search_queries", []))
|
| 830 |
+
all_queries.extend(direction.get("broad_queries", []))
|
| 831 |
+
print(f" ็ๆ {len(all_queries)} ไธชๆ็ดขๆฅ่ฏข")
|
| 832 |
+
|
| 833 |
+
# ===== ็ฌฌไบๅฑ๏ผๅผๆบไปฃ็ ๅ็ฐ =====
|
| 834 |
+
print(f"[3/5] ๆญฃๅจๆ็ดข GitHub ไปๅบ...")
|
| 835 |
+
candidates = search_repos(all_queries, max_per_keyword=5)
|
| 836 |
+
candidates = candidates[:top_n]
|
| 837 |
+
print(f" ๅป้ๅๆพๅฐ {len(candidates)} ไธชๅ้ไปๅบ")
|
| 838 |
+
|
| 839 |
+
if not candidates:
|
| 840 |
+
return {
|
| 841 |
+
"paper": paper,
|
| 842 |
+
"direction": direction,
|
| 843 |
+
"repos": [],
|
| 844 |
+
"error": "ๆชๆพๅฐ็ธๅ
ณๅผๆบไปๅบ",
|
| 845 |
+
}
|
| 846 |
+
|
| 847 |
+
# ===== ็ฌฌไธๅฑ๏ผๅฏๅค็ฐๆง + ๅฏนๆฏๅฎ้ช้้
ๅบฆ่ฏไผฐ =====
|
| 848 |
+
print(f"[4/5] ๆญฃๅจ่ฏไผฐ {len(candidates)} ไธชๅ้ไปๅบ...")
|
| 849 |
+
evaluated = []
|
| 850 |
+
for i, repo in enumerate(candidates):
|
| 851 |
+
full_name = repo["full_name"]
|
| 852 |
+
owner, name = full_name.split("/", 1)
|
| 853 |
+
# ๅฐ่ฏๅฐไปๅบๅน้
ๅฐๅฏนๅบ็ๆนๆณๆ๏ผ็ฎๅ่งๅ๏ผๆ่ฟฐไธญๅ
ๅซๆนๆณๆๅ็งฐ๏ผ
|
| 854 |
+
matched_family = _match_family(repo, direction.get("method_families", []))
|
| 855 |
+
print(f" ({i+1}/{len(candidates)}) ่ฏไผฐ {full_name} [{matched_family or 'ๆชๅฝ็ฑป'}]...")
|
| 856 |
+
|
| 857 |
+
try:
|
| 858 |
+
readme = fetch_readme(owner, name)
|
| 859 |
+
deps = fetch_dependencies(owner, name)
|
| 860 |
+
evaluation = evaluate_repo(repo, readme, deps, matched_family)
|
| 861 |
+
except Exception as e:
|
| 862 |
+
evaluation = {
|
| 863 |
+
"overall_score": 0,
|
| 864 |
+
"reproducibility_score": 0,
|
| 865 |
+
"benchmark_fitness_score": 0,
|
| 866 |
+
"verdict": "error",
|
| 867 |
+
"reasoning": f"่ฏไผฐๅคฑ่ดฅ: {str(e)[:100]}",
|
| 868 |
+
"env_score": 0, "doc_score": 0, "code_score": 0,
|
| 869 |
+
"community_score": 0, "dep_score": 0, "benchmark_score": 0,
|
| 870 |
+
"risks": [], "benchmark_readiness": "not_ready",
|
| 871 |
+
"suggested_use": "่ฏไผฐๅคฑ่ดฅ๏ผ่ฏทๆๅจๆฃๆฅ",
|
| 872 |
+
}
|
| 873 |
+
|
| 874 |
+
evaluated.append({
|
| 875 |
+
**repo,
|
| 876 |
+
"method_family": matched_family,
|
| 877 |
+
"evaluation": evaluation,
|
| 878 |
+
})
|
| 879 |
+
|
| 880 |
+
# ๆ็ปผๅ่ฏๅ้ๅบ
|
| 881 |
+
evaluated.sort(key=lambda r: r["evaluation"].get("overall_score", 0), reverse=True)
|
| 882 |
+
|
| 883 |
+
print(f"[5/5] ็ๆ็ ๆฅ...")
|
| 884 |
+
return {
|
| 885 |
+
"paper": paper,
|
| 886 |
+
"direction": direction,
|
| 887 |
+
"repos": evaluated,
|
| 888 |
+
}
|
| 889 |
+
|
| 890 |
+
def _match_family(repo: dict, families: list[dict]) -> str:
|
| 891 |
+
"""็ฎๅ็ไปๅบโๆนๆณๆๅน้
๏ผๅบไบๆ่ฟฐๅ topics"""
|
| 892 |
+
desc = (repo.get("description") or "").lower()
|
| 893 |
+
topics = " ".join(repo.get("topics", [])).lower()
|
| 894 |
+
text = desc + " " + topics
|
| 895 |
+
|
| 896 |
+
for mf in families:
|
| 897 |
+
family_name = mf.get("family_name", "").lower()
|
| 898 |
+
if family_name and family_name in text:
|
| 899 |
+
return mf["family_name"]
|
| 900 |
+
return ""
|
| 901 |
+
|
| 902 |
+
if __name__ == "__main__":
|
| 903 |
+
if len(sys.argv) < 2:
|
| 904 |
+
print("็จๆณ: python run.py <arxiv_url>")
|
| 905 |
+
print("็คบไพ: python run.py https://arxiv.org/abs/1706.03762")
|
| 906 |
+
sys.exit(1)
|
| 907 |
+
|
| 908 |
+
result = run(sys.argv[1])
|
| 909 |
+
|
| 910 |
+
if result.get("error"):
|
| 911 |
+
print(f"\nโ {result['error']}")
|
| 912 |
+
else:
|
| 913 |
+
# ไฝฟ็จ app.py ไธญ็ format_report ่พๅบ
|
| 914 |
+
from app import format_report
|
| 915 |
+
print(format_report(result))
|
| 916 |
+
```
|
| 917 |
+
|
| 918 |
+
### 6.4 Gradio ็้ข `app.py`
|
| 919 |
+
|
| 920 |
+
```python
|
| 921 |
+
# app.py
|
| 922 |
+
import gradio as gr
|
| 923 |
+
from run import run
|
| 924 |
+
|
| 925 |
+
def diagnose(arxiv_url: str) -> str:
|
| 926 |
+
"""Gradio ๅ่ฐ๏ผ่พๅ
ฅ arxiv URL โ ่พๅบ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ"""
|
| 927 |
+
url = arxiv_url.strip()
|
| 928 |
+
if not url:
|
| 929 |
+
return "## ่ฏท่พๅ
ฅ arxiv ่ฎบๆ้พๆฅ"
|
| 930 |
+
|
| 931 |
+
try:
|
| 932 |
+
result = run(url)
|
| 933 |
+
except ValueError as e:
|
| 934 |
+
return f"## ่พๅ
ฅๆ ผๅผ้่ฏฏ\n\n{str(e)}"
|
| 935 |
+
except RuntimeError as e:
|
| 936 |
+
return f"## API ่ฏทๆฑๅคฑ่ดฅ\n\n{str(e)}"
|
| 937 |
+
except Exception as e:
|
| 938 |
+
return f"## ่ฟ่กๅบ้\n\n```\n{str(e)}\n```"
|
| 939 |
+
|
| 940 |
+
if result.get("error"):
|
| 941 |
+
return f"## ๆชๆพๅฐ็ธๅ
ณไปฃ็ \n\n{result['error']}"
|
| 942 |
+
|
| 943 |
+
return format_report(result)
|
| 944 |
+
|
| 945 |
+
def format_report(result: dict) -> str:
|
| 946 |
+
"""ๅฐ run() ็็ปๆๆ ผๅผๅไธบ"็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ" Markdown"""
|
| 947 |
+
paper = result["paper"]
|
| 948 |
+
direction = result["direction"]
|
| 949 |
+
repos = result["repos"]
|
| 950 |
+
|
| 951 |
+
# ===== ็ ๆฅๅคด้จ =====
|
| 952 |
+
md = f"""# ResearchRadar ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ
|
| 953 |
+
|
| 954 |
+
---
|
| 955 |
+
|
| 956 |
+
## ไธใ่ฎบๆไฟกๆฏ
|
| 957 |
+
|
| 958 |
+
| ้กน็ฎ | ๅ
ๅฎน |
|
| 959 |
+
|------|------|
|
| 960 |
+
| **ๆ ้ข** | {paper['title']} |
|
| 961 |
+
| **arXiv ID** | [{paper['arxiv_id']}](https://arxiv.org/abs/{paper['arxiv_id']}) |
|
| 962 |
+
| **ไฝ่
** | {', '.join(paper['authors'][:5])}{'...' if len(paper['authors']) > 5 else ''} |
|
| 963 |
+
| **ๅ่กจๆถ้ด** | {paper.get('published', 'N/A')[:10]} |
|
| 964 |
+
| **ๅ็ฑป** | {', '.join(paper['categories']) if paper.get('categories') else 'N/A'} |
|
| 965 |
+
|
| 966 |
+
---
|
| 967 |
+
|
| 968 |
+
## ไบใ็ ็ฉถๆนๅๅ
จๆฏ
|
| 969 |
+
|
| 970 |
+
### ๅญ้ขๅๅฎไฝ
|
| 971 |
+
**{direction.get('subfield', 'ๆช็ฅ')}**
|
| 972 |
+
|
| 973 |
+
### ๅฝๅ่ถๅฟ
|
| 974 |
+
{direction.get('subfield_trend', 'ๆๆ ๅๆ')}
|
| 975 |
+
|
| 976 |
+
### ๆนๆณๆ่ฐฑ็ณป
|
| 977 |
+
|
| 978 |
+
| # | ๆนๆณๆ | ่ฏดๆ | ไปฃ่กจๅทฅไฝ |
|
| 979 |
+
|---|--------|------|----------|
|
| 980 |
+
"""
|
| 981 |
+
for i, mf in enumerate(direction.get("method_families", [])):
|
| 982 |
+
md += f"| {i+1} | **{mf.get('family_name', '')}** | {mf.get('description', '')} | {mf.get('representative_work', '')} |\n"
|
| 983 |
+
|
| 984 |
+
md += """
|
| 985 |
+
---
|
| 986 |
+
|
| 987 |
+
## ไธใๅผๆบๅฎ็ฐ่ฏไผฐๆๅ
|
| 988 |
+
|
| 989 |
+
"""
|
| 990 |
+
# ===== ไปๅบๆๅ =====
|
| 991 |
+
for i, repo in enumerate(repos):
|
| 992 |
+
ev = repo["evaluation"]
|
| 993 |
+
verdict_icon = {
|
| 994 |
+
"reproducible": "โ
", "partially": "โ ๏ธ",
|
| 995 |
+
"not_reproducible": "โ", "error": "๐ฅ"
|
| 996 |
+
}.get(ev.get("verdict", ""), "โ")
|
| 997 |
+
readiness_icon = {
|
| 998 |
+
"ready": "๐ข", "partial": "๐ก", "not_ready": "๐ด"
|
| 999 |
+
}.get(ev.get("benchmark_readiness", ""), "โช")
|
| 1000 |
+
|
| 1001 |
+
family_tag = f" `[{repo.get('method_family', 'ๆชๅฝ็ฑป')}]`" if repo.get("method_family") else ""
|
| 1002 |
+
|
| 1003 |
+
md += f"""### {i+1}. [{repo['full_name']}]({repo['html_url']}){family_tag}
|
| 1004 |
+
|
| 1005 |
+
{verdict_icon} ๅฏๅค็ฐๆง: **{ev.get('reproducibility_score', ev.get('overall_score', 'N/A'))}/80** | {readiness_icon} ๅฏนๆฏๅฎ้ช้้
ๅบฆ: **{ev.get('benchmark_fitness_score', ev.get('benchmark_score', 'N/A'))}/20** | ็ปผๅ: **{ev.get('overall_score', 'N/A')}/100**
|
| 1006 |
+
|
| 1007 |
+
| ็ปดๅบฆ | ๅพๅ | ๆปกๅ | ่ฏดๆ |
|
| 1008 |
+
|------|:----:|:----:|------|
|
| 1009 |
+
| ็ฏๅข้
็ฝฎ | {ev.get('env_score', 'N/A')} | 15 | ไพ่ตๆไปถๅฎๆดๅบฆ |
|
| 1010 |
+
| ๆๆกฃ่ดจ้ | {ev.get('doc_score', 'N/A')} | 20 | ๅฎ่ฃ
/่ฎญ็ป/ๆฐๆฎ่ฏดๆ |
|
| 1011 |
+
| ไปฃ็ ๅฏ็จๆง | {ev.get('code_score', 'N/A')} | 20 | ่ฎญ็ป+ๆจ็่ๆฌๅฎๆดๆง |
|
| 1012 |
+
| ็คพๅบๆดป่ท | {ev.get('community_score', 'N/A')} | 10 | Star + ๆดๆฐ้ข็ |
|
| 1013 |
+
| ไพ่ตๅฅๅบท | {ev.get('dep_score', 'N/A')} | 15 | ไพ่ตๅ
ๅฏ็จๆง |
|
| 1014 |
+
| **ๅฏนๆฏๅฎ้ช** | **{ev.get('benchmark_score', 'N/A')}** | **20** | **ๆ ๅๅ่ฏไผฐ + ้ข่ฎญ็ปๆ้** |
|
| 1015 |
+
|
| 1016 |
+
โญ Star: {repo.get('stars', 0)} | ๅน้
: `{repo.get('match_keyword', '')}`
|
| 1017 |
+
|
| 1018 |
+
**ๅๆ**: {ev.get('reasoning', 'N/A')}
|
| 1019 |
+
|
| 1020 |
+
**ๅฏนๆฏๅฎ้ชๅปบ่ฎฎ**: {ev.get('suggested_use', 'N/A')}
|
| 1021 |
+
|
| 1022 |
+
"""
|
| 1023 |
+
if ev.get("risks"):
|
| 1024 |
+
md += "**้ฃ้ฉ็น**: " + " | ".join(f"`{r}`" for r in ev["risks"]) + "\n"
|
| 1025 |
+
md += "\n---\n\n"
|
| 1026 |
+
|
| 1027 |
+
# ===== ๅฏนๆฏๅฎ้ชๆจ่ๆป็ป =====
|
| 1028 |
+
ready_repos = [r for r in repos if r["evaluation"].get("benchmark_readiness") == "ready"]
|
| 1029 |
+
partial_repos = [r for r in repos if r["evaluation"].get("benchmark_readiness") == "partial"]
|
| 1030 |
+
|
| 1031 |
+
md += """## ๅใๅฏนๆฏๅฎ้ชๆจ่ๆป็ป
|
| 1032 |
+
|
| 1033 |
+
"""
|
| 1034 |
+
if ready_repos:
|
| 1035 |
+
md += "### ๐ข ๅฏ็ดๆฅ็จไบๅฏนๆฏๅฎ้ช\n\n"
|
| 1036 |
+
for r in ready_repos:
|
| 1037 |
+
md += f"- **[{r['full_name']}]({r['html_url']})** โ {r['evaluation'].get('suggested_use', '')}\n"
|
| 1038 |
+
md += "\n"
|
| 1039 |
+
|
| 1040 |
+
if partial_repos:
|
| 1041 |
+
md += "### ๐ก ้่ฆๅฐ้ไฟฎๆนๅๅฏ็จ\n\n"
|
| 1042 |
+
for r in partial_repos:
|
| 1043 |
+
md += f"- **[{r['full_name']}]({r['html_url']})** โ {r['evaluation'].get('suggested_use', '')}\n"
|
| 1044 |
+
md += "\n"
|
| 1045 |
+
|
| 1046 |
+
not_ready = [r for r in repos if r["evaluation"].get("benchmark_readiness") not in ("ready", "partial")]
|
| 1047 |
+
if not_ready:
|
| 1048 |
+
md += "### ๐ด ไป
้ๅๅ่ไปฃ็ ๅฎ็ฐ\n\n"
|
| 1049 |
+
for r in not_ready:
|
| 1050 |
+
md += f"- **[{r['full_name']}]({r['html_url']})** โ {r['evaluation'].get('suggested_use', r['evaluation'].get('reasoning', 'N/A')[:80])}...\n"
|
| 1051 |
+
md += "\n"
|
| 1052 |
+
|
| 1053 |
+
md += """
|
| 1054 |
+
---
|
| 1055 |
+
|
| 1056 |
+
> ResearchRadar ยท ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ + ๅฏนๆฏๅฎ้ชๆจ่
|
| 1057 |
+
"""
|
| 1058 |
+
|
| 1059 |
+
return md
|
| 1060 |
+
|
| 1061 |
+
DEMO_EXAMPLES = [
|
| 1062 |
+
["https://arxiv.org/abs/1706.03762"], # Attention Is All You Need (Transformer)
|
| 1063 |
+
["https://arxiv.org/abs/2010.11929"], # An Image is Worth 16x16 Words (ViT)
|
| 1064 |
+
["https://arxiv.org/abs/2006.11239"], # Denoising Diffusion Probabilistic Models (DDPM)
|
| 1065 |
+
]
|
| 1066 |
+
|
| 1067 |
+
demo = gr.Interface(
|
| 1068 |
+
fn=diagnose,
|
| 1069 |
+
inputs=gr.Textbox(
|
| 1070 |
+
label="่ฎบๆ arxiv ้พๆฅ",
|
| 1071 |
+
placeholder="https://arxiv.org/abs/1706.03762",
|
| 1072 |
+
lines=1,
|
| 1073 |
+
),
|
| 1074 |
+
outputs=gr.Markdown(label="็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ"),
|
| 1075 |
+
title="ResearchRadar โ ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ",
|
| 1076 |
+
description="่พๅ
ฅไธ็ฏ AI ่ฎบๆ็ arxiv ้พๆฅ๏ผAI ๅธฎไฝ ๆธๆธ
็ ็ฉถๆนๅๅ
จๆฏ๏ผๆพๅฐๆ้้
็ๅผๆบๅฎ็ฐ๏ผ่ฏไผฐ่ฝๅฆ็ดๆฅ็จไบๅฏนๆฏๅฎ้ชใ",
|
| 1077 |
+
examples=DEMO_EXAMPLES,
|
| 1078 |
+
theme="soft",
|
| 1079 |
+
)
|
| 1080 |
+
|
| 1081 |
+
if __name__ == "__main__":
|
| 1082 |
+
demo.launch(server_name="0.0.0.0", share=False)
|
| 1083 |
+
```
|
| 1084 |
+
|
| 1085 |
+
---
|
| 1086 |
+
|
| 1087 |
+
## ไธใๆฐๆฎๆตไธๆงๅถๆต
|
| 1088 |
+
|
| 1089 |
+
### 7.1 ๅฎๆด้พ่ทฏ๏ผไธๅฑๆถๆ๏ผ
|
| 1090 |
+
|
| 1091 |
+
```
|
| 1092 |
+
็จๆท่พๅ
ฅ arxiv URL
|
| 1093 |
+
โ
|
| 1094 |
+
โผ
|
| 1095 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1096 |
+
โ paper_fetcher.fetch_paper_info() โ โ arxiv API
|
| 1097 |
+
โ ่พๅบ: {title, abstract, authors, ...} โ
|
| 1098 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1099 |
+
โ
|
| 1100 |
+
โผ
|
| 1101 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1102 |
+
โ direction_analyzer.analyze_direction() โ โ DeepSeek API (1 ๆฌก)
|
| 1103 |
+
โ ่พๅบ: {subfield, method_families[], โ
|
| 1104 |
+
โ broad_queries[]} โ
|
| 1105 |
+
โ โป ๅๆถๅฎๆๅญ้ขๅ่ฏๅซ + ๆนๆณๆๆขณ็ + โ
|
| 1106 |
+
โ ๆ็ดข่ฏ็ๆ โ
|
| 1107 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1108 |
+
โ
|
| 1109 |
+
โผ
|
| 1110 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1111 |
+
โ repo_searcher.search_repos() ๏ฟฝ๏ฟฝ โ GitHub Search API (N ๆฌก)
|
| 1112 |
+
โ ่พๅ
ฅ: ๆๆๆนๆณๆๆ็ดข่ฏ + ๅฎฝๆณๆ็ดข่ฏ โ
|
| 1113 |
+
โ ่พๅบ: ๅป้ๆๅบๅ็ๅ้ไปๅบ top 5 โ
|
| 1114 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1115 |
+
โ
|
| 1116 |
+
โผ (ๅฏนๆฏไธชๅ้ไปๅบๅพช็ฏ)
|
| 1117 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1118 |
+
โ repo_fetcher.fetch_readme() โ โ GitHub Content API
|
| 1119 |
+
โ repo_fetcher.fetch_dependencies() โ
|
| 1120 |
+
โ ่พๅบ: {readme, dependencies} โ
|
| 1121 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1122 |
+
โ
|
| 1123 |
+
โผ
|
| 1124 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1125 |
+
โ repo_evaluator.evaluate_repo() โ โ DeepSeek API (ๆฏไธชไปๅบ 1 ๆฌก)
|
| 1126 |
+
โ ่พๅบ: ๅ
ญ็ปดๅบฆ่ฏๅ๏ผๅฏๅค็ฐๆง 5 ็ปด + โ
|
| 1127 |
+
โ ๅฏนๆฏๅฎ้ช้้
ๅบฆ 1 ็ปด๏ผ โ
|
| 1128 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1129 |
+
โ
|
| 1130 |
+
โผ
|
| 1131 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1132 |
+
โ ๆ overall_score ้ๅบ โ
|
| 1133 |
+
โ format_report() โ ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ โ
|
| 1134 |
+
โ ๅ
ๅซ๏ผๆนๅ่งฃ่ฏป + ๆนๆณๆ่ฐฑ็ณป + ไปๅบๆ่ก โ
|
| 1135 |
+
โ + ๅฏนๆฏๅฎ้ชๆจ่ โ
|
| 1136 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1137 |
+
```
|
| 1138 |
+
|
| 1139 |
+
### 7.2 API ่ฐ็จๆฌกๆฐไผฐ็ฎ๏ผๅๆฌก่ฟ่ก๏ผ
|
| 1140 |
+
|
| 1141 |
+
| ๆญฅ้ชค | API | ่ฐ็จๆฌกๆฐ |
|
| 1142 |
+
|------|-----|:--------:|
|
| 1143 |
+
| ่ฎบๆไฟกๆฏ | arxiv API | 1 |
|
| 1144 |
+
| ็ ็ฉถๆนๅ่งฃๆ | DeepSeek | 1 |
|
| 1145 |
+
| GitHub ๆ็ดข | GitHub Search | N๏ผๆนๆณๆร2 + ๅฎฝๆณร2 โ 10 ๆฌก๏ผ |
|
| 1146 |
+
| ไปๅบ่ฏฆๆ
๏ผร5๏ผ | GitHub Content | 5 |
|
| 1147 |
+
| ๅฏๅค็ฐๆง+้้
ๅบฆ่ฏไผฐ๏ผร5๏ผ | DeepSeek | 5 |
|
| 1148 |
+
|
| 1149 |
+
**ๅๆฌก่ฟ่กๆป่ๆถไผฐ็ฎ**๏ผ็บฆ 25-45 ็ง๏ผไธฒ่กๆง่ก๏ผใไธป่ฆ่ๆถๅจ GitHub ๆ็ดข๏ผ10 ๆฌก ร ๆฏๆฌก็บฆ 1-2 ็ง๏ผๅ 5 ไธชไปๅบ็่ฏไผฐ๏ผ5 ๆฌก LLM ่ฐ็จ ร ๆฏๆฌก 3-5 ็ง๏ผใ
|
| 1150 |
+
|
| 1151 |
+
---
|
| 1152 |
+
|
| 1153 |
+
## ๅ
ซใๅ
ณ้ฎ่็นไธ้็จ็ข
|
| 1154 |
+
|
| 1155 |
+
| ๅจๆฌก | ็ฎๆ | ็ฒ๏ผๆฐๆฎๅฑ๏ผ | ไน๏ผLLM+้ๆๅฑ๏ผ | ไบคไป็ฉ |
|
| 1156 |
+
|:----:|------|-------------|-----------------|--------|
|
| 1157 |
+
| **Week 1** | ๅฐๅบ + ไธๅฑ MVP | `paper_fetcher.py` + `repo_searcher.py` + `repo_fetcher.py` + ่ฏๆต้ Part A ๆ 3 ็ฏ + Part B ๆ 6 ไธช | `direction_analyzer.py` + `repo_evaluator.py` + `run.py` + `app.py` + ๆถๆๅพ | `python run.py <arxiv_url>` ๅฎๆด้พ่ทฏ + ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ |
|
| 1158 |
+
| **Week 2** | ็ซฏๅฐ็ซฏ้พ่ทฏ | Workflow ไผๅ๏ผLLM ๅคๆญไพ่ตๆฏๅฆ่ฟ่ฝ่ฃ
๏ผใๅ Tavily ็คพๅบๆ็ดขใๅ Issue ๆๅ | Agent C ๅ็๏ผๆฐด่ดด/็Bug ๅ็ฑป๏ผไธๅๅ็ฏ๏ผใๅฎๅๆนๆณๆๅฝ็ฑป้ป่พ | ๅฎๆด้พ่ทฏ + ่ฏๆต้ๅบ็บฟๅ็กฎ็ |
|
| 1159 |
+
| **Week 3** | ๅ็กฎ็ๆปๅ
ณ | ๆ็ปญๆฉๅ
่ฏๆต้๏ผ่ฎบๆโไปๅบ ground truth๏ผใไผๅๆฐๆฎ้้่ดจ้ | Prompt ่ฐไผใๆนๆณๆ่ฏๅซๅ็กฎ็ใๅ
ญ็ปดๆ้็จ่ฏๆต้ๅๆจ | ็ ็ฉถๆนๅ่ฏๅซๅ็กฎ็ โฅ 80%ใๅฏๅค็ฐๆงๅ็กฎ็ โฅ 75% |
|
| 1160 |
+
| **Week 4** | ๅ็ฏ + ๅขๅผบๆ็ดข | Gradio ็้ขๅ็บง๏ผๆนๆณๆๅๅๅฑ็คบ๏ผใๅขๅ PapersWithCode ๆฐๆฎๆบ | Agent C ๅ็ฏๆบๅถใAgent D ่พน็ๅๆฐๅ่ฟญไปฃ | ๅธฆๅ็ฏ็๏ผๅ็กฎ็ โฅ 80% |
|
| 1161 |
+
| **Week 5** | UI ๅ็บง + ็ป่ฅๅๅค | ๅฝๅถ demo ่ง้ขใๆด็ๆฑๆฅๆๆ๏ผๅๅค 2 ็ฏ่ฎบๆ็ๅฎๆดๅ
จๆฏ็ ๆฅๅฏนๆฏ๏ผ | ๆตๅผ่พๅบใๆๆนๆณๆๅๅๅฑ็คบ | ็ป่ฅ็ญ่พฉๆๆ |
|
| 1162 |
+
| **Week 6** | ็ผๅฒ | ๆฅๆผ่กฅ็ผบใ่ฏๆต้ๆฐ้ฎ้ขไฟฎๅค | ๅไธ | ๆ็ป็ญ่พฉ |
|
| 1163 |
+
|
| 1164 |
+
---
|
| 1165 |
+
|
| 1166 |
+
## ไนใๆไปถ็ปๆ
|
| 1167 |
+
|
| 1168 |
+
```
|
| 1169 |
+
ResearchRadar/
|
| 1170 |
+
โโโ paper_fetcher.py # ็ฒ๏ผarxiv ่ฎบๆไฟกๆฏๆๅ
|
| 1171 |
+
โโโ repo_searcher.py # ็ฒ๏ผGitHub ไปฃ็ ๆ็ดข๏ผๅคๅ
ณ้ฎ่ฏๅป้๏ผ
|
| 1172 |
+
โโโ repo_fetcher.py # ็ฒ๏ผไปๅบ่ฏฆๆ
ๆๅ๏ผREADME + ไพ่ต + Issues๏ผ
|
| 1173 |
+
โโโ direction_analyzer.py # ไน๏ผLLM ็ ็ฉถๆนๅ่งฃๆ + ๆนๆณๆๆขณ็ + ๆ็ดข่ฏ็ๆ
|
| 1174 |
+
โโโ repo_evaluator.py # ไน๏ผLLM ๅฏๅค็ฐๆง๏ผ5็ปด๏ผ+ ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผ1็ปด๏ผ่ฏไผฐ
|
| 1175 |
+
โโโ run.py # ไน๏ผไธๅฑไธปๆต็จ่ฐๅบฆ
|
| 1176 |
+
โโโ app.py # ไน๏ผGradio ็้ข + ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅๆ ผๅผๅ
|
| 1177 |
+
โโโ eval.py # ็ฒ๏ผ่ฏๆต่ๆฌ๏ผๆนๅ่ฏๅซๅ็กฎ็ + ๅฏๅค็ฐๆงๅ็กฎ็๏ผ
|
| 1178 |
+
โโโ test_set/
|
| 1179 |
+
โ โโโ papers.json # Part A๏ผ่ฎบๆโ็ ็ฉถๆนๅ ground truth + ๅทฒ็ฅๅฎ็ฐไปๅบ
|
| 1180 |
+
โ โโโ repos.json # Part B๏ผไปๅบโๅฏๅค็ฐๆง ground truth
|
| 1181 |
+
โโโ requirements.txt # ้กน็ฎไพ่ต๏ผrequests, gradio, openai
|
| 1182 |
+
โโโ README.md
|
| 1183 |
+
```
|
| 1184 |
+
|
| 1185 |
+
**`requirements.txt`**๏ผ
|
| 1186 |
+
```
|
| 1187 |
+
requests>=2.31
|
| 1188 |
+
gradio>=4.0
|
| 1189 |
+
openai>=1.0
|
| 1190 |
+
```
|
| 1191 |
+
|
| 1192 |
+
---
|
| 1193 |
+
|
| 1194 |
+
## ๅใ็ฌฌไธๅจไบๅคฉๆถ้ด็บฟ
|
| 1195 |
+
|
| 1196 |
+
| ๅคฉ | ็ฒ | ไน |
|
| 1197 |
+
|----|----|-----|
|
| 1198 |
+
| **ๅจไธ** | ๅ `paper_fetcher.py`๏ผๅจ 5 ็ฏ่ฎบๆไธๆต่ฏ arxiv APIใ็ณ่ฏท GitHub Token | ๅ `direction_analyzer.py` prompt๏ผ็จ 3-5 ็ฏ่ฎบๆๆต่ฏ๏ผๅญ้ขๅ่ฏๅซๆฏๅฆๅ็๏ผๆนๆณๆๆฏๅฆ่ฆ็ๅ
จ๏ผๆ็ดข่ฏ่ดจ้ๅฆไฝ๏ผ |
|
| 1199 |
+
| **ๅจไบ** | ๅ `repo_searcher.py` + `repo_fetcher.py`๏ผ่่ฐๆ็ดขโๆๅ้พ่ทฏใไธคไธช token ้ฝ้
ๅฅฝ่ฝฎๆข | ๅ `repo_evaluator.py` prompt๏ผ็จ 5 ไธชๅทฒ็ฅไปๅบๆต่ฏๅ
ญ็ปด่ฏๅๆฏๅฆๅ็๏ผ็นๅซๆณจๆ"ๅฏๅค็ฐ"ๅ"้้
ๅบฆ"ๆๆฒกๆๅบๅๅผ |
|
| 1200 |
+
| **ๅจไธ** | ๅๅค 3 ็ฏ demo ่ฎบๆ + ๆ Part A ่ฏๆต้๏ผๆนๅ + ๆนๆณๆ + ๅทฒ็ฅๅฎ็ฐไปๅบ๏ผ๏ผ็กฎไฟๆฏ็ฏๆๅฐ็ไปๅบๆไปฃ่กจๆง | ๅ `run.py` ๅฎๆดไธๅฑ้พ่ทฏ + `app.py` ๅ
จๆฏ็ ๆฅๆ ผๅผๅ๏ผไธๅไธ็ฒ่่ฐ |
|
| 1201 |
+
| **ๅจๅ** | ๆ Part B ่ฏๆต้๏ผ6-8 ไธชไปๅบ๏ผ๏ผๅค็่พน็ case๏ผ่ฎบๆๆไธๅฐใไปๅบๆฒก READMEใๆนๅ่ฏๅซ้่ฏฏ๏ผ | debug ๆดๆก้พ่ทฏ๏ผๆถ้ดๆถ่ใJSON ่งฃๆๅคฑ่ดฅใAPI ๅผๅธธๅค็ใๅๅค PPT ไธๅฑๆถๆๅพ |
|
| 1202 |
+
| **ๅจไบไธๅ** | ๅฎๆด่ตฐไธ้ demo ๆต็จ + ๅๅค่ฎฒ็จฟ๏ผ3 ็ฏ่ฎบๆๅ่ฎฒไปไนๆ
ไบ๏ผๆนๅๅ
จๆฏโไปฃ็ ๅ็ฐโๅฏนๆฏๅฎ้ชๆจ่๏ผ | ๅไธ๏ผ่่ฐ + ็ญ่พฉ้ขๆผ |
|
| 1203 |
+
| **ๅจไบไธๅ** | **ๆฑๆฅ** | **ๆฑๆฅ** |
|
| 1204 |
+
|
| 1205 |
+
---
|
| 1206 |
+
|
| 1207 |
+
## ๅไธใไฝ ไปฌ้่ฆๅณๅฎ็ไบๆ
|
| 1208 |
+
|
| 1209 |
+
ๅจๅผๅงๅไปฃ็ ไนๅ๏ผไธ้ขๅ ไธช้ฎ้ข้่ฆ็ฒๅไนๅไธๆฅๅฏนๆธ
ๆฅใไธ็จไธๆฌกๅ็ญๅฎ๏ผๅฏไปฅ่พนๅ่พนๅณๅฎ๏ผ
|
| 1210 |
+
|
| 1211 |
+
1. **็ฒๅไนๅ่ช็ณ่ฏท GitHub Token ไบๅ๏ผ** ๆ็ดขๆฅๅฃ้้ๅพไธฅ๏ผ30ๆฌก/ๅ้๏ผ๏ผไธคไธช token ่ฝฎๆขๆฏๆไฝ้
็ฝฎใๅฆๆๆฒกๆ๏ผๅจไธ็ฌฌไธไปถไบๅฐฑๅป [github.com/settings/tokens](https://github.com/settings/tokens) ๅ็ณ่ฏทไธไธช Fine-grained token๏ผๅชๅพ้ public repo ่ฏปๆ้๏ผใ
|
| 1212 |
+
|
| 1213 |
+
2. **DeepSeek API key ็ฐๅจๅฐฑ่ฝ็จๅ๏ผ** ่ฐๆฟ็ key๏ผๅจไธไธๅๅ
็จๆ็ฎๅ็ `curl` ๆ Python ่ๆฌ้ช่ฏ key ๆๆใ่ฟไปถไบ้ปๅกๆๆ LLM ๆจกๅใ
|
| 1214 |
+
|
| 1215 |
+
3. **3 ็ฏ demo ่ฎบๆ้ไปไน๏ผ** ๅปบ่ฎฎ้ไธ็ฏ็ปๅ
ธ่ฎบๆ๏ผๅฆ TransformerใResNetใDDPM๏ผๆนๆณๆไธฐๅฏใๅผๆบๅฎ็ฐๅคใๆผ็คบๆๆๅฅฝ๏ผ๏ผๅไปไฝ ไปฌๅ่ชๆนๅๅ้ไธ็ฏใๅ
ณ้ฎๆฏ่ฆ็กฎไฟๆฏ็ฏ่ฎบๆ้ฝ่ฝๆๅฐ 3+ ไธชไปๅบ๏ผๅฆๅ demo ๆถๆฒกไธ่ฅฟๅฑ็คบใ
|
| 1216 |
+
|
| 1217 |
+
4. **ๆนๅ่งฃๆ๏ผdirection_analyzer๏ผ็่ฏๆตๆ ๅๆไนๅฎ๏ผ** ่ฟๆฏๆดไธช็ณป็ปๆ"ไธป่ง"็ๆจกๅใๅญ้ขๅๅฎไฝๅฏนไธๅฏน๏ผๆนๆณๆๅ
จไธๅ
จ๏ผๆ็ดข่ฏๅฅฝไธๅฅฝ๏ผไฝ ไปฌ้่ฆๅฎไธไธช็ฎๅ็ๅคๅฎ่งๅ๏ผๆฏๅฆ"ๅญ้ขๅ็ฑไบบๅทฅ็กฎ่ฎคๆญฃ็กฎ"ใ"ๆนๆณๆ่ณๅฐ่ฆ็ 3 ไธช่ฏฅ้ขๅ็ๅ
ฌ่ฎคไธปๆตๆนๅ"ใ
|
| 1218 |
+
|
| 1219 |
+
5. **"ๅฏนๆฏๅฎ้ช้้
ๅบฆ"็ ground truth ๆไนๆ ๏ผ** ่ฟไธชๆฏ"ๅฏๅค็ฐๆง"ๆด้พๆ ๆณจใๅฏๅค็ฐๆงๅฏไปฅ่ฏ็่ฃ
็ฏๅข่ทไธไธ๏ผ้้
ๅบฆ้่ฆๅคๆญ"่ฟไธชไปๅบ่ฝ็ดๆฅ่ทๅบ่ฎบๆ้็ๆๆ ๅ"ใๅปบ่ฎฎๅ
็จไฝ ไปฌ่ชๅทฑ็ๆ็ไปๅบๆ 5 ไธช๏ผๅๆฉๅฑๅฐ 20 ไธชใ
|
| 1220 |
+
|
| 1221 |
+
6. **่ฎบๆๅคชๆฐๆไธๅฐไปฃ็ ๆไนๅค็๏ผ** ๆฐ่ฎบๆ๏ผๅฆ 2025 ๅนด็๏ผๅพๅพๆฒกๆๅผๆบๅฎ็ฐ๏ผไฝ่ฟๆฐๆฐๆฏๅทฅๅ
ท็ไปทๅผโโๆๅๅ่ฏไฝ "่ฟไธชๆนๅ่ฟๆฒกๆๆ็ไปฃ็ ๏ผไฝ ๅฏ่ฝ่ฆไปๅคดๅฎ็ฐ"ใๆผ็คบๆถๅฆๆ้ๅฐ่ฟ็งๆ
ๅต๏ผไฝ ๅบ่ฏฅๆไน่ฎฒ่ฟไธชๆ
ไบ๏ผ
|
| 1222 |
+
|
| 1223 |
+
---
|
| 1224 |
+
|
| 1225 |
+
> **ๆๅไธๅฅ**๏ผไฝ ไปฌๆฏ็ ไธๅฐ็ฝ๏ผ่ฟๅฎๅ
จไธไธขไบบใ6 ๅ้ๆผ็คบ๏ผ่ฏๅงไธไผ่ขซ่ฑๅจ UI ๆๅจ๏ผไฝไผ่ขซใๆธ
ๆฅ็้ป่พ + ็ๅฎ็ๆฐๆฎ + ่ฏๅฎ็ๅฑ้ใ่ฏดๆใๅซไผช่ฃ
๏ผๅซ้ ๅใไฝ ไปฌ็ไปทๅผๆฏ"ๅธฎ็ ็ฉถ่
่็ไป่ฎบๆๅฐ่ท้ๅฏนๆฏๅฎ้ช็ๆถ้ด"๏ผ่ฟไธชไปทๅผไธๅฅ่ฏๅฐฑ่ฝ่ฎฒๆธ
ๆฅใ
|
ResearchRadar_ไน_ไปปๅกไนฆ.md
ADDED
|
@@ -0,0 +1,1575 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ResearchRadar ไน๏ผๅณ็ญ+้ๆๅฑ๏ผไปปๅกไนฆ
|
| 2 |
+
|
| 3 |
+
> ่ง่ฒ๏ผไน โ LLM ๅณ็ญๆจกๅ + ไธปๆต็จ่ฐๅบฆ + Gradio ็้ข
|
| 4 |
+
> ็ฎๆ ๏ผ็ฌฌไธๅจ็ปๆๅ๏ผ`python run.py <arxiv_url>` ่ฝ่ท้ๅฎๆดไธๅฑ้พ่ทฏ๏ผ่พๅบ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ
|
| 5 |
+
> ๅ็ฝฎๆกไปถ๏ผDeepSeek API key ๅทฒ้ช่ฏๅฏ็จ
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## ใใๅ
็่งฃไฝ ่ฆๆญๅปบ็ๆฏไปไนโโAgent ไธ Workflow ็ๆฌ่ดจ
|
| 10 |
+
|
| 11 |
+
> ไฝ ๆฏๅฐ็ฝ๏ผ่ฟไธไธขไบบใๅพๅคๅไบๅฅฝๅ ๅนดไปฃ็ ็ไบบไนๆฒกๆๆ Agent ๅฐๅบๆฏไปไนใ่ฟไธ่ๅฏ่ฝๆฏๆดไธชไปปๅกไนฆๆ้่ฆ็้จๅใ
|
| 12 |
+
|
| 13 |
+
### 0.1 Agent ๆฏไปไน๏ผ็จไฝ ่ฝๅฌๆ็่ฏ๏ผ
|
| 14 |
+
|
| 15 |
+
**Agent = ไธไธชๆๅคๆญ่ฝๅ็ๅฝๆฐ**ใ่ทๆฎ้ๅฝๆฐ็ๅฏไธๅบๅซๆฏ๏ผๅฎไธ้ ๅๆญป็่งๅๅๅคๆญ๏ผ่ๆฏๆไฟกๆฏไธข็ป LLM๏ผ่ฎฉ LLM ๆฅ"ๅธฎไฝ ็ไธ็ผ็ถๅๅๅณๅฎ"ใ
|
| 16 |
+
|
| 17 |
+
็จไฝ ็ๆ็ๅบๆฏไธพไพ๏ผ
|
| 18 |
+
|
| 19 |
+
- **ไธ้่ฆ Agent ็ไบ**๏ผไฝ ๅป GitHub ็ไธไธชไปๅบๆๅคๅฐ starใ่ฟๅฐฑๆฏ็จ็ผ็็๏ผไธ้่ฆๅจ่ๅญใๅๆไปฃ็ ๅฐฑๆฏ `requests.get(url) โ resp.json()["stargazers_count"]`ใ่ฟๆฏ **Workflow**ใ
|
| 20 |
+
|
| 21 |
+
- **้่ฆ Agent ็ไบ**๏ผ็ปไฝ 100 ๆก GitHub Issue๏ผ่ฎฉไฝ ๅคๆญๅชไบๆฏ็ bug ๅชไบๆฏ"ๅคงไฝฌๆฑไปฃ็ "็ๆฐด่ดดใ่ฟ้่ฆ็่งฃ Issue ็ๅ
ๅฎน๏ผ้่ฆๅจ่ๅญใไฝ 100 ๆกไฝ ไบบๅทฅ็ไธ่ฟๆฅ๏ผๆไปฅๅไธไธชๅฝๆฐ๏ผๆ Issue ๆๆฌไธข็ป DeepSeek๏ผ่ฎฉๅฎๅธฎไฝ ๅ็ฑปใ่ฟๅฐฑๆฏ **Agent**ใ
|
| 22 |
+
|
| 23 |
+
**Agent ็ๆฌ่ดจๅฐฑๆฏไธไธช Python ๅฝๆฐ๏ผๅฝๆฐไฝ้ๆ่ฟไธ่ก**๏ผ
|
| 24 |
+
|
| 25 |
+
```python
|
| 26 |
+
response = client.chat.completions.create(
|
| 27 |
+
model="deepseek-chat",
|
| 28 |
+
messages=[{"role": "system", "content": "ไฝ ๆฏXXไธๅฎถ..."},
|
| 29 |
+
{"role": "user", "content": "ๅธฎๆๅคๆญ..."}],
|
| 30 |
+
)
|
| 31 |
+
# LLM ่ฟๅ็ๅคๆญ็ปๆๅฐฑๆฏ Agent ็"ๅณ็ญ"
|
| 32 |
+
return response.choices[0].message.content
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
**ไธ้่ฆ LangChain๏ผไธ้่ฆ LangGraph๏ผไธ้่ฆไปปไฝๆกๆถใ** ไฝ ไปฌ่ทฏ็บฟๅคง็บฒ้่ฏด็"4 ไธชๅฝๆฐ + ไธไธช dict + if/else๏ผ300 ่ก่ฝๆๅฎ"ๅฐฑๆฏ่ฟไธชๆๆใ
|
| 36 |
+
|
| 37 |
+
### 0.2 Workflow ๆฏไปไน
|
| 38 |
+
|
| 39 |
+
**Workflow = ไธๆกๅๆญป็ๆตๆฐด็บฟ**ใๆฏไธๆญฅๅไปไนๆฏ็กฎๅฎ็๏ผไธ้่ฆ LLM ๆฅๅ้ๆฉใ
|
| 40 |
+
|
| 41 |
+
```python
|
| 42 |
+
# ่ฟๅฐฑๆฏไธไธช Workflow๏ผ3 ๆญฅ๏ผๆฏไธๆญฅๅไปไนๆฏๅๆญป็
|
| 43 |
+
def workflow_example(url):
|
| 44 |
+
data = requests.get(url).json() # ๆญฅ้ชค 1๏ผๆๆฐๆฎ
|
| 45 |
+
cleaned = clean_data(data) # ๆญฅ้ชค 2๏ผๆธ
ๆด
|
| 46 |
+
return cleaned # ๆญฅ้ชค 3๏ผ่ฟๅ
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
Workflow ้ๆฒกๆ `if LLM่ฏดAๅฐฑ่ตฐB` ่ฟ็ง้ป่พใ่ทฏๅพๆฏ็กฎๅฎ็ใ
|
| 50 |
+
|
| 51 |
+
### 0.3 ไฝ ็้กน็ฎ้๏ผๅชไธชๆฏ Agent๏ผๅชไธชๆฏ Workflow
|
| 52 |
+
|
| 53 |
+
ๆดไธช ResearchRadar ็ณป็ปๅฏไปฅๆ่ฟไธชๆ ๅ้ๆฐๆ ๆณจ๏ผ
|
| 54 |
+
|
| 55 |
+
```
|
| 56 |
+
็จๆท่พๅ
ฅ arxiv URL
|
| 57 |
+
โ
|
| 58 |
+
โผ
|
| 59 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 60 |
+
โ paper_fetcher.fetch_paper_info() โ โ WORKFLOW๏ผ็ฒ๏ผ
|
| 61 |
+
โ ๅ็ไบๆ
๏ผ่ฐ arxiv API๏ผ่งฃๆ XML๏ผ่ฟๅ dict โ
|
| 62 |
+
โ ไธ้่ฆ LLM๏ผ่ทฏๅพๅๆญป โ
|
| 63 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 64 |
+
โ
|
| 65 |
+
โผ
|
| 66 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 67 |
+
โ direction_analyzer.analyze_direction() โ โ AGENT๏ผไน โ
ไฝ ่ด่ดฃ๏ผ
|
| 68 |
+
โ ๅ็ไบๆ
๏ผLLM ็่งฃ่ฎบๆ โ ๅคๆญๅญ้ขๅ โ โ
|
| 69 |
+
โ ๆขณ็ๆนๆณๆ โ ็ๆๆ็ดข่ฏ โ
|
| 70 |
+
โ ้่ฆ LLM๏ผๆฏ็๏ผLLM ๅจๅ"ๅคๆญ" โ
|
| 71 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 72 |
+
โ
|
| 73 |
+
โผ
|
| 74 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 75 |
+
โ repo_searcher.search_repos() โ โ WORKFLOW๏ผ็ฒ๏ผ
|
| 76 |
+
โ ๅ็ไบๆ
๏ผ็จๆ็ดข่ฏ่ฐ GitHub API๏ผ โ
|
| 77 |
+
โ ๅป้๏ผๆ star ๆๅบ โ
|
| 78 |
+
โ ไธ้่ฆ LLM๏ผๅฐฑๆฏๅพช็ฏ่ฐ API โ
|
| 79 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 80 |
+
โ
|
| 81 |
+
โผ
|
| 82 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 83 |
+
โ repo_fetcher.fetch_readme() โ โ WORKFLOW๏ผ็ฒ๏ผ
|
| 84 |
+
โ repo_fetcher.fetch_dependencies() โ
|
| 85 |
+
โ ๅ็ไบๆ
๏ผ่ฐ GitHub API๏ผbase64 ่งฃ็ ๏ผ โ
|
| 86 |
+
โ ่ฟๅๆไปถๅ
ๅฎน โ
|
| 87 |
+
โ ไธ้่ฆ LLM โ
|
| 88 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 89 |
+
โ
|
| 90 |
+
โผ
|
| 91 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 92 |
+
โ repo_evaluator.evaluate_repo() โ โ AGENT๏ผไน โ
ไฝ ่ด่ดฃ๏ผ
|
| 93 |
+
โ ๅ็ไบๆ
๏ผLLM ้
่ฏป README + ไพ่ตๆไปถ โ โ
|
| 94 |
+
โ ๅคๆญๅฏๅค็ฐๆง + ๅฏนๆฏๅฎ้ช้้
ๅบฆ โ
|
| 95 |
+
โ ้่ฆ LLM๏ผๆฏ็๏ผLLM ๅจๅ"่ฏๅๅคๆญ" โ
|
| 96 |
+
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 97 |
+
โ
|
| 98 |
+
โผ
|
| 99 |
+
Markdown ็ ๆฅ
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
**ไธๅฅ่ฏๆป็ป**๏ผๆดไธช็ณป็ป = ็ฒ็ 3 ไธช Workflow + ไฝ ็ 2 ไธช Agent + 1 ไธช่ฐๅบฆๅจ๏ผrun.py๏ผๆๅฎไปฌไธฒ่ตทๆฅใ
|
| 103 |
+
|
| 104 |
+
### 0.4 Agent ๅ Workflow ็ๆญๅปบๆ่ทฏๅฏนๆฏ
|
| 105 |
+
|
| 106 |
+
| | Workflow๏ผ็ฒ่ด่ดฃ๏ผ | Agent๏ผไฝ ่ด่ดฃ๏ผ |
|
| 107 |
+
|------|------|------|
|
| 108 |
+
| **ๆ ธๅฟๅทฅไฝ** | ๆๆธ
ๆฅ API ๆไน่ฐใ่ฟๅไปไนๆ ผๅผใๆไน่งฃๆ | ่ฎพ่ฎกไธๆฎตๆๅญ๏ผprompt๏ผ๏ผๅ่ฏ LLM ๅฎๆฏไปไน่ง่ฒใ่ฆๅคๆญไปไนใ่พๅบไปไนๆ ผๅผ |
|
| 109 |
+
| **้พๅบฆๅจๅช** | ๅ็งๅผๅธธๅค็๏ผAPI ๆไบใ้้ไบใๆฐๆฎๆ ผๅผๅไบ๏ผ | LLM ่ฟๅ็ JSON ๆ ผๅผไธๅฏนใ่ฏๅไธ็ฌฆๅๅธธ่ฏใไธๅ่ฎบๆ็่พๅบ่ดจ้ไธ็จณๅฎ |
|
| 110 |
+
| **่ฐ่ฏๆนๅผ** | `print()` ็ API ่ฟๅไบไปไน | ๆๅทฅๆข 3-5 ็ฏ่ฎบๆ/ไปๅบๆต่ฏ๏ผ็ LLM ็ๅคๆญๆฏๅฆๅ็ |
|
| 111 |
+
| **ไฝ ้่ฆ็ๆ่ฝ** | ไผ็จ `requests` ๅบใไผ็ API ๆๆกฃ | ไผๅๆธ
ๆฐ็ promptใไผๅค็ LLM ่พๅบๆ ผๅผ |
|
| 112 |
+
|
| 113 |
+
### 0.5 ไฝ ็ 4 ไธชๆไปถๅ่ชๆฏไปไน
|
| 114 |
+
|
| 115 |
+
| ไฝ ็ๆไปถ | ็ฑปๅ | ็ฎ็ญ่ฏดๆ |
|
| 116 |
+
|----------|------|----------|
|
| 117 |
+
| `direction_analyzer.py` | **Agent** | ้้ขๅชๆไธไธชๆ ธๅฟๅฝๆฐ `analyze_direction()`๏ผๅฎ่ฐ LLM ๅๆนๅๅคๆญ |
|
| 118 |
+
| `repo_evaluator.py` | **Agent** | ้้ขๅชๆไธไธชๆ ธๅฟๅฝๆฐ `evaluate_repo()`๏ผๅฎ่ฐ LLM ๅ่ฏๅๅคๆญ |
|
| 119 |
+
| `run.py` | **่ฐๅบฆๅจ** | ๆขไธๆฏ Agent ไนไธๆฏ Workflow๏ผๆฏไธๆฎต"่ถๆฐดไปฃ็ "๏ผๆ้กบๅบ่ฐ็จ Workflow ๅ Agent๏ผๆๆฐๆฎๅจๅฎไปฌไน้ดไผ ้ |
|
| 120 |
+
| `app.py` | **็้ข** | ๅ
่ฃ
ไธไธช Gradio ๅฃณ๏ผ่ฎฉ็จๆท่ฝ่พๅ
ฅ URL ็ๅฐ็ ๆฅ |
|
| 121 |
+
|
| 122 |
+
### 0.6 ไฝ ๅ็ฒ็ๆฅๅฃ็บฆๅฎ
|
| 123 |
+
|
| 124 |
+
็ฒ่ด่ดฃๆญ Workflow ็ปไฝ ๆไพๆฐๆฎ๏ผไฝ ่ด่ดฃๆญ Agent ๅๅคๆญใไฝ ๅช้่ฆ็ฅ้็ฒ็ๅฝๆฐ็ญพๅ๏ผ
|
| 125 |
+
|
| 126 |
+
| ็ฒ็ๆไปถ | ไฝ ่ฐ็จ็ๅฝๆฐ | ่พๅ
ฅ | ่พๅบ |
|
| 127 |
+
|----------|-------------|------|------|
|
| 128 |
+
| `paper_fetcher.py` | `fetch_paper_info(url)` | arxiv URL ๅญ็ฌฆไธฒ | `{"arxiv_id", "title", "abstract", "authors", "categories", "published"}` |
|
| 129 |
+
| `repo_searcher.py` | `search_repos(keywords, max_per_keyword=5)` | ๅ
ณ้ฎ่ฏๅญ็ฌฆไธฒๅ่กจ | `[{"full_name", "html_url", "description", "stars", "topics", ...}, ...]` |
|
| 130 |
+
| `repo_fetcher.py` | `fetch_readme(owner, repo)` | owner ๅญ็ฌฆไธฒ, repo ๅญ็ฌฆไธฒ | README ๆๆฌ ๆ None |
|
| 131 |
+
| `repo_fetcher.py` | `fetch_dependencies(owner, repo)` | owner ๅญ็ฌฆไธฒ, repo ๅญ็ฌฆไธฒ | `{"requirements.txt": "...", "environment.yml": "...", ...}` |
|
| 132 |
+
|
| 133 |
+
**ไฝ ่ฆๅ็ฒ็กฎ่ฎค็**๏ผไปฅไธ 4 ไธชๅฝๆฐๅๅๅๆฐๅไธ่ฆๆน๏ผๅฆๅ `run.py` ่ฐไธ้ใ
|
| 134 |
+
|
| 135 |
+
### 0.7 ๅทฅไธ็ผบ้ทๅผๅธธๆฃๆต้ขๅ้้
|
| 136 |
+
|
| 137 |
+
ไฝ ไปฌๆๅฎ็้ขๅๆฏ**ๅทฅไธ็ผบ้ทๅผๅธธๆฃๆต**๏ผIndustrial Defect Anomaly Detection๏ผใ่ฟไธช้ขๅๅพ้ๅ ResearchRadar๏ผๅ ไธบ๏ผ
|
| 138 |
+
|
| 139 |
+
- ๆๆ็กฎ็ๆนๆณๆ่ฐฑ็ณป๏ผๅบไบ้ๆ็๏ผAutoEncoder/VAE๏ผใๅบไบๅตๅ
ฅ็๏ผPaDiM/PatchCore๏ผใๅบไบๅธ็็ฝ็ป็๏ผSTFPM/EfficientAD๏ผใๅบไบๅๆ็ผบ้ท็๏ผDRAEM/Defect-GAN๏ผ
|
| 140 |
+
- ๆๅ
ฌ่ฎค็ๆฐๆฎ้๏ผMVTec ADใBTADใKSDD2
|
| 141 |
+
- ๆ้ซ่ดจ้ๅผๆบ้กน็ฎ๏ผOpenVINO anomalibใPaDiMใPatchCoreใEfficientAD
|
| 142 |
+
- ๆฏ CV ้ขๅ็ๆดป่ทๅญๆนๅ๏ผGitHub ไธ่ฝๆพๅฐ่ถณๅคๅค็ๅ้ไปๅบ
|
| 143 |
+
|
| 144 |
+
ไปฅไธๆฏไฝ ่ฐ่ฏ prompt ๆถๅปบ่ฎฎ็จ็ๆต่ฏ่ฎบๆ๏ผ้่ฟไธช้ขๅ็็ปๅ
ธ่ฎบๆ๏ผ๏ผ
|
| 145 |
+
|
| 146 |
+
| ่ฎบๆ | arxiv ID | ไธบไปไน้ๅๆต่ฏ |
|
| 147 |
+
|------|----------|---------------|
|
| 148 |
+
| PaDiM (2021) | `2011.08785` | ๅตๅ
ฅๆนๆณๆไปฃ่กจ๏ผGitHub ๅฎ็ฐๅค |
|
| 149 |
+
| PatchCore (2022) | `2106.08265` | ๅตๅ
ฅๆนๆณๆ๏ผๆ anomalib ๅฎๆนๅฎ็ฐ |
|
| 150 |
+
| EfficientAD (2023) | `2303.14535` | ๅธ็็ฝ็ป๏ผ่พๆฐ๏ผๅฎ็ฐ็ธๅฏนๅฐ๏ผๆต่ฏ"ๆไธๅฐไปฃ็ "็ๆ
ๅต๏ผ |
|
| 151 |
+
| DRAEM (2021) | `2108.07610` | ๅๆ็ผบ้ทๆนๆณ๏ผๆๅฎๆนไปฃ็ |
|
| 152 |
+
| DeepSVDD (2018) | ้ arxiv๏ผICML 2018 | ็ปๅ
ธๅ็ฑปๅ็ฑปๆนๆณ๏ผๅคไธช็คพๅบๅฎ็ฐ |
|
| 153 |
+
|
| 154 |
+
---
|
| 155 |
+
|
| 156 |
+
## ไธใAgent 1๏ผ`direction_analyzer.py` โ ็ ็ฉถๆนๅ่งฃๆ
|
| 157 |
+
|
| 158 |
+
> **็ฑปๅ๏ผAgent** | ่ฟๆฏไฝ ่ด่ดฃ็็ฌฌไธไธช Agent
|
| 159 |
+
> **ๆ ธๅฟๅคๆญ**๏ผ็ปๅฎ่ฎบๆๆ ้ข+ๆ่ฆ๏ผLLM ๅคๆญๅฎๅฑไบไปไนๅญ้ขๅใ่ฏฅ้ขๅๆๅชไบๆนๆณๆใๅบ่ฏฅ็จไปไนๆ็ดข่ฏ
|
| 160 |
+
|
| 161 |
+
### 1.1 ่ฟไธช Agent ่ฆ่งฃๅณไปไน้ฎ้ข
|
| 162 |
+
|
| 163 |
+
ไปฅๅพ็ๆนๆกๆฏ"ไป่ฎบๆๆ ้ข+ๆ่ฆๆๅๅ
ณ้ฎ่ฏๆ GitHub"ใไฝ่ฟไธๅคโโ็ ็ฉถ่
้่ฆ็ไธๆฏไธๅ ๅ
ณ้ฎ่ฏ๏ผ่ๆฏ**ๅฏน่ฏฅ็ ็ฉถๆนๅ็็ณป็ป็่งฃ**ใ
|
| 164 |
+
|
| 165 |
+
ๆฏๅฆ่พๅ
ฅไธ็ฏๅทฅไธ็ผบ้ทๆฃๆต็่ฎบๆ๏ผๅฆ PaDiM๏ผ๏ผ่ฟไธช Agent ๅบ่ฏฅ่พๅบ๏ผ
|
| 166 |
+
- ๅญ้ขๅ๏ผUnsupervised Industrial Defect Detection / Anomaly Detection
|
| 167 |
+
- ๆนๆณๆ๏ผๅบไบๅตๅ
ฅ็๏ผPaDiM/PatchCore๏ผใๅบไบ้ๆ็๏ผAutoEncoder/VAE๏ผใๅบไบๅธ็็ฝ็ป็๏ผSTFPM/EfficientAD๏ผใๅบไบๅๆ็ผบ้ท็๏ผDRAEM๏ผ
|
| 168 |
+
- ๆ็ดข่ฏ๏ผๆฏไธชๆน๏ฟฝ๏ฟฝ๏ฟฝๆ็ GitHub ๆ็ดข่ฏ
|
| 169 |
+
|
| 170 |
+
**่ฟๆดไธชๅคๆญ่ฟ็จๅฐฑๆฏ Agent ็"ๅณ็ญ"**โโๅฎไธๆฏไปๆฐๆฎๅบๆฅๅบๆฅ็๏ผๆฏ LLM ๆ นๆฎ่ฎบๆๅ
ๅฎน็่งฃๅๅๅบ็ๅคๆญใ
|
| 171 |
+
|
| 172 |
+
### 1.2 ่ฟไธช Agent ็ๆญๅปบๆ่ทฏ
|
| 173 |
+
|
| 174 |
+
```
|
| 175 |
+
ๆญฅ้ชค 1๏ผๅ System Prompt๏ผๅ่ฏ LLM ๅฎๆฏไปไน่ง่ฒใ่ฆ่พๅบไปไน๏ผ
|
| 176 |
+
ๆญฅ้ชค 2๏ผๅ User Prompt ๆจกๆฟ๏ผๆ่ฎบๆๆ ้ขๅๆ่ฆๅกซๅ
ฅๆจกๆฟ๏ผ
|
| 177 |
+
ๆญฅ้ชค 3๏ผ่ฐ OpenAI SDK ๅ้็ป DeepSeek
|
| 178 |
+
ๆญฅ้ชค 4๏ผ่งฃๆ LLM ่ฟๅ็ JSON
|
| 179 |
+
ๆญฅ้ชค 5๏ผ็จ 3-5 ็ฏ่ฎบๆๆต่ฏ๏ผ็ LLM ็ๆนๅๅคๆญๆฏๅฆๅ็
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
**ๆญๅปบ็ๅ
ณ้ฎไธๅจไบไปฃ็ ๏ผไปฃ็ ไธๅฐ 50 ่ก๏ผ๏ผๅจไบ Prompt ๅๅพๅฅฝไธๅฅฝใ** Prompt ๅณๅฎไบ Agent ็ๅคๆญ่ดจ้ใ
|
| 183 |
+
|
| 184 |
+
### 1.3 ๅฎๆดไปฃ็
|
| 185 |
+
|
| 186 |
+
```python
|
| 187 |
+
# direction_analyzer.py
|
| 188 |
+
# ============================================================
|
| 189 |
+
# ็ฑปๅ๏ผAGENT๏ผไน่ด่ดฃ๏ผ
|
| 190 |
+
# ๅ่ฝ๏ผLLM ่งฃๆ็ ็ฉถๆนๅ โ ๅญ้ขๅ + ๆนๆณๆ่ฐฑ็ณป + GitHub ๆ็ดข่ฏ
|
| 191 |
+
# ============================================================
|
| 192 |
+
import json
|
| 193 |
+
import re
|
| 194 |
+
from openai import OpenAI
|
| 195 |
+
|
| 196 |
+
# ้
็ฝฎ
|
| 197 |
+
DEEPSEEK_API_KEY = "sk-a115c4388d444cf688d323855edb36da"
|
| 198 |
+
DEEPSEEK_BASE_URL = "https://api.deepseek.com"
|
| 199 |
+
MODEL = "deepseek-chat"
|
| 200 |
+
|
| 201 |
+
client = OpenAI(api_key=DEEPSEEK_API_KEY, base_url=DEEPSEEK_BASE_URL)
|
| 202 |
+
|
| 203 |
+
# ============================================================
|
| 204 |
+
# System Prompt โโ ่ฟๆฏๆดไธชๆจกๅ็็ต้ญ๏ผ่ฐไผไธป่ฆ่ฐ่ฟ้
|
| 205 |
+
# ============================================================
|
| 206 |
+
DIRECTION_SYSTEM_PROMPT = """ไฝ ๆฏไธไธช AI ็ ็ฉถ้ขๅ็ๅฏผ่ชไธๅฎถใไฝ ็ไปปๅกๆฏ๏ผ็ปๅฎไธ็ฏ่ฎบๆ็ๆ ้ขๅๆ่ฆ๏ผๅธฎๅฉ็ ็ฉถ่
ๅฟซ้ไบ่งฃ่ฏฅๆนๅ็ๅๆฒฟๅผๆบ็ๆใ
|
| 207 |
+
|
| 208 |
+
## ไฝ ็ๅๆๆกๆถ
|
| 209 |
+
|
| 210 |
+
### ๅฑๆฌก 1๏ผๅญ้ขๅๅฎไฝ
|
| 211 |
+
- ่ฟ็ฏ่ฎบๆๅฑไบ AI/ML/CV/NLP ็ๅชไธชๅ
ทไฝๅญ้ขๅ๏ผ
|
| 212 |
+
- ไธ่ฆ็ปๅบ็ฌผ็ป็็ญๆก๏ผๅฆ "Deep Learning"๏ผ๏ผ่ฆ็ปๅบๅ
ทไฝๅญ้ขๅ๏ผๅฆ "Transformer-based Neural Machine Translation"๏ผ
|
| 213 |
+
- ่ฏดๆ่ฏฅๅญ้ขๅๅจ 2024-2025 ๅนด็ไธปๆต่ถๅฟ๏ผ1-2 ๅฅ่ฏ๏ผไธญๆ๏ผ
|
| 214 |
+
|
| 215 |
+
### ๅฑๆฌก 2๏ผๆนๆณๆ่ฐฑ็ณป
|
| 216 |
+
- ่ฏฅๅญ้ขๅ็ฎๅๆๅชไบไธปๆตๆนๆณๆ/ๅไฝ/ๆๆฏ่ทฏ็บฟ๏ผ
|
| 217 |
+
- ๆฏไธชๆนๆณๆ็ไปฃ่กจๅทฅไฝๆฏไปไน๏ผ่ฎบๆๆ็ฅๅ้กน็ฎๅ๏ผ๏ผ
|
| 218 |
+
- ่พๅบ 3-6 ไธชๆนๆณๆ๏ผไธ่ฆๅคชๅค๏ผๅคชๅคๆ็ดขไผๆ
ข๏ผ๏ผไนไธ่ฆๅคชๅฐ๏ผๅคชๅฐ่ฆ็้ขไธๅค๏ผ
|
| 219 |
+
- ๆฏไธชๆนๆณๆไธๅฅ่ฏ่ฏดๆๅ
ถๆ ธๅฟ็น็น
|
| 220 |
+
|
| 221 |
+
### ๅฑๆฌก 3๏ผๆ็ดข็ญ็ฅ
|
| 222 |
+
- ไธบๆฏไธชๆนๆณๆ็ๆ 2-3 ไธช GitHub ๆ็ดขๆฅ่ฏข
|
| 223 |
+
- ๆ็ดขๆฅ่ฏขไฝฟ็จ่ฑๆ๏ผๆ ผๅผ๏ผๆนๆณๅ + ๆๆฏๅ
ณ้ฎ่ฏ + ๆ็ดข้ๅฎ่ฏ
|
| 224 |
+
- ๆ็ดข้ๅฎ่ฏไฝฟ็จ๏ผimplementation, pytorch, official, tensorflow, code
|
| 225 |
+
- ้ขๅค็ๆ 3 ไธช่ฆ็ๅ
จ้ขๅ็ๅฎฝๆณๆ็ดข
|
| 226 |
+
- ๅฎฝๆณๆ็ดขไธ้ๅฎๅ
ทไฝๆนๆณๅ๏ผ็จๅญ้ขๅๅ+้ๅฎ่ฏ
|
| 227 |
+
|
| 228 |
+
## ๆ็ดขๆฅ่ฏข่ดจ้่ฆๆฑ
|
| 229 |
+
- ๅฅฝ็ๆฅ่ฏข็คบไพ๏ผ"vision transformer implementation pytorch"
|
| 230 |
+
- ๅฅฝ็ๆฅ่ฏข็คบไพ๏ผ"denoising diffusion probabilistic model official code"
|
| 231 |
+
- ๅ็ๆฅ่ฏข็คบไพ๏ผ"transformer"๏ผๅคชๅฎฝๆณ๏ผ
|
| 232 |
+
- ๅ็ๆฅ่ฏข็คบไพ๏ผ"a novel approach for image classification using deep learning"๏ผๅคชๅคๅบ่ฏ๏ผ
|
| 233 |
+
|
| 234 |
+
## ่พๅบๆ ผๅผ๏ผไธฅๆ ผ JSON๏ผไธ่ฆไปปไฝ้ขๅคๆๅญ๏ผไธ่ฆ markdown ไปฃ็ ๅๆ ่ฎฐ๏ผ
|
| 235 |
+
{
|
| 236 |
+
"subfield": "ๅ
ทไฝๅญ้ขๅๅ็งฐ",
|
| 237 |
+
"subfield_trend": "่ฏฅๅญ้ขๅ 2024-2025 ็ไธปๆต่ถๅฟ๏ผ1-2 ๅฅไธญๆ๏ผ",
|
| 238 |
+
"method_families": [
|
| 239 |
+
{
|
| 240 |
+
"family_name": "ๆนๆณๆ็ฎ็งฐ",
|
| 241 |
+
"description": "ไธๅฅ่ฏๆ ธๅฟ็น็น",
|
| 242 |
+
"representative_work": "ไปฃ่กจ่ฎบๆๆ็ฅๅ้กน็ฎ",
|
| 243 |
+
"search_queries": ["ๆ็ดข่ฏ1", "ๆ็ดข่ฏ2", "ๆ็ดข่ฏ3"]
|
| 244 |
+
}
|
| 245 |
+
],
|
| 246 |
+
"broad_queries": ["ๅฎฝๆณๆ็ดข1", "ๅฎฝๆณๆ็ดข2", "ๅฎฝๆณๆ็ดข3"]
|
| 247 |
+
}
|
| 248 |
+
"""
|
| 249 |
+
|
| 250 |
+
def analyze_direction(title: str, abstract: str) -> dict:
|
| 251 |
+
"""ไป่ฎบๆๆ ้ขๅๆ่ฆไธญ่งฃๆ็ ็ฉถๆนๅๅนถ็ๆๆ็ดข็ญ็ฅใ
|
| 252 |
+
|
| 253 |
+
Args:
|
| 254 |
+
title: ่ฎบๆๆ ้ข
|
| 255 |
+
abstract: ่ฎบๆๆ่ฆ๏ผไผ่ชๅจๆชๆญๅฐ 2500 ๅญ็ฌฆ๏ผ
|
| 256 |
+
|
| 257 |
+
Returns:
|
| 258 |
+
dict: ๅ
ๅซ subfield, subfield_trend, method_families, broad_queries
|
| 259 |
+
"""
|
| 260 |
+
# ๆชๆญๆ่ฆ๏ผ้ฒๆญข่ถ
ๅบ token ้ๅถ
|
| 261 |
+
abstract_truncated = abstract[:2500] if abstract else "๏ผๆ่ฆไธๅฏ็จ๏ผ"
|
| 262 |
+
title_clean = title.strip() if title else "๏ผๆ ้ขไธๅฏ็จ๏ผ"
|
| 263 |
+
|
| 264 |
+
user_prompt = f"""## ่ฎบๆๆ ้ข
|
| 265 |
+
{title_clean}
|
| 266 |
+
|
| 267 |
+
## ่ฎบๆๆ่ฆ
|
| 268 |
+
{abstract_truncated}
|
| 269 |
+
|
| 270 |
+
่ฏทๅๆ่ฏฅ่ฎบๆ็็ ็ฉถๆนๅๅนถ็ๆๆ็ดข็ญ็ฅใ"""
|
| 271 |
+
|
| 272 |
+
response = client.chat.completions.create(
|
| 273 |
+
model=MODEL,
|
| 274 |
+
messages=[
|
| 275 |
+
{"role": "system", "content": DIRECTION_SYSTEM_PROMPT},
|
| 276 |
+
{"role": "user", "content": user_prompt},
|
| 277 |
+
],
|
| 278 |
+
temperature=0.4, # 0.4 ็ปๆนๆณๆๆขณ็ไฟ็ไธไบๅคๆ ทๆง
|
| 279 |
+
max_tokens=2000,
|
| 280 |
+
# ๅฆๆ DeepSeek ๆฏๆ response_format๏ผๅๆถไธ้ข่ฟ่ก็ๆณจ้ๅฏไปฅๆๅ JSON ้ตๅฎ็
|
| 281 |
+
# response_format={"type": "json_object"},
|
| 282 |
+
)
|
| 283 |
+
raw = response.choices[0].message.content.strip()
|
| 284 |
+
return _parse_json_safe(raw)
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
def _parse_json_safe(raw: str) -> dict:
|
| 288 |
+
"""ๅฎๅ
จ่งฃๆ LLM ่ฟๅ็ JSON๏ผๅค็ๅ็งๅธธ่ง็ๆ ผๅผ้ฎ้ขใ
|
| 289 |
+
|
| 290 |
+
LLM ๅฏ่ฝ่ฟๅ๏ผ
|
| 291 |
+
1. ็บฏ JSON๏ผ{"subfield": "..."}
|
| 292 |
+
2. markdown ๅ
๏ฟฝ๏ฟฝ๏ฟฝ๏ผ```json\n{...}\n```
|
| 293 |
+
3. ๅธฆๅ็ผๆๅญ๏ผ่ฟๆฏๅๆ็ปๆ๏ผ\n{...}
|
| 294 |
+
4. ๆ ผๅผ้่ฏฏ๏ผ็ผบๅฐๅผๅทใๅฐพ้จ้ๅท็ญ
|
| 295 |
+
"""
|
| 296 |
+
# ็ญ็ฅ 1๏ผ็ดๆฅ่งฃๆ
|
| 297 |
+
try:
|
| 298 |
+
return json.loads(raw)
|
| 299 |
+
except json.JSONDecodeError:
|
| 300 |
+
pass
|
| 301 |
+
|
| 302 |
+
# ็ญ็ฅ 2๏ผๆๅ markdown ไปฃ็ ๅ
|
| 303 |
+
match = re.search(r'```(?:json)?\s*([\s\S]*?)```', raw)
|
| 304 |
+
if match:
|
| 305 |
+
try:
|
| 306 |
+
return json.loads(match.group(1).strip())
|
| 307 |
+
except json.JSONDecodeError:
|
| 308 |
+
pass
|
| 309 |
+
|
| 310 |
+
# ็ญ็ฅ 3๏ผๆๅ็ฌฌไธไธช { ... } ๅฏน่ฑก๏ผ่ดชๅฉชๅน้
ๆๅคๅฑ๏ผ
|
| 311 |
+
match = re.search(r'\{[\s\S]*\}', raw)
|
| 312 |
+
if match:
|
| 313 |
+
try:
|
| 314 |
+
return json.loads(match.group(0))
|
| 315 |
+
except json.JSONDecodeError:
|
| 316 |
+
pass
|
| 317 |
+
|
| 318 |
+
# ็ญ็ฅ 4๏ผๅ
จ้จๅคฑ่ดฅ๏ผๆๅบๅผๅธธ๏ผๅธฆไธๅๅงๅ
ๅฎนๆนไพฟ่ฐ่ฏ๏ผ
|
| 319 |
+
raise ValueError(
|
| 320 |
+
f"direction_analyzer: ๆ ๆณ่งฃๆ LLM ่ฟๅ็ JSONใ\n"
|
| 321 |
+
f"ๅๅง่ฟๅ๏ผๅ 500 ๅญ็ฌฆ๏ผ:\n{raw[:500]}"
|
| 322 |
+
)
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
# ============================================================
|
| 326 |
+
# ่ชๆตไปฃ็ โโ ๅๅฎๅ่ฟ่ก python direction_analyzer.py ้ช่ฏ
|
| 327 |
+
# ============================================================
|
| 328 |
+
if __name__ == "__main__":
|
| 329 |
+
# ๆต่ฏ็จไพ 1๏ผTransformer๏ผ็ปๅ
ธ่ฎบๆ๏ผๆนๆณๆไธฐๅฏ๏ผ
|
| 330 |
+
print("=" * 60)
|
| 331 |
+
print("ๆต่ฏ 1๏ผTransformer ่ฎบๆ")
|
| 332 |
+
print("=" * 60)
|
| 333 |
+
result = analyze_direction(
|
| 334 |
+
"Attention Is All You Need",
|
| 335 |
+
"The dominant sequence transduction models are based on complex recurrent "
|
| 336 |
+
"or convolutional neural networks... We propose a new simple network "
|
| 337 |
+
"architecture, the Transformer, based solely on attention mechanisms."
|
| 338 |
+
)
|
| 339 |
+
print(f"ๅญ้ขๅ: {result.get('subfield')}")
|
| 340 |
+
print(f"ๆนๆณๆ: {[mf.get('family_name') for mf in result.get('method_families', [])]}")
|
| 341 |
+
print(f"ๆปๆ็ดข่ฏๆฐ: {sum(len(mf.get('search_queries', [])) for mf in result.get('method_families', [])) + len(result.get('broad_queries', []))}")
|
| 342 |
+
|
| 343 |
+
print()
|
| 344 |
+
|
| 345 |
+
# ๆต่ฏ็จไพ 2๏ผPaDiM๏ผๅทฅไธ็ผบ้ทๆฃๆต๏ผไฝ ็้ขๅ๏ผ
|
| 346 |
+
print("=" * 60)
|
| 347 |
+
print("ๆต่ฏ 2๏ผPaDiM ่ฎบๆ๏ผๅทฅไธ็ผบ้ทๆฃๆต๏ผ")
|
| 348 |
+
print("=" * 60)
|
| 349 |
+
result = analyze_direction(
|
| 350 |
+
"PaDiM: a Patch Distribution Modeling Framework for Anomaly Detection and Localization",
|
| 351 |
+
"We present a new framework for anomaly detection and localization based on "
|
| 352 |
+
"patch distribution modeling. PaDiM uses pretrained convolutional neural networks "
|
| 353 |
+
"to extract patch features and models their distribution using multivariate "
|
| 354 |
+
"Gaussian distributions. It achieves state-of-the-art results on MVTec AD and "
|
| 355 |
+
"STC datasets for industrial defect detection."
|
| 356 |
+
)
|
| 357 |
+
print(f"ๅญ้ขๅ: {result.get('subfield')}")
|
| 358 |
+
print(f"่ถๅฟ: {result.get('subfield_trend')}")
|
| 359 |
+
print(f"ๆนๆณๆๆฐ้: {len(result.get('method_families', []))}")
|
| 360 |
+
for mf in result.get("method_families", []):
|
| 361 |
+
print(f" - {mf.get('family_name')}: {mf.get('description')[:60]}...")
|
| 362 |
+
print(f"ๅฎฝๆณๆ็ดข่ฏ: {result.get('broad_queries', [])}")
|
| 363 |
+
|
| 364 |
+
print()
|
| 365 |
+
|
| 366 |
+
# ๆต่ฏ็จไพ 3๏ผEfficientAD๏ผ่พๆฐ่ฎบๆ๏ผๆไธๅฐไปฃ็ ็ๆต่ฏ๏ผ
|
| 367 |
+
print("=" * 60)
|
| 368 |
+
print("ๆต่ฏ 3๏ผEfficientAD ่ฎบๆ๏ผ2023๏ผ่พๆฐ๏ผ")
|
| 369 |
+
print("=" * 60)
|
| 370 |
+
result = analyze_direction(
|
| 371 |
+
"EfficientAD: Accurate Visual Anomaly Detection at Millisecond-Level Latencies",
|
| 372 |
+
"We propose EfficientAD, a lightweight anomaly detection method that achieves "
|
| 373 |
+
"millisecond-level latency. It uses a teacher-student architecture with a simple "
|
| 374 |
+
"student network that learns to mimic the teacher's features on normal images only."
|
| 375 |
+
)
|
| 376 |
+
print(f"ๅญ้ขๅ: {result.get('subfield')}")
|
| 377 |
+
print(f"ๆนๆณๆ: {[mf.get('family_name') for mf in result.get('method_families', [])]}")
|
| 378 |
+
```
|
| 379 |
+
|
| 380 |
+
### 1.3 ่ฐ่ฏๆๅ
|
| 381 |
+
|
| 382 |
+
**้ฎ้ข 1๏ผLLM ่ฟๅ็ไธๆฏ JSON**
|
| 383 |
+
- ็็ถ๏ผ`ValueError: direction_analyzer: ๆ ๆณ่งฃๆ LLM ่ฟๅ็ JSON`
|
| 384 |
+
- ๆๆฅ๏ผๆๅฐ `raw[:500]` ็็ LLM ๅฐๅบๅไบไปไน
|
| 385 |
+
- ไฟฎๅค๏ผๅฆๆ LLM ้ข็น่ฟๅ้ JSON๏ผๅจ system prompt ็ฌฌไธๅฅๅ `ไฝ ๅฟ
้กปๅช่ฟๅไธไธช JSON ๅฏน่ฑก๏ผไธ่ฆๆไปปไฝ่งฃ้ๆๅญใ`
|
| 386 |
+
- ๅค้๏ผๅฆๆ DeepSeek ๆฏๆ `response_format={"type": "json_object"}` ๅฐฑๅผๅฏ๏ผ่งไปฃ็ ไธญ็ๆณจ้่ก๏ผ
|
| 387 |
+
|
| 388 |
+
**้ฎ้ข 2๏ผๆนๆณๆๅคชๅฐ๏ผๆฏๅฆๅชๆ 2 ไธช๏ผ**
|
| 389 |
+
- ็็ถ๏ผๆ็ดข่ฆ็้ขไธๅค๏ผๆพไธๅฐ่ถณๅค็ไปๅบ
|
| 390 |
+
- ไฟฎๅค๏ผๅจ system prompt ้ๆ"่พๅบ 3-6 ไธชๆนๆณๆ"ๆนๆ"ๅฟ
้กป่พๅบ่ณๅฐ 4 ไธชๆนๆณๆ"
|
| 391 |
+
|
| 392 |
+
**้ฎ้ข 3๏ผๆ็ดข่ฏ่ดจ้ๅทฎ๏ผๆไธๅฐไปๅบ๏ผ**
|
| 393 |
+
- ็็ถ๏ผ็ๆ็ๆ็ดข่ฏๅจ GitHub ไธ่ฟๅ็ฉบ็ปๆๆๆ ๅ
ณ็ปๆ
|
| 394 |
+
- ๆต่ฏๆนๆณ๏ผๅคๅถ็ๆ็ๆ็ดข่ฏ๏ผๆๅจๅจ GitHub ๆ็ดขๆก้ๆ๏ผ็็ปๆ่ดจ้
|
| 395 |
+
- ไฟฎๅค๏ผๅจ system prompt ็ๆ็ดข็คบไพ้จๅๅขๅ ๆดๅคๅฅฝ/ๅไพๅญ
|
| 396 |
+
|
| 397 |
+
**้ฎ้ข 4๏ผๆนๆณๆๅ็งฐๅคชๅญฆๆฏๅ๏ผGitHub ๆไธๅฐ**
|
| 398 |
+
- ็็ถ๏ผๆนๆณๆๅซ "Gated Linear Unit Enhanced Multi-Head Self-Attention"๏ผGitHub ๆฒก็ปๆ
|
| 399 |
+
- ไฟฎๅค๏ผๅจ prompt ้่ฆๆฑๆ็ดข่ฏไฝฟ็จๅธธ็จ๏ฟฝ๏ฟฝ็ฎ็งฐ่้่ฎบๆๅ
จๅ
|
| 400 |
+
|
| 401 |
+
---
|
| 402 |
+
|
| 403 |
+
## ไบใAgent 2๏ผ`repo_evaluator.py` โ ๅฏๅค็ฐๆง + ้้
ๅบฆ่ฏไผฐ
|
| 404 |
+
|
| 405 |
+
> **็ฑปๅ๏ผAgent** | ่ฟๆฏไฝ ่ด่ดฃ็็ฌฌไบไธช Agent
|
| 406 |
+
> **ๆ ธๅฟๅคๆญ**๏ผ็ปๅฎไธไธชไปๅบ็ README + ไพ่ตๆไปถ๏ผLLM ๅคๆญๅฎ่ฝไธ่ฝ่ทใ้ไธ้ๅๆฟๆฅๅๅฏนๆฏๅฎ้ช
|
| 407 |
+
|
| 408 |
+
### 2.1 ่ฟไธช Agent ่ฆ่งฃๅณไปไน้ฎ้ข
|
| 409 |
+
|
| 410 |
+
ๅฝไฝ ้่ฟ Agent 1๏ผๆนๅ่งฃๆ๏ผๅ็ฒ็ไธคไธช Workflow๏ผๆ็ดข+ๆๅ๏ผๆฟๅฐไบ 5 ไธชๅ้ไปๅบๅ๏ผ้่ฆๅคๆญไธคไธชๅฑ้ข๏ผ
|
| 411 |
+
1. **่ฝไธ่ฝ่ท๏ผ**๏ผๅฏๅค็ฐๆง 5 ็ปดๅบฆ๏ผ80 ๅ๏ผโโ ่ฟๆฏ"ๆๆฏๅฏ่กๆง"
|
| 412 |
+
2. **้ไธ้ๅ็ดๆฅๆฟๆฅๅๅฏนๆฏๅฎ้ช๏ผ**๏ผ้้
ๅบฆ 1 ็ปดๅบฆ๏ผ20 ๅ๏ผโโ ่ฟๆฏ"่ฎบๆๅฎ็จๆง"
|
| 413 |
+
|
| 414 |
+
ไธคไธชๅฑ้ขๅฟ
้กปๅๅผๆๅใๆฏๅฆ anomalib๏ผOpenVINO ็ๅผๅธธๆฃๆตๅบ๏ผ๏ผ
|
| 415 |
+
- ๅฏๅค็ฐๆง่ฏๅ้ซ๏ผREADME ๅฎๅใๆ requirements.txtใpip install ๅณ็จ๏ผ
|
| 416 |
+
- ้้
ๅบฆ่ฏๅ้ซ๏ผๆๆ ๅ benchmark ่ๆฌใๆฏๆ MVTec AD ๆฐๆฎ้ใๆ้ข่ฎญ็ปๆ้๏ผ
|
| 417 |
+
|
| 418 |
+
่ไธไธช"ๅชๆๆจ็่ๆฌ็ไธชไบบ้กน็ฎ"๏ผ
|
| 419 |
+
- ๅฏๅค็ฐๆงๅฏ่ฝ่ฟ่ก๏ผ่ฝ่ท้ demo๏ผ
|
| 420 |
+
- ้้
ๅบฆไธๅฎไฝ๏ผๆฒกๆ่ฎญ็ป่ๆฌๅๆ ๅๅ่ฏไผฐ๏ผไธ่ฝ็จไบ่ทๅฏนๆฏๅฎ้ช๏ผ
|
| 421 |
+
|
| 422 |
+
### 2.2 ่ฟไธช Agent ็ๆญๅปบๆ่ทฏ
|
| 423 |
+
|
| 424 |
+
```
|
| 425 |
+
ๆญฅ้ชค 1๏ผๅ System Prompt๏ผๅฎไนๅ
ญ็ปดๅบฆ่ฏๅๆกๆถ + ๆฏไธช็ปดๅบฆ็ๅๆฐ้็น
|
| 426 |
+
ๆญฅ้ชค 2๏ผๅ User Prompt ๆจกๆฟ๏ผๅกซๅ
ฅ README + ไพ่ตๆไปถ + ไปๅบๅ
ไฟกๆฏ๏ผ
|
| 427 |
+
ๆญฅ้ชค 3๏ผ่ฐ OpenAI SDK ๅ้็ป DeepSeek
|
| 428 |
+
ๆญฅ้ชค 4๏ผ่งฃๆ LLM ่ฟๅ็ JSON
|
| 429 |
+
ๆญฅ้ชค 5๏ผ็จ 5 ไธชไฝ ่ชๅทฑ็ๆ็ไปๅบๆต่ฏ๏ผ2 ๅฅฝ + 2 ๅทฎ + 1 ไธญ๏ผ๏ผๅฏนๆฏ LLM ่ฏๅ vs ไฝ ็ไบบๅทฅ่ฏๅ
|
| 430 |
+
```
|
| 431 |
+
|
| 432 |
+
**่ฟไธช Agent ๆ้พ็้จๅ**๏ผ่ฎฉ LLM ๅบๅ"่ฝ่ท"ๅ"้ๅ่ทๅฏนๆฏๅฎ้ช"ใๅพๅคๅๅญฆ่
ไผๆ่ฟไธคไธชๆฆๅฟตๆททๆทใๅฆๆไฝ ็ prompt ๆฒกๅๆธ
ๆฅ๏ผLLM ไนไผๆททๆทใ่ฐ่ฏๆถ้็นๆฃๆฅ๏ผREADME ๅฅฝไฝๅชๆๆจ็็ไปๅบ๏ผ้้
ๅบฆๆฏๅฆ็็ไฝไบ 10 ๅใ
|
| 433 |
+
|
| 434 |
+
### 2.3 ๅฎๆดไปฃ็
|
| 435 |
+
|
| 436 |
+
```python
|
| 437 |
+
# repo_evaluator.py
|
| 438 |
+
# ============================================================
|
| 439 |
+
# ็ฑปๅ๏ผAGENT๏ผไน่ด่ดฃ๏ผ
|
| 440 |
+
# ๅ่ฝ๏ผLLM ๅ
ญ็ปดๅบฆ่ฏๅ๏ผๅฏๅค็ฐๆง 5 ็ปด + ๅฏนๆฏๅฎ้ช้้
ๅบฆ 1 ็ปด๏ผ
|
| 441 |
+
# ============================================================
|
| 442 |
+
import json
|
| 443 |
+
import re
|
| 444 |
+
from openai import OpenAI
|
| 445 |
+
|
| 446 |
+
DEEPSEEK_API_KEY = "sk-a115c4388d444cf688d323855edb36da"
|
| 447 |
+
DEEPSEEK_BASE_URL = "https://api.deepseek.com"
|
| 448 |
+
MODEL = "deepseek-chat"
|
| 449 |
+
|
| 450 |
+
client = OpenAI(api_key=DEEPSEEK_API_KEY, base_url=DEEPSEEK_BASE_URL)
|
| 451 |
+
|
| 452 |
+
# ============================================================
|
| 453 |
+
# System Prompt
|
| 454 |
+
# ============================================================
|
| 455 |
+
EVAL_SYSTEM_PROMPT = """ไฝ ๆฏไธไธช AI ่ฎบๆไปฃ็ ่ฏไผฐไธๅฎถใไฝ ้่ฆๅๆถ่ฏไผฐไธไธช GitHub ไปๅบ็ไธคไธชๆน้ข๏ผ
|
| 456 |
+
- **ๅฏๅค็ฐๆง**๏ผ่ฟไธชไปๅบ็ไปฃ็ ่ฝไธ่ฝ่ขซไปไบบๆๅ่ท้๏ผ
|
| 457 |
+
- **ๅฏนๆฏๅฎ้ช้้
ๅบฆ**๏ผ่ฟไธชไปๅบ้ไธ้ๅ็ดๆฅๆฟๆฅๅ่ฎบๆๅๅฏนๆฏๅฎ้ช๏ผbaseline / comparison๏ผ๏ผ
|
| 458 |
+
|
| 459 |
+
## ่ฏไผฐๆกๆถ๏ผๅ
ญ็ปดๅบฆ๏ผๆปๅ 100๏ผ
|
| 460 |
+
|
| 461 |
+
### ๅฏๅค็ฐๆง๏ผไบ็ปดๅบฆ๏ผๅ่ฎก 80 ๅ๏ผ
|
| 462 |
+
|
| 463 |
+
1. **็ฏๅข้
็ฝฎๅฎๆดๆง๏ผ0-15 ๅ๏ผ**
|
| 464 |
+
- 15 ๅ๏ผๆไพไบ requirements.txt / environment.yml๏ผๆๆไพ่ต็ๆฌๅทๆ็กฎ
|
| 465 |
+
- 8-14 ๅ๏ผๆไพ่ตๆไปถไฝ้จๅ็ๆฌๅทไฝฟ็จ่ๅด๏ผ>=, ~=๏ผๆ็ผบๅคฑ
|
| 466 |
+
- 0-7 ๅ๏ผๆฒกๆไพ่ตๆไปถๆไธฅ้ไธๅฎๆด
|
| 467 |
+
|
| 468 |
+
2. **ๆๆกฃ่ดจ้๏ผ0-20 ๅ๏ผ**
|
| 469 |
+
- 16-20 ๅ๏ผๆๆธ
ๆฐ็ๅฎ่ฃ
ๆญฅ้ชคใ่ฎญ็ปๅฝไปคใๆจ็ๅฝไปคใๆฐๆฎ้่ทๅๆนๅผ
|
| 470 |
+
- 8-15 ๅ๏ผๆๅบๆฌ่ฏดๆไฝๅ
ณ้ฎๆญฅ้ชค็ผบๅคฑ๏ผๅฆๆฒก่ฏดๆฐๆฎ้ๅจๅชไธ่ฝฝ๏ผ
|
| 471 |
+
- 0-7 ๅ๏ผREADME ๅชๆ้กน็ฎ็ฎไป๏ผๆฒกๆๅฏๆง่กๅฝไปค
|
| 472 |
+
|
| 473 |
+
3. **ไปฃ็ ๅฏ็จๆง๏ผ0-20 ๅ๏ผ**
|
| 474 |
+
- 16-20 ๅ๏ผ่ฎญ็ป่ๆฌ + ๆจ็่ๆฌ + ้
็ฝฎๆไปถ + ๆจกๅๅฎไนๅ
ฅๅฃๅฎๆด
|
| 475 |
+
- 8-15 ๅ๏ผๆๆ ธๅฟไปฃ็ ไฝ็ผบๅฐๅ
ณ้ฎ็ปไปถ๏ผๅฆๅชๆๆจ็ๆฒกๆ่ฎญ็ป๏ผ
|
| 476 |
+
- 0-7 ๅ๏ผไปฃ็ ๆฎ็ผบ๏ผๅชๆ้ชจๆถๆ shell ่ๆฌ
|
| 477 |
+
|
| 478 |
+
4. **็คพๅบๆดป่ทๅบฆ๏ผ0-10 ๅ๏ผ**
|
| 479 |
+
- 8-10 ๅ๏ผStar > 500๏ผๆ่ฟๅๅนดๆ commit๏ผIssue ๆไบบๅๅค
|
| 480 |
+
- 4-7 ๅ๏ผๆไธๅฎๅ
ณๆณจๅบฆไฝๆดๆฐไธ้ข็น
|
| 481 |
+
- 0-3 ๅ๏ผ้ฟๆไธๆดๆฐ๏ผStar < 10
|
| 482 |
+
|
| 483 |
+
5. **ไพ่ตๅฅๅบทๅบฆ๏ผ0-15 ๅ๏ผ**
|
| 484 |
+
- 12-15 ๅ๏ผไพ่ตๅ
จๆฏไธปๆตๆดป่ทๅ
๏ผ็ๆฌ็ธไบๅ
ผๅฎน
|
| 485 |
+
- 6-11 ๅ๏ผๆๅฐ้่ฟๆถไพ่ตไฝไธๅฝฑๅๅฎ่ฃ
|
| 486 |
+
- 0-5 ๅ๏ผไพ่ตๆถๅๅทฒๅๆญข็ปดๆค็ๅ
๏ผๅฆ TensorFlow 1.xใPython 2๏ผ๏ผๅทฒ็ฅๆ ๆณๅจ็ฐไปฃ็ฏๅขๅฎ่ฃ
|
| 487 |
+
|
| 488 |
+
### ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผไธ็ปดๅบฆ๏ผ20 ๅ๏ผ
|
| 489 |
+
|
| 490 |
+
6. **ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผ0-20 ๅ๏ผ**
|
| 491 |
+
- 16-20 ๅ๏ผๆไพๆ ๅ benchmark ่ฏไผฐ่ๆฌ + ้ข่ฎญ็ปๆ้ไธ่ฝฝ + ๅ
ฌๅผๆฐๆฎ้ๆฏๆ๏ผๅฏ็ดๆฅ่ทๅบ่ฎบๆๅธธ็จๆๆ ๏ผๅฏไปฅๆ ็ผๆๅ
ฅ่ฎบๆ็ Experiment section
|
| 492 |
+
- 10-15 ๅ๏ผๆ่ฎญ็ป่ๆฌๅ่ฏไผฐไปฃ็ ๏ผไฝ้่ฆ่ชๅทฑๅๅคๆฐๆฎๆ้้
ๆฐๆฎ้ๆ ผๅผ
|
| 493 |
+
- 0-9 ๅ๏ผๅชๆๆจ็ demoใไฝฟ็จ็งๆๆฐๆฎ้ใๆฒกๆๆ ๅๅ่ฏไผฐๆต็จใๆๆฒกๆ้ข่ฎญ็ปๆ้
|
| 494 |
+
|
| 495 |
+
## ่พๅบๆ ผๅผ๏ผไธฅๆ ผ JSON๏ผ
|
| 496 |
+
{
|
| 497 |
+
"reproducibility_score": 80,
|
| 498 |
+
"benchmark_fitness_score": 20,
|
| 499 |
+
"overall_score": 100,
|
| 500 |
+
"verdict": "reproducible",
|
| 501 |
+
"env_score": 15,
|
| 502 |
+
"doc_score": 20,
|
| 503 |
+
"code_score": 20,
|
| 504 |
+
"community_score": 10,
|
| 505 |
+
"dep_score": 15,
|
| 506 |
+
"benchmark_score": 20,
|
| 507 |
+
"reasoning": "200ๅญไปฅๅ
็ไธญๆๅๆ๏ผๅฟ
้กปๅบๅ'่ฝไธ่ฝ่ท'ๅ'้ไธ้ๅ่ทๅฏนๆฏๅฎ้ช'ไธคไธชๅฑ้ข",
|
| 508 |
+
"risks": ["้ฃ้ฉ1", "้ฃ้ฉ2"],
|
| 509 |
+
"benchmark_readiness": "ready",
|
| 510 |
+
"suggested_use": "ๅฏไปฅ็ดๆฅไฝไธบๅฏนๆฏๅฎ้ช baseline"
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
## ๅคๅฎ่งๅ
|
| 514 |
+
- overall_score >= 70 โ verdict = "reproducible"
|
| 515 |
+
- 40 <= overall_score < 70 โ verdict = "partially"
|
| 516 |
+
- overall_score < 40 โ verdict = "not_reproducible"
|
| 517 |
+
|
| 518 |
+
- benchmark_score >= 16 โ benchmark_readiness = "ready"
|
| 519 |
+
- 10 <= benchmark_score < 16 โ benchmark_readiness = "partial"
|
| 520 |
+
- benchmark_score < 10 โ benchmark_readiness = "not_ready"
|
| 521 |
+
|
| 522 |
+
## bench_readiness ไธ suggested_use ็ๅฏนๅบๅ
ณ็ณป
|
| 523 |
+
- "ready" โ "ๅฏไปฅ็ดๆฅไฝไธบๅฏนๆฏๅฎ้ช baseline"
|
| 524 |
+
- "partial" โ "้่ฆๅฐ้ไฟฎๆนๅๅฏ็จไบๅฏนๆฏๅฎ้ช"
|
| 525 |
+
- "not_ready" โ "ไป
้ๅๅ่ไปฃ็ ๅฎ็ฐ๏ผไธ้ๅ็ดๆฅ่ทๅฏนๆฏๅฎ้ช"
|
| 526 |
+
"""
|
| 527 |
+
|
| 528 |
+
|
| 529 |
+
def evaluate_repo(
|
| 530 |
+
repo: dict,
|
| 531 |
+
readme: str | None,
|
| 532 |
+
dependencies: dict[str, str],
|
| 533 |
+
method_family: str = "",
|
| 534 |
+
) -> dict:
|
| 535 |
+
"""่ฏไผฐๅไธชไปๅบ็ๅฏๅค็ฐๆงๅๅฏนๆฏๅฎ้ช้้
ๅบฆใ
|
| 536 |
+
|
| 537 |
+
Args:
|
| 538 |
+
repo: ไปๅบๅ
ไฟกๆฏ dict๏ผๆฅ่ช repo_searcher๏ผ๏ผๅ
ๅซ full_name, html_url, stars ็ญ
|
| 539 |
+
readme: README ๆไปถๅ
จๆ๏ผๆ None๏ผ
|
| 540 |
+
dependencies: {ๆไปถๅ: ๆไปถๅ
ๅฎน} ็ dict
|
| 541 |
+
method_family: ่ฏฅไปๅบๆๅฑ็ๆนๆณๆๅ็งฐ๏ผ็ฉบๅญ็ฌฆไธฒ่กจ็คบๆชๅฝ็ฑป๏ผ
|
| 542 |
+
|
| 543 |
+
Returns:
|
| 544 |
+
dict: ๅ
ญ็ปดๅบฆ่ฏๅ็ปๆ
|
| 545 |
+
"""
|
| 546 |
+
# ๆ้ README ่พๅ
ฅ
|
| 547 |
+
readme_text = (readme or "README ๆชๆพๅฐ")[:2500]
|
| 548 |
+
|
| 549 |
+
# ๆ้ ไพ่ตๆไปถ่พๅ
ฅ
|
| 550 |
+
if dependencies:
|
| 551 |
+
deps_parts = []
|
| 552 |
+
for fname, content in dependencies.items():
|
| 553 |
+
truncated = content[:1000] if content else "(็ฉบๆไปถ)"
|
| 554 |
+
deps_parts.append(f"### {fname}\n```\n{truncated}\n```")
|
| 555 |
+
deps_text = "\n\n".join(deps_parts)
|
| 556 |
+
else:
|
| 557 |
+
deps_text = "ๆชๆพๅฐไปปไฝไพ่ตๆไปถ๏ผrequirements.txt / environment.yml ็ญ๏ผ"
|
| 558 |
+
|
| 559 |
+
# ๆนๆณๆๆ็คบ
|
| 560 |
+
family_hint = f"\n- ๆนๆณๆ: {method_family}" if method_family else ""
|
| 561 |
+
|
| 562 |
+
user_prompt = f"""## ไปๅบๅบๆฌไฟกๆฏ
|
| 563 |
+
- ๅ็งฐ: {repo.get('full_name', 'ๆช็ฅ')}
|
| 564 |
+
- URL: {repo.get('html_url', '')}
|
| 565 |
+
- Stars: {repo.get('stars', 0)}
|
| 566 |
+
- ๆ่ฟฐ: {repo.get('description', 'ๆ ๆ่ฟฐ')}
|
| 567 |
+
- ๆๅๆดๆฐ: {repo.get('updated_at', 'ๆช็ฅ')}
|
| 568 |
+
- ไธป่ฆ่ฏญ่จ: {repo.get('language', 'ๆช็ฅ')}{family_hint}
|
| 569 |
+
|
| 570 |
+
## README ๅ
ๅฎน
|
| 571 |
+
{readme_text}
|
| 572 |
+
|
| 573 |
+
## ไพ่ตๆไปถ
|
| 574 |
+
{deps_text}
|
| 575 |
+
|
| 576 |
+
่ฏท่ฏไผฐ่ฏฅไปๅบ็ๅฏๅค็ฐๆงๅๅฏนๆฏๅฎ้ช้้
ๅบฆใ"""
|
| 577 |
+
|
| 578 |
+
response = client.chat.completions.create(
|
| 579 |
+
model=MODEL,
|
| 580 |
+
messages=[
|
| 581 |
+
{"role": "system", "content": EVAL_SYSTEM_PROMPT},
|
| 582 |
+
{"role": "user", "content": user_prompt},
|
| 583 |
+
],
|
| 584 |
+
temperature=0.3, # ่ฏไผฐไปปๅก็จไฝๆธฉๅบฆ
|
| 585 |
+
max_tokens=2000,
|
| 586 |
+
)
|
| 587 |
+
raw = response.choices[0].message.content.strip()
|
| 588 |
+
return _parse_json_safe(raw)
|
| 589 |
+
|
| 590 |
+
|
| 591 |
+
def _parse_json_safe(raw: str) -> dict:
|
| 592 |
+
"""ๅฎๅ
จ JSON ่งฃๆ๏ผๅค็ง็ญ็ฅๅฎน้"""
|
| 593 |
+
try:
|
| 594 |
+
return json.loads(raw)
|
| 595 |
+
except json.JSONDecodeError:
|
| 596 |
+
pass
|
| 597 |
+
|
| 598 |
+
match = re.search(r'```(?:json)?\s*([\s\S]*?)```', raw)
|
| 599 |
+
if match:
|
| 600 |
+
try:
|
| 601 |
+
return json.loads(match.group(1).strip())
|
| 602 |
+
except json.JSONDecodeError:
|
| 603 |
+
pass
|
| 604 |
+
|
| 605 |
+
match = re.search(r'\{[\s\S]*\}', raw)
|
| 606 |
+
if match:
|
| 607 |
+
try:
|
| 608 |
+
return json.loads(match.group(0))
|
| 609 |
+
except json.JSONDecodeError:
|
| 610 |
+
pass
|
| 611 |
+
|
| 612 |
+
raise ValueError(
|
| 613 |
+
f"repo_evaluator: ๆ ๆณ่งฃๆ LLM ่ฟๅ็ JSONใ\n"
|
| 614 |
+
f"ๅๅง่ฟๅ๏ผๅ 500 ๅญ็ฌฆ๏ผ:\n{raw[:500]}"
|
| 615 |
+
)
|
| 616 |
+
|
| 617 |
+
|
| 618 |
+
# ============================================================
|
| 619 |
+
# ่ชๆตไปฃ็ โโ ๅๅฎๅ่ฟ่ก python repo_evaluator.py ้ช่ฏ
|
| 620 |
+
# ============================================================
|
| 621 |
+
if __name__ == "__main__":
|
| 622 |
+
# ๆต่ฏ 1๏ผanomalib๏ผๅทฅไธ็ผบ้ทๆฃๆต้ขๅ็ๆๆ้กน็ฎ๏ผๅบ่ฏฅๆฏ้ซๅ๏ผ
|
| 623 |
+
print("=" * 60)
|
| 624 |
+
print("ๆต่ฏ 1๏ผOpenVINO anomalib๏ผ้ขๆ๏ผๅฏๅค็ฐๆง้ซ + ้้
ๅบฆ้ซ๏ผ")
|
| 625 |
+
print("=" * 60)
|
| 626 |
+
mock_repo = {
|
| 627 |
+
"full_name": "openvinotoolkit/anomalib",
|
| 628 |
+
"html_url": "https://github.com/openvinotoolkit/anomalib",
|
| 629 |
+
"stars": 4000,
|
| 630 |
+
"description": "An anomaly detection library comprising state-of-the-art algorithms and features such as experiment management, hyper-parameter optimization, and edge inference.",
|
| 631 |
+
"updated_at": "2026-01-15T00:00:00Z",
|
| 632 |
+
"language": "Python",
|
| 633 |
+
}
|
| 634 |
+
mock_readme = """# Anomalib
|
| 635 |
+
A library for benchmarking, developing and deploying deep learning based anomaly detection algorithms.
|
| 636 |
+
|
| 637 |
+
## Installation
|
| 638 |
+
```
|
| 639 |
+
pip install anomalib
|
| 640 |
+
```
|
| 641 |
+
|
| 642 |
+
## Training
|
| 643 |
+
```python
|
| 644 |
+
from anomalib.engine import Engine
|
| 645 |
+
engine = Engine()
|
| 646 |
+
engine.train()
|
| 647 |
+
```
|
| 648 |
+
|
| 649 |
+
## Supported Datasets
|
| 650 |
+
- MVTec AD
|
| 651 |
+
- BTAD
|
| 652 |
+
- KSDD2
|
| 653 |
+
|
| 654 |
+
## Benchmarking
|
| 655 |
+
Use `tools/benchmark.py` for standardized evaluation across all models.
|
| 656 |
+
"""
|
| 657 |
+
mock_deps = {"requirements.txt": "torch>=1.10\npytorch-lightning>=1.7\nopencv-python\nnumpy\nscikit-learn"}
|
| 658 |
+
result = evaluate_repo(mock_repo, mock_readme, mock_deps, "Embedding-based")
|
| 659 |
+
print(f" ็ปผๅ: {result.get('overall_score')}/100")
|
| 660 |
+
print(f" ๅฏๅค็ฐๆง: {result.get('reproducibility_score')}/80")
|
| 661 |
+
print(f" ้้
ๅบฆ: {result.get('benchmark_fitness_score')}/20")
|
| 662 |
+
print(f" ๅคๅฎ: {result.get('verdict')} | ๅฎ้ชๅฐฑ็ปช: {result.get('benchmark_readiness')}")
|
| 663 |
+
|
| 664 |
+
print()
|
| 665 |
+
|
| 666 |
+
# ๆต่ฏ 2๏ผไธไธชๅชๆๆจ็ demo ็ไธชไบบ้กน็ฎ๏ผๅบ่ฏฅๆฏไฝ้้
ๅบฆ๏ผ
|
| 667 |
+
print("=" * 60)
|
| 668 |
+
print("ๆต่ฏ 2๏ผไป
ๆจ็็ไธชไบบ้กน็ฎ๏ผ้ขๆ๏ผๅฏๅค็ฐๆงไธญ็ญ + ้้
ๅบฆไฝ๏ผ")
|
| 669 |
+
print("=" * 60)
|
| 670 |
+
mock_repo2 = {
|
| 671 |
+
"full_name": "someone/anomaly-detection-demo",
|
| 672 |
+
"html_url": "https://github.com/someone/anomaly-detection-demo",
|
| 673 |
+
"stars": 15,
|
| 674 |
+
"description": "A simple demo of anomaly detection using pretrained models.",
|
| 675 |
+
"updated_at": "2024-03-01T00:00:00Z",
|
| 676 |
+
"language": "Python",
|
| 677 |
+
}
|
| 678 |
+
mock_readme2 = """# Anomaly Detection Demo
|
| 679 |
+
A simple inference demo.
|
| 680 |
+
|
| 681 |
+
## Usage
|
| 682 |
+
```
|
| 683 |
+
python demo.py --image path/to/image.jpg
|
| 684 |
+
```
|
| 685 |
+
|
| 686 |
+
Pretrained weights: download from Google Drive (link may expire).
|
| 687 |
+
"""
|
| 688 |
+
mock_deps2 = {}
|
| 689 |
+
result2 = evaluate_repo(mock_repo2, mock_readme2, mock_deps2, "Embedding-based")
|
| 690 |
+
print(f" ็ปผๅ: {result2.get('overall_score')}/100")
|
| 691 |
+
print(f" ้้
ๅบฆ: {result2.get('benchmark_fitness_score')}/20")
|
| 692 |
+
print(f" ๅคๅฎ: {result2.get('verdict')} | ๅฎ้ชๅฐฑ็ปช: {result2.get('benchmark_readiness')}")
|
| 693 |
+
print(f" ๅปบ่ฎฎ: {result2.get('suggested_use')}")
|
| 694 |
+
```
|
| 695 |
+
|
| 696 |
+
### 2.3 ่ฐ่ฏๆๅ
|
| 697 |
+
|
| 698 |
+
**้ฎ้ข 1๏ผๅฏๅค็ฐๆงๅ้้
ๅบฆๅๆฐๆปๆฏ้ซๅบฆ็ธๅ
ณ๏ผๆฒกๅๅผ๏ผ**
|
| 699 |
+
- ็็ถ๏ผ`reproducibility_score` ้ซ โ `benchmark_fitness_score` ไน้ซ๏ผไฝๅ็
|
| 700 |
+
- ๅๅ ๏ผLLM ๆฒก็่งฃ่ฟไธคไธชๆฏ็ฌ็ซ็็ปดๅบฆ
|
| 701 |
+
- ไฟฎๅค๏ผๅจ system prompt ไธญๅ ไธๅฅๆ็กฎ็ๅไพ๏ผใไพๅฆ๏ผไธไธชไปๅบๅฏไปฅ README ๅพๅฎๅ๏ผๆๆกฃ 20 ๅ๏ผไฝๅชๆไพๆจ็ demo ๆฒกๆ่ฎญ็ป๏ผ้้
ๅบฆ 5 ๅ๏ผใไธคไธช็ปดๅบฆๅฟ
้กป็ฌ็ซๅคๆญใใ
|
| 702 |
+
|
| 703 |
+
**้ฎ้ข 2๏ผ่ฏๅๅคช้ซๆๅคชไฝ๏ผไธ็ฌฆๅๅธธ่ฏ๏ผ**
|
| 704 |
+
- ็็ถ๏ผๆๆไปๅบ้ฝๅจ 80+ ๆ 30-
|
| 705 |
+
- ๆต่ฏ๏ผๆ้ 3 ไธชไฝ ่ชๅทฑ็ๆ็ไปๅบ๏ผไธไธชๅฅฝไธไธชๅไธไธชไธญ้ด๏ผ๏ผไบบๅทฅๆๅ๏ผๅฏนๆฏ LLM ๆๅ
|
| 706 |
+
- ไฟฎๅค๏ผๅจ system prompt ไธญ่ฐๆดๅๆฐๆฎต็ๆ่ฟฐๆๅขๅ ๅ่้็น
|
| 707 |
+
|
| 708 |
+
**้ฎ้ข 3๏ผreasoning ๅคช็ฌผ็ป๏ผ"่ฏฅไปๅบ่ดจ้่พ้ซ"๏ผ**
|
| 709 |
+
- ็็ถ๏ผๅๆๆฒกๆๅผ็จๅ
ทไฝๅ
ๅฎน
|
| 710 |
+
- ไฟฎๅค๏ผๅจ system prompt ็ reasoning ๆ่ฟฐไธญๅ ใๅฟ
้กปๅผ็จ README ๆไพ่ตๆไปถไธญ็ๅ
ทไฝๅ
ๅฎนไฝไธบ่ฏๆฎใ
|
| 711 |
+
|
| 712 |
+
---
|
| 713 |
+
|
| 714 |
+
## ไธใ่ฐๅบฆๅจ๏ผ`run.py` โ ๆ Agent ๅ Workflow ไธฒ่ตทๆฅ
|
| 715 |
+
|
| 716 |
+
> **็ฑปๅ๏ผ่ฐๅบฆๅจ๏ผ่ถๆฐดไปฃ็ ๏ผ** | ๆขไธๆฏ Agent ไนไธๆฏ Workflow
|
| 717 |
+
> **ๆ ธๅฟ้ป่พ**๏ผๆ้กบๅบ่ฐ็จ Workflow๏ผ็ฒ๏ผๅ Agent๏ผไฝ ๏ผ๏ผๅจๅฎไปฌไน้ดไผ ้ๆฐๆฎ
|
| 718 |
+
|
| 719 |
+
### 3.1 ่ฟไธช่ฐๅบฆๅจ่ฆ่งฃๅณไปไน้ฎ้ข
|
| 720 |
+
|
| 721 |
+
ไฝ ็ฐๅจๆไบ๏ผ
|
| 722 |
+
- ็ฒ็ๅทฅไฝ๏ผ3 ไธช Workflow๏ผ`fetch_paper_info` โ `search_repos` โ `fetch_readme`/`fetch_dependencies`๏ผ
|
| 723 |
+
- ไฝ ็ๅทฅไฝ๏ผ2 ไธช Agent๏ผ`analyze_direction` โ `evaluate_repo`๏ผ
|
| 724 |
+
|
| 725 |
+
ไฝ่ฟไบๆฏไบ็ธ็ฌ็ซ็ๅฝๆฐใ่ฐๅบฆๅจ็่่ดฃๅฐฑๆฏ**ๆๆญฃ็กฎ็้กบๅบ่ฐ็จๅฎไปฌ๏ผๆไธไธไธช็่พๅบไผ ็ปไธไธไธช็่พๅ
ฅ**ใ
|
| 726 |
+
|
| 727 |
+
```
|
| 728 |
+
่ฐๅบฆๅจ = ไธไธชๅฝๆฐ run(url)๏ผ้้ขๆ้กบๅบๅไบ๏ผ
|
| 729 |
+
1. ่ฐ็ฒ็ Workflow: fetch_paper_info(url) โ ๆฟๅฐ่ฎบๆไฟกๆฏ
|
| 730 |
+
2. ่ฐไฝ ็ Agent: analyze_direction(...) โ ๆฟๅฐๆนๅ+ๆ็ดข่ฏ
|
| 731 |
+
3. ่ฐ็ฒ็ Workflow: search_repos(...) โ ๆฟๅฐๅ้ไปๅบ
|
| 732 |
+
4. ่ฐ็ฒ็ Workflow: fetch_readme/deps(...) โ ๆฟๅฐๆฏไธชไปๅบ็่ฏฆๆ
|
| 733 |
+
5. ่ฐไฝ ็ Agent: evaluate_repo(...) โ ๆฟๅฐๆฏไธชไปๅบ็่ฏๅ
|
| 734 |
+
6. ๆฑๆป่ฟๅ
|
| 735 |
+
```
|
| 736 |
+
|
| 737 |
+
**ๅฐฑ่ฟไน็ฎๅใ** ๆฒกๆๅ็ฏใๆฒกๆๅนถๅใๆฒกๆๆตๅผใ่ฟ 6 ๆญฅๅฐฑๆฏ run.py ็ๅ
จ้จๅ
ๅฎนใ
|
| 738 |
+
|
| 739 |
+
### 3.2 ๅฎๆดไปฃ็
|
| 740 |
+
|
| 741 |
+
```python
|
| 742 |
+
# run.py
|
| 743 |
+
import sys
|
| 744 |
+
|
| 745 |
+
# ============================================================
|
| 746 |
+
# ๅฏผๅ
ฅๆๆๆจกๅ
|
| 747 |
+
# ============================================================
|
| 748 |
+
from paper_fetcher import fetch_paper_info # ็ฒ็ๆจกๅ
|
| 749 |
+
from direction_analyzer import analyze_direction # ไฝ ็ๆจกๅ
|
| 750 |
+
from repo_searcher import search_repos # ็ฒ็ๆจกๅ
|
| 751 |
+
from repo_fetcher import fetch_readme, fetch_dependencies # ็ฒ็ๆจกๅ
|
| 752 |
+
from repo_evaluator import evaluate_repo # ไฝ ็ๆจกๅ
|
| 753 |
+
|
| 754 |
+
|
| 755 |
+
def run(arxiv_url: str, top_n: int = 5) -> dict:
|
| 756 |
+
"""ไธปๅ
ฅๅฃ๏ผไป่ฎบๆ arxiv URL ๅฐ็ ็ฉถๆนๅๅ
จๆฏ + ไปฃ็ ๆจ่็ๅฎๆด้พ่ทฏใ
|
| 757 |
+
|
| 758 |
+
Args:
|
| 759 |
+
arxiv_url: arxiv ่ฎบๆ URL๏ผๅฆ https://arxiv.org/abs/1706.03762
|
| 760 |
+
top_n: ๆ็ปไฟ็็ๅ้ไปๅบๆฐ้
|
| 761 |
+
|
| 762 |
+
Returns:
|
| 763 |
+
dict: {
|
| 764 |
+
"paper": {...},
|
| 765 |
+
"direction": {...},
|
| 766 |
+
"repos": [{...evaluation...}, ...],
|
| 767 |
+
"error": "..." # ไป
ๅจๅฎๅ
จๅคฑ่ดฅๆถๅญๅจ
|
| 768 |
+
}
|
| 769 |
+
"""
|
| 770 |
+
# ================================================================
|
| 771 |
+
# ็ฌฌไธๅฑ๏ผ็ ็ฉถๆนๅ่งฃๆ
|
| 772 |
+
# ================================================================
|
| 773 |
+
print("=" * 60)
|
| 774 |
+
print("[1/5] ๆญฃๅจ่ทๅ่ฎบๆไฟกๆฏ...")
|
| 775 |
+
try:
|
| 776 |
+
paper = fetch_paper_info(arxiv_url)
|
| 777 |
+
except Exception as e:
|
| 778 |
+
return {"error": f"่ทๅ่ฎบๆไฟกๆฏๅคฑ่ดฅ: {e}"}
|
| 779 |
+
|
| 780 |
+
title = paper.get("title", "")
|
| 781 |
+
abstract = paper.get("abstract", "")
|
| 782 |
+
print(f" ๆ ้ข: {title[:100]}...")
|
| 783 |
+
print(f" ไฝ่
: {', '.join(paper.get('authors', [])[:3])}")
|
| 784 |
+
print(f" ๅ็ฑป: {', '.join(paper.get('categories', []))}")
|
| 785 |
+
|
| 786 |
+
print()
|
| 787 |
+
print("[2/5] ๆญฃๅจ่งฃๆ็ ็ฉถๆนๅ๏ผLLM ่ฐ็จ #1๏ผ...")
|
| 788 |
+
try:
|
| 789 |
+
direction = analyze_direction(title, abstract)
|
| 790 |
+
except Exception as e:
|
| 791 |
+
return {
|
| 792 |
+
"paper": paper,
|
| 793 |
+
"error": f"็ ็ฉถๆนๅ่งฃๆๅคฑ่ดฅ: {e}",
|
| 794 |
+
}
|
| 795 |
+
|
| 796 |
+
subfield = direction.get("subfield", "ๆช็ฅ")
|
| 797 |
+
families = direction.get("method_families", [])
|
| 798 |
+
print(f" ๅญ้ขๅ: {subfield}")
|
| 799 |
+
print(f" ่ถๅฟ: {direction.get('subfield_trend', '')[:80]}...")
|
| 800 |
+
print(f" ๆนๆณๆ ({len(families)} ไธช):")
|
| 801 |
+
for mf in families:
|
| 802 |
+
print(f" - {mf.get('family_name', '?')}: {mf.get('description', '')[:60]}...")
|
| 803 |
+
|
| 804 |
+
# ๆฑๆปๆๆๆ็ดขๆฅ่ฏข
|
| 805 |
+
all_queries = []
|
| 806 |
+
for mf in families:
|
| 807 |
+
all_queries.extend(mf.get("search_queries", []))
|
| 808 |
+
all_queries.extend(direction.get("broad_queries", []))
|
| 809 |
+
print(f" ็ๆ {len(all_queries)} ไธชๆ็ดขๆฅ่ฏข")
|
| 810 |
+
|
| 811 |
+
# ================================================================
|
| 812 |
+
# ็ฌฌไบๅฑ๏ผๅผๆบไปฃ็ ๅ็ฐ
|
| 813 |
+
# ================================================================
|
| 814 |
+
print()
|
| 815 |
+
print(f"[3/5] ๆญฃๅจๆ็ดข GitHub ไปๅบ๏ผ{len(all_queries)} ไธชๆฅ่ฏข๏ผ...")
|
| 816 |
+
try:
|
| 817 |
+
candidates = search_repos(all_queries, max_per_keyword=5)
|
| 818 |
+
except Exception as e:
|
| 819 |
+
return {
|
| 820 |
+
"paper": paper,
|
| 821 |
+
"direction": direction,
|
| 822 |
+
"error": f"GitHub ๆ็ดขๅคฑ่ดฅ: {e}",
|
| 823 |
+
}
|
| 824 |
+
|
| 825 |
+
candidates = candidates[:top_n]
|
| 826 |
+
print(f" ๅป้ๅ่ทๅพ {len(candidates)} ไธชๅ้ไปๅบ")
|
| 827 |
+
|
| 828 |
+
if not candidates:
|
| 829 |
+
return {
|
| 830 |
+
"paper": paper,
|
| 831 |
+
"direction": direction,
|
| 832 |
+
"repos": [],
|
| 833 |
+
"error": "ๆชๆพๅฐ็ธๅ
ณๅผๆบไปๅบใ่ฏฅๆนๅๅฏ่ฝๅคชๆฐๆๅคชๅท้จ๏ผๆๆ ้ซ่ดจ้ๅผๆบๅฎ็ฐใ",
|
| 834 |
+
}
|
| 835 |
+
|
| 836 |
+
print(" ๅ้ๅ่กจ:")
|
| 837 |
+
for i, c in enumerate(candidates):
|
| 838 |
+
print(f" {i+1}. {c['full_name']} โญ{c.get('stars', 0)}")
|
| 839 |
+
|
| 840 |
+
# ================================================================
|
| 841 |
+
# ็ฌฌไธๅฑ๏ผๅฏๅค็ฐๆง + ๅฏนๆฏๅฎ้ช้้
ๅบฆ่ฏไผฐ
|
| 842 |
+
# ================================================================
|
| 843 |
+
print()
|
| 844 |
+
print(f"[4/5] ๆญฃๅจ่ฏไผฐ {len(candidates)} ไธชไปๅบ...")
|
| 845 |
+
evaluated = []
|
| 846 |
+
|
| 847 |
+
for i, repo in enumerate(candidates):
|
| 848 |
+
full_name = repo["full_name"]
|
| 849 |
+
try:
|
| 850 |
+
owner, name = full_name.split("/", 1)
|
| 851 |
+
except ValueError:
|
| 852 |
+
print(f" ({i+1}/{len(candidates)}) ่ทณ่ฟ๏ผๆ ๆณ่งฃๆไปๅบๅ๏ผ: {full_name}")
|
| 853 |
+
continue
|
| 854 |
+
|
| 855 |
+
# ๅฐ่ฏๅน้
ๆนๆณๆ
|
| 856 |
+
matched_family = _match_family(repo, families)
|
| 857 |
+
family_tag = f"[{matched_family}]" if matched_family else "[ๆชๅฝ็ฑป]"
|
| 858 |
+
print(f" ({i+1}/{len(candidates)}) ่ฏไผฐ {full_name} {family_tag}...")
|
| 859 |
+
|
| 860 |
+
try:
|
| 861 |
+
readme = fetch_readme(owner, name)
|
| 862 |
+
deps = fetch_dependencies(owner, name)
|
| 863 |
+
evaluation = evaluate_repo(repo, readme, deps, matched_family)
|
| 864 |
+
except Exception as e:
|
| 865 |
+
print(f" โ ่ฏไผฐๅคฑ่ดฅ: {e}")
|
| 866 |
+
evaluation = _make_error_evaluation(str(e))
|
| 867 |
+
|
| 868 |
+
evaluated.append({
|
| 869 |
+
"full_name": repo.get("full_name", ""),
|
| 870 |
+
"html_url": repo.get("html_url", ""),
|
| 871 |
+
"description": repo.get("description", ""),
|
| 872 |
+
"stars": repo.get("stars", 0),
|
| 873 |
+
"language": repo.get("language", ""),
|
| 874 |
+
"updated_at": repo.get("updated_at", ""),
|
| 875 |
+
"topics": repo.get("topics", []),
|
| 876 |
+
"match_keyword": repo.get("match_keyword", ""),
|
| 877 |
+
"method_family": matched_family,
|
| 878 |
+
"evaluation": evaluation,
|
| 879 |
+
})
|
| 880 |
+
|
| 881 |
+
# ๆ็ปผๅ่ฏๅ้ๅบๆๅ
|
| 882 |
+
evaluated.sort(key=lambda r: r["evaluation"].get("overall_score", 0), reverse=True)
|
| 883 |
+
|
| 884 |
+
# ================================================================
|
| 885 |
+
# ๆฑๆป่ฟๅ
|
| 886 |
+
# ================================================================
|
| 887 |
+
print()
|
| 888 |
+
print(f"[5/5] ๅฎๆ๏ผ")
|
| 889 |
+
best = evaluated[0] if evaluated else None
|
| 890 |
+
if best:
|
| 891 |
+
print(f" ๆ้ซๅ: {best['full_name']} ({best['evaluation'].get('overall_score', 0)}/100)")
|
| 892 |
+
print("=" * 60)
|
| 893 |
+
|
| 894 |
+
return {
|
| 895 |
+
"paper": paper,
|
| 896 |
+
"direction": direction,
|
| 897 |
+
"repos": evaluated,
|
| 898 |
+
}
|
| 899 |
+
|
| 900 |
+
|
| 901 |
+
def _match_family(repo: dict, families: list[dict]) -> str:
|
| 902 |
+
"""็ฎๆ็ไปๅบโๆนๆณๆๅน้
ใ
|
| 903 |
+
|
| 904 |
+
็ญ็ฅ๏ผ
|
| 905 |
+
1. ๆฃๆฅไปๅบ topics ๆฏๅฆๅ
ๅซๆนๆณๆๅ
ณ้ฎ่ฏ
|
| 906 |
+
2. ๆฃๆฅไปๅบๆ่ฟฐๆฏๅฆๅ
ๅซๆนๆณๆๅ็งฐ
|
| 907 |
+
3. ้ฝๆฒกๅน้
ๅฐ่ฟๅ็ฉบๅญ็ฌฆไธฒ๏ผๆชๅฝ็ฑป๏ผ
|
| 908 |
+
"""
|
| 909 |
+
desc = (repo.get("description") or "").lower()
|
| 910 |
+
topics = " ".join(repo.get("topics", [])).lower()
|
| 911 |
+
combined = desc + " " + topics
|
| 912 |
+
|
| 913 |
+
for mf in families:
|
| 914 |
+
family_name = mf.get("family_name", "")
|
| 915 |
+
if not family_name:
|
| 916 |
+
continue
|
| 917 |
+
|
| 918 |
+
# ๅฐ่ฏ็ฒพ็กฎๅน้
+ ้จๅๅน้
|
| 919 |
+
name_lower = family_name.lower()
|
| 920 |
+
# ไพๅฆ "Vision Transformer" -> ["vision", "transformer"]
|
| 921 |
+
name_parts = name_lower.split()
|
| 922 |
+
|
| 923 |
+
# ๆฃๆฅ่ณๅฐ 2/3 ็ๅ็งฐ่ฏๅบ็ฐๅจ combined ไธญ
|
| 924 |
+
if len(name_parts) >= 2:
|
| 925 |
+
match_count = sum(1 for part in name_parts if part in combined)
|
| 926 |
+
if match_count >= max(2, len(name_parts) * 2 // 3):
|
| 927 |
+
return family_name
|
| 928 |
+
else:
|
| 929 |
+
# ๅ่ฏๆนๆณๅ็ดๆฅๅน้
|
| 930 |
+
if name_lower in combined:
|
| 931 |
+
return family_name
|
| 932 |
+
|
| 933 |
+
return ""
|
| 934 |
+
|
| 935 |
+
|
| 936 |
+
def _make_error_evaluation(error_msg: str) -> dict:
|
| 937 |
+
"""ๆ้ ไธไธช่กจ็คบ่ฏไผฐๅคฑ่ดฅ็ evaluation dict"""
|
| 938 |
+
return {
|
| 939 |
+
"reproducibility_score": 0,
|
| 940 |
+
"benchmark_fitness_score": 0,
|
| 941 |
+
"overall_score": 0,
|
| 942 |
+
"verdict": "error",
|
| 943 |
+
"env_score": 0,
|
| 944 |
+
"doc_score": 0,
|
| 945 |
+
"code_score": 0,
|
| 946 |
+
"community_score": 0,
|
| 947 |
+
"dep_score": 0,
|
| 948 |
+
"benchmark_score": 0,
|
| 949 |
+
"reasoning": f"่ฏไผฐๅคฑ่ดฅ: {error_msg[:100]}",
|
| 950 |
+
"risks": ["่ฏไผฐ่ฟ็จๅบ้๏ผ่ฏทๆๅจๆฃๆฅ่ฏฅไปๅบ"],
|
| 951 |
+
"benchmark_readiness": "not_ready",
|
| 952 |
+
"suggested_use": "่ฏไผฐๅคฑ่ดฅ๏ผ่ฏทๆๅจๆฃๆฅ",
|
| 953 |
+
}
|
| 954 |
+
|
| 955 |
+
|
| 956 |
+
# ============================================================
|
| 957 |
+
# ๅฝไปค่กๅ
ฅๅฃ
|
| 958 |
+
# ============================================================
|
| 959 |
+
if __name__ == "__main__":
|
| 960 |
+
if len(sys.argv) < 2:
|
| 961 |
+
print("็จๆณ: python run.py <arxiv_url>")
|
| 962 |
+
print("็คบไพ: python run.py https://arxiv.org/abs/1706.03762")
|
| 963 |
+
print("็คบไพ: python run.py https://arxiv.org/abs/2010.11929")
|
| 964 |
+
sys.exit(1)
|
| 965 |
+
|
| 966 |
+
url = sys.argv[1]
|
| 967 |
+
result = run(url)
|
| 968 |
+
|
| 969 |
+
if result.get("error"):
|
| 970 |
+
print(f"\n{'='*60}")
|
| 971 |
+
print(f"่ฟ่กๆชๅฎๅ
จๆๅ")
|
| 972 |
+
print(f"{'='*60}")
|
| 973 |
+
print(f" {result['error']}")
|
| 974 |
+
|
| 975 |
+
# ๅณไฝฟๆ error๏ผๅฆๆๆ้จๅ็ปๆไนๆๅฐๅบๆฅ
|
| 976 |
+
if result.get("paper"):
|
| 977 |
+
print(f"\n ่ฎบๆไฟกๆฏๅทฒ่ทๅ: {result['paper'].get('title', '')[:80]}")
|
| 978 |
+
if result.get("direction"):
|
| 979 |
+
print(f" ๆนๅ่งฃๆๅทฒๅฎๆ: {result['direction'].get('subfield', '')}")
|
| 980 |
+
else:
|
| 981 |
+
# ๅฏผๅ
ฅ format_report ๅนถๆๅฐ
|
| 982 |
+
from app import format_report
|
| 983 |
+
print(format_report(result))
|
| 984 |
+
```
|
| 985 |
+
|
| 986 |
+
### 3.3 ่ฐ่ฏๆๅ
|
| 987 |
+
|
| 988 |
+
**้ฎ้ข 1๏ผๆดไธช้พ่ทฏ่ทๅฐๆไธๆญฅๅกไฝไธๅจ**
|
| 989 |
+
- ๅๅ ๏ผๆไธช API ่ฐ็จ่ถ
ๆถๆ้้
|
| 990 |
+
- ๆๆฅ๏ผ็็ป็ซฏๆๅๆๅฐ็ๆฏ `[1/5]` `[2/5]` `[3/5]` ่ฟๆฏ `[4/5]`
|
| 991 |
+
- ๅกๅจ `[1/5]` โ arxiv API ้ฎ้ข
|
| 992 |
+
- ๅกๅจ `[2/5]` โ DeepSeek API ้ฎ้ข
|
| 993 |
+
- ๅกๅจ `[3/5]` โ GitHub Search API ้้
|
| 994 |
+
- ๅกๅจ `[4/5]` โ GitHub Content API ๆ repo_evaluator ็ DeepSeek ่ฐ็จ้ฎ้ข
|
| 995 |
+
|
| 996 |
+
**้ฎ้ข 2๏ผ`[3/5]` ่ฟๅ 0 ไธชๅ้ไปๅบ**
|
| 997 |
+
- ๆๆฅ๏ผๆๅฐ `all_queries`๏ผๅคๅถๅ ไธชๅป GitHub ๆๅจๆ๏ผ็ๆฏไธๆฏๆ็ดข่ฏๆฌ่บซ็้ฎ้ข
|
| 998 |
+
- ไฟฎๅคๆนๅ๏ผ่ฐ direction_analyzer ็ prompt๏ผ่ง 1.3 ่๏ผ
|
| 999 |
+
|
| 1000 |
+
**้ฎ้ข 3๏ผ`_match_family` ๅน้
ไธๅฐๆนๆณๆ**
|
| 1001 |
+
- ่ฟๆฏ Week 1 ็ๅทฒ็ฅ้ๅถใ็ฎๆๅน้
ๅบไบๅญ็ฌฆไธฒๅ
ๅซ๏ผ็ฒพๅๅบฆไธ้ซ
|
| 1002 |
+
- Week 1 ๆฅๅ"ๆชๅฝ็ฑป"็็ปๆ๏ผWeek 3 ๅ็จ LLM ๅ็ฒพๅๅฝ็ฑป
|
| 1003 |
+
|
| 1004 |
+
---
|
| 1005 |
+
|
| 1006 |
+
## ๅใ็้ข๏ผ`app.py` โ Gradio ็้ข + ็ ๆฅๆ ผๅผๅ
|
| 1007 |
+
|
| 1008 |
+
> **็ฑปๅ๏ผ็้ขๅฑ** | ไธๆฏ Agent ไนไธๆฏ Workflow
|
| 1009 |
+
> **ๆ ธๅฟ่่ดฃ**๏ผๆ run.py ็ dict ่พๅบๅๆไบบ็ฑปๅฏ่ฏป็ Markdown ็ ๆฅ๏ผๅ
่ฃ
ไธไธช Gradio ๅฃณ
|
| 1010 |
+
|
| 1011 |
+
### 4.1 ่ฟไธชๆจกๅ่ฆ่งฃๅณไปไน้ฎ้ข
|
| 1012 |
+
|
| 1013 |
+
ไธคไธช่่ดฃ๏ผ
|
| 1014 |
+
1. **`format_report()`**๏ผๆ `run.py` ่ฟๅ็ dict ๅๆ"็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ"๏ผไฝ ๅทฒ็ปๅจๅ้ข็ๅฐ่ฟ็ปๆไบ๏ผ
|
| 1015 |
+
2. **`diagnose()`**๏ผGradio ็ๅ่ฐๅฝๆฐ๏ผ็จๆท่พๅ
ฅ arxiv URL โ ่ฐ `run()` โ ่ฐ `format_report()` โ ๆพ็คบ
|
| 1016 |
+
|
| 1017 |
+
### 4.2 ๅฎๆดไปฃ็
|
| 1018 |
+
|
| 1019 |
+
```python
|
| 1020 |
+
# app.py
|
| 1021 |
+
import gradio as gr
|
| 1022 |
+
from run import run
|
| 1023 |
+
|
| 1024 |
+
|
| 1025 |
+
def diagnose(arxiv_url: str) -> str:
|
| 1026 |
+
"""Gradio ๅ่ฐ๏ผ็จๆท่พๅ
ฅ arxiv URL โ ่ฟๅ Markdown ็ ๆฅ"""
|
| 1027 |
+
url = arxiv_url.strip()
|
| 1028 |
+
if not url:
|
| 1029 |
+
return "## โ ๏ธ ่ฏท่พๅ
ฅ arxiv ่ฎบๆ้พๆฅ\n\n็คบไพ: `https://arxiv.org/abs/1706.03762`"
|
| 1030 |
+
|
| 1031 |
+
# ๆง่กๅฎๆด้พ่ทฏ
|
| 1032 |
+
try:
|
| 1033 |
+
result = run(url)
|
| 1034 |
+
except ValueError as e:
|
| 1035 |
+
return f"## โ ่พๅ
ฅๆ ผๅผ้่ฏฏ\n\n{str(e)}\n\n่ฏท็กฎ่ฎค่พๅ
ฅ็ๆฏๆๆ็ arxiv ้พๆฅใ"
|
| 1036 |
+
except RuntimeError as e:
|
| 1037 |
+
return f"## โ API ่ฏทๆฑๅคฑ่ดฅ\n\n{str(e)}\n\n่ฏทๆฃๆฅ็ฝ็ป่ฟๆฅๆ็จๅ้่ฏใ"
|
| 1038 |
+
except Exception as e:
|
| 1039 |
+
return f"## โ ่ฟ่กๅบ้\n\n```\n{type(e).__name__}: {str(e)}\n```\n\n่ฏทๅฐไปฅไธ้่ฏฏไฟกๆฏๅ้ฆ็ปๅผๅ่
ใ"
|
| 1040 |
+
|
| 1041 |
+
# ๅค็้จๅๅคฑ่ดฅ็ๆ
ๅต
|
| 1042 |
+
if result.get("error") and not result.get("repos"):
|
| 1043 |
+
paper = result.get("paper", {})
|
| 1044 |
+
direction = result.get("direction", {})
|
| 1045 |
+
title = paper.get("title", "ๆช็ฅ") if paper else "ๆช็ฅ"
|
| 1046 |
+
|
| 1047 |
+
md = f"""# ResearchRadar ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ
|
| 1048 |
+
|
| 1049 |
+
---
|
| 1050 |
+
|
| 1051 |
+
## ่ฎบๆไฟกๆฏ
|
| 1052 |
+
|
| 1053 |
+
**{title}**
|
| 1054 |
+
|
| 1055 |
+
---
|
| 1056 |
+
|
| 1057 |
+
## โ ๏ธ ๆช่ฝๅฎๆๅฎๆด่ฏไผฐ
|
| 1058 |
+
|
| 1059 |
+
**ๅๅ **: {result['error']}
|
| 1060 |
+
|
| 1061 |
+
"""
|
| 1062 |
+
if direction:
|
| 1063 |
+
md += f"""## ็ ็ฉถๆนๅ่งฃๆ๏ผ้จๅ็ปๆ๏ผ
|
| 1064 |
+
|
| 1065 |
+
**ๅญ้ขๅ**: {direction.get('subfield', 'N/A')}
|
| 1066 |
+
|
| 1067 |
+
**่ถๅฟ**: {direction.get('subfield_trend', 'N/A')}
|
| 1068 |
+
"""
|
| 1069 |
+
md += """
|
| 1070 |
+
---
|
| 1071 |
+
> ่ฏฅ่ฎบๆๆนๅๅฏ่ฝๅคชๆฐๆๅคชๅท้จ๏ผๆๆ ้ซ่ดจ้ๅผๆบๅฎ็ฐใ่ฟๆฐๅฅฝๅธฎๅฉไฝ ๅคๆญโโๅจ่ฟไธชๆนๅๅผๅฑ็ ็ฉถ้่ฆไปๅคดๅฎ็ฐใ
|
| 1072 |
+
"""
|
| 1073 |
+
return md
|
| 1074 |
+
|
| 1075 |
+
# ๆญฃๅธธๆ
ๅต
|
| 1076 |
+
return format_report(result)
|
| 1077 |
+
|
| 1078 |
+
|
| 1079 |
+
def format_report(result: dict) -> str:
|
| 1080 |
+
"""ๅฐ run() ็็ปๆๆ ผๅผๅไธบ Markdown ็ ๆฅใ
|
| 1081 |
+
|
| 1082 |
+
็ ๆฅ็ปๆ๏ผ
|
| 1083 |
+
1. ่ฎบๆไฟกๆฏ
|
| 1084 |
+
2. ็ ็ฉถๆนๅๅ
จๆฏ๏ผๅญ้ขๅ + ่ถๅฟ + ๆนๆณๆ่ฐฑ็ณป๏ผ
|
| 1085 |
+
3. ๅผๆบๅฎ็ฐ่ฏไผฐๆๅ๏ผๅ
ญ็ปดๅบฆ่ฏๅๆ็ป๏ผ
|
| 1086 |
+
4. ๅฏนๆฏๅฎ้ชๆจ่ๆป็ป๏ผๆๅฐฑ็ปชๅบฆๅ็ป๏ผ
|
| 1087 |
+
"""
|
| 1088 |
+
paper = result.get("paper", {})
|
| 1089 |
+
direction = result.get("direction", {})
|
| 1090 |
+
repos = result.get("repos", [])
|
| 1091 |
+
|
| 1092 |
+
# ================================================================
|
| 1093 |
+
# ็ฌฌไธ้จๅ๏ผ่ฎบๆไฟกๆฏ
|
| 1094 |
+
# ================================================================
|
| 1095 |
+
arxiv_id = paper.get("arxiv_id", "")
|
| 1096 |
+
arxiv_url = f"https://arxiv.org/abs/{arxiv_id}" if arxiv_id else ""
|
| 1097 |
+
|
| 1098 |
+
md = "# ResearchRadar ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ\n\n---\n\n## ไธใ่ฎบๆไฟกๆฏ\n\n"
|
| 1099 |
+
md += "| ้กน็ฎ | ๅ
ๅฎน |\n|------|------|\n"
|
| 1100 |
+
md += f"| **ๆ ้ข** | {paper.get('title', 'N/A')} |\n"
|
| 1101 |
+
if arxiv_url:
|
| 1102 |
+
md += f"| **arXiv** | [{arxiv_id}]({arxiv_url}) |\n"
|
| 1103 |
+
else:
|
| 1104 |
+
md += f"| **arXiv ID** | {arxiv_id or 'N/A'} |\n"
|
| 1105 |
+
md += f"| **ไฝ่
** | {', '.join(paper.get('authors', ['N/A'])[:5])}"
|
| 1106 |
+
if len(paper.get("authors", [])) > 5:
|
| 1107 |
+
md += f" ็ญ {len(paper.get('authors', []))} ไบบ"
|
| 1108 |
+
md += " |\n"
|
| 1109 |
+
published = paper.get("published", "")
|
| 1110 |
+
if published:
|
| 1111 |
+
md += f"| **ๅ่กจๆถ้ด** | {published[:10]} |\n"
|
| 1112 |
+
categories = paper.get("categories", [])
|
| 1113 |
+
if categories:
|
| 1114 |
+
md += f"| **ๅ็ฑป** | {', '.join(categories)} |\n"
|
| 1115 |
+
|
| 1116 |
+
# ================================================================
|
| 1117 |
+
# ็ฌฌไบ้จๅ๏ผ็ ็ฉถๆนๅๅ
จๆฏ
|
| 1118 |
+
# ================================================================
|
| 1119 |
+
md += "\n---\n\n## ไบใ็ ็ฉถๆนๅๅ
จๆฏ\n\n"
|
| 1120 |
+
md += f"### ๅญ้ขๅๅฎไฝ\n\n**{direction.get('subfield', 'ๆช็ฅ')}**\n\n"
|
| 1121 |
+
md += f"### ๅฝๅ่ถๅฟ\n\n{direction.get('subfield_trend', 'ๆๆ ๅๆ')}\n\n"
|
| 1122 |
+
md += "### ๆนๆณๆ่ฐฑ็ณป\n\n"
|
| 1123 |
+
md += "| # | ๆนๆณๆ | ๆ ธๅฟ็น็น | ไปฃ่กจๅทฅไฝ |\n|---|--------|----------|----------|\n"
|
| 1124 |
+
|
| 1125 |
+
families = direction.get("method_families", [])
|
| 1126 |
+
for i, mf in enumerate(families):
|
| 1127 |
+
family_name = mf.get("family_name", f"ๆนๆณๆ {i+1}")
|
| 1128 |
+
desc = mf.get("description", "")[:80]
|
| 1129 |
+
rep = mf.get("representative_work", "")[:60]
|
| 1130 |
+
md += f"| {i+1} | **{family_name}** | {desc} | {rep} |\n"
|
| 1131 |
+
|
| 1132 |
+
if not families:
|
| 1133 |
+
md += "| - | ๆช่ฝ่ฏๅซๅบๆ็กฎ็ๆนๆณๆ | - | - |\n"
|
| 1134 |
+
|
| 1135 |
+
# ================================================================
|
| 1136 |
+
# ็ฌฌไธ้จๅ๏ผๅผๆบๅฎ็ฐ่ฏไผฐๆๅ
|
| 1137 |
+
# ================================================================
|
| 1138 |
+
md += "\n---\n\n## ไธใๅผๆบๅฎ็ฐ่ฏไผฐๆๅ\n\n"
|
| 1139 |
+
|
| 1140 |
+
if not repos:
|
| 1141 |
+
md += "**ๆชๆพๅฐ็ธๅ
ณๅผๆบไปๅบใ**\n\n"
|
| 1142 |
+
return md
|
| 1143 |
+
|
| 1144 |
+
for i, repo in enumerate(repos):
|
| 1145 |
+
full_name = repo.get("full_name", f"ไปๅบ {i+1}")
|
| 1146 |
+
html_url = repo.get("html_url", "")
|
| 1147 |
+
ev = repo.get("evaluation", {})
|
| 1148 |
+
mf = repo.get("method_family", "")
|
| 1149 |
+
|
| 1150 |
+
# ๅพๆ ๆ ๅฐ
|
| 1151 |
+
verdict_icon = {
|
| 1152 |
+
"reproducible": "โ
",
|
| 1153 |
+
"partially": "โ ๏ธ",
|
| 1154 |
+
"not_reproducible": "โ",
|
| 1155 |
+
"error": "๐ฅ",
|
| 1156 |
+
}.get(ev.get("verdict", ""), "โ")
|
| 1157 |
+
|
| 1158 |
+
readiness_icon = {
|
| 1159 |
+
"ready": "๐ข",
|
| 1160 |
+
"partial": "๐ก",
|
| 1161 |
+
"not_ready": "๐ด",
|
| 1162 |
+
}.get(ev.get("benchmark_readiness", ""), "โช")
|
| 1163 |
+
|
| 1164 |
+
family_tag = f" `[{mf}]`" if mf else ""
|
| 1165 |
+
|
| 1166 |
+
md += f"### {i+1}. [{full_name}]({html_url}){family_tag}\n\n"
|
| 1167 |
+
|
| 1168 |
+
repro_score = ev.get("reproducibility_score", ev.get("overall_score", "N/A"))
|
| 1169 |
+
bench_score = ev.get("benchmark_fitness_score", ev.get("benchmark_score", "N/A"))
|
| 1170 |
+
overall = ev.get("overall_score", "N/A")
|
| 1171 |
+
|
| 1172 |
+
md += f"{verdict_icon} **ๅฏๅค็ฐๆง: {repro_score}/80** | "
|
| 1173 |
+
md += f"{readiness_icon} **ๅฏนๆฏๅฎ้ช้้
ๅบฆ: {bench_score}/20** | "
|
| 1174 |
+
md += f"**็ปผๅ: {overall}/100**\n\n"
|
| 1175 |
+
|
| 1176 |
+
# ๅ
ญ็ปดๅบฆๅพๅ่กจ
|
| 1177 |
+
md += "| ็ปดๅบฆ | ๅพๅ | ๆปกๅ | ่ฏดๆ |\n"
|
| 1178 |
+
md += "|------|:----:|:----:|------|\n"
|
| 1179 |
+
md += f"| ็ฏๅข้
็ฝฎ | {_fmt(ev.get('env_score'))} | 15 | ไพ่ตๆไปถๅฎๆดๆง |\n"
|
| 1180 |
+
md += f"| ๆๆกฃ่ดจ้ | {_fmt(ev.get('doc_score'))} | 20 | ๅฎ่ฃ
/่ฎญ็ป/ๆฐๆฎ่ฏดๆ |\n"
|
| 1181 |
+
md += f"| ไปฃ็ ๅฏ็จๆง | {_fmt(ev.get('code_score'))} | 20 | ่ฎญ็ป+ๆจ็่ๆฌ |\n"
|
| 1182 |
+
md += f"| ็คพๅบๆดป่ทๅบฆ | {_fmt(ev.get('community_score'))} | 10 | Star + ๆดๆฐ้ข็ |\n"
|
| 1183 |
+
md += f"| ไพ่ตๅฅๅบทๅบฆ | {_fmt(ev.get('dep_score'))} | 15 | ไพ่ตๅ
ผๅฎนๆง |\n"
|
| 1184 |
+
md += f"| **ๅฏนๆฏๅฎ้ช** | **{_fmt(ev.get('benchmark_score'))}** | **20** | **benchmark + ้ข่ฎญ็ปๆ้** |\n"
|
| 1185 |
+
|
| 1186 |
+
md += f"\nโญ Star: {repo.get('stars', 0)}"
|
| 1187 |
+
if repo.get("match_keyword"):
|
| 1188 |
+
md += f" | ๅน้
่ฏ: `{repo.get('match_keyword', '')}`"
|
| 1189 |
+
md += "\n\n"
|
| 1190 |
+
|
| 1191 |
+
# ๅๆๅๅปบ่ฎฎ
|
| 1192 |
+
reasoning = ev.get("reasoning", "N/A")
|
| 1193 |
+
md += f"**ๅๆ**: {reasoning}\n\n"
|
| 1194 |
+
md += f"**ๅฏนๆฏๅฎ้ชๅปบ่ฎฎ**: {ev.get('suggested_use', 'N/A')}\n\n"
|
| 1195 |
+
|
| 1196 |
+
# ้ฃ้ฉ
|
| 1197 |
+
risks = ev.get("risks", [])
|
| 1198 |
+
if risks:
|
| 1199 |
+
md += "**้ฃ้ฉ็น**: " + " ยท ".join(f"`{r}`" for r in risks) + "\n\n"
|
| 1200 |
+
|
| 1201 |
+
md += "---\n\n"
|
| 1202 |
+
|
| 1203 |
+
# ================================================================
|
| 1204 |
+
# ็ฌฌๅ้จๅ๏ผๅฏนๆฏๅฎ้ชๆจ่ๆป็ป
|
| 1205 |
+
# ================================================================
|
| 1206 |
+
md += "## ๅใๅฏนๆฏๅฎ้ชๆจ่ๆป็ป\n\n"
|
| 1207 |
+
|
| 1208 |
+
ready = [r for r in repos if r["evaluation"].get("benchmark_readiness") == "ready"]
|
| 1209 |
+
partial = [r for r in repos if r["evaluation"].get("benchmark_readiness") == "partial"]
|
| 1210 |
+
not_ready = [
|
| 1211 |
+
r for r in repos
|
| 1212 |
+
if r["evaluation"].get("benchmark_readiness") not in ("ready", "partial")
|
| 1213 |
+
]
|
| 1214 |
+
|
| 1215 |
+
if ready:
|
| 1216 |
+
md += "### ๐ข ๅฏ็ดๆฅ็จไบๅฏนๆฏๅฎ้ช\n\n"
|
| 1217 |
+
for r in ready:
|
| 1218 |
+
url = r.get("html_url", "#")
|
| 1219 |
+
name = r.get("full_name", "ๆช็ฅ")
|
| 1220 |
+
suggestion = r["evaluation"].get("suggested_use", "")
|
| 1221 |
+
md += f"- **[{name}]({url})** โ {suggestion}\n"
|
| 1222 |
+
md += "\n"
|
| 1223 |
+
|
| 1224 |
+
if partial:
|
| 1225 |
+
md += "### ๐ก ้่ฆๅฐ้ไฟฎๆนๅๅฏ็จ\n\n"
|
| 1226 |
+
for r in partial:
|
| 1227 |
+
url = r.get("html_url", "#")
|
| 1228 |
+
name = r.get("full_name", "ๆช็ฅ")
|
| 1229 |
+
suggestion = r["evaluation"].get("suggested_use", "")
|
| 1230 |
+
md += f"- **[{name}]({url})** โ {suggestion}\n"
|
| 1231 |
+
md += "\n"
|
| 1232 |
+
|
| 1233 |
+
if not_ready:
|
| 1234 |
+
md += "### ๐ด ไป
้ๅๅ่ไปฃ็ ๅฎ็ฐ\n\n"
|
| 1235 |
+
for r in not_ready:
|
| 1236 |
+
url = r.get("html_url", "#")
|
| 1237 |
+
name = r.get("full_name", "ๆช็ฅ")
|
| 1238 |
+
reason = r["evaluation"].get("suggested_use") or r["evaluation"].get("reasoning", "")
|
| 1239 |
+
md += f"- **[{name}]({url})** โ {reason[:120]}...\n"
|
| 1240 |
+
md += "\n"
|
| 1241 |
+
|
| 1242 |
+
md += "---\n\n> ResearchRadar ยท ่ฎบๆ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ + ๅฏนๆฏๅฎ้ชๆจ่\n"
|
| 1243 |
+
|
| 1244 |
+
return md
|
| 1245 |
+
|
| 1246 |
+
|
| 1247 |
+
def _fmt(value) -> str:
|
| 1248 |
+
"""ๆ ผๅผๅๆฐๅผ๏ผNone ๆพ็คบไธบ N/A"""
|
| 1249 |
+
if value is None:
|
| 1250 |
+
return "N/A"
|
| 1251 |
+
return str(value)
|
| 1252 |
+
|
| 1253 |
+
|
| 1254 |
+
# ============================================================
|
| 1255 |
+
# Gradio ๅฏๅจ
|
| 1256 |
+
# ============================================================
|
| 1257 |
+
DEMO_EXAMPLES = [
|
| 1258 |
+
["https://arxiv.org/abs/2011.08785"], # PaDiM๏ผๅทฅไธ็ผบ้ทๆฃๆต๏ผไฝ ็้ขๅ๏ผ
|
| 1259 |
+
["https://arxiv.org/abs/1706.03762"], # Attention Is All You Need๏ผ็ปๅ
ธ๏ผ
|
| 1260 |
+
["https://arxiv.org/abs/2108.07610"], # DRAEM๏ผ็ผบ้ทๆฃๆต๏ผๅๆ็ผบ้ทๆนๆณ๏ผ
|
| 1261 |
+
]
|
| 1262 |
+
|
| 1263 |
+
demo = gr.Interface(
|
| 1264 |
+
fn=diagnose,
|
| 1265 |
+
inputs=gr.Textbox(
|
| 1266 |
+
label="่ฎบๆ arxiv ้พๆฅ",
|
| 1267 |
+
placeholder="https://arxiv.org/abs/1706.03762",
|
| 1268 |
+
lines=1,
|
| 1269 |
+
),
|
| 1270 |
+
outputs=gr.Markdown(label="็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ"),
|
| 1271 |
+
title="ResearchRadar โ ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ",
|
| 1272 |
+
description=(
|
| 1273 |
+
"่พๅ
ฅไธ็ฏ AI ่ฎบๆ็ arxiv ้พๆฅ๏ผAI ๅธฎไฝ ๏ผ\n"
|
| 1274 |
+
"1. ๆธๆธ
่ฏฅ็ ็ฉถๆนๅ็ๅๆฒฟๅ
จๆฏ๏ผๅญ้ขๅ + ๆนๆณๆ่ฐฑ็ณป๏ผ\n"
|
| 1275 |
+
"2. ๆพๅฐๆ้้
็ๅผๆบๅฎ็ฐ\n"
|
| 1276 |
+
"3. ่ฏไผฐๆฏไธชไปๅบ่ฝๅฆ็ดๆฅ็จไบๅ่ฎบๆ่ทๅฏนๆฏๅฎ้ช"
|
| 1277 |
+
),
|
| 1278 |
+
examples=DEMO_EXAMPLES,
|
| 1279 |
+
theme="soft",
|
| 1280 |
+
)
|
| 1281 |
+
|
| 1282 |
+
if __name__ == "__main__":
|
| 1283 |
+
# share=False: ไป
ๆฌๅฐ่ฎฟ้ฎ
|
| 1284 |
+
# share=True: ็ๆๅ
ฌ็ฝ้พๆฅ๏ผๆผ็คบๆถๅฆๆ็ฝ็ปๅ
่ฎธๅฏไปฅ็จ๏ผ
|
| 1285 |
+
demo.launch(server_name="0.0.0.0", share=False)
|
| 1286 |
+
```
|
| 1287 |
+
|
| 1288 |
+
---
|
| 1289 |
+
|
| 1290 |
+
## ไธญ้ดๆป็ป๏ผไฝ ๆญๅปบ็ 4 ไธชๆไปถไธ Agent/Workflow ็ๅ
ณ็ณป
|
| 1291 |
+
|
| 1292 |
+
ๅจไฝ ่ขซไปฃ็ ็ป่ๆทนๆฒกไนๅ๏ผๅ
้ๅไธๆญฅ็ๅ
จๆฏ๏ผ
|
| 1293 |
+
|
| 1294 |
+
```
|
| 1295 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1296 |
+
โ run.py๏ผ่ฐๅบฆๅจ๏ผไฝ ๅ๏ผ โ
|
| 1297 |
+
โ โ
|
| 1298 |
+
โ ็ฌฌ 1 ๆญฅ๏ผpaper = fetch_paper_info(url) โ ็ฒ็ Workflow โ
|
| 1299 |
+
โ โ โ
|
| 1300 |
+
โ ็ฌฌ 2 ๆญฅ๏ผdirection = analyze_direction() โ ไฝ ็ Agent 1 โ
|
| 1301 |
+
โ โ โ
|
| 1302 |
+
โ ็ฌฌ 3 ๆญฅ๏ผrepos = search_repos(queries) โ ็ฒ็ Workflow โ
|
| 1303 |
+
โ โ โ
|
| 1304 |
+
โ ็ฌฌ 4 ๆญฅ๏ผdetails = fetch_readme/deps() โ ็ฒ็ Workflow โ
|
| 1305 |
+
โ โ โ
|
| 1306 |
+
โ ็ฌฌ 5 ๆญฅ๏ผscores = evaluate_repo() โ ไฝ ็ Agent 2 โ
|
| 1307 |
+
โ โ โ
|
| 1308 |
+
โ ็ฌฌ 6 ๆญฅ๏ผreturn ๆฑๆป็ปๆ โ
|
| 1309 |
+
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1310 |
+
โ
|
| 1311 |
+
โผ
|
| 1312 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1313 |
+
โ app.py๏ผ็้ข๏ผไฝ ๅ๏ผ โ
|
| 1314 |
+
โ format_report(ๆฑๆป็ปๆ) โ Markdown ็ ๆฅ โ ็จๆท็ๅฐ โ
|
| 1315 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1316 |
+
```
|
| 1317 |
+
|
| 1318 |
+
**ไฝ ้่ฆๅฎ้
ๅ็ไธ่ฅฟๆ่งฃไธๆฅๅฐฑๆฏ**๏ผ
|
| 1319 |
+
|
| 1320 |
+
| ๆไปถ | ๆ ธๅฟๅทฅไฝ้ | ไปฃ็ ่กๆฐ๏ผไผฐ็ฎ๏ผ |
|
| 1321 |
+
|------|-----------|:--------:|
|
| 1322 |
+
| `direction_analyzer.py` | ๅ 1 ๆฎต System Prompt + 1 ๆฎต User Prompt ๆจกๆฟ + JSON ่งฃๆ | ~90 ่ก |
|
| 1323 |
+
| `repo_evaluator.py` | ๅ 1 ๆฎต System Prompt + 1 ๆฎต User Prompt ๆจกๆฟ + JSON ่งฃๆ | ~110 ่ก |
|
| 1324 |
+
| `run.py` | 6 ๆญฅ้กบๅบ่ฐ็จ + try/except + `_match_family` + print ่ฟๅบฆ | ~120 ่ก |
|
| 1325 |
+
| `app.py` | `format_report()` ๅญ็ฌฆไธฒๆผๆฅ + Gradio ๅ
่ฃ
| ~180 ่ก |
|
| 1326 |
+
|
| 1327 |
+
**ๅ
ฑ่ฎก็บฆ 500 ่ก Python๏ผๆ ธๅฟๆๆไธๆฏไปฃ็ ้๏ผ่ๆฏ Prompt ๅทฅ็จใ**
|
| 1328 |
+
|
| 1329 |
+
---
|
| 1330 |
+
|
| 1331 |
+
## ไบใ็ฌฌไธๅจไบๅคฉๆง่ก่ฎกๅ
|
| 1332 |
+
|
| 1333 |
+
### ไฝ ็ 5 ๅคฉๆถ้ด็บฟ
|
| 1334 |
+
|
| 1335 |
+
```
|
| 1336 |
+
ๅจไธ โโโ ๅ direction_analyzer.py + ่ฐ prompt
|
| 1337 |
+
ๅจไบ โโโ ๅ repo_evaluator.py + ่ฐๅ
ญ็ปด่ฏๅ
|
| 1338 |
+
ๅจไธ โโโ ๅ run.py + app.py + ไธๅไธ็ฒ่่ฐ
|
| 1339 |
+
ๅจๅ โโโ debug ๆดๆก้พ่ทฏ + PPT ไธๅฑๆถๆๅพ + ็ถๆ schema
|
| 1340 |
+
ๅจไบ โโโ ่่ฐๅฝฉๆ + ไธๅๆฑๆฅ
|
| 1341 |
+
```
|
| 1342 |
+
|
| 1343 |
+
### ๆฏๆฅ่ฏฆ็ปไปปๅก
|
| 1344 |
+
|
| 1345 |
+
#### ๅจไธ๏ผๆนๅ่งฃๆๆจกๅ
|
| 1346 |
+
|
| 1347 |
+
| ๆถ้ด | ไปปๅก | ้ชๆถๆ ๅ |
|
| 1348 |
+
|------|------|----------|
|
| 1349 |
+
| ไธๅ | ๅปบ `direction_analyzer.py`๏ผๅคๅถไธๆๅฎๆดไปฃ็ | ่ฟ่ก่ชๆต๏ผๆๅๆๅฐ Transformer ๅ PaDiM ็ๆนๅ่งฃๆ็ปๆ |
|
| 1350 |
+
| ไธๅ | ็จ 3-5 ็ฏ่ฎบๆๆต่ฏ๏ผTransformer + PaDiM(2011.08785) + PatchCore(2106.08265) + EfficientAD(2303.14535) + DRAEM(2108.07610) | ๆฏ็ฏ่ฎบๆ็ๆนๆณๆ โฅ 3 ไธช๏ผๆ็ดข่ฏๅจ GitHub ๆๅจๆๆ็ปๆใ็นๅซๅ
ณๆณจ๏ผๅทฅไธ็ผบ้ทๆฃๆต็่ฎบๆๆฏๅฆ่ขซๆญฃ็กฎๅฝ็ฑปๅฐ anomaly detection/defect detection ๅญ้ขๅ |
|
| 1351 |
+
| ๆไธ | ๆ นๆฎๆต่ฏ็ปๆ่ฐ system prompt๏ผๆนๆณๆๅคชๅฐ๏ผๆ็ดข่ฏๅคชๅญฆๆฏๅ๏ผๅญ้ขๅๅฎไฝไธๅ๏ผ๏ผ | 5 ็ฏ่ฎบๆ็ๆนๅ่งฃๆ็ปๆไฝ ้ฝ่งๅพ"ๅ็" |
|
| 1352 |
+
|
| 1353 |
+
#### ๅจไบ๏ผ่ฏไผฐๆจกๅ
|
| 1354 |
+
|
| 1355 |
+
| ๆถ้ด | ไปปๅก | ้ชๆถๆ ๅ |
|
| 1356 |
+
|------|------|----------|
|
| 1357 |
+
| ไธๅ | ๅปบ `repo_evaluator.py`๏ผๅคๅถๅฎๆดไปฃ็ | ่ฟ่ก่ชๆต๏ผanomalib ่ฏๅๅจ 70-95 ไน้ด๏ผไป
ๆจ็็ไปๅบ้้
ๅบฆ < 10 |
|
| 1358 |
+
| ไธๅ | ๆๆ 5 ไธชๅทฅไธ็ผบ้ทๆฃๆต้ขๅ็ไปๅบๆต่ฏ๏ผๅฆ anomalib / PaDiM / PatchCore / 2 ไธชไธชไบบ้กน็ฎ๏ผ๏ผไบบๅทฅ่ฏๅ vs LLM ่ฏๅๅฏนๆฏ | ๅฏๅค็ฐๆงๅ้้
ๅบฆไธคไธช็ปดๅบฆ่ฝ็ๅบ็ฌ็ซๆงโโanomalib ไธค็ปด้ฝ้ซ๏ผๅชๆๆจ็ demo ็้กน็ฎ้้
ๅบฆ่ฟไฝไบๅฏๅค็ฐๆง |
|
| 1359 |
+
| ๆไธ | ่ฐ prompt๏ผ้็นๅ
ณๆณจ"้้
ๅบฆ"่ฏๅๆฏๅฆๅ็ | ๆๆ ๅ benchmark ่ๆฌ็ไปๅบ้้
ๅบฆ > 15๏ผๅชๆๆจ็ demo ็ < 10 |
|
| 1360 |
+
|
| 1361 |
+
#### ๅจไธ๏ผไธฒ่ + UI
|
| 1362 |
+
|
| 1363 |
+
| ๆถ้ด | ไปปๅก | ้ชๆถๆ ๅ |
|
| 1364 |
+
|------|------|----------|
|
| 1365 |
+
| ไธๅ | ๅปบ `run.py`๏ผๅคๅถๅฎๆดไปฃ็ | `python run.py https://arxiv.org/abs/2011.08785`๏ผPaDiM๏ผ่ฝ่ท้ๅฎๆดไธๅฑ้พ่ทฏ |
|
| 1366 |
+
| ไธๅ | ๅปบ `app.py`๏ผๅคๅถๅฎๆดไปฃ็ ๏ผไธ็ฒ่่ฐ | ๆต่งๅจๆๅผ `http://127.0.0.1:7860`๏ผ่พๅ
ฅ PaDiM arxiv URL๏ผ็ๅฐๅฎๆด็ ๆฅ๏ผๆนๆณๆๅ
ๅซ Embedding-based / Reconstruction-based ็ญ |
|
| 1367 |
+
| ๆไธ | ๅค็ๅ็ง่พน็ๆ
ๅต๏ผ่งไธๆนๅจไธๆฅ่ฝๅ checklist๏ผ | ่ง checklist |
|
| 1368 |
+
|
| 1369 |
+
**ๅจไธๆฅ่ฝๅ checklist**๏ผ
|
| 1370 |
+
- [ ] `python run.py <arxiv_url>` ่ฝ่ท้๏ผ็ป็ซฏๆๅฐ `[5/5] ๅฎๆ๏ผ`
|
| 1371 |
+
- [ ] ๆไธๅฐไปๅบๆถ๏ผไธๅดฉๆบ๏ผ่ฟๅ `error` ๅญๆฎต + ๆนๅ่งฃๆ็ปๆ
|
| 1372 |
+
- [ ] ๆไธชไปๅบๆๅๅคฑ่ดฅๆถ๏ผ่ฏฅไปๅบๆ ่ฎฐไธบ error๏ผๅ
ถไปไปๅบๆญฃๅธธ่ฏไผฐ
|
| 1373 |
+
- [ ] ๅฎๆด็ ๆฅๅจ Gradio ไธญๆพ็คบๆญฃๅธธ๏ผMarkdown ๆธฒๆๆญฃ็กฎ
|
| 1374 |
+
- [ ] ็ซฏๅฐ็ซฏ่ๆถ < 60 ็ง
|
| 1375 |
+
|
| 1376 |
+
#### ๅจๅ๏ผdebug + PPT
|
| 1377 |
+
|
| 1378 |
+
| ๆถ้ด | ไปปๅก | ไบงๅบ |
|
| 1379 |
+
|------|------|------|
|
| 1380 |
+
| ไธๅ | ็จ 3 ็ฏ demo ่ฎบๆๅ่ท 3 ้๏ผ่ฎฐๅฝๆฏๆฌก็ปๆ็ไธ่ดๆง | ๅ็ฐๆ้ข็น็ๅคฑ่ดฅๆจกๅผ๏ผไฟฎๅคๆ่ฎฐๅฝไธบ"ๅทฒ็ฅ้ๅถ" |
|
| 1381 |
+
| ไธๅ | ็ป PPT ไธญ็ไธๅฑๆถๆๅพ + ็ถๆ schema + Agent I/O schema | 3 ้กต PPT ๅ็จฟ |
|
| 1382 |
+
| ๆไธ | ๅๅค็ญ่พฉๅฏ่ฝ่ขซ้ฎๅฐ็ๆๆฏ้ฎ้ข๏ผ่ง้ๅฝ A๏ผ | ็ญ่พฉ Q&A ๆๆกฃ |
|
| 1383 |
+
|
| 1384 |
+
#### ๅจไบ๏ผๅฝฉๆ + ๆฑๆฅ
|
| 1385 |
+
|
| 1386 |
+
| ๆถ้ด | ไปปๅก |
|
| 1387 |
+
|------|------|
|
| 1388 |
+
| ไธๅ | ๅฎๆด่ตฐไธ้ demo ๆต็จ๏ผๆญฃๆ ทๆฌ่ฎบๆ โ ่ดๆ ทๆฌ่ฎบๆ โ ็ฐ่ฒๆ ทๆฌ๏ผ๏ผๆฏๆญฅ้
ไธ่ฎฒ่งฃ่ฏ |
|
| 1389 |
+
| ไธๅ | **ๆฑๆฅ** |
|
| 1390 |
+
|
| 1391 |
+
---
|
| 1392 |
+
|
| 1393 |
+
## ๅ
ญใไฝ ็็ถๆ schema ่ฎพ่ฎก
|
| 1394 |
+
|
| 1395 |
+
ไฝ ้่ฆๅฎไน้กน็ฎไธญ็ๆ ธๅฟๆฐๆฎ็ปๆใ่ฟ้จๅๅฏไปฅ็จๅจ PPT ไธญๅฑ็คบไฝ ็ๆถๆ่ฎพ่ฎก่ฝๅใ
|
| 1396 |
+
|
| 1397 |
+
```python
|
| 1398 |
+
# state.py โโ ๅฎไนๆดไธช็ณป็ป็ๆฐๆฎๆจกๅ๏ผPPT ็จ๏ผWeek 1 ไธๅผบๅถ่ฆๆฑๅๆไปฃ็ ๏ผ
|
| 1399 |
+
|
| 1400 |
+
from dataclasses import dataclass, field
|
| 1401 |
+
from typing import Optional
|
| 1402 |
+
|
| 1403 |
+
# ---- ็ฌฌไธๅฑ๏ผ็ ็ฉถๆนๅ ----
|
| 1404 |
+
|
| 1405 |
+
@dataclass
|
| 1406 |
+
class MethodFamily:
|
| 1407 |
+
"""ๆนๆณๆ"""
|
| 1408 |
+
family_name: str # ๅฆ "Vanilla Transformer"
|
| 1409 |
+
description: str # ไธๅฅ่ฏๆ ธๅฟ็น็น
|
| 1410 |
+
representative_work: str # ไปฃ่กจ่ฎบๆ
|
| 1411 |
+
search_queries: list[str] # GitHub ๆ็ดข่ฏ
|
| 1412 |
+
|
| 1413 |
+
|
| 1414 |
+
@dataclass
|
| 1415 |
+
class DirectionAnalysis:
|
| 1416 |
+
"""็ ็ฉถๆนๅ่งฃๆ็ปๆ"""
|
| 1417 |
+
subfield: str # ๅญ้ขๅๅ
|
| 1418 |
+
subfield_trend: str # ๅฝๅ่ถๅฟ
|
| 1419 |
+
method_families: list[MethodFamily]
|
| 1420 |
+
broad_queries: list[str] # ๅฎฝๆณๆ็ดข่ฏ
|
| 1421 |
+
|
| 1422 |
+
|
| 1423 |
+
# ---- ็ฌฌไบๅฑ๏ผๅ้ไปๅบ ----
|
| 1424 |
+
|
| 1425 |
+
@dataclass
|
| 1426 |
+
class CandidateRepo:
|
| 1427 |
+
"""ๅ้ไปๅบ"""
|
| 1428 |
+
full_name: str # "huggingface/transformers"
|
| 1429 |
+
html_url: str
|
| 1430 |
+
description: str
|
| 1431 |
+
stars: int
|
| 1432 |
+
language: str
|
| 1433 |
+
updated_at: str
|
| 1434 |
+
topics: list[str]
|
| 1435 |
+
match_keyword: str # ๅฝไธญๅชไธชๆ็ดข่ฏ
|
| 1436 |
+
method_family: str # ๅฝ็ฑปๅฐๅชไธชๆนๆณๆ๏ผๅฏไธบ็ฉบ๏ผ
|
| 1437 |
+
readme: Optional[str] = None
|
| 1438 |
+
dependencies: dict[str, str] = field(default_factory=dict)
|
| 1439 |
+
|
| 1440 |
+
|
| 1441 |
+
# ---- ็ฌฌไธๅฑ๏ผ่ฏไผฐ็ปๆ ----
|
| 1442 |
+
|
| 1443 |
+
@dataclass
|
| 1444 |
+
class EvalResult:
|
| 1445 |
+
"""ๅไธชไปๅบ็่ฏไผฐ็ปๆ"""
|
| 1446 |
+
reproducibility_score: int # ๅฏๅค็ฐๆงๆปๅ (0-80)
|
| 1447 |
+
benchmark_fitness_score: int # ๅฏนๆฏๅฎ้ช้้
ๅบฆๆปๅ (0-20)
|
| 1448 |
+
overall_score: int # ็ปผๅๆปๅ (0-100)
|
| 1449 |
+
verdict: str # reproducible / partially / not_reproducible
|
| 1450 |
+
env_score: int # 0-15
|
| 1451 |
+
doc_score: int # 0-20
|
| 1452 |
+
code_score: int # 0-20
|
| 1453 |
+
community_score: int # 0-10
|
| 1454 |
+
dep_score: int # 0-15
|
| 1455 |
+
benchmark_score: int # 0-20
|
| 1456 |
+
reasoning: str # ๅๆๆๆฌ
|
| 1457 |
+
risks: list[str] # ้ฃ้ฉๅ่กจ
|
| 1458 |
+
benchmark_readiness: str # ready / partial / not_ready
|
| 1459 |
+
suggested_use: str # ๅปบ่ฎฎ็จ้
|
| 1460 |
+
|
| 1461 |
+
|
| 1462 |
+
# ---- ้กถๅฑ๏ผๅฎๆด็ ๆฅ ----
|
| 1463 |
+
|
| 1464 |
+
@dataclass
|
| 1465 |
+
class ResearchReport:
|
| 1466 |
+
"""ๅฎๆด็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ"""
|
| 1467 |
+
paper_info: dict
|
| 1468 |
+
direction: DirectionAnalysis
|
| 1469 |
+
repos: list[tuple[CandidateRepo, EvalResult]]
|
| 1470 |
+
```
|
| 1471 |
+
|
| 1472 |
+
---
|
| 1473 |
+
|
| 1474 |
+
## ไธใๆไปถ็ปๆ๏ผไฝ ่ด่ดฃ็ๆไปถ็จ โ
ๆ ่ฎฐ๏ผ
|
| 1475 |
+
|
| 1476 |
+
```
|
| 1477 |
+
ResearchRadar/
|
| 1478 |
+
โโโ paper_fetcher.py # ็ฒ
|
| 1479 |
+
โโโ repo_searcher.py # ็ฒ
|
| 1480 |
+
โโโ repo_fetcher.py # ็ฒ
|
| 1481 |
+
โโโ direction_analyzer.py # โ
ไฝ ๏ผLLM ็ ็ฉถๆนๅ่งฃๆ + ๆนๆณๆ + ๆ็ดข่ฏ
|
| 1482 |
+
โโโ repo_evaluator.py # โ
ไฝ ๏ผLLM ๅ
ญ็ปดๅบฆ่ฏๅ
|
| 1483 |
+
โโโ run.py # โ
ไฝ ๏ผไธๅฑ่ฐๅบฆๅจ
|
| 1484 |
+
โโโ app.py # โ
ไฝ ๏ผGradio + ็ ๆฅๆ ผๅผๅ
|
| 1485 |
+
โโโ state.py # โ
ไฝ ๏ผ็ถๆ schema๏ผPPT ็จ๏ผๅฏ้๏ผ
|
| 1486 |
+
โโโ eval.py # ็ฒ
|
| 1487 |
+
โโโ test_set/ # ็ฒ
|
| 1488 |
+
โโโ requirements.txt
|
| 1489 |
+
โโโ README.md
|
| 1490 |
+
```
|
| 1491 |
+
|
| 1492 |
+
**ไฝ ็ `requirements.txt` ้ๆฑ้กน**๏ผ
|
| 1493 |
+
```
|
| 1494 |
+
openai>=1.0 # DeepSeek ้่ฟ OpenAI SDK ่ฐ็จ
|
| 1495 |
+
gradio>=4.0 # UI
|
| 1496 |
+
```
|
| 1497 |
+
|
| 1498 |
+
---
|
| 1499 |
+
|
| 1500 |
+
## ๅ
ซใPPT ไธญไฝ ้่ฆๅๅค็ๅ
ๅฎน
|
| 1501 |
+
|
| 1502 |
+
6 ๅ้ๆผ็คบไธญ๏ผไฝ ็ PPT ้จๅๅปบ่ฎฎๅ 2-3 ้กต๏ผ
|
| 1503 |
+
|
| 1504 |
+
### Page 1๏ผไธๅฑๆถๆๅพ
|
| 1505 |
+
```
|
| 1506 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1507 |
+
โ ResearchRadar ไธๅฑๆถๆ โ
|
| 1508 |
+
โ โ
|
| 1509 |
+
โ โ ็ ็ฉถๆนๅ่งฃๆ (Agent) โ
|
| 1510 |
+
โ arxiv API โ LLM โ ๅญ้ขๅ+ๆนๆณๆ โ
|
| 1511 |
+
โ โ โ
|
| 1512 |
+
โ โก ๅผๆบไปฃ็ ๅ็ฐ (Workflow) โ
|
| 1513 |
+
โ GitHub Search โ ๅป้ โ ๅ้ไปๅบ โ
|
| 1514 |
+
โ โ โ
|
| 1515 |
+
โ โข ๅฏๅค็ฐๆง+้้
ๅบฆ่ฏไผฐ (Agent) โ
|
| 1516 |
+
โ GitHub API โ LLM โ ๅ
ญ็ปด่ฏๅ โ
|
| 1517 |
+
โ โ โ
|
| 1518 |
+
โ ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ โ
|
| 1519 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1520 |
+
```
|
| 1521 |
+
|
| 1522 |
+
### Page 2๏ผ็ถๆๆต่ฝฌ
|
| 1523 |
+
```
|
| 1524 |
+
arxiv URL โ paper_info dict
|
| 1525 |
+
โ
|
| 1526 |
+
direction dict (subfield + method_families + queries)
|
| 1527 |
+
โ
|
| 1528 |
+
[repo dict, repo dict, ...] (top 5)
|
| 1529 |
+
โ
|
| 1530 |
+
ๆฏไธช repo ้ๅ evaluation dict (ๅ
ญ็ปด่ฏๅ)
|
| 1531 |
+
โ
|
| 1532 |
+
ResearchReport (ๆฑๆป โ format_report โ Markdown)
|
| 1533 |
+
```
|
| 1534 |
+
|
| 1535 |
+
### Page 3๏ผ6 ๅจ้็จ็ข๏ผไธ็ฒๅ
ฑ็จ๏ผ
|
| 1536 |
+
ๅฑ็คบ่ทฏ็บฟๅพ๏ผๅผบ่ฐ Week 1 ๅทฒ็ปๅฎ็ฐไธๅฑๅ
จ้พ่ทฏใ
|
| 1537 |
+
|
| 1538 |
+
---
|
| 1539 |
+
|
| 1540 |
+
## ไนใๅธธ่งๆ
้ๆจกๅผ้ๆฅ่กจ
|
| 1541 |
+
|
| 1542 |
+
| ็ฐ่ฑก | ๆๆฅๅฝไปค | ๅฏ่ฝๅๅ | ไฟฎๅค |
|
| 1543 |
+
|------|----------|----------|------|
|
| 1544 |
+
| `direction_analyzer` JSON ่งฃๆๅคฑ่ดฅ | ๅจไปฃ็ ไธญ `print(raw[:300])` | DeepSeek ่ฟๅไบ markdown ๅ
่ฃนๆ็บฏๆๆฌ | ๆฃๆฅ `_parse_json_safe` ็ไธ็ง็ญ็ฅๆฏๅฆ่ฆ็๏ผๆๅ prompt ็บฆๆ |
|
| 1545 |
+
| GitHub ๆไธๅฐไปๅบ | `print(all_queries)` ็ถๅๆๅจๅป GitHub ๆ | ๆ็ดข่ฏๅคชๅญฆๆฏๅ๏ผGitHub ไธๅน้
| ่ฐ direction_analyzer prompt๏ผๅขๅ "ๆ็ดข่ฏ็จๆฅๅธธๆๆฏๆฏ่ฏญ"็็บฆๆ |
|
| 1546 |
+
| ๆๅฐ็ไปๅบๅคชๅค๏ผ100+๏ผ | ๆญฃๅธธ๏ผ`search_repos` ๅ
้จๆ star ๆๅบๅ top | ๆฒก้ฎ้ข | ไธ้่ฆไฟฎๅค |
|
| 1547 |
+
| `repo_evaluator` ่ฏๅๅ
จๆฏ 70+ | ๆขไธไธชๅ
ฌ่ฎค็ไปๅบๆต่ฏ | LLM ่ฏๅๅๅฎฝๅฎน | ๅจ prompt ไธญๅ "ๅคๆฐไปๅบ็ๅๆฐๅบ่ฏฅๅจ 40-70 ไน้ด"็้ๅฎ |
|
| 1548 |
+
| Gradio ็ฝๅฑ | ็ป็ซฏ็้่ฏฏๆฅๅฟ | `app.py` import ๆฅ้ๆ็ซฏๅฃๅฒ็ช | ๆฃๆฅๆๆ import๏ผๆๆข็ซฏๅฃ `server_port=7861` |
|
| 1549 |
+
| ๆดๆก้พ่ทฏ > 2 ๅ้ | ๅๅซ่ฎกๆถๆฏไธชๆญฅ้ชค | GitHub ๆ็ดขไธฒ่ก 10+ ๆฌก | Week 2 ไผๅ๏ผๅ
็จ `top_n=3` ๅๅฐๅ้ๆฐ |
|
| 1550 |
+
|
| 1551 |
+
---
|
| 1552 |
+
|
| 1553 |
+
## ้ๅฝ A๏ผ็ญ่พฉๅฏ่ฝ่ขซ้ฎๅฐ็้ฎ้ข
|
| 1554 |
+
|
| 1555 |
+
1. **"ไธบไปไนไธ็จ LangChain/LangGraph๏ผ"**
|
| 1556 |
+
โ ๆไปฌ็็ณป็ป่งๆจกไธ้่ฆ็ผๆๆกๆถใAgent ๅฐฑๆฏไธไธช่ฐไบ LLM ็ Python ๅฝๆฐ๏ผWorkflow ๅฐฑๆฏไธไธชๆฒก่ฐ LLM ็ Python ๅฝๆฐ๏ผrun.py ๅฐฑๆฏไธๆฎต่ถๆฐดไปฃ็ ๆ้กบๅบ่ฐ็จๅฎไปฌใๆปๅ
ฑไธๅฐ 500 ่ก๏ผๆกๆถ็ๅญฆไน ๆๆฌๅๆฝ่ฑกๅผ้่ฟ่ถ
ๅฎๅธฆๆฅ็ๆถ็ใ
|
| 1557 |
+
|
| 1558 |
+
2. **"ๆนๅ่งฃๆ็ๅ็กฎ็ๆไนไฟ่ฏ๏ผ"**
|
| 1559 |
+
โ Week 1 ๆฏ baseline๏ผๆไปฌ็จไบบ็ผ้ช่ฏไบ 5 ็ฏ่ฎบๆ๏ผๅซๅทฅไธ็ผบ้ทๆฃๆต้ขๅ็ PaDiMใPatchCore ็ญ๏ผ็ๆนๅ่งฃๆ็ปๆใWeek 3 ไผๅปบ็ซๆนๅ่งฃๆ็่ฏๆต้๏ผ็จๅฏ้ๅๆๆ ่ฐไผใ
|
| 1560 |
+
|
| 1561 |
+
3. **"Agent ๅฐๅบๆฏๆไนๆญๅปบ็๏ผ"**
|
| 1562 |
+
โ ไธๆญฅ๏ผๅ System Prompt ๅฎไน่ง่ฒๅ่พๅบๆ ผๅผ โ ๅ User Prompt ๅกซๅ
ฅๅ
ทไฝๆฐๆฎ โ ่ฐ DeepSeek API ๆฟๅฐ JSON ็ปๆใAgent ไธๆฏไธไธชไผ่ชๅทฑ่ท็็จๅบ๏ผๅฐฑๆฏไธไธชๅฝๆฐ้ๆไธ่ก `client.chat.completions.create(...)`ใ
|
| 1563 |
+
|
| 1564 |
+
4. **"ๅฏนๆฏๅฎ้ช้้
ๅบฆๅๅฏๅค็ฐๆงๆไปไนๅบๅซ๏ผ"**
|
| 1565 |
+
โ ๅฏๅค็ฐๆงๅ็ญ"่ฝไธ่ฝ่ท"๏ผ้้
ๅบฆๅ็ญ"่ทไบ่ฝไธ่ฝๅ่ฟๅฎ้ช้จๅ"ใไปฅ anomalib ไธบไพ๏ผๅฏๅค็ฐๆง 78/80๏ผREADME ๅฎๅใpip install ๅณ็จ๏ผ๏ผ้้
ๅบฆ 19/20๏ผๆๆ ๅ benchmark ่ๆฌใๆฏๆ MVTec AD ๆฐๆฎ้ใๆ้ข่ฎญ็ปๆ้๏ผใ่ไธไธชๅชๆๆจ็ demo ็้กน็ฎๅฏไปฅๅฏๅค็ฐๆง 55/80 ไฝ้้
ๅบฆ 5/20ใ
|
| 1566 |
+
|
| 1567 |
+
5. **"ไฝ ๅ็ฒๆไนๅๅทฅ๏ผ"**
|
| 1568 |
+
โ ไป่ด่ดฃๆๆ Workflow๏ผarxiv APIใGitHub ๆ็ดขใๆไปถๆๅ่ฟไบ็กฎๅฎๆงๆต็จ๏ผ๏ผๆ่ด่ดฃๆๆ Agent๏ผๆนๅ่งฃๆใๅฏๅค็ฐๆง่ฏไผฐ่ฟไบ้่ฆ LLM ๅๅคๆญ็ๆจกๅ๏ผ๏ผไปฅๅๆไธค่
ไธฒ่ตทๆฅ็่ฐๅบฆๅจใๆๅ่ฝๅฑๅ่ไธๆฏๆๆจกๅๅ๏ผไฟ่ฏๆฅๅฃๆธ
ๆฐใ
|
| 1569 |
+
|
| 1570 |
+
6. **"ๅทฅไธ็ผบ้ทๆฃๆต่ฟไธชๆนๅๆไปไน็นๆฎๆง๏ผ"**
|
| 1571 |
+
โ ่ฟไธชๆนๅๆนๆณๆๆธ
ๆฐ๏ผEmbedding-based / Reconstruction-based / Teacher-Student / Synthetic Defect๏ผ๏ผๆๅ
ฌ่ฎค benchmark๏ผMVTec AD๏ผ๏ผๆ anomalib ่ฟๆ ท็ไธ็ซๅผๅผๆบๅบใ้ๅธธ้ๅ็จ ResearchRadar ๅๆนๅๅ
จๆฏๅฑ็คบโโ่พๅ
ฅไธ็ฏ่ฎบๆๅฐฑ่ฝ็ๅฐๆดไธช้ขๅ็ๆนๆณๆๅฐๅพใ
|
| 1572 |
+
|
| 1573 |
+
---
|
| 1574 |
+
|
| 1575 |
+
> **ๆๅไธไธชๅปบ่ฎฎ**๏ผๅจไธๅฐๅจไบ๏ผๆฏๅคฉไธๅ 5 ็นๅ็ฒ่ฑ 10 ๅ้ๅฏนไธไธ่ฟๅบฆใไฝ ไปฌ็ๅทฅไฝๆไบค็้ข๏ผไฝ ็ run.py ่ฐไป็ fetcher/searcher๏ผ๏ผๆฅๅฃ็บฆๅฎๆธ
ๆฅๅฐฑไธไผๅจๅจไธ่่ฐๆถๅดฉใ
|
app.py
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# app.py
|
| 2 |
+
# ============================================================
|
| 3 |
+
# ็ฑปๅ๏ผ็้ขๅฑ๏ผไน่ด่ดฃ๏ผ
|
| 4 |
+
# ๅ่ฝ๏ผGradio ็้ข + ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅๆ ผๅผๅ
|
| 5 |
+
# ็จๆณ๏ผpython app.py โ ๆต่งๅจๆๅผ http://127.0.0.1:7860
|
| 6 |
+
# ๅ
ฌ็ฝ๏ผ่ฎพ็ฝฎ NGROK_AUTH_TOKEN ็ฏๅขๅ้ๅ่ชๅจ็ๆๅ
ฌ็ฝ้พๆฅ
|
| 7 |
+
# ============================================================
|
| 8 |
+
import sys
|
| 9 |
+
import os
|
| 10 |
+
import gradio as gr
|
| 11 |
+
|
| 12 |
+
# ่ชๅจๅ ่ฝฝ .env ๆไปถ
|
| 13 |
+
_ENV_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env")
|
| 14 |
+
if os.path.isfile(_ENV_PATH):
|
| 15 |
+
with open(_ENV_PATH, "r", encoding="utf-8") as _f:
|
| 16 |
+
for _line in _f:
|
| 17 |
+
_line = _line.strip()
|
| 18 |
+
if _line and not _line.startswith("#") and "=" in _line:
|
| 19 |
+
_key, _val = _line.split("=", 1)
|
| 20 |
+
if _key not in os.environ:
|
| 21 |
+
os.environ[_key] = _val.strip().strip('"').strip("'")
|
| 22 |
+
|
| 23 |
+
try:
|
| 24 |
+
from run import run
|
| 25 |
+
except (ImportError, ModuleNotFoundError) as e:
|
| 26 |
+
print(f"[้่ฏฏ] ๆ ๆณๅฏผๅ
ฅ run.py๏ผ่ฏท็กฎ่ฎค็ฒๅทฒไบคไปๆๆ Workflow ๆจกๅใ")
|
| 27 |
+
print(f" {e}")
|
| 28 |
+
sys.exit(1)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def diagnose(arxiv_url: str) -> str:
|
| 32 |
+
"""Gradio ๅ่ฐ๏ผ็จๆท่พๅ
ฅ arxiv URL โ ่ฟๅ Markdown ็ ๆฅ"""
|
| 33 |
+
url = arxiv_url.strip()
|
| 34 |
+
if not url:
|
| 35 |
+
return "## โ ๏ธ ่ฏท่พๅ
ฅ arxiv ่ฎบๆ้พๆฅ\n\n็คบไพ: `https://arxiv.org/abs/2011.08785`"
|
| 36 |
+
|
| 37 |
+
try:
|
| 38 |
+
result = run(url)
|
| 39 |
+
except ValueError as e:
|
| 40 |
+
return f"## โ ่พๅ
ฅๆ ผๅผ้่ฏฏ\n\n{str(e)}\n\n่ฏท็กฎ่ฎค่พๅ
ฅ็ๆฏๆๆ็ arxiv ้พๆฅใ"
|
| 41 |
+
except RuntimeError as e:
|
| 42 |
+
return f"## โ API ่ฏทๆฑๅคฑ่ดฅ\n\n{str(e)}\n\n่ฏทๆฃๆฅ็ฝ็ป่ฟๆฅๆ็จๅ้่ฏใ"
|
| 43 |
+
except Exception as e:
|
| 44 |
+
return f"## โ ่ฟ่กๅบ้\n\n```\n{type(e).__name__}: {str(e)}\n```\n\n่ฏทๅฐไปฅไธ้่ฏฏไฟกๆฏๅ้ฆ็ปๅผๅ่
ใ"
|
| 45 |
+
|
| 46 |
+
# ๅค็้จๅๅคฑ่ดฅ็ๆ
ๅต
|
| 47 |
+
if result.get("error") and not result.get("repos"):
|
| 48 |
+
paper = result.get("paper", {})
|
| 49 |
+
direction = result.get("direction", {})
|
| 50 |
+
title = paper.get("title", "ๆช็ฅ") if paper else "ๆช็ฅ"
|
| 51 |
+
|
| 52 |
+
md = f"""# ResearchRadar ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ
|
| 53 |
+
|
| 54 |
+
---
|
| 55 |
+
|
| 56 |
+
## ่ฎบๆไฟกๆฏ
|
| 57 |
+
|
| 58 |
+
**{title}**
|
| 59 |
+
|
| 60 |
+
---
|
| 61 |
+
|
| 62 |
+
## โ ๏ธ ๆช่ฝๅฎๆๅฎๆด่ฏไผฐ
|
| 63 |
+
|
| 64 |
+
**ๅๅ **: {result['error']}
|
| 65 |
+
|
| 66 |
+
"""
|
| 67 |
+
if direction:
|
| 68 |
+
md += f"""## ็ ็ฉถๆนๅ่งฃๆ๏ผ้จๅ็ปๆ๏ผ
|
| 69 |
+
|
| 70 |
+
**ๅญ้ขๅ**: {direction.get('subfield', 'N/A')}
|
| 71 |
+
|
| 72 |
+
**่ถๅฟ**: {direction.get('subfield_trend', 'N/A')}
|
| 73 |
+
"""
|
| 74 |
+
md += """
|
| 75 |
+
---
|
| 76 |
+
> ่ฏฅ่ฎบๆๆนๅๅฏ่ฝๅคชๆฐๆๅคชๅท้จ๏ผๆๆ ้ซ่ดจ้ๅผๆบๅฎ็ฐใ่ฟๆฐๅฅฝๅธฎๅฉไฝ ๅคๆญโโๅจ่ฟไธชๆนๅๅผๅฑ็ ็ฉถ้่ฆไปๅคดๅฎ็ฐใ
|
| 77 |
+
"""
|
| 78 |
+
return md
|
| 79 |
+
|
| 80 |
+
return format_report(result)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def format_report(result: dict) -> str:
|
| 84 |
+
"""ๅฐ run() ็็ปๆๆ ผๅผๅไธบ"็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ" Markdownใ
|
| 85 |
+
|
| 86 |
+
็ ๆฅ็ปๆ๏ผ
|
| 87 |
+
1. ่ฎบๆไฟกๆฏ
|
| 88 |
+
2. ็ ็ฉถๆนๅๅ
จๆฏ๏ผๅญ้ขๅ + ่ถๅฟ + ๆนๆณๆ่ฐฑ็ณป + ๅผๆบ่ฆ็ๅบฆ๏ผ
|
| 89 |
+
3. ๆนๆณๆๅผๆบ่ฆ็ๅบฆ๏ผๅชไบๅทฒๆๅฎ็ฐใๅชไบๆฏ็ฉบ็ฝ๏ผ
|
| 90 |
+
4. ๅผๆบๅฎ็ฐ่ฏไผฐๆๅ๏ผๅ
ญ็ปดๅบฆ่ฏๅๆ็ป๏ผ
|
| 91 |
+
5. ๅฏนๆฏๅฎ้ชๆจ่ๆป็ป๏ผๆๅฐฑ็ปชๅบฆๅ็ป๏ผ
|
| 92 |
+
"""
|
| 93 |
+
paper = result.get("paper", {})
|
| 94 |
+
direction = result.get("direction", {})
|
| 95 |
+
repos = result.get("repos", [])
|
| 96 |
+
|
| 97 |
+
# ===== ็ฌฌไธ้จๅ๏ผ่ฎบๆไฟกๆฏ =====
|
| 98 |
+
arxiv_id = paper.get("arxiv_id", "")
|
| 99 |
+
arxiv_url = f"https://arxiv.org/abs/{arxiv_id}" if arxiv_id else ""
|
| 100 |
+
|
| 101 |
+
md = "# ResearchRadar ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ\n\n---\n\n## ไธใ่ฎบๆไฟกๆฏ\n\n"
|
| 102 |
+
md += "| ้กน็ฎ | ๅ
ๅฎน |\n|------|------|\n"
|
| 103 |
+
md += f"| **ๆ ้ข** | {paper.get('title', 'N/A')} |\n"
|
| 104 |
+
if arxiv_url:
|
| 105 |
+
md += f"| **arXiv** | [{arxiv_id}]({arxiv_url}) |\n"
|
| 106 |
+
else:
|
| 107 |
+
md += f"| **arXiv ID** | {arxiv_id or 'N/A'} |\n"
|
| 108 |
+
md += f"| **ไฝ่
** | {', '.join(paper.get('authors', ['N/A'])[:5])}"
|
| 109 |
+
if len(paper.get("authors", [])) > 5:
|
| 110 |
+
md += f" ็ญ {len(paper.get('authors', []))} ไบบ"
|
| 111 |
+
md += " |\n"
|
| 112 |
+
published = paper.get("published", "")
|
| 113 |
+
if published:
|
| 114 |
+
md += f"| **ๅ่กจๆถ้ด** | {published[:10]} |\n"
|
| 115 |
+
categories = paper.get("categories", [])
|
| 116 |
+
if categories:
|
| 117 |
+
md += f"| **ๅ็ฑป** | {', '.join(categories)} |\n"
|
| 118 |
+
|
| 119 |
+
# ===== ็ฌฌไบ้จๅ๏ผ็ ็ฉถๆนๅๅ
จๆฏ =====
|
| 120 |
+
md += "\n---\n\n## ไบใ็ ็ฉถๆนๅๅ
จๆฏ\n\n"
|
| 121 |
+
md += f"### ๅญ้ขๅๅฎไฝ\n\n**{direction.get('subfield', 'ๆช็ฅ')}**\n\n"
|
| 122 |
+
md += f"### ๅฝๅ่ถๅฟ\n\n{direction.get('subfield_trend', 'ๆๆ ๅๆ')}\n\n"
|
| 123 |
+
md += "### ๆนๆณๆ่ฐฑ็ณป\n\n"
|
| 124 |
+
md += "| # | ๆนๆณๆ | ๆ ธๅฟ็น็น | ไปฃ่กจๅทฅไฝ |\n|---|--------|----------|----------|\n"
|
| 125 |
+
|
| 126 |
+
families = direction.get("method_families", [])
|
| 127 |
+
for i, mf in enumerate(families):
|
| 128 |
+
family_name = mf.get("family_name", f"ๆนๆณๆ {i+1}")
|
| 129 |
+
desc = mf.get("description", "")[:80]
|
| 130 |
+
rep = mf.get("representative_work", "")[:60]
|
| 131 |
+
md += f"| {i+1} | **{family_name}** | {desc} | {rep} |\n"
|
| 132 |
+
|
| 133 |
+
if not families:
|
| 134 |
+
md += "| - | ๆช่ฝ่ฏๅซๅบๆ็กฎ็ๆนๆณ๏ฟฝ๏ฟฝ๏ฟฝ | - | - |\n"
|
| 135 |
+
|
| 136 |
+
# ๆนๆณๆๅผๆบ่ฆ็ๅบฆ
|
| 137 |
+
md += "\n### ๆนๆณๆๅผๆบ่ฆ็ๅบฆ\n\n"
|
| 138 |
+
covered = []
|
| 139 |
+
uncovered = []
|
| 140 |
+
for mf in families:
|
| 141 |
+
name = mf.get("family_name", "ๆช็ฅ")
|
| 142 |
+
matched = mf.get("matched_repos", [])
|
| 143 |
+
if matched:
|
| 144 |
+
covered.append((name, matched))
|
| 145 |
+
else:
|
| 146 |
+
uncovered.append(name)
|
| 147 |
+
|
| 148 |
+
if covered:
|
| 149 |
+
md += "| ๆนๆณๆ | ๅผๆบไปๅบๆฐ | ่ฆ็็ถๆ |\n"
|
| 150 |
+
md += "|--------|:----------:|:--------:|\n"
|
| 151 |
+
for name, matched in covered:
|
| 152 |
+
md += f"| **{name}** | {len(matched)} | ๐ข ๅทฒๆๅฎ็ฐ |\n"
|
| 153 |
+
if uncovered:
|
| 154 |
+
for name in uncovered:
|
| 155 |
+
md += f"| **{name}** | 0 | ๐ด ๆๆ ๅผๆบๅฎ็ฐ |\n"
|
| 156 |
+
md += "\n> ๐ก ่ฟไบๆนๆณๆๆๆ ๅผๆบๅฎ็ฐโโๅฏ่ฝๆฏ็ ็ฉถ็ฉบ็ฝๆๅฏนๆฏๅฎ้ช็ๅทฎๅผๅๆนๅใ\n"
|
| 157 |
+
md += "\n"
|
| 158 |
+
|
| 159 |
+
# ===== ็ฌฌไธ้จๅ๏ผไปๅบ่ฏไผฐๆๅ =====
|
| 160 |
+
md += "\n---\n\n## ๅใๅผๆบๅฎ็ฐ่ฏไผฐๆๅ\n\n"
|
| 161 |
+
|
| 162 |
+
if not repos:
|
| 163 |
+
md += "**ๆชๆพๅฐ็ธๅ
ณๅผๆบไปๅบใ**\n\n"
|
| 164 |
+
return md
|
| 165 |
+
|
| 166 |
+
for i, repo in enumerate(repos):
|
| 167 |
+
full_name = repo.get("full_name", f"ไปๅบ {i+1}")
|
| 168 |
+
html_url = repo.get("html_url", "")
|
| 169 |
+
ev = repo.get("evaluation", {})
|
| 170 |
+
mf = repo.get("method_family", "")
|
| 171 |
+
|
| 172 |
+
verdict_icon = {
|
| 173 |
+
"reproducible": "โ
", "partially": "โ ๏ธ",
|
| 174 |
+
"not_reproducible": "โ", "error": "๐ฅ",
|
| 175 |
+
}.get(ev.get("verdict", ""), "โ")
|
| 176 |
+
|
| 177 |
+
readiness_icon = {
|
| 178 |
+
"ready": "๐ข", "partial": "๐ก", "not_ready": "๐ด",
|
| 179 |
+
}.get(ev.get("benchmark_readiness", ""), "โช")
|
| 180 |
+
|
| 181 |
+
family_tag = f" `[{mf}]`" if mf else ""
|
| 182 |
+
|
| 183 |
+
md += f"### {i+1}. [{full_name}]({html_url}){family_tag}\n\n"
|
| 184 |
+
|
| 185 |
+
repro_score = ev.get("reproducibility_score", ev.get("overall_score", "N/A"))
|
| 186 |
+
bench_score = ev.get("benchmark_fitness_score", ev.get("benchmark_score", "N/A"))
|
| 187 |
+
overall = ev.get("overall_score", "N/A")
|
| 188 |
+
|
| 189 |
+
md += f"{verdict_icon} **ๅฏๅค็ฐๆง: {repro_score}/80** | "
|
| 190 |
+
md += f"{readiness_icon} **ๅฏนๆฏๅฎ้ช้้
ๅบฆ: {bench_score}/20** | "
|
| 191 |
+
md += f"**็ปผๅ: {overall}/100**\n\n"
|
| 192 |
+
|
| 193 |
+
md += "| ็ปดๅบฆ | ๅพๅ | ๆปกๅ | ่ฏดๆ |\n"
|
| 194 |
+
md += "|------|:----:|:----:|------|\n"
|
| 195 |
+
md += f"| ็ฏๅข้
็ฝฎ | {_fmt(ev.get('env_score'))} | 15 | ไพ่ตๆไปถๅฎๆดๆง |\n"
|
| 196 |
+
md += f"| ๆๆกฃ่ดจ้ | {_fmt(ev.get('doc_score'))} | 20 | ๅฎ่ฃ
/่ฎญ็ป/ๆฐๆฎ่ฏดๆ |\n"
|
| 197 |
+
md += f"| ไปฃ็ ๅฏ็จๆง | {_fmt(ev.get('code_score'))} | 20 | ่ฎญ็ป+ๆจ็่ๆฌ |\n"
|
| 198 |
+
md += f"| ็คพๅบๆดป่ทๅบฆ | {_fmt(ev.get('community_score'))} | 10 | Star + ๆดๆฐ้ข็ |\n"
|
| 199 |
+
md += f"| ไพ่ตๅฅๅบทๅบฆ | {_fmt(ev.get('dep_score'))} | 15 | ไพ่ตๅ
ผๅฎนๆง |\n"
|
| 200 |
+
md += f"| **ๅฏนๆฏๅฎ้ช** | **{_fmt(ev.get('benchmark_score'))}** | **20** | **benchmark + ้ข่ฎญ็ปๆ้** |\n"
|
| 201 |
+
|
| 202 |
+
md += f"\nโญ Star: {repo.get('stars', 0)}"
|
| 203 |
+
if repo.get("match_keyword"):
|
| 204 |
+
md += f" | ๅน้
่ฏ: `{repo.get('match_keyword', '')}`"
|
| 205 |
+
md += "\n\n"
|
| 206 |
+
|
| 207 |
+
reasoning = ev.get("reasoning", "N/A")
|
| 208 |
+
md += f"**ๅๆ**: {reasoning}\n\n"
|
| 209 |
+
md += f"**ๅฏนๆฏๅฎ้ชๅปบ่ฎฎ**: {ev.get('suggested_use', 'N/A')}\n\n"
|
| 210 |
+
|
| 211 |
+
risks = ev.get("risks", [])
|
| 212 |
+
if risks:
|
| 213 |
+
md += "**้ฃ้ฉ็น**: " + " ยท ".join(f"`{r}`" for r in risks) + "\n\n"
|
| 214 |
+
|
| 215 |
+
md += "---\n\n"
|
| 216 |
+
|
| 217 |
+
# ===== ็ฌฌๅ้จๅ๏ผๅฏนๆฏๅฎ้ชๆจ่ๆป็ป =====
|
| 218 |
+
md += "## ไบใๅฏนๆฏๅฎ้ชๆจ่ๆป็ป\n\n"
|
| 219 |
+
|
| 220 |
+
ready = [r for r in repos if r["evaluation"].get("benchmark_readiness") == "ready"]
|
| 221 |
+
partial = [r for r in repos if r["evaluation"].get("benchmark_readiness") == "partial"]
|
| 222 |
+
not_ready = [
|
| 223 |
+
r for r in repos
|
| 224 |
+
if r["evaluation"].get("benchmark_readiness") not in ("ready", "partial")
|
| 225 |
+
]
|
| 226 |
+
|
| 227 |
+
if ready:
|
| 228 |
+
md += "### ๐ข ๅฏ็ดๆฅ็จไบๅฏนๆฏๅฎ้ช\n\n"
|
| 229 |
+
for r in ready:
|
| 230 |
+
url = r.get("html_url", "#")
|
| 231 |
+
name = r.get("full_name", "ๆช็ฅ")
|
| 232 |
+
suggestion = r["evaluation"].get("suggested_use", "")
|
| 233 |
+
md += f"- **[{name}]({url})** โ {suggestion}\n"
|
| 234 |
+
md += "\n"
|
| 235 |
+
|
| 236 |
+
if partial:
|
| 237 |
+
md += "### ๐ก ้่ฆๅฐ้ไฟฎๆนๅๅฏ็จ\n\n"
|
| 238 |
+
for r in partial:
|
| 239 |
+
url = r.get("html_url", "#")
|
| 240 |
+
name = r.get("full_name", "ๆช็ฅ")
|
| 241 |
+
suggestion = r["evaluation"].get("suggested_use", "")
|
| 242 |
+
md += f"- **[{name}]({url})** โ {suggestion}\n"
|
| 243 |
+
md += "\n"
|
| 244 |
+
|
| 245 |
+
if not_ready:
|
| 246 |
+
md += "### ๐ด ไป
้ๅๅ่ไปฃ็ ๅฎ็ฐ\n\n"
|
| 247 |
+
for r in not_ready:
|
| 248 |
+
url = r.get("html_url", "#")
|
| 249 |
+
name = r.get("full_name", "ๆช็ฅ")
|
| 250 |
+
reason = r["evaluation"].get("suggested_use") or r["evaluation"].get("reasoning", "")
|
| 251 |
+
md += f"- **[{name}]({url})** โ {reason[:120]}...\n"
|
| 252 |
+
md += "\n"
|
| 253 |
+
|
| 254 |
+
md += "---\n\n> ResearchRadar ยท ่ฎบๆ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ + ๅฏนๆฏๅฎ้ชๆจ่\n"
|
| 255 |
+
|
| 256 |
+
return md
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
def _fmt(value) -> str:
|
| 260 |
+
"""ๆ ผๅผๅๆฐๅผ๏ผNone ๆพ็คบไธบ N/A"""
|
| 261 |
+
if value is None:
|
| 262 |
+
return "N/A"
|
| 263 |
+
return str(value)
|
| 264 |
+
|
| 265 |
+
|
| 266 |
+
# ============================================================
|
| 267 |
+
# Gradio ๅฏๅจ
|
| 268 |
+
# ============================================================
|
| 269 |
+
DEMO_EXAMPLES = [
|
| 270 |
+
["https://arxiv.org/abs/2011.08785"], # PaDiM๏ผๅทฅไธ็ผบ้ทๆฃๆต๏ผ
|
| 271 |
+
["https://arxiv.org/abs/1706.03762"], # Attention Is All You Need
|
| 272 |
+
["https://arxiv.org/abs/2108.07610"], # DRAEM๏ผ็ผบ้ทๆฃๆต๏ผๅๆ็ผบ้ทๆนๆณ๏ผ
|
| 273 |
+
]
|
| 274 |
+
|
| 275 |
+
demo = gr.Interface(
|
| 276 |
+
fn=diagnose,
|
| 277 |
+
inputs=gr.Textbox(
|
| 278 |
+
label="่ฎบๆ arxiv ้พๆฅ",
|
| 279 |
+
placeholder="https://arxiv.org/abs/2011.08785",
|
| 280 |
+
lines=1,
|
| 281 |
+
),
|
| 282 |
+
outputs=gr.Markdown(label="็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ"),
|
| 283 |
+
title="ResearchRadar โ ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ",
|
| 284 |
+
description=(
|
| 285 |
+
"่พๅ
ฅไธ็ฏ AI ่ฎบๆ็ arxiv ้พๆฅ๏ผAI ๅธฎไฝ ๏ผ\n"
|
| 286 |
+
"1. ๆธๆธ
่ฏฅ็ ็ฉถๆนๅ็ๅๆฒฟๅ
จๆฏ๏ผๅญ้ขๅ + ๆนๆณๆ่ฐฑ็ณป๏ผ\n"
|
| 287 |
+
"2. ๆพๅฐๆ้้
็ๅผๆบๅฎ็ฐ\n"
|
| 288 |
+
"3. ่ฏไผฐๆฏไธชไปๅบ่ฝๅฆ็ดๆฅ็จไบๅ่ฎบๆ่ทๅฏนๆฏๅฎ้ช"
|
| 289 |
+
),
|
| 290 |
+
examples=DEMO_EXAMPLES,
|
| 291 |
+
)
|
| 292 |
+
|
| 293 |
+
if __name__ == "__main__":
|
| 294 |
+
public_url = None
|
| 295 |
+
|
| 296 |
+
# ๅฐ่ฏ ngrok ๅ
ฌ็ฝ้ง้๏ผๅฝๅ
ๅฏ็จ๏ผ
|
| 297 |
+
ngrok_token = os.getenv("NGROK_AUTH_TOKEN", "")
|
| 298 |
+
if ngrok_token:
|
| 299 |
+
try:
|
| 300 |
+
from pyngrok import ngrok, conf
|
| 301 |
+
conf.get_default().auth_token = ngrok_token
|
| 302 |
+
tunnel = ngrok.connect(7860, "http")
|
| 303 |
+
public_url = tunnel.public_url
|
| 304 |
+
print(f"\n{'='*60}")
|
| 305 |
+
print(f" ๅ
ฌ็ฝ้พๆฅ: {public_url}")
|
| 306 |
+
print(f" ไปปไฝไบบๅฏไปฅๆๅผๆญค้พๆฅไฝฟ็จ ResearchRadar")
|
| 307 |
+
print(f"{'='*60}\n")
|
| 308 |
+
except Exception as e:
|
| 309 |
+
print(f" [WARN] ngrok ๅฏๅจๅคฑ่ดฅ: {e}")
|
| 310 |
+
print(f" ้็บงไธบไป
ๆฌๅฐ่ฎฟ้ฎ")
|
| 311 |
+
|
| 312 |
+
if not public_url:
|
| 313 |
+
print("\n ๆช้
็ฝฎๅ
ฌ็ฝ้ง้๏ผไป
ๆฌๅฐ่ฎฟ้ฎ: http://127.0.0.1:7860")
|
| 314 |
+
print(" ๅฆ้ๅ
ฌ็ฝ่ฎฟ้ฎ๏ผ่ฏท่ฎพ็ฝฎ NGROK_AUTH_TOKEN ็ฏๅขๅ้")
|
| 315 |
+
print(" ๅ
่ดน่ทๅ token: https://dashboard.ngrok.com/get-started/your-authtoken\n")
|
| 316 |
+
|
| 317 |
+
demo.launch(server_name="0.0.0.0", share=False, theme="soft", show_error=True)
|
direction_analyzer.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# direction_analyzer.py
|
| 2 |
+
# ============================================================
|
| 3 |
+
# ็ฑปๅ๏ผAGENT๏ผไน่ด่ดฃ๏ผ
|
| 4 |
+
# ๅ่ฝ๏ผๅบไบ GitHub ๆ็ดข็ปๆ + ่ฎบๆไฟกๆฏ โ ๅฝ็บณๆนๆณๆ่ฐฑ็ณป
|
| 5 |
+
# ็จๆณ๏ผpython direction_analyzer.py๏ผ่ชๆต๏ผ
|
| 6 |
+
# ============================================================
|
| 7 |
+
from llm_utils import call_llm_json, parse_json_safe, validate_direction_output, fix_windows_encoding
|
| 8 |
+
|
| 9 |
+
DIRECTION_SYSTEM_PROMPT = """ไฝ ๆฏไธไธช AI ็ ็ฉถ้ขๅ็ๅผๆบ็ๆๅๆๅธใไฝ ็ไปปๅกๆฏ๏ผๆฟๅฐไธ็ฏ่ฎบๆๅ GitHub ไธๆๅฐ็็ธๅ
ณไปๅบๅ่กจ๏ผๅธฎ็ ็ฉถ่
็ๆธ
โโ่ฟไบไปๅบๅๅซๅฑไบไปไนๆนๆณๆใๅชไบๆนๆณๆๆๆ็ๅผๆบๅฎ็ฐใๅชไบ่ฟๆฏ็ฉบ็ฝใ
|
| 10 |
+
|
| 11 |
+
## ๅๆๆต็จ
|
| 12 |
+
|
| 13 |
+
### ๆญฅ้ชค 1๏ผๅฎไฝๅญ้ขๅ
|
| 14 |
+
- ็ปๅ่ฎบๆๅ
ๅฎนๅไปๅบๆ่ฟฐ๏ผๅคๆญ่ฏฅ่ฎบๆๅฑไบๅชไธชๅ
ทไฝๅญ้ขๅ
|
| 15 |
+
- ไธ่ฆ็ฌผ็ป๏ผๅฆ"ๆทฑๅบฆๅญฆไน "๏ผ๏ผ่ฆๅ
ทไฝ๏ผๅฆ"ๅทฅไธๅพๅๅผๅธธๆฃๆต"๏ผ
|
| 16 |
+
- ่ฏดๆ่ฏฅๅญ้ขๅๅจ 2024-2025 ๅนด็ไธปๆต่ถๅฟ๏ผ1-2 ๅฅไธญๆ๏ผ
|
| 17 |
+
|
| 18 |
+
### ๆญฅ้ชค 2๏ผๅฝ็บณๆนๆณๆ
|
| 19 |
+
- ๆต่งๆๆไปๅบ็ description ๅ topics๏ผๅฐๅ็ฑปๆนๆณ็ไปๅบๅฝไธบไธๆ
|
| 20 |
+
- ๆฏไธชๆนๆณๆ็ปๅบ๏ผๅ็งฐใไธๅฅ่ฏๆ ธๅฟ็น็นใไปฃ่กจ่ฎบๆ/้กน็ฎ
|
| 21 |
+
- ่พๅบ 3-6 ไธชๆนๆณๆ
|
| 22 |
+
- ๅฆๆไธไธชไปๅบๆๆพไธๅฑไบไปปไฝไธๆ๏ผๅฆๅชๆฏๆ็จใ่ฎบๆๅ่กจ๏ผ๏ผไธ่ฆๅผบ่กๅฝ็ฑป
|
| 23 |
+
- ้่ฆ๏ผๆนๆณๆๅ็งฐๅฐฝ้ไฝฟ็จ่ฑๆ๏ผๅฆ"Patch Distribution Modeling"๏ผ๏ผไพฟไบๅ็ปญๆ็ดข
|
| 24 |
+
|
| 25 |
+
### ๆญฅ้ชค 3๏ผไธบๆฏไธชๆนๆณๆๅๅบๅฝๅฑไปๅบ
|
| 26 |
+
- matched_repos ๅกซ่ฏฅๆๅ
ๅซ็ไปๅบ full_name ๅ่กจ
|
| 27 |
+
- ๅฆๆไธไธชไปๅบๅฏไปฅๅฑไบๅคไธชๆ๏ผๅฆๅๆถๅฎ็ฐไบๆนๆณAๅๆนๆณB๏ผ๏ผ้ๆๅน้
็้ฃไธช
|
| 28 |
+
|
| 29 |
+
### ๆญฅ้ชค 4๏ผ็ๆ็ฒพๅๆ็ดข่ฏ
|
| 30 |
+
- ไธบๆฏไธชๆนๆณๆ็ๆ 2-3 ไธช GitHub ๆ็ดขๆฅ่ฏข๏ผ่ฑๆ๏ผ
|
| 31 |
+
- ๆ ผๅผ๏ผๆนๆณๅ + ๆๆฏๅ
ณ้ฎ่ฏ + ้ๅฎ่ฏ๏ผimplementation / pytorch / official / code๏ผ
|
| 32 |
+
- ้ขๅค็ๆ 3 ไธชๅฎฝๆณๆ็ดข่ฏ๏ผ็จไบๆฅๆพๆช่ขซๅฝๅๆ็ดข่ฆ็็ๆนๆณๆ
|
| 33 |
+
|
| 34 |
+
## ๆ็ดขๆฅ่ฏข่ดจ้่ฆๆฑ
|
| 35 |
+
- ๅฅฝ็ๆฅ่ฏข๏ผ"patch distribution modeling anomaly detection pytorch"
|
| 36 |
+
- ๅ็ๆฅ่ฏข๏ผ"anomaly"๏ผๅคชๅฎฝๆณ๏ผ
|
| 37 |
+
- ๅ็ๆฅ่ฏข๏ผ"a novel approach for industrial defect detection using deep learning"๏ผๅคชๅคๅบ่ฏ๏ผ
|
| 38 |
+
|
| 39 |
+
## ่พๅบๆ ผๅผ๏ผไธฅๆ ผ JSON๏ผ็ดงๅๆ ผๅผไธ่ฆ็ผฉ่ฟๅๅคไฝ็ฉบๆ ผ๏ผ
|
| 40 |
+
{
|
| 41 |
+
"subfield": "ๅ
ทไฝๅญ้ขๅๅ็งฐ",
|
| 42 |
+
"subfield_trend": "่ฏฅๅญ้ขๅ 2024-2025 ็ไธปๆต่ถๅฟ๏ผ1-2 ๅฅไธญๆ๏ผ",
|
| 43 |
+
"method_families": [
|
| 44 |
+
{
|
| 45 |
+
"family_name": "ๆนๆณๆ็ฎ็งฐ",
|
| 46 |
+
"description": "ไธๅฅ่ฏๆ ธๅฟ็น็น",
|
| 47 |
+
"representative_work": "ไปฃ่กจ่ฎบๆๆ็ฅๅ้กน็ฎ",
|
| 48 |
+
"matched_repos": ["owner/repo1", "owner/repo2"],
|
| 49 |
+
"search_queries": ["ๆ็ดข่ฏ1", "ๆ็ดข่ฏ2"]
|
| 50 |
+
}
|
| 51 |
+
],
|
| 52 |
+
"broad_queries": ["ๅฎฝๆณๆ็ดข1", "ๅฎฝๆณๆ็ดข2", "ๅฎฝๆณๆ็ดข3"]
|
| 53 |
+
}
|
| 54 |
+
"""
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def analyze_direction(title: str, abstract: str, repos: list[dict] | None = None) -> dict:
|
| 58 |
+
"""ๅบไบ่ฎบๆไฟกๆฏๅ GitHub ๆ็ดข็ปๆ๏ผๅฝ็บณๆนๆณๆ่ฐฑ็ณปใ
|
| 59 |
+
|
| 60 |
+
Args:
|
| 61 |
+
title: ่ฎบๆๆ ้ข
|
| 62 |
+
abstract: ่ฎบๆๆ่ฆ๏ผไผ่ชๅจๆชๆญ๏ผ
|
| 63 |
+
repos: GitHub ๆ็ดข็ปๆๅ่กจ๏ผๆฏไธช dict ๅ
ๅซ full_name, description,
|
| 64 |
+
stars, language, topics, html_urlใๅฆๆไธบ None ๆ็ฉบๅ่กจ๏ผ
|
| 65 |
+
ๅไป
ๅบไบ LLM ่ช่บซ็ฅ่ฏๅๆ๏ผ้็บงๆจกๅผ๏ผใ
|
| 66 |
+
|
| 67 |
+
Returns:
|
| 68 |
+
dict: ๅ
ๅซ subfield, subfield_trend, method_families, broad_queries
|
| 69 |
+
"""
|
| 70 |
+
abstract_truncated = abstract[:2000] if abstract else "๏ผๆ่ฆไธๅฏ็จ๏ผ"
|
| 71 |
+
title_clean = title.strip() if title else "๏ผๆ ้ขไธๅฏ็จ๏ผ"
|
| 72 |
+
|
| 73 |
+
# ๆๅปบไปๅบๅ่กจๆๆฌ
|
| 74 |
+
if repos:
|
| 75 |
+
repo_lines = []
|
| 76 |
+
for r in repos[:20]: # ๆๅคไผ 20 ไธชไปๅบ็ป LLM
|
| 77 |
+
full_name = r.get("full_name", "")
|
| 78 |
+
desc = r.get("description", "")[:100]
|
| 79 |
+
stars = r.get("stars", 0)
|
| 80 |
+
topics = ", ".join(r.get("topics", [])[:5])
|
| 81 |
+
language = r.get("language", "")
|
| 82 |
+
repo_lines.append(
|
| 83 |
+
f"- **{full_name}** (โญ{stars}, {language}) โ {desc}\n"
|
| 84 |
+
f" topics: {topics}"
|
| 85 |
+
)
|
| 86 |
+
repos_text = "\n".join(repo_lines)
|
| 87 |
+
else:
|
| 88 |
+
repos_text = "๏ผๆชๆไพ GitHub ๆ็ดข็ปๆ๏ผ่ฏทๅบไบไฝ ็่ฎญ็ป็ฅ่ฏ่ฟ่กๅๆ๏ผ"
|
| 89 |
+
|
| 90 |
+
user_prompt = f"""## ่ฎบๆไฟกๆฏ
|
| 91 |
+
**ๆ ้ข**: {title_clean}
|
| 92 |
+
|
| 93 |
+
**ๆ่ฆ**: {abstract_truncated}
|
| 94 |
+
|
| 95 |
+
## GitHub ๆ็ดข็ปๆ๏ผๅ
ฑ {len(repos) if repos else 0} ไธชไปๅบ๏ผ
|
| 96 |
+
|
| 97 |
+
{repos_text}
|
| 98 |
+
|
| 99 |
+
่ฏทๅๆไปฅไธ่ฎบๆๅไปๅบๆฐๆฎ๏ผๅฝ็บณๆนๆณๆ่ฐฑ็ณปใ"""
|
| 100 |
+
|
| 101 |
+
raw = call_llm_json(DIRECTION_SYSTEM_PROMPT, user_prompt, temperature=0.4, max_tokens=5000)
|
| 102 |
+
data = parse_json_safe(raw, "direction_analyzer")
|
| 103 |
+
return validate_direction_output(data)
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
# ============================================================
|
| 107 |
+
# ่ชๆต
|
| 108 |
+
# ============================================================
|
| 109 |
+
if __name__ == "__main__":
|
| 110 |
+
fix_windows_encoding()
|
| 111 |
+
|
| 112 |
+
# ๆ้ ๆจกๆ GitHub ๆ็ดข็ปๆ
|
| 113 |
+
mock_repos = [
|
| 114 |
+
{
|
| 115 |
+
"full_name": "openvinotoolkit/anomalib",
|
| 116 |
+
"description": "An anomaly detection library comprising state-of-the-art algorithms.",
|
| 117 |
+
"stars": 4000, "language": "Python",
|
| 118 |
+
"topics": ["anomaly-detection", "pytorch", "benchmarking", "industrial-inspection"],
|
| 119 |
+
"html_url": "https://github.com/openvinotoolkit/anomalib",
|
| 120 |
+
},
|
| 121 |
+
{
|
| 122 |
+
"full_name": "hcw-00/PatchCore",
|
| 123 |
+
"description": "Official implementation of PatchCore: Towards Total Recall in Industrial Anomaly Detection.",
|
| 124 |
+
"stars": 850, "language": "Python",
|
| 125 |
+
"topics": ["anomaly-detection", "memory-bank", "pytorch"],
|
| 126 |
+
"html_url": "https://github.com/hcw-00/PatchCore",
|
| 127 |
+
},
|
| 128 |
+
{
|
| 129 |
+
"full_name": "taikiinoue45/STFPM",
|
| 130 |
+
"description": "Student-Teacher Feature Pyramid Matching for Anomaly Detection (PyTorch).",
|
| 131 |
+
"stars": 320, "language": "Python",
|
| 132 |
+
"topics": ["teacher-student", "anomaly-detection", "pytorch"],
|
| 133 |
+
"html_url": "https://github.com/taikiinoue45/STFPM",
|
| 134 |
+
},
|
| 135 |
+
{
|
| 136 |
+
"full_name": "VitjanZ/DRAEM",
|
| 137 |
+
"description": "DRAEM: Discriminatively trained reconstruction embedding for surface anomaly detection.",
|
| 138 |
+
"stars": 180, "language": "Python",
|
| 139 |
+
"topics": ["synthetic-defect", "anomaly-detection", "reconstruction"],
|
| 140 |
+
"html_url": "https://github.com/VitjanZ/DRAEM",
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"full_name": "marugoto/CFLow",
|
| 144 |
+
"description": "CFLow: Real-time unsupervised anomaly detection via conditional normalizing flows.",
|
| 145 |
+
"stars": 130, "language": "Python",
|
| 146 |
+
"topics": ["normalizing-flow", "anomaly-detection", "pytorch"],
|
| 147 |
+
"html_url": "https://github.com/marugoto/CFLow",
|
| 148 |
+
},
|
| 149 |
+
{
|
| 150 |
+
"full_name": "xiahaifeng1995/PaDiM-Anomaly-Detection",
|
| 151 |
+
"description": "Unofficial implementation of PaDiM: Patch Distribution Modeling for anomaly detection.",
|
| 152 |
+
"stars": 150, "language": "Python",
|
| 153 |
+
"topics": ["padim", "anomaly-detection", "mvtec-ad"],
|
| 154 |
+
"html_url": "https://github.com/xiahaifeng1995/PaDiM-Anomaly-Detection",
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"full_name": "someone/anomaly-detection-tutorial",
|
| 158 |
+
"description": "A tutorial collection of anomaly detection papers and resources.",
|
| 159 |
+
"stars": 45, "language": "Markdown",
|
| 160 |
+
"topics": ["awesome-list", "anomaly-detection"],
|
| 161 |
+
"html_url": "https://github.com/someone/anomaly-detection-tutorial",
|
| 162 |
+
},
|
| 163 |
+
]
|
| 164 |
+
|
| 165 |
+
print("=" * 60)
|
| 166 |
+
print("Agent 1 ๆต่ฏ๏ผๅบไบ GitHub ไปๅบ็ๆนๆณๆๅฝ็บณ")
|
| 167 |
+
print("=" * 60)
|
| 168 |
+
|
| 169 |
+
result = analyze_direction(
|
| 170 |
+
"PaDiM: a Patch Distribution Modeling Framework for Anomaly Detection and Localization",
|
| 171 |
+
"We present a new framework for anomaly detection and localization based on "
|
| 172 |
+
"patch distribution modeling. PaDiM uses pretrained convolutional neural networks "
|
| 173 |
+
"to extract patch features and models their distribution using multivariate "
|
| 174 |
+
"Gaussian distributions.",
|
| 175 |
+
mock_repos,
|
| 176 |
+
)
|
| 177 |
+
|
| 178 |
+
print(f"ๅญ้ขๅ: {result.get('subfield')}")
|
| 179 |
+
print(f"่ถๅฟ: {result.get('subfield_trend')}")
|
| 180 |
+
print(f"ๆนๆณๆๆฐ้: {len(result.get('method_families', []))}")
|
| 181 |
+
for mf in result.get("method_families", []):
|
| 182 |
+
repos_in_family = mf.get("matched_repos", [])
|
| 183 |
+
print(f" - {mf.get('family_name')}: {mf.get('description')[:60]}...")
|
| 184 |
+
print(f" ๅฝๅฑไปๅบ: {repos_in_family}")
|
| 185 |
+
print(f" ๆ็ดข่ฏ: {mf.get('search_queries', [])}")
|
| 186 |
+
print(f"ๅฎฝๆณๆ็ดข่ฏ: {result.get('broad_queries', [])}")
|
| 187 |
+
total_queries = sum(len(mf.get('search_queries', [])) for mf in result.get('method_families', [])) + len(result.get('broad_queries', []))
|
| 188 |
+
print(f"ๆปๆ็ดข่ฏๆฐ: {total_queries}")
|
| 189 |
+
|
| 190 |
+
print()
|
| 191 |
+
print("=" * 60)
|
| 192 |
+
print("Agent 1 ๆต่ฏ๏ผ้็บงๆจกๅผ๏ผๆ GitHub ๆฐๆฎ๏ผ")
|
| 193 |
+
print("=" * 60)
|
| 194 |
+
|
| 195 |
+
result2 = analyze_direction(
|
| 196 |
+
"Attention Is All You Need",
|
| 197 |
+
"The dominant sequence transduction models are based on complex recurrent "
|
| 198 |
+
"or convolutional neural networks...",
|
| 199 |
+
None,
|
| 200 |
+
)
|
| 201 |
+
print(f"ๅญ้ขๅ: {result2.get('subfield')}")
|
| 202 |
+
print(f"ๆนๆณๆ: {[mf.get('family_name') for mf in result2.get('method_families', [])]}")
|
gradio_output.log
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
| 0 |
|
| 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Downloading ngrok ...
|
| 2 |
|
| 3 |
|
| 4 |
+
============================================================
|
| 5 |
+
๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ: https://anvil-wackiness-hazing.ngrok-free.dev
|
| 6 |
+
๏ฟฝฮบ๏ฟฝ๏ฟฝหฟ๏ฟฝ๏ฟฝิด๒ฟชด๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝสน๏ฟฝ๏ฟฝ ResearchRadar
|
| 7 |
+
============================================================
|
| 8 |
+
|
| 9 |
+
* Running on local URL: http://0.0.0.0:7860
|
| 10 |
+
* To create a public link, set `share=True` in `launch()`.
|
llm_utils.py
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# llm_utils.py
|
| 2 |
+
# ============================================================
|
| 3 |
+
# ็ฑปๅ๏ผๅ
ฌๅ
ฑๅทฅๅ
ทๆจกๅ๏ผไน่ด่ดฃ๏ผ
|
| 4 |
+
# ๅ่ฝ๏ผOpenAI ๅฎขๆท็ซฏ้
็ฝฎใJSON ๅฎๅ
จ่งฃๆใLLM ่ฐ็จ้่ฏใ่พๅบๆ ก้ช
|
| 5 |
+
# ่ขซ direction_analyzer.py ๅ repo_evaluator.py ๅ
ฑ็จ
|
| 6 |
+
# ============================================================
|
| 7 |
+
|
| 8 |
+
import json
|
| 9 |
+
import re
|
| 10 |
+
import time
|
| 11 |
+
import sys
|
| 12 |
+
import os
|
| 13 |
+
from openai import OpenAI
|
| 14 |
+
|
| 15 |
+
# ---- ้
็ฝฎ ----
|
| 16 |
+
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "sk-a115c4388d444cf688d323855edb36da")
|
| 17 |
+
DEEPSEEK_BASE_URL = "https://api.deepseek.com"
|
| 18 |
+
MODEL = "deepseek-v4-pro"
|
| 19 |
+
MAX_RETRIES = 3 # API ่ฐ็จๅคฑ่ดฅๆถๆๅค้่ฏๆฌกๆฐ
|
| 20 |
+
RETRY_DELAY = 2.0 # ้่ฏ้ด้๏ผ็ง๏ผ๏ผๆๆฐๅข้ฟ
|
| 21 |
+
|
| 22 |
+
_client = None
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def get_client() -> OpenAI:
|
| 26 |
+
"""่ทๅ OpenAI ๅฎขๆท็ซฏๅไพ"""
|
| 27 |
+
global _client
|
| 28 |
+
if _client is None:
|
| 29 |
+
_client = OpenAI(api_key=DEEPSEEK_API_KEY, base_url=DEEPSEEK_BASE_URL)
|
| 30 |
+
return _client
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# ---- LLM ่ฐ็จ๏ผๅธฆ้่ฏ๏ผ ----
|
| 34 |
+
|
| 35 |
+
def call_llm(
|
| 36 |
+
system_prompt: str,
|
| 37 |
+
user_prompt: str,
|
| 38 |
+
temperature: float = 0.3,
|
| 39 |
+
max_tokens: int = 2000,
|
| 40 |
+
response_format: dict | None = None,
|
| 41 |
+
) -> str:
|
| 42 |
+
"""่ฐ็จ DeepSeek API๏ผ่ชๅจ้่ฏใ
|
| 43 |
+
|
| 44 |
+
Args:
|
| 45 |
+
system_prompt: ็ณป็ปๆ็คบ่ฏ
|
| 46 |
+
user_prompt: ็จๆทๆ็คบ่ฏ
|
| 47 |
+
temperature: ๆธฉๅบฆๅๆฐ
|
| 48 |
+
max_tokens: ๆๅคง่พๅบ token ๆฐ
|
| 49 |
+
response_format: OpenAI ๅ
ผๅฎน็ response_format๏ผๅฆ {"type": "json_object"}
|
| 50 |
+
|
| 51 |
+
Returns:
|
| 52 |
+
LLM ่ฟๅ็ๅๅงๆๆฌ
|
| 53 |
+
|
| 54 |
+
Raises:
|
| 55 |
+
RuntimeError: ้่ฏๆฌกๆฐ็จๅฐฝๅไปๅคฑ่ดฅ
|
| 56 |
+
"""
|
| 57 |
+
client = get_client()
|
| 58 |
+
last_error = None
|
| 59 |
+
|
| 60 |
+
for attempt in range(MAX_RETRIES):
|
| 61 |
+
try:
|
| 62 |
+
kwargs = dict(
|
| 63 |
+
model=MODEL,
|
| 64 |
+
messages=[
|
| 65 |
+
{"role": "system", "content": system_prompt},
|
| 66 |
+
{"role": "user", "content": user_prompt},
|
| 67 |
+
],
|
| 68 |
+
temperature=temperature,
|
| 69 |
+
max_tokens=max_tokens,
|
| 70 |
+
timeout=120.0,
|
| 71 |
+
)
|
| 72 |
+
if response_format is not None:
|
| 73 |
+
kwargs["response_format"] = response_format
|
| 74 |
+
|
| 75 |
+
response = client.chat.completions.create(**kwargs)
|
| 76 |
+
content = response.choices[0].message.content
|
| 77 |
+
if content is None or not content.strip():
|
| 78 |
+
raise ValueError("API ่ฟๅ็ฉบๅ
ๅฎน")
|
| 79 |
+
return content.strip()
|
| 80 |
+
except Exception as e:
|
| 81 |
+
last_error = e
|
| 82 |
+
if attempt < MAX_RETRIES - 1:
|
| 83 |
+
wait = RETRY_DELAY * (2 ** attempt)
|
| 84 |
+
print(f" [้่ฏ {attempt+1}/{MAX_RETRIES}] API ่ฐ็จๅคฑ่ดฅ: {e}๏ผ{wait:.0f}s ๅ้่ฏ...")
|
| 85 |
+
time.sleep(wait)
|
| 86 |
+
|
| 87 |
+
raise RuntimeError(f"LLM API ่ฐ็จๅคฑ่ดฅ๏ผๅทฒ้่ฏ {MAX_RETRIES} ๆฌก๏ผ: {last_error}")
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def call_llm_json(
|
| 91 |
+
system_prompt: str,
|
| 92 |
+
user_prompt: str,
|
| 93 |
+
temperature: float = 0.3,
|
| 94 |
+
max_tokens: int = 2000,
|
| 95 |
+
) -> str:
|
| 96 |
+
"""่ฐ็จ DeepSeek API ๅนถๅผบๅถ JSON ่พๅบๆจกๅผใ
|
| 97 |
+
|
| 98 |
+
่ฟๆฏ call_llm ็ไพฟๆทๅฐ่ฃ
๏ผ่ชๅจ่ฎพ็ฝฎ response_format={"type": "json_object"}ใ
|
| 99 |
+
DeepSeek API ๅจ JSON ๆจกๅผไธไผ็บฆๆ่พๅบไธบๅๆณ JSON๏ผๅคงๅน
ๅๅฐๆ ผๅผๅๅทฎใ
|
| 100 |
+
"""
|
| 101 |
+
return call_llm(
|
| 102 |
+
system_prompt=system_prompt,
|
| 103 |
+
user_prompt=user_prompt,
|
| 104 |
+
temperature=temperature,
|
| 105 |
+
max_tokens=max_tokens,
|
| 106 |
+
response_format={"type": "json_object"},
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
# ---- JSON ๅฎๅ
จ่งฃๆ ----
|
| 111 |
+
|
| 112 |
+
def parse_json_safe(raw: str, module_name: str = "") -> dict:
|
| 113 |
+
"""ๅฎๅ
จ่งฃๆ LLM ่ฟๅ็ JSON๏ผ7 ็ง็ญ็ฅไพๆฌกๅฐ่ฏใ
|
| 114 |
+
|
| 115 |
+
LLM ๅฏ่ฝ่ฟๅ๏ผ
|
| 116 |
+
1. ็บฏ JSON
|
| 117 |
+
2. ```json ... ``` ไปฃ็ ๅๅ
่ฃน
|
| 118 |
+
3. ``` ... ``` ๆ ่ฏญ่จๆ ่ฎฐๅ
่ฃน
|
| 119 |
+
4. ๅธฆๅ็ผๆๅญ + JSON
|
| 120 |
+
5. ๅธฆๅ็ผๆๅญ + JSON
|
| 121 |
+
6. ๅค่กไธญๅคนๆ JSON ๅฏน่ฑก
|
| 122 |
+
7. ๅซๆช่ฝฌไนๆงๅถๅญ็ฌฆ็ JSON
|
| 123 |
+
"""
|
| 124 |
+
# ๅ
จๅฑ้ขๅค็๏ผๆฟๆขๆช่ฝฌไน็ๆงๅถๅญ็ฌฆ๏ผๆข่กใๅถ่กจ็ฌฆ๏ผ
|
| 125 |
+
# JSON ๅญ็ฌฆไธฒๅ
ไธๅ
่ฎธ่ฟไบๅญ็ฌฆ๏ผๆฟๆขไธบ็ฉบๆ ผไธไผๅฝฑๅๅๆณ็ JSON ็ปๆ
|
| 126 |
+
raw = raw.replace('\r\n', ' ').replace('\n', ' ').replace('\r', ' ').replace('\t', ' ')
|
| 127 |
+
|
| 128 |
+
strategies_tried = []
|
| 129 |
+
|
| 130 |
+
# ็ญ็ฅ 1๏ผ็ดๆฅ่งฃๆ
|
| 131 |
+
try:
|
| 132 |
+
return json.loads(raw)
|
| 133 |
+
except json.JSONDecodeError as e:
|
| 134 |
+
strategies_tried.append(f"็ดๆฅ่งฃๆ: {e}")
|
| 135 |
+
|
| 136 |
+
# ็ญ็ฅ 2๏ผๆๅ ```json ... ``` ไปฃ็ ๅ
|
| 137 |
+
match = re.search(r'```json\s*([\s\S]*?)```', raw)
|
| 138 |
+
if match:
|
| 139 |
+
try:
|
| 140 |
+
return json.loads(match.group(1).strip())
|
| 141 |
+
except json.JSONDecodeError:
|
| 142 |
+
pass
|
| 143 |
+
|
| 144 |
+
# ็ญ็ฅ 3๏ผๆๅ ``` ... ``` ไปปๆไปฃ็ ๅ
|
| 145 |
+
match = re.search(r'```\s*([\s\S]*?)```', raw)
|
| 146 |
+
if match:
|
| 147 |
+
try:
|
| 148 |
+
return json.loads(match.group(1).strip())
|
| 149 |
+
except json.JSONDecodeError:
|
| 150 |
+
pass
|
| 151 |
+
|
| 152 |
+
# ็ญ็ฅ 4๏ผๆๅๆๅคๅฑ { ... }
|
| 153 |
+
match = re.search(r'\{[\s\S]*\}', raw)
|
| 154 |
+
if match:
|
| 155 |
+
try:
|
| 156 |
+
return json.loads(match.group(0))
|
| 157 |
+
except json.JSONDecodeError:
|
| 158 |
+
pass
|
| 159 |
+
|
| 160 |
+
# ็ญ็ฅ 5๏ผไฟฎๅคๅธธ่ง JSON ้่ฏฏ๏ผๅฐพ้จ้ๅทใๅๅผๅท๏ผ
|
| 161 |
+
cleaned = raw.strip()
|
| 162 |
+
cleaned = re.sub(r',\s*}', '}', cleaned) # ็งป้คๅฐพ้จ้ๅท
|
| 163 |
+
cleaned = re.sub(r',\s*]', ']', cleaned) # ็งป้คๆฐ็ปๅฐพ้จ้ๅท
|
| 164 |
+
try:
|
| 165 |
+
return json.loads(cleaned)
|
| 166 |
+
except json.JSONDecodeError:
|
| 167 |
+
pass
|
| 168 |
+
|
| 169 |
+
# ็ญ็ฅ 6๏ผๅฐ่ฏๆพๅ
ๅซ "subfield" ๆ "score" ็ { ... }
|
| 170 |
+
for keyword in ["subfield", "overall_score", "score"]:
|
| 171 |
+
pattern = r'\{[^{}]*"' + keyword + r'"[^{}]*\{[^{}]*\}[^{}]*\}|\{[^{}]*"' + keyword + r'"[^{}]*\}'
|
| 172 |
+
match = re.search(pattern, raw)
|
| 173 |
+
if match:
|
| 174 |
+
try:
|
| 175 |
+
return json.loads(match.group(0))
|
| 176 |
+
except json.JSONDecodeError:
|
| 177 |
+
pass
|
| 178 |
+
|
| 179 |
+
# ๅ
จ้จๅคฑ่ดฅ
|
| 180 |
+
module_tag = f"[{module_name}] " if module_name else ""
|
| 181 |
+
raise ValueError(
|
| 182 |
+
f"{module_tag}ๆ ๆณ่งฃๆ LLM ่ฟๅ็ JSONใ\n"
|
| 183 |
+
f"ๅๅง่ฟๅ๏ผๅ 500 ๅญ็ฌฆ๏ผ:\n{raw[:500]}"
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
# ---- ่พๅบๆ ก้ช ----
|
| 188 |
+
|
| 189 |
+
def validate_direction_output(data: dict) -> dict:
|
| 190 |
+
"""ๆ ก้ช direction_analyzer ็่พๅบ๏ผๅกซๅ
็ผบๅคฑๅญๆฎตไธบ้ป่ฎคๅผใ"""
|
| 191 |
+
if not isinstance(data, dict):
|
| 192 |
+
raise ValueError(f"direction_analyzer ่พๅบไธๆฏ dict๏ผ่ๆฏ {type(data).__name__}")
|
| 193 |
+
|
| 194 |
+
# ็กฎไฟ method_families ๆฏ list
|
| 195 |
+
families = data.get("method_families", [])
|
| 196 |
+
if not isinstance(families, list):
|
| 197 |
+
families = []
|
| 198 |
+
|
| 199 |
+
# ๆ ก้ชๆฏไธชๆนๆณๆ
|
| 200 |
+
validated_families = []
|
| 201 |
+
for mf in families:
|
| 202 |
+
if not isinstance(mf, dict):
|
| 203 |
+
continue
|
| 204 |
+
validated_families.append({
|
| 205 |
+
"family_name": mf.get("family_name", "ๆชๅฝๅๆนๆณๆ"),
|
| 206 |
+
"description": mf.get("description", ""),
|
| 207 |
+
"representative_work": mf.get("representative_work", ""),
|
| 208 |
+
"search_queries": mf.get("search_queries", []) if isinstance(mf.get("search_queries"), list) else [],
|
| 209 |
+
"matched_repos": mf.get("matched_repos", []) if isinstance(mf.get("matched_repos"), list) else [],
|
| 210 |
+
})
|
| 211 |
+
|
| 212 |
+
# ็กฎไฟ broad_queries ๆฏ list
|
| 213 |
+
broad_queries = data.get("broad_queries", [])
|
| 214 |
+
if not isinstance(broad_queries, list):
|
| 215 |
+
broad_queries = []
|
| 216 |
+
|
| 217 |
+
return {
|
| 218 |
+
"subfield": data.get("subfield", "ๆช็ฅๅญ้ขๅ"),
|
| 219 |
+
"subfield_trend": data.get("subfield_trend", "ๆๆ ่ถๅฟๅๆ"),
|
| 220 |
+
"method_families": validated_families,
|
| 221 |
+
"broad_queries": broad_queries,
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def validate_eval_output(data: dict) -> dict:
|
| 226 |
+
"""ๆ ก้ช repo_evaluator ็่พๅบ๏ผๅกซๅ
็ผบๅคฑๅญๆฎตไธบ้ป่ฎคๅผใ"""
|
| 227 |
+
if not isinstance(data, dict):
|
| 228 |
+
raise ValueError(f"repo_evaluator ่พๅบไธๆฏ dict๏ผ่ๆฏ {type(data).__name__}")
|
| 229 |
+
|
| 230 |
+
# ๆฐๅผๅญๆฎต้ป่ฎค 0
|
| 231 |
+
int_fields = [
|
| 232 |
+
"reproducibility_score", "benchmark_fitness_score", "overall_score",
|
| 233 |
+
"env_score", "doc_score", "code_score", "community_score", "dep_score",
|
| 234 |
+
"benchmark_score",
|
| 235 |
+
]
|
| 236 |
+
for field in int_fields:
|
| 237 |
+
if field not in data or not isinstance(data[field], (int, float)):
|
| 238 |
+
data[field] = 0
|
| 239 |
+
else:
|
| 240 |
+
data[field] = int(data[field])
|
| 241 |
+
|
| 242 |
+
# ๅญ็ฌฆไธฒๅญๆฎต
|
| 243 |
+
data.setdefault("verdict", "error")
|
| 244 |
+
data.setdefault("reasoning", "่ฏไผฐๆช่ฟๅๅๆ")
|
| 245 |
+
data.setdefault("benchmark_readiness", "not_ready")
|
| 246 |
+
data.setdefault("suggested_use", "่ฏทๆๅจ่ฏไผฐ่ฏฅไปๅบ")
|
| 247 |
+
|
| 248 |
+
# ๅ่กจๅญๆฎต
|
| 249 |
+
if "risks" not in data or not isinstance(data["risks"], list):
|
| 250 |
+
data["risks"] = []
|
| 251 |
+
|
| 252 |
+
return data
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
# ---- Windows ็ป็ซฏ็ผ็ ----
|
| 256 |
+
|
| 257 |
+
def fix_windows_encoding():
|
| 258 |
+
"""ไฟฎๅค Windows ็ป็ซฏไธญๆๆพ็คบไนฑ็ ้ฎ้ข"""
|
| 259 |
+
if sys.platform == "win32":
|
| 260 |
+
try:
|
| 261 |
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
| 262 |
+
except Exception:
|
| 263 |
+
pass
|
paper_fetcher.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import urllib.request
|
| 2 |
+
import urllib.error
|
| 3 |
+
import xml.etree.ElementTree as ET
|
| 4 |
+
import re
|
| 5 |
+
import time
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def extract_arxiv_id(url: str) -> str:
|
| 9 |
+
"""ไป arxiv URL ๆๅ่ฎบๆ ID
|
| 10 |
+
|
| 11 |
+
ๆฏๆๆ ผๅผ:
|
| 12 |
+
- https://arxiv.org/abs/1706.03762
|
| 13 |
+
- https://arxiv.org/abs/1706.03762v2
|
| 14 |
+
- https://arxiv.org/pdf/1706.03762.pdf
|
| 15 |
+
- arxiv:1706.03762
|
| 16 |
+
- 1706.03762
|
| 17 |
+
"""
|
| 18 |
+
match = re.search(r'arxiv\.org/(?:abs|pdf)/(\d{4}\.\d{4,5})(?:v\d+)?(?:\.pdf)?', url)
|
| 19 |
+
if match:
|
| 20 |
+
return match.group(1)
|
| 21 |
+
match = re.search(r'(?:arxiv:)?(\d{4}\.\d{4,5})', url)
|
| 22 |
+
if match:
|
| 23 |
+
return match.group(1)
|
| 24 |
+
raise ValueError(f"ๆ ๆณไป URL ๆๅ arxiv ID: {url}")
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def fetch_paper_info(arxiv_url: str) -> dict:
|
| 28 |
+
"""ไป arxiv ่ทๅ่ฎบๆๅ
ไฟกๆฏ
|
| 29 |
+
|
| 30 |
+
Returns:
|
| 31 |
+
dict: {
|
| 32 |
+
"arxiv_id": str, "title": str, "abstract": str,
|
| 33 |
+
"authors": [str, ...], "categories": [str, ...], "published": str
|
| 34 |
+
}
|
| 35 |
+
"""
|
| 36 |
+
arxiv_id = extract_arxiv_id(arxiv_url)
|
| 37 |
+
api_url = f"http://export.arxiv.org/api/query?id_list={arxiv_id}&max_results=1"
|
| 38 |
+
|
| 39 |
+
req = urllib.request.Request(api_url, headers={"User-Agent": "ResearchRadar/1.0"})
|
| 40 |
+
|
| 41 |
+
last_error = None
|
| 42 |
+
for attempt in range(3):
|
| 43 |
+
try:
|
| 44 |
+
with urllib.request.urlopen(req, timeout=30) as resp:
|
| 45 |
+
xml_text = resp.read().decode("utf-8")
|
| 46 |
+
break
|
| 47 |
+
except urllib.error.HTTPError as e:
|
| 48 |
+
last_error = e
|
| 49 |
+
if e.code in (429, 503) and attempt < 2:
|
| 50 |
+
wait = 5 * (2 ** attempt)
|
| 51 |
+
print(f" arxiv API ้้๏ผ{wait}s ๅ้่ฏ...")
|
| 52 |
+
time.sleep(wait)
|
| 53 |
+
continue
|
| 54 |
+
raise RuntimeError(f"arxiv API ่ฏทๆฑๅคฑ่ดฅ (HTTP {e.code})๏ผ่ฏทๆฃๆฅ่ฎบๆ ID ๆฏๅฆๆญฃ็กฎ")
|
| 55 |
+
except urllib.error.URLError as e:
|
| 56 |
+
last_error = e
|
| 57 |
+
if attempt < 2:
|
| 58 |
+
wait = 3 * (2 ** attempt)
|
| 59 |
+
print(f" ็ฝ็ป้่ฏฏ๏ผ{wait}s ๅ้่ฏ: {e.reason}")
|
| 60 |
+
time.sleep(wait)
|
| 61 |
+
continue
|
| 62 |
+
raise RuntimeError(f"ๆ ๆณ่ฟๆฅ arxiv API๏ผ่ฏทๆฃๆฅ็ฝ็ป: {e.reason}")
|
| 63 |
+
else:
|
| 64 |
+
raise RuntimeError(f"arxiv API ่ฏทๆฑๅคฑ่ดฅ (HTTP {getattr(last_error, 'code', '?')})๏ผ้่ฏ 3 ๆฌกไปๅคฑ่ดฅ")
|
| 65 |
+
|
| 66 |
+
root = ET.fromstring(xml_text)
|
| 67 |
+
ns = {
|
| 68 |
+
"atom": "http://www.w3.org/2005/Atom",
|
| 69 |
+
"arxiv": "http://arxiv.org/schemas/atom",
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
entry = root.find("atom:entry", ns)
|
| 73 |
+
if entry is None:
|
| 74 |
+
raise ValueError(f"arxiv ๆชๆพๅฐ่ฎบๆ {arxiv_id}๏ผ่ฏทๆฃๆฅ ID ๆฏๅฆๆญฃ็กฎ")
|
| 75 |
+
|
| 76 |
+
title_el = entry.find("atom:title", ns)
|
| 77 |
+
summary_el = entry.find("atom:summary", ns)
|
| 78 |
+
title = title_el.text.strip().replace("\n", " ") if title_el is not None and title_el.text else ""
|
| 79 |
+
abstract = summary_el.text.strip().replace("\n", " ") if summary_el is not None and summary_el.text else ""
|
| 80 |
+
|
| 81 |
+
authors = [
|
| 82 |
+
a.find("atom:name", ns).text
|
| 83 |
+
for a in entry.findall("atom:author", ns)
|
| 84 |
+
if a.find("atom:name", ns) is not None
|
| 85 |
+
]
|
| 86 |
+
categories = [
|
| 87 |
+
c.get("term", "") for c in entry.findall("atom:category", ns)
|
| 88 |
+
]
|
| 89 |
+
published_el = entry.find("atom:published", ns)
|
| 90 |
+
published = published_el.text if published_el is not None and published_el.text else ""
|
| 91 |
+
|
| 92 |
+
return {
|
| 93 |
+
"arxiv_id": arxiv_id,
|
| 94 |
+
"title": title,
|
| 95 |
+
"abstract": abstract,
|
| 96 |
+
"authors": authors,
|
| 97 |
+
"categories": categories,
|
| 98 |
+
"published": published,
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
if __name__ == "__main__":
|
| 103 |
+
# ่ชๆต๏ผ็จ PaDiM ่ฎบๆๆต่ฏ
|
| 104 |
+
test_url = "https://arxiv.org/abs/2011.08785"
|
| 105 |
+
paper = fetch_paper_info(test_url)
|
| 106 |
+
print("=== paper_fetcher ่ชๆต ===")
|
| 107 |
+
for k, v in paper.items():
|
| 108 |
+
val = str(v)
|
| 109 |
+
if len(val) > 120:
|
| 110 |
+
val = val[:120] + "..."
|
| 111 |
+
print(f" {k}: {val}")
|
| 112 |
+
print(" ๆๆๅฟ
้ๅญๆฎต:",
|
| 113 |
+
all(k in paper for k in ["arxiv_id", "title", "abstract", "authors"]))
|
repo_evaluator.py
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# repo_evaluator.py
|
| 2 |
+
# ============================================================
|
| 3 |
+
# ็ฑปๅ๏ผAGENT๏ผไน่ด่ดฃ๏ผ
|
| 4 |
+
# ๅ่ฝ๏ผLLM ๅ
ญ็ปดๅบฆ่ฏๅ๏ผๅฏๅค็ฐๆง 5 ็ปด + ๅฏนๆฏๅฎ้ช้้
ๅบฆ 1 ็ปด๏ผ
|
| 5 |
+
# ็จๆณ๏ผpython repo_evaluator.py๏ผ่ชๆต๏ผ
|
| 6 |
+
# ============================================================
|
| 7 |
+
from llm_utils import call_llm_json, parse_json_safe, validate_eval_output, fix_windows_encoding
|
| 8 |
+
|
| 9 |
+
EVAL_SYSTEM_PROMPT = """ไฝ ๆฏไธไธช AI ่ฎบๆไปฃ็ ่ฏไผฐไธๅฎถใไฝ ้่ฆๅๆถ่ฏไผฐไธไธช GitHub ไปๅบ็ไธคไธชๆน้ข๏ผ
|
| 10 |
+
- **ๅฏๅค็ฐๆง**๏ผ่ฟไธชไปๅบ็ไปฃ็ ่ฝไธ่ฝ่ขซไปไบบๆๅ่ท้๏ผ
|
| 11 |
+
- **ๅฏนๆฏๅฎ้ช้้
ๅบฆ**๏ผ่ฟไธชไปๅบ้ไธ้ๅ็ดๆฅๆฟๆฅๅ่ฎบๆๅๅฏนๆฏๅฎ้ช๏ผbaseline / comparison๏ผ๏ผ
|
| 12 |
+
|
| 13 |
+
## ่ฏไผฐๆกๆถ๏ผๅ
ญ็ปดๅบฆ๏ผๆปๅ 100๏ผ
|
| 14 |
+
|
| 15 |
+
### ๅฏๅค็ฐๆง๏ผไบ็ปดๅบฆ๏ผๅ่ฎก 80 ๅ๏ผ
|
| 16 |
+
|
| 17 |
+
1. **็ฏๅข้
็ฝฎๅฎๆดๆง๏ผ0-15 ๅ๏ผ**
|
| 18 |
+
- 15 ๅ๏ผๆไพไบ requirements.txt / environment.yml๏ผๆๆไพ่ต็ๆฌๅทๆ็กฎ
|
| 19 |
+
- 8-14 ๅ๏ผๆไพ่ตๆไปถไฝ้จๅ็ๆฌๅทไฝฟ็จ่ๅด๏ผ>=, ~=๏ผๆ็ผบๅคฑ
|
| 20 |
+
- 0-7 ๅ๏ผๆฒกๆไพ่ตๆไปถๆไธฅ้ไธๅฎๆด
|
| 21 |
+
|
| 22 |
+
2. **ๆๆกฃ่ดจ้๏ผ0-20 ๅ๏ผ**
|
| 23 |
+
- 16-20 ๅ๏ผๆๆธ
ๆฐ็ๅฎ่ฃ
ๆญฅ้ชคใ่ฎญ็ปๅฝไปคใๆจ็ๅฝไปคใๆฐๆฎ้่ทๅๆนๅผ
|
| 24 |
+
- 8-15 ๅ๏ผๆๅบๆฌ่ฏดๆไฝๅ
ณ้ฎๆญฅ้ชค็ผบๅคฑ๏ผๅฆๆฒก่ฏดๆฐๆฎ้ๅจๅชไธ่ฝฝ๏ผ
|
| 25 |
+
- 0-7 ๅ๏ผREADME ๅชๆ้กน็ฎ็ฎไป๏ผๆฒกๆๅฏๆง่กๅฝไปค
|
| 26 |
+
|
| 27 |
+
3. **ไปฃ็ ๅฏ็จๆง๏ผ0-20 ๅ๏ผ**
|
| 28 |
+
- 16-20 ๅ๏ผ่ฎญ็ป่ๆฌ + ๆจ็่ๆฌ + ้
็ฝฎๆไปถ + ๆจกๅๅฎไนๅ
ฅๅฃๅฎๆด
|
| 29 |
+
- 8-15 ๅ๏ผๆๆ ธๅฟไปฃ็ ไฝ็ผบๅฐๅ
ณ้ฎ็ปไปถ๏ผๅฆๅชๆๆจ็ๆฒกๆ่ฎญ็ป๏ผ
|
| 30 |
+
- 0-7 ๅ๏ผไปฃ็ ๆฎ็ผบ๏ผๅชๆ้ชจๆถๆ shell ่ๆฌ
|
| 31 |
+
|
| 32 |
+
4. **็คพๅบๆดป่ทๅบฆ๏ผ0-10 ๅ๏ผ**
|
| 33 |
+
- 8-10 ๅ๏ผStar > 500๏ผๆ่ฟๅๅนดๆ commit๏ผIssue ๆไบบๅๅค
|
| 34 |
+
- 4-7 ๅ๏ผๆไธๅฎๅ
ณๆณจๅบฆไฝๆดๆฐไธ้ข็น
|
| 35 |
+
- 0-3 ๅ๏ผ้ฟๆไธๆดๆฐ๏ผStar < 10
|
| 36 |
+
|
| 37 |
+
5. **ไพ่ตๅฅๅบทๅบฆ๏ผ0-15 ๅ๏ผ**
|
| 38 |
+
- 12-15 ๅ๏ผไพ่ตๅ
จๆฏไธปๆตๆดป่ทๅ
๏ผ็ๆฌ็ธไบๅ
ผๅฎน
|
| 39 |
+
- 6-11 ๅ๏ผๆๅฐ้่ฟๆถไพ่ตไฝไธๅฝฑๅๅฎ่ฃ
|
| 40 |
+
- 0-5 ๅ๏ผไพ่ตๆถๅๅทฒๅๆญข็ปดๆค็ๅ
๏ผๅฆ TensorFlow 1.xใPython 2๏ผ๏ผๅทฒ็ฅๆ ๆณๅจ็ฐไปฃ็ฏๅขๅฎ่ฃ
|
| 41 |
+
|
| 42 |
+
### ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผไธ็ปดๅบฆ๏ผ20 ๅ๏ผ
|
| 43 |
+
|
| 44 |
+
6. **ๅฏนๆฏๅฎ้ช้้
ๅบฆ๏ผ0-20 ๅ๏ผ**
|
| 45 |
+
- 16-20 ๅ๏ผๆไพๆ ๅ benchmark ่ฏไผฐ่ๆฌ + ้ข่ฎญ็ปๆ้ไธ่ฝฝ + ๅ
ฌๅผๆฐๆฎ้ๆฏๆ๏ผๅฏ็ดๆฅ่ทๅบ่ฎบๆๅธธ็จๆๆ ๏ผๅฏไปฅๆ ็ผๆๅ
ฅ่ฎบๆ็ Experiment section
|
| 46 |
+
- 10-15 ๅ๏ผๆ่ฎญ็ป่ๆฌๅ่ฏไผฐไปฃ็ ๏ผไฝ้่ฆ่ชๅทฑๅๅคๆฐๆฎๆ้้
ๆฐๆฎ้ๆ ผๅผ
|
| 47 |
+
- 0-9 ๅ๏ผๅชๆๆจ็ demoใไฝฟ็จ็งๆๆฐๆฎ้ใๆฒกๆๆ ๅๅ่ฏไผฐๆต็จใๆๆฒกๆ้ข่ฎญ็ปๆ้
|
| 48 |
+
|
| 49 |
+
## Few-Shot ่ฏๅ้ๅฎ็คบไพ
|
| 50 |
+
|
| 51 |
+
### ็คบไพ 1๏ผ้ซ่ดจ้ไปๅบ๏ผๅฆ anomalib๏ผ
|
| 52 |
+
- ไปๅบ: openvinotoolkit/anomalib, 4000 Stars, 2026ๅนดๆดๆฐ
|
| 53 |
+
- README ๅซ่ฏฆ็ปๅฎ่ฃ
ๆญฅ้ชคใ่ฎญ็ปๅฝไปคใๆฐๆฎ้ๅ่กจ
|
| 54 |
+
- ไพ่ต: requirements.txt ๅซ torch>=1.10, pytorch-lightning>=1.7, opencv-python
|
| 55 |
+
- ๆๆ ๅๅ benchmark ่ๆฌ tools/benchmark.py๏ผๆฏๆ MVTec AD ็ญๆ ๅๆฐๆฎ้
|
| 56 |
+
|
| 57 |
+
ๆญฃ็กฎ่ฏๅ JSON๏ผ
|
| 58 |
+
{
|
| 59 |
+
"reproducibility_score": 75,
|
| 60 |
+
"benchmark_fitness_score": 18,
|
| 61 |
+
"overall_score": 93,
|
| 62 |
+
"verdict": "reproducible",
|
| 63 |
+
"env_score": 14,
|
| 64 |
+
"doc_score": 18,
|
| 65 |
+
"code_score": 18,
|
| 66 |
+
"community_score": 10,
|
| 67 |
+
"dep_score": 15,
|
| 68 |
+
"benchmark_score": 18,
|
| 69 |
+
"reasoning": "่ฏฅไปๅบ็ฑปไผผanomalib็บงๅซ๏ผๆๆกฃๅฎๅๆๅฎ่ฃ
/่ฎญ็ป/ๆฐๆฎ่ฏดๆ๏ผไพ่ตๆไปถๅฎๆดไธไฝฟ็จไธปๆตๆดป่ทๅ
๏ผ็คพๅบๆดป่ท๏ผ4000+ Stars๏ผ๏ผๆไพๆ ๅๅbenchmark่ๆฌๅ้ข่ฎญ็ปๆ้๏ผๅฏ็ดๆฅ่ทๅบ่ฎบๆๅธธ็จๆๆ ใๅฏๅค็ฐๆง้ซ๏ผๅฎ่ฃ
ๅฐ่ฎญ็ปๆต็จๆธ
ๆฐ๏ผ๏ผ้้
ๅบฆ้ซ๏ผbenchmarkๅฏ็ดๆฅ็จไบๅฏนๆฏๅฎ้ช๏ผใ",
|
| 70 |
+
"risks": ["้จๅไพ่ต็ๆฌๅทไฝฟ็จ>=่ๅด๏ผๅฏ่ฝๅญๅจbreaking change้ฃ้ฉ"],
|
| 71 |
+
"benchmark_readiness": "ready",
|
| 72 |
+
"suggested_use": "ๅฏไปฅ็ดๆฅไฝไธบๅฏนๆฏๅฎ้ช baseline"
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
### ็คบไพ 2๏ผไฝ่ดจ้ไปๅบ๏ผไป
ๆจ็ demo๏ผ
|
| 76 |
+
- ไปๅบ: someone/anomaly-demo, 15 Stars, 2024ๅนดๆดๆฐ
|
| 77 |
+
- README ๅชๆ: "A simple demo. python demo.py --image path/to/image.jpg. Pretrained weights: Google Drive link"
|
| 78 |
+
- ๆ ไพ่ตๆไปถ
|
| 79 |
+
- ไป
ๆๆจ็่ๆฌ๏ผๆ ่ฎญ็ปไปฃ็ ใๆ ่ฏไผฐ่ๆฌ
|
| 80 |
+
|
| 81 |
+
ๆญฃ็กฎ่ฏๅ JSON๏ผ
|
| 82 |
+
{
|
| 83 |
+
"reproducibility_score": 15,
|
| 84 |
+
"benchmark_fitness_score": 3,
|
| 85 |
+
"overall_score": 18,
|
| 86 |
+
"verdict": "not_reproducible",
|
| 87 |
+
"env_score": 2,
|
| 88 |
+
"doc_score": 4,
|
| 89 |
+
"code_score": 4,
|
| 90 |
+
"community_score": 2,
|
| 91 |
+
"dep_score": 3,
|
| 92 |
+
"benchmark_score": 3,
|
| 93 |
+
"reasoning": "ๅฏๅค็ฐๆงๆไฝ๏ผๆ ไพ่ตๆไปถๆ ๆณๅค็ฐ็ฏๅข๏ผๆๆกฃไป
ๆๅ่กๅฝไปค๏ผ้ข่ฎญ็ปๆ้้พๆฅๅฏ่ฝๅคฑๆใ้้
ๅบฆๆไฝ๏ผไป
ๆๆจ็demo๏ผๆ ่ฎญ็ป่ๆฌ๏ผๆ ๆ ๅ่ฏไผฐๆต็จ๏ผๆ ๆณ็ดๆฅ็จไบๅฏนๆฏๅฎ้ชใ",
|
| 94 |
+
"risks": ["ๆ ไพ่ตๆไปถ", "้ข่ฎญ็ปๆ้ๆฅ่ชGoogle Drive้พๆฅๅฏ่ฝๅคฑๆ", "ๆ ่ฎญ็ปไปฃ็ "],
|
| 95 |
+
"benchmark_readiness": "not_ready",
|
| 96 |
+
"suggested_use": "ไป
้ๅๅ่ไปฃ็ ๅฎ็ฐ๏ผไธ้ๅ็ดๆฅ่ทๅฏนๆฏๅฎ้ช"
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
## ้่ฆๆ้
|
| 100 |
+
- ๅฏๅค็ฐๆงๅ้้
ๅบฆๆฏไธคไธช็ฌ็ซ็็ปดๅบฆ๏ผๅฟ
้กปๅๅผๅคๆญ
|
| 101 |
+
- ไพๅฆ๏ผไธไธชไปๅบๅฏไปฅ README ๅพ๏ฟฝ๏ฟฝๅ๏ผๆๆกฃ 20 ๅ๏ผไฝๅชๆไพๆจ็ demo ๆฒกๆ่ฎญ็ป๏ผ้้
ๅบฆ 5 ๅ๏ผ
|
| 102 |
+
- ๅๅฆ๏ผanomalib ๅจๅฏๅค็ฐๆง๏ผๆๆกฃๅฅฝใๆ requirements.txt๏ผๅ้้
ๅบฆ๏ผๆ benchmark ่ๆฌใๆ้ข่ฎญ็ปๆ้๏ผ้ฝๅพ้ซ
|
| 103 |
+
|
| 104 |
+
## ่พๅบๆ ผๅผ๏ผไธฅๆ ผ JSON๏ผ็ดงๅๆ ผๅผไธ่ฆ็ผฉ่ฟๅๅคไฝ็ฉบๆ ผ๏ผ
|
| 105 |
+
{
|
| 106 |
+
"reproducibility_score": 80,
|
| 107 |
+
"benchmark_fitness_score": 20,
|
| 108 |
+
"overall_score": 100,
|
| 109 |
+
"verdict": "reproducible",
|
| 110 |
+
"env_score": 15,
|
| 111 |
+
"doc_score": 20,
|
| 112 |
+
"code_score": 20,
|
| 113 |
+
"community_score": 10,
|
| 114 |
+
"dep_score": 15,
|
| 115 |
+
"benchmark_score": 20,
|
| 116 |
+
"reasoning": "200ๅญไปฅๅ
็ไธญๆๅๆ๏ผๅฟ
้กปๅบๅ'่ฝไธ่ฝ่ท'ๅ'้ไธ้ๅ่ทๅฏนๆฏๅฎ้ช'ไธคไธชๅฑ้ข",
|
| 117 |
+
"risks": ["้ฃ้ฉ1", "้ฃ้ฉ2"],
|
| 118 |
+
"benchmark_readiness": "ready",
|
| 119 |
+
"suggested_use": "ๅฏไปฅ็ดๆฅไฝไธบๅฏนๆฏๅฎ้ช baseline"
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
## ๅคๅฎ่งๅ
|
| 123 |
+
- overall_score >= 70 โ verdict = "reproducible"
|
| 124 |
+
- 40 <= overall_score < 70 โ verdict = "partially"
|
| 125 |
+
- overall_score < 40 โ verdict = "not_reproducible"
|
| 126 |
+
|
| 127 |
+
- benchmark_score >= 16 โ benchmark_readiness = "ready"
|
| 128 |
+
- 10 <= benchmark_score < 16 โ benchmark_readiness = "partial"
|
| 129 |
+
- benchmark_score < 10 โ benchmark_readiness = "not_ready"
|
| 130 |
+
|
| 131 |
+
## benchmark_readiness ไธ suggested_use ็ๅฏนๅบๅ
ณ็ณป
|
| 132 |
+
- "ready" โ "ๅฏไปฅ็ดๆฅไฝไธบๅฏนๆฏๅฎ้ช baseline"
|
| 133 |
+
- "partial" โ "้่ฆๅฐ้ไฟฎๆนๅๅฏ็จไบๅฏนๆฏๅฎ้ช"
|
| 134 |
+
- "not_ready" โ "ไป
้ๅๅ่ไปฃ็ ๅฎ็ฐ๏ผไธ้ๅ็ดๆฅ่ทๅฏนๆฏๅฎ้ช"
|
| 135 |
+
"""
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def evaluate_repo(
|
| 139 |
+
repo: dict,
|
| 140 |
+
readme: str | None,
|
| 141 |
+
dependencies: dict[str, str],
|
| 142 |
+
method_family: str = "",
|
| 143 |
+
) -> dict:
|
| 144 |
+
"""่ฏไผฐๅไธชไปๅบ็ๅฏๅค็ฐๆงๅๅฏนๆฏๅฎ้ช้้
ๅบฆใ
|
| 145 |
+
|
| 146 |
+
Args:
|
| 147 |
+
repo: ไปๅบๅ
ไฟกๆฏ dict๏ผๅ
ๅซ full_name, html_url, stars ็ญ
|
| 148 |
+
readme: README ๆไปถๅ
จๆ๏ผๆ None๏ผ
|
| 149 |
+
dependencies: {ๆไปถๅ: ๆไปถๅ
ๅฎน} ็ dict
|
| 150 |
+
method_family: ่ฏฅไปๅบๆๅฑ็ๆนๆณๆๅ็งฐ๏ผ็ฉบๅญ็ฌฆไธฒ่กจ็คบๆชๅฝ็ฑป๏ผ
|
| 151 |
+
|
| 152 |
+
Returns:
|
| 153 |
+
dict: ๅ
ญ็ปดๅบฆ่ฏๅ็ปๆ
|
| 154 |
+
"""
|
| 155 |
+
readme_text = (readme or "README ๆชๆพๅฐ")[:2500]
|
| 156 |
+
|
| 157 |
+
if dependencies:
|
| 158 |
+
deps_parts = []
|
| 159 |
+
for fname, content in dependencies.items():
|
| 160 |
+
truncated = content[:1000] if content else "(็ฉบๆไปถ)"
|
| 161 |
+
deps_parts.append(f"### {fname}\n```\n{truncated}\n```")
|
| 162 |
+
deps_text = "\n\n".join(deps_parts)
|
| 163 |
+
else:
|
| 164 |
+
deps_text = "ๆชๆพๅฐไปปไฝไพ่ตๆไปถ๏ผrequirements.txt / environment.yml ็ญ๏ผ"
|
| 165 |
+
|
| 166 |
+
family_hint = f"\n- ๆนๆณๆ: {method_family}" if method_family else ""
|
| 167 |
+
|
| 168 |
+
user_prompt = f"""## ไปๅบๅบๆฌไฟกๆฏ
|
| 169 |
+
- ๅ็งฐ: {repo.get('full_name', 'ๆช็ฅ')}
|
| 170 |
+
- URL: {repo.get('html_url', '')}
|
| 171 |
+
- Stars: {repo.get('stars', 0)}
|
| 172 |
+
- ๆ่ฟฐ: {repo.get('description', 'ๆ ๆ่ฟฐ')}
|
| 173 |
+
- ๆๅๆดๆฐ: {repo.get('updated_at', 'ๆช็ฅ')}
|
| 174 |
+
- ไธป่ฆ่ฏญ่จ: {repo.get('language', 'ๆช็ฅ')}{family_hint}
|
| 175 |
+
|
| 176 |
+
## README ๅ
ๅฎน
|
| 177 |
+
{readme_text}
|
| 178 |
+
|
| 179 |
+
## ไพ่ตๆไปถ
|
| 180 |
+
{deps_text}
|
| 181 |
+
|
| 182 |
+
่ฏท่ฏไผฐ่ฏฅไปๅบ็ๅฏๅค็ฐๆงๅๅฏนๆฏๅฎ้ช้้
ๅบฆใ"""
|
| 183 |
+
|
| 184 |
+
raw = call_llm_json(EVAL_SYSTEM_PROMPT, user_prompt, temperature=0.3, max_tokens=4000)
|
| 185 |
+
data = parse_json_safe(raw, "repo_evaluator")
|
| 186 |
+
return validate_eval_output(data)
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
# ============================================================
|
| 190 |
+
# ่ชๆต
|
| 191 |
+
# ============================================================
|
| 192 |
+
if __name__ == "__main__":
|
| 193 |
+
fix_windows_encoding()
|
| 194 |
+
|
| 195 |
+
# ๆต่ฏ 1๏ผanomalib๏ผๅทฅไธ็ผบ้ทๆฃๆตๆๆ้กน็ฎ๏ผ้ขๆ้ซๅ๏ผ
|
| 196 |
+
print("=" * 60)
|
| 197 |
+
print("ๆต่ฏ 1๏ผOpenVINO anomalib๏ผ้ขๆ๏ผๅฏๅค็ฐๆง้ซ + ้้
ๅบฆ้ซ๏ผ")
|
| 198 |
+
print("=" * 60)
|
| 199 |
+
mock_repo = {
|
| 200 |
+
"full_name": "openvinotoolkit/anomalib",
|
| 201 |
+
"html_url": "https://github.com/openvinotoolkit/anomalib",
|
| 202 |
+
"stars": 4000,
|
| 203 |
+
"description": "An anomaly detection library comprising state-of-the-art algorithms and features such as experiment management, hyper-parameter optimization, and edge inference.",
|
| 204 |
+
"updated_at": "2026-01-15T00:00:00Z",
|
| 205 |
+
"language": "Python",
|
| 206 |
+
}
|
| 207 |
+
mock_readme = """# Anomalib
|
| 208 |
+
A library for benchmarking, developing and deploying deep learning based anomaly detection algorithms.
|
| 209 |
+
|
| 210 |
+
## Installation
|
| 211 |
+
```
|
| 212 |
+
pip install anomalib
|
| 213 |
+
```
|
| 214 |
+
|
| 215 |
+
## Training
|
| 216 |
+
```python
|
| 217 |
+
from anomalib.engine import Engine
|
| 218 |
+
engine = Engine()
|
| 219 |
+
engine.train()
|
| 220 |
+
```
|
| 221 |
+
|
| 222 |
+
## Supported Datasets
|
| 223 |
+
- MVTec AD
|
| 224 |
+
- BTAD
|
| 225 |
+
- KSDD2
|
| 226 |
+
|
| 227 |
+
## Benchmarking
|
| 228 |
+
Use `tools/benchmark.py` for standardized evaluation across all models.
|
| 229 |
+
"""
|
| 230 |
+
mock_deps = {"requirements.txt": "torch>=1.10\npytorch-lightning>=1.7\nopencv-python\nnumpy\nscikit-learn"}
|
| 231 |
+
result = evaluate_repo(mock_repo, mock_readme, mock_deps, "Embedding-based")
|
| 232 |
+
print(f" ็ปผๅ: {result.get('overall_score')}/100")
|
| 233 |
+
print(f" ๅฏๅค็ฐๆง: {result.get('reproducibility_score')}/80")
|
| 234 |
+
print(f" ้้
ๅบฆ: {result.get('benchmark_fitness_score')}/20")
|
| 235 |
+
print(f" ๅคๅฎ: {result.get('verdict')} | ๅฎ้ชๅฐฑ็ปช: {result.get('benchmark_readiness')}")
|
| 236 |
+
print(f" ๅๆ: {result.get('reasoning')}")
|
| 237 |
+
|
| 238 |
+
print()
|
| 239 |
+
|
| 240 |
+
# ๆต่ฏ 2๏ผๅชๆๆจ็ demo ็ไธชไบบ้กน็ฎ๏ผ้ขๆไฝ้้
ๅบฆ๏ผ
|
| 241 |
+
print("=" * 60)
|
| 242 |
+
print("ๆต่ฏ 2๏ผไป
ๆจ็็ไธชไบบ้กน็ฎ๏ผ้ขๆ๏ผๅฏๅค็ฐๆงไธญ็ญ + ้้
ๅบฆไฝ๏ผ")
|
| 243 |
+
print("=" * 60)
|
| 244 |
+
mock_repo2 = {
|
| 245 |
+
"full_name": "someone/anomaly-detection-demo",
|
| 246 |
+
"html_url": "https://github.com/someone/anomaly-detection-demo",
|
| 247 |
+
"stars": 15,
|
| 248 |
+
"description": "A simple demo of anomaly detection using pretrained models.",
|
| 249 |
+
"updated_at": "2024-03-01T00:00:00Z",
|
| 250 |
+
"language": "Python",
|
| 251 |
+
}
|
| 252 |
+
mock_readme2 = """# Anomaly Detection Demo
|
| 253 |
+
A simple inference demo.
|
| 254 |
+
|
| 255 |
+
## Usage
|
| 256 |
+
```
|
| 257 |
+
python demo.py --image path/to/image.jpg
|
| 258 |
+
```
|
| 259 |
+
|
| 260 |
+
Pretrained weights: download from Google Drive (link may expire).
|
| 261 |
+
"""
|
| 262 |
+
mock_deps2 = {}
|
| 263 |
+
result2 = evaluate_repo(mock_repo2, mock_readme2, mock_deps2, "Embedding-based")
|
| 264 |
+
print(f" ็ปผๅ: {result2.get('overall_score')}/100")
|
| 265 |
+
print(f" ๅฏๅค็ฐๆง: {result2.get('reproducibility_score')}/80")
|
| 266 |
+
print(f" ้้
ๅบฆ: {result2.get('benchmark_fitness_score')}/20")
|
| 267 |
+
print(f" ๅคๅฎ: {result2.get('verdict')} | ๅฎ้ชๅฐฑ็ปช: {result2.get('benchmark_readiness')}")
|
| 268 |
+
print(f" ๅปบ่ฎฎ: {result2.get('suggested_use')}")
|
repo_fetcher.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import base64
|
| 3 |
+
import requests
|
| 4 |
+
|
| 5 |
+
API_BASE = "https://api.github.com"
|
| 6 |
+
|
| 7 |
+
DEPENDENCY_FILENAMES = [
|
| 8 |
+
"requirements.txt", "environment.yml", "environment.yaml",
|
| 9 |
+
"setup.py", "setup.cfg", "pyproject.toml",
|
| 10 |
+
"Pipfile", "Pipfile.lock", "Dockerfile", "Makefile", "CMakeLists.txt",
|
| 11 |
+
]
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def _get_headers():
|
| 15 |
+
token = os.getenv("GITHUB_TOKEN", "")
|
| 16 |
+
headers = {"Accept": "application/vnd.github.v3+json"}
|
| 17 |
+
if token:
|
| 18 |
+
headers["Authorization"] = f"Bearer {token}"
|
| 19 |
+
return headers
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def _github_get(path: str) -> dict | None:
|
| 23 |
+
"""็ปไธ็ GitHub API GET ่ฏทๆฑ๏ผๅคฑ่ดฅ่ฟๅ None"""
|
| 24 |
+
headers = _get_headers()
|
| 25 |
+
url = f"{API_BASE}{path}"
|
| 26 |
+
try:
|
| 27 |
+
resp = requests.get(url, headers=headers, timeout=15)
|
| 28 |
+
if resp.status_code == 404:
|
| 29 |
+
return None
|
| 30 |
+
if resp.status_code in (403, 429):
|
| 31 |
+
print(f"[่ญฆๅ] GitHub API ้้: {path}")
|
| 32 |
+
return None
|
| 33 |
+
resp.raise_for_status()
|
| 34 |
+
return resp.json()
|
| 35 |
+
except Exception as e:
|
| 36 |
+
print(f"[่ญฆๅ] GitHub API ่ฏทๆฑๅคฑ่ดฅ ({path}): {e}")
|
| 37 |
+
return None
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def fetch_readme(owner: str, name: str) -> str | None:
|
| 41 |
+
"""่ทๅไปๅบ README ๆไปถๅ
ๅฎน"""
|
| 42 |
+
try:
|
| 43 |
+
data = _github_get(f"/repos/{owner}/{name}/readme")
|
| 44 |
+
if not data:
|
| 45 |
+
return None
|
| 46 |
+
content = data.get("content", "")
|
| 47 |
+
return base64.b64decode(content).decode("utf-8", errors="replace")
|
| 48 |
+
except Exception:
|
| 49 |
+
return None
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def fetch_dependencies(owner: str, name: str) -> dict[str, str]:
|
| 53 |
+
"""่ทๅไปๅบ็ไพ่ตๆไปถ
|
| 54 |
+
|
| 55 |
+
Returns:
|
| 56 |
+
dict: {ๆไปถๅ: ๆไปถๅ
ๅฎน}๏ผๆพไธๅฐไปปไฝไพ่ตๆไปถๆถ่ฟๅ {}
|
| 57 |
+
"""
|
| 58 |
+
result = {}
|
| 59 |
+
try:
|
| 60 |
+
contents = _github_get(f"/repos/{owner}/{name}/contents") or []
|
| 61 |
+
for item in contents:
|
| 62 |
+
fname = item.get("name", "")
|
| 63 |
+
if fname in DEPENDENCY_FILENAMES:
|
| 64 |
+
file_data = _github_get(f"/repos/{owner}/{name}/contents/{fname}")
|
| 65 |
+
if file_data and file_data.get("content"):
|
| 66 |
+
try:
|
| 67 |
+
decoded = base64.b64decode(file_data["content"]).decode("utf-8", errors="replace")
|
| 68 |
+
result[fname] = decoded
|
| 69 |
+
except Exception:
|
| 70 |
+
pass
|
| 71 |
+
except Exception:
|
| 72 |
+
pass
|
| 73 |
+
return result
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
if __name__ == "__main__":
|
| 77 |
+
# ่ชๆต๏ผๅฏน anomalib ไปๅบ่ฐ็จ
|
| 78 |
+
owner, name = "openvinotoolkit", "anomalib"
|
| 79 |
+
print("=== repo_fetcher ่ชๆต ===")
|
| 80 |
+
|
| 81 |
+
readme = fetch_readme(owner, name)
|
| 82 |
+
print(f"README ้ฟๅบฆ: {len(readme) if readme else 0} ๅญ็ฌฆ")
|
| 83 |
+
if readme:
|
| 84 |
+
print(f" ๅ 200 ๅญ็ฌฆ: {readme[:200]}...")
|
| 85 |
+
|
| 86 |
+
deps = fetch_dependencies(owner, name)
|
| 87 |
+
print(f"ไพ่ตๆไปถ: {len(deps)} ไธช โ {list(deps.keys())}")
|
| 88 |
+
for fname, content in deps.items():
|
| 89 |
+
print(f" {fname}: {len(content)} ๅญ็ฌฆ")
|
repo_searcher.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
import os
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def search_repos(queries: list[str], max_per_keyword: int = 5) -> list[dict]:
|
| 6 |
+
"""ๅจ GitHub ๆ็ดขไปๅบ
|
| 7 |
+
|
| 8 |
+
Args:
|
| 9 |
+
queries: ๆ็ดขๆฅ่ฏขๅญ็ฌฆไธฒๅ่กจ
|
| 10 |
+
max_per_keyword: ๆฏไธชๆฅ่ฏขๆๅคไฟ็็ไปๅบๆฐ
|
| 11 |
+
|
| 12 |
+
Returns:
|
| 13 |
+
list[dict]: ๅทฒๅป้๏ผๆ full_name๏ผใๆ stars ้ๅบๆๅ็ๅ้ไปๅบๅ่กจใ
|
| 14 |
+
ๆฏไธช dict ๅ
ๅซ: full_name, html_url, description, stars,
|
| 15 |
+
language, updated_at, topics, match_keyword
|
| 16 |
+
"""
|
| 17 |
+
token = os.getenv("GITHUB_TOKEN", "")
|
| 18 |
+
headers = {"Accept": "application/vnd.github.v3+json"}
|
| 19 |
+
if token:
|
| 20 |
+
headers["Authorization"] = f"Bearer {token}"
|
| 21 |
+
|
| 22 |
+
seen = set()
|
| 23 |
+
results = []
|
| 24 |
+
|
| 25 |
+
for kw in queries:
|
| 26 |
+
query = f"{kw} language:python stars:>=5"
|
| 27 |
+
url = "https://api.github.com/search/repositories"
|
| 28 |
+
params = {"q": query, "sort": "stars", "order": "desc", "per_page": max_per_keyword}
|
| 29 |
+
|
| 30 |
+
try:
|
| 31 |
+
resp = requests.get(url, headers=headers, params=params, timeout=15)
|
| 32 |
+
if resp.status_code == 403 and "rate limit" in resp.text.lower():
|
| 33 |
+
print(f"[่ญฆๅ] GitHub ๆ็ดข้้๏ผ่ทณ่ฟๅ
ณ้ฎ่ฏ: {kw}")
|
| 34 |
+
continue
|
| 35 |
+
resp.raise_for_status()
|
| 36 |
+
data = resp.json()
|
| 37 |
+
except Exception as e:
|
| 38 |
+
print(f"[่ญฆๅ] ๆ็ดขๅ
ณ้ฎ่ฏ '{kw}' ๅคฑ่ดฅ: {e}")
|
| 39 |
+
continue
|
| 40 |
+
|
| 41 |
+
for item in data.get("items", []):
|
| 42 |
+
full_name = item["full_name"]
|
| 43 |
+
if full_name not in seen:
|
| 44 |
+
seen.add(full_name)
|
| 45 |
+
results.append({
|
| 46 |
+
"full_name": full_name,
|
| 47 |
+
"html_url": item["html_url"],
|
| 48 |
+
"description": item.get("description", ""),
|
| 49 |
+
"stars": item.get("stargazers_count", 0),
|
| 50 |
+
"language": item.get("language", ""),
|
| 51 |
+
"updated_at": item.get("updated_at", ""),
|
| 52 |
+
"topics": item.get("topics", []),
|
| 53 |
+
"match_keyword": kw,
|
| 54 |
+
})
|
| 55 |
+
|
| 56 |
+
results.sort(key=lambda r: r["stars"], reverse=True)
|
| 57 |
+
return results
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
if __name__ == "__main__":
|
| 61 |
+
# ่ชๆต๏ผ็จๅ ไธชๆ็ดข่ฏ่ฐ็จ
|
| 62 |
+
test_queries = [
|
| 63 |
+
"padim anomaly detection pytorch",
|
| 64 |
+
"patch distribution modeling anomaly detection",
|
| 65 |
+
]
|
| 66 |
+
repos = search_repos(test_queries, max_per_keyword=3)
|
| 67 |
+
print(f"=== repo_searcher ่ชๆต ===\nๆพๅฐ {len(repos)} ไธชไปๅบ:")
|
| 68 |
+
for r in repos:
|
| 69 |
+
print(f" {r['full_name']} โญ{r['stars']} โ {r.get('match_keyword', '?')}")
|
requirements.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio>=6.0
|
| 2 |
+
openai>=2.0
|
| 3 |
+
requests>=2.30
|
run.py
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# run.py
|
| 2 |
+
# ============================================================
|
| 3 |
+
# ็ฑปๅ๏ผ่ฐๅบฆๅจ๏ผไน่ด่ดฃ๏ผ
|
| 4 |
+
# ๅ่ฝ๏ผๆ"ๅ
ๆๅๅๆ"ๆต็จไธฒ่ Workflow๏ผ็ฒ๏ผๅ Agent๏ผไน๏ผ
|
| 5 |
+
# ็จๆณ๏ผpython run.py <arxiv_url>
|
| 6 |
+
# ็คบไพ๏ผpython run.py https://arxiv.org/abs/2011.08785
|
| 7 |
+
# ============================================================
|
| 8 |
+
import sys
|
| 9 |
+
import time
|
| 10 |
+
import re
|
| 11 |
+
import os
|
| 12 |
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 13 |
+
|
| 14 |
+
# ่ชๅจๅ ่ฝฝ .env ๆไปถ
|
| 15 |
+
_ENV_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env")
|
| 16 |
+
if os.path.isfile(_ENV_PATH):
|
| 17 |
+
with open(_ENV_PATH, "r", encoding="utf-8") as _f:
|
| 18 |
+
for _line in _f:
|
| 19 |
+
_line = _line.strip()
|
| 20 |
+
if _line and not _line.startswith("#") and "=" in _line:
|
| 21 |
+
_key, _val = _line.split("=", 1)
|
| 22 |
+
if _key not in os.environ:
|
| 23 |
+
os.environ[_key] = _val.strip().strip('"').strip("'")
|
| 24 |
+
|
| 25 |
+
# ---- ๅฏผๅ
ฅ็ฒ็ Workflow ๆจกๅ ----
|
| 26 |
+
try:
|
| 27 |
+
from paper_fetcher import fetch_paper_info
|
| 28 |
+
except ImportError as e:
|
| 29 |
+
raise ImportError(
|
| 30 |
+
f"็ผบๅฐๆจกๅ: paper_fetcher.py๏ผ็ฒ่ด่ดฃ๏ผ๏ผ่ฏท็ญๅพ
็ฒไบคไปใ\n"
|
| 31 |
+
f" ๅๅง้่ฏฏ: {e}"
|
| 32 |
+
) from e
|
| 33 |
+
|
| 34 |
+
try:
|
| 35 |
+
from repo_searcher import search_repos
|
| 36 |
+
except ImportError as e:
|
| 37 |
+
raise ImportError(
|
| 38 |
+
f"็ผบๅฐๆจกๅ: repo_searcher.py๏ผ็ฒ่ด่ดฃ๏ผ๏ผ่ฏท็ญๅพ
็ฒไบคไปใ\n"
|
| 39 |
+
f" ๅๅง้่ฏฏ: {e}"
|
| 40 |
+
) from e
|
| 41 |
+
|
| 42 |
+
try:
|
| 43 |
+
from repo_fetcher import fetch_readme, fetch_dependencies
|
| 44 |
+
except ImportError as e:
|
| 45 |
+
raise ImportError(
|
| 46 |
+
f"็ผบๅฐๆจกๅ: repo_fetcher.py๏ผ็ฒ่ด่ดฃ๏ผ๏ผ่ฏท็ญๅพ
็ฒไบคไปใ\n"
|
| 47 |
+
f" ๅๅง้่ฏฏ: {e}"
|
| 48 |
+
) from e
|
| 49 |
+
|
| 50 |
+
from direction_analyzer import analyze_direction
|
| 51 |
+
from repo_evaluator import evaluate_repo
|
| 52 |
+
from llm_utils import call_llm_json, parse_json_safe
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def run(arxiv_url: str, top_n: int = 5) -> dict:
|
| 56 |
+
"""ไธปๅ
ฅๅฃ๏ผๅ
ๆ็ดข GitHub โ ๅๅบไบๅฎ้
ไปๅบๅฝ็บณๆนๆณๆ โ ๆๅ่ฏไผฐใ
|
| 57 |
+
|
| 58 |
+
ๆฐๆต็จ๏ผๆนๆก B๏ผ๏ผ
|
| 59 |
+
็ฌฌไธๅฑ๏ผ่ฎบๆไฟกๆฏ่ทๅ (Workflow)
|
| 60 |
+
็ฌฌไบๅฑ๏ผๅฎฝๆณ GitHub ๆ็ดข (Workflow)
|
| 61 |
+
็ฌฌไธๅฑ๏ผๅบไบไปๅบๆฐๆฎๅฝ็บณๆนๆณๆ (Agent 1) โ ไธๅๆฏ LLM ๅญ่ฎฐๅฟ
|
| 62 |
+
็ฌฌๅๅฑ๏ผไปๅบ่ฏไผฐ (Agent 2)
|
| 63 |
+
|
| 64 |
+
Args:
|
| 65 |
+
arxiv_url: arxiv ่ฎบๆ URL
|
| 66 |
+
top_n: ๆ็ป่ฏไผฐ็ไปๅบๆฐ้
|
| 67 |
+
|
| 68 |
+
Returns:
|
| 69 |
+
dict: {"paper": {...}, "direction": {...}, "repos": [{...}], "error": "..."}
|
| 70 |
+
"""
|
| 71 |
+
t_start = time.time()
|
| 72 |
+
|
| 73 |
+
# ================================================================
|
| 74 |
+
# [1/5] ่ฎบๆไฟกๆฏ่ทๅ๏ผ็ฒ Workflow๏ผ
|
| 75 |
+
# ================================================================
|
| 76 |
+
print("=" * 60)
|
| 77 |
+
print("[1/5] ๆญฃๅจ่ทๅ่ฎบๆไฟกๆฏ...")
|
| 78 |
+
t0 = time.time()
|
| 79 |
+
try:
|
| 80 |
+
paper = fetch_paper_info(arxiv_url)
|
| 81 |
+
except Exception as e:
|
| 82 |
+
return {"error": f"่ทๅ่ฎบๆไฟกๆฏๅคฑ่ดฅ: {e}"}
|
| 83 |
+
|
| 84 |
+
title = paper.get("title", "")
|
| 85 |
+
abstract = paper.get("abstract", "")
|
| 86 |
+
print(f" ๆ ้ข: {title[:100]}...")
|
| 87 |
+
print(f" ไฝ่
: {', '.join(paper.get('authors', [])[:3])}")
|
| 88 |
+
print(f" ๅ็ฑป: {', '.join(paper.get('categories', []))}")
|
| 89 |
+
print(f" ่ๆถ: {time.time() - t0:.1f}s")
|
| 90 |
+
|
| 91 |
+
# ================================================================
|
| 92 |
+
# [2/5] ๅฎฝๆณ GitHub ๆ็ดข๏ผ็ฒ Workflow๏ผ
|
| 93 |
+
# ================================================================
|
| 94 |
+
print()
|
| 95 |
+
print("[2/5] ๆญฃๅจๅฎฝๆณๆ็ดข GitHub๏ผๅ
ๆไปๅบ๏ผๅ่ฎฉ Agent ๅๆ๏ผ...")
|
| 96 |
+
t0 = time.time()
|
| 97 |
+
|
| 98 |
+
broad_queries = _extract_broad_queries(title, abstract)
|
| 99 |
+
print(f" ็ๆ {len(broad_queries)} ไธชๅฎฝๆณๆ็ดข่ฏ:")
|
| 100 |
+
for q in broad_queries:
|
| 101 |
+
print(f" - {q}")
|
| 102 |
+
|
| 103 |
+
try:
|
| 104 |
+
broad_results = search_repos(broad_queries, max_per_keyword=5)
|
| 105 |
+
except Exception as e:
|
| 106 |
+
return {
|
| 107 |
+
"paper": paper,
|
| 108 |
+
"error": f"GitHub ๆ็ดขๅคฑ่ดฅ: {e}",
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
print(f" ๅป้ๅ่ทๅพ {len(broad_results)} ไธชๅ้ไปๅบ")
|
| 112 |
+
print(f" ่ๆถ: {time.time() - t0:.1f}s")
|
| 113 |
+
|
| 114 |
+
if not broad_results:
|
| 115 |
+
return {
|
| 116 |
+
"paper": paper,
|
| 117 |
+
"direction": {},
|
| 118 |
+
"repos": [],
|
| 119 |
+
"error": "ๆชๆพๅฐ็ธๅ
ณๅผๆบไปๅบใ่ฏฅๆนๅๅฏ่ฝๅคชๆฐๆๅคชๅท้จ๏ผๆๆ ้ซ่ดจ้ๅผๆบๅฎ็ฐใ",
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
# ================================================================
|
| 123 |
+
# [2.5] LLM ่ฟๆปคไธ็ธๅ
ณไปๅบ
|
| 124 |
+
# ================================================================
|
| 125 |
+
print()
|
| 126 |
+
print("[2.5] ๆญฃๅจ็จ LLM ่ฟๆปคไธ็ธๅ
ณไปๅบ...")
|
| 127 |
+
t0 = time.time()
|
| 128 |
+
filtered_results = _filter_repos(title, abstract, broad_results)
|
| 129 |
+
print(f" ่ๆถ: {time.time() - t0:.1f}s")
|
| 130 |
+
|
| 131 |
+
# ================================================================
|
| 132 |
+
# [3/5] ๅบไบไปๅบๆฐๆฎๅฝ็บณๆนๆณๆ๏ผAgent 1๏ผ โ ๆ ธๅฟๆนๅจ
|
| 133 |
+
# ================================================================
|
| 134 |
+
print()
|
| 135 |
+
print(f"[3/5] ๆญฃๅจๅๆ {len(filtered_results)} ไธชไปๅบ๏ผๅฝ็บณๆนๆณๆ๏ผAgent 1๏ผ...")
|
| 136 |
+
t0 = time.time()
|
| 137 |
+
|
| 138 |
+
try:
|
| 139 |
+
direction = analyze_direction(title, abstract, filtered_results)
|
| 140 |
+
except Exception as e:
|
| 141 |
+
return {
|
| 142 |
+
"paper": paper,
|
| 143 |
+
"error": f"็ ็ฉถๆนๅ่งฃๆๅคฑ่ดฅ: {e}",
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
subfield = direction.get("subfield", "ๆช็ฅ")
|
| 147 |
+
families = direction.get("method_families", [])
|
| 148 |
+
print(f" ๅญ้ขๅ: {subfield}")
|
| 149 |
+
print(f" ่ถๅฟ: {direction.get('subfield_trend', '')[:80]}...")
|
| 150 |
+
print(f" ๆนๆณๆ ({len(families)} ไธช):")
|
| 151 |
+
for mf in families:
|
| 152 |
+
matched = mf.get("matched_repos", [])
|
| 153 |
+
print(f" - {mf.get('family_name', '?')}: {len(matched)} ไธชไปๅบ {matched}")
|
| 154 |
+
print(f" ่ๆถ: {time.time() - t0:.1f}s")
|
| 155 |
+
|
| 156 |
+
# ================================================================
|
| 157 |
+
# [4/5] ็ญ้ไปๅบ + ๆๅปบๆนๆณๆๅฝๅฑๆ ๅฐ
|
| 158 |
+
# ================================================================
|
| 159 |
+
print()
|
| 160 |
+
print(f"[4/5] ๆญฃๅจ็ญ้ๅนถ่ทๅไปๅบ่ฏฆๆ
...")
|
| 161 |
+
t0 = time.time()
|
| 162 |
+
|
| 163 |
+
# ไป Agent 1 ็ matched_repos ไธญๅปบ็ซ full_name โ family_name ๆ ๅฐ
|
| 164 |
+
repo_family_map = {}
|
| 165 |
+
for mf in families:
|
| 166 |
+
family_name = mf.get("family_name", "")
|
| 167 |
+
for repo_name in mf.get("matched_repos", []):
|
| 168 |
+
repo_family_map[repo_name] = family_name
|
| 169 |
+
|
| 170 |
+
# ไป filtered_results ไธญ็ญ้๏ผไผๅ
้ๆๆนๆณๆๅฝๅฑ็๏ผๅๆ stars ๆๅบ
|
| 171 |
+
classified = [r for r in filtered_results if r["full_name"] in repo_family_map]
|
| 172 |
+
unclassified = [r for r in filtered_results if r["full_name"] not in repo_family_map]
|
| 173 |
+
classified.sort(key=lambda r: r.get("stars", 0), reverse=True)
|
| 174 |
+
unclassified.sort(key=lambda r: r.get("stars", 0), reverse=True)
|
| 175 |
+
|
| 176 |
+
candidates = (classified + unclassified)[:top_n]
|
| 177 |
+
|
| 178 |
+
print(f" ๆๆนๆณๆๅฝๅฑ: {len(classified)} ไธช๏ผๆชๅฝ็ฑป: {len(unclassified)} ไธช")
|
| 179 |
+
print(f" ๆ็ป้ๅ {len(candidates)} ไธชไปๅบ:")
|
| 180 |
+
for i, c in enumerate(candidates):
|
| 181 |
+
family = repo_family_map.get(c["full_name"], "ๆชๅฝ็ฑป")
|
| 182 |
+
print(f" {i+1}. {c['full_name']} [{family}] Stars:{c.get('stars', 0)}")
|
| 183 |
+
print(f" ่ๆถ: {time.time() - t0:.1f}s")
|
| 184 |
+
|
| 185 |
+
# ================================================================
|
| 186 |
+
# [5/5] ไปๅบ่ฏฆๆ
่ทๅ + ่ฏไผฐ๏ผAgent 2๏ผๅนถ่ก๏ผ
|
| 187 |
+
# ================================================================
|
| 188 |
+
print()
|
| 189 |
+
print(f"[5/5] ๆญฃๅจ่ทๅไปๅบ่ฏฆๆ
ๅนถ่ฏไผฐ๏ผAgent 2๏ผ{len(candidates)} ไธชไปๅบๅนถ่ก๏ผ...")
|
| 190 |
+
t0 = time.time()
|
| 191 |
+
|
| 192 |
+
def _eval_single(repo, idx, total):
|
| 193 |
+
"""ๅไธชไปๅบ่ฏไผฐ๏ผๅจ็บฟ็จไธญๆง่ก๏ผ"""
|
| 194 |
+
full_name = repo["full_name"]
|
| 195 |
+
try:
|
| 196 |
+
owner, name = full_name.split("/", 1)
|
| 197 |
+
except ValueError:
|
| 198 |
+
return idx, None
|
| 199 |
+
|
| 200 |
+
matched_family = repo_family_map.get(full_name, "")
|
| 201 |
+
family_tag = f"[{matched_family}]" if matched_family else "[ๆชๅฝ็ฑป]"
|
| 202 |
+
print(f" ({idx+1}/{total}) {full_name} {family_tag}...")
|
| 203 |
+
|
| 204 |
+
try:
|
| 205 |
+
readme = fetch_readme(owner, name)
|
| 206 |
+
deps = fetch_dependencies(owner, name)
|
| 207 |
+
evaluation = evaluate_repo(repo, readme, deps, matched_family)
|
| 208 |
+
except Exception as e:
|
| 209 |
+
print(f" [WARN] {full_name} ่ฏไผฐๅคฑ่ดฅ: {e}")
|
| 210 |
+
evaluation = _make_error_evaluation(str(e))
|
| 211 |
+
|
| 212 |
+
return idx, {
|
| 213 |
+
"full_name": repo.get("full_name", ""),
|
| 214 |
+
"html_url": repo.get("html_url", ""),
|
| 215 |
+
"description": repo.get("description", ""),
|
| 216 |
+
"stars": repo.get("stars", 0),
|
| 217 |
+
"language": repo.get("language", ""),
|
| 218 |
+
"updated_at": repo.get("updated_at", ""),
|
| 219 |
+
"topics": repo.get("topics", []),
|
| 220 |
+
"match_keyword": repo.get("match_keyword", ""),
|
| 221 |
+
"method_family": matched_family,
|
| 222 |
+
"evaluation": evaluation,
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
n = len(candidates)
|
| 226 |
+
evaluated = [None] * n
|
| 227 |
+
with ThreadPoolExecutor(max_workers=min(n, 5)) as executor:
|
| 228 |
+
futures = {
|
| 229 |
+
executor.submit(_eval_single, repo, i, n): i
|
| 230 |
+
for i, repo in enumerate(candidates)
|
| 231 |
+
}
|
| 232 |
+
for future in as_completed(futures):
|
| 233 |
+
idx, result = future.result()
|
| 234 |
+
if result is not None:
|
| 235 |
+
evaluated[idx] = result
|
| 236 |
+
|
| 237 |
+
evaluated = [r for r in evaluated if r is not None]
|
| 238 |
+
|
| 239 |
+
# ๆ็ปผๅ่ฏๅ้ๅบๆๅ
|
| 240 |
+
evaluated.sort(key=lambda r: r["evaluation"].get("overall_score", 0), reverse=True)
|
| 241 |
+
print(f" ่ๆถ: {time.time() - t0:.1f}s")
|
| 242 |
+
|
| 243 |
+
# ================================================================
|
| 244 |
+
# ๆฑๆป
|
| 245 |
+
# ================================================================
|
| 246 |
+
print()
|
| 247 |
+
print("=" * 60)
|
| 248 |
+
print("ๅฎๆ๏ผ")
|
| 249 |
+
best = evaluated[0] if evaluated else None
|
| 250 |
+
if best:
|
| 251 |
+
print(f" ๆ้ซๅ: {best['full_name']} ({best['evaluation'].get('overall_score', 0)}/100)")
|
| 252 |
+
print(f" ๆป่ๆถ: {time.time() - t_start:.1f}s")
|
| 253 |
+
print("=" * 60)
|
| 254 |
+
|
| 255 |
+
return {
|
| 256 |
+
"paper": paper,
|
| 257 |
+
"direction": direction,
|
| 258 |
+
"repos": evaluated,
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
def _extract_broad_queries(title: str, abstract: str) -> list[str]:
|
| 263 |
+
"""็จ LLM ไป่ฎบๆๆ ้ขๅๆ่ฆไธญ็ๆ GitHub ๆ็ดขๅ
ณ้ฎ่ฏใ
|
| 264 |
+
|
| 265 |
+
็ธๆฏ่งๅๆๅ๏ผLLM ็่งฃ่ฎบๆๅ่ฝ็ๆๆด็ฒพๅ็้ขๅๆ็ดข่ฏใ
|
| 266 |
+
ๅฆๆ LLM ่ฐ็จๅคฑ่ดฅ๏ผ้็บงไธบ่งๅๆๅใ
|
| 267 |
+
"""
|
| 268 |
+
system_prompt = """ไฝ ๆฏๅญฆๆฏ่ฎบๆๆ็ดขไธๅฎถใๆ นๆฎ่ฎบๆๆ ้ขๅๆ่ฆ๏ผ็ๆ 6-8 ไธช GitHub ๆ็ดขๆฅ่ฏข๏ผ็จไบๆพๅฐ่ฏฅ็ ็ฉถๆนๅ็ๅผๆบๅฎ็ฐใ
|
| 269 |
+
|
| 270 |
+
่ฆๆฑ๏ผ
|
| 271 |
+
- ๆฅ่ฏขๅฟ
้กปๆฏ่ฑๆ๏ผ็จ็ฉบๆ ผๅ้ๅ
ณ้ฎ่ฏ
|
| 272 |
+
- ๅ
ๅซๆนๆณๅ/ๆๆฏๅ
ณ้ฎ่ฏ + ้ๅฎ่ฏ๏ผimplementation / pytorch / code๏ผ
|
| 273 |
+
- ๅ
ๅซ 1-2 ไธชๅฎฝๆณ็้ขๅๆฅ่ฏข๏ผๅฆ "anomaly detection pytorch library"๏ผ
|
| 274 |
+
- ไธ่ฆ็จๅผๅทๆ็นๆฎ็ฌฆๅท
|
| 275 |
+
- ้ฟๅ
ๅคชๆณ็่ฏ๏ผๅฆๅไธไธช "anomaly"๏ผ
|
| 276 |
+
|
| 277 |
+
่พๅบไธฅๆ ผ JSON๏ผ
|
| 278 |
+
{"queries": ["query1", "query2", ...]}"""
|
| 279 |
+
|
| 280 |
+
user_prompt = f"""่ฎบๆๆ ้ข: {title[:300]}
|
| 281 |
+
ๆ่ฆ: {abstract[:800]}
|
| 282 |
+
|
| 283 |
+
่ฏทไธบ่ฏฅ่ฎบๆ็ๆ GitHub ๆ็ดขๆฅ่ฏขใ"""
|
| 284 |
+
|
| 285 |
+
try:
|
| 286 |
+
raw = call_llm_json(system_prompt, user_prompt, temperature=0.3, max_tokens=500)
|
| 287 |
+
data = parse_json_safe(raw, "broad_queries")
|
| 288 |
+
queries = data.get("queries", [])
|
| 289 |
+
if isinstance(queries, list) and len(queries) >= 3:
|
| 290 |
+
return queries[:10]
|
| 291 |
+
except Exception as e:
|
| 292 |
+
print(f" [WARN] LLM ๅ
ณ้ฎ่ฏ็ๆๅคฑ่ดฅ๏ผ้็บงไธบ่งๅๆๅ: {e}")
|
| 293 |
+
|
| 294 |
+
return _extract_broad_queries_fallback(title, abstract)
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
def _extract_broad_queries_fallback(title: str, abstract: str) -> list[str]:
|
| 298 |
+
"""ไป่ฎบๆๆ ้ขๅๆ่ฆไธญๆๅๅฎฝๆณๆ็ดขๅ
ณ้ฎ่ฏ๏ผ่งๅ้็บง็๏ผใ
|
| 299 |
+
|
| 300 |
+
็ญ็ฅ๏ผๆๅๆๆไน็่ฏ็ป + ๆ็ดข้ๅฎ่ฏ๏ผๆๅคๆ ทๆง้ๆ ท๏ผไธๅๅๆ ้ขๅ็ผ๏ผใ
|
| 301 |
+
ไธไพ่ต LLM๏ผ็บฏ่งๅๆๅใ
|
| 302 |
+
"""
|
| 303 |
+
abstract_first = abstract.split(".")[0] if abstract else ""
|
| 304 |
+
text = f"{title} {abstract_first}".lower()
|
| 305 |
+
text = re.sub(r'[^\w\s-]', ' ', text)
|
| 306 |
+
words = text.split()
|
| 307 |
+
|
| 308 |
+
stop_words = {
|
| 309 |
+
'a', 'an', 'the', 'of', 'for', 'in', 'on', 'to', 'and', 'or', 'is', 'are',
|
| 310 |
+
'we', 'our', 'that', 'this', 'with', 'from', 'by', 'as', 'at', 'be', 'it',
|
| 311 |
+
'its', 'not', 'can', 'has', 'have', 'been', 'was', 'were', 'will', 'would',
|
| 312 |
+
'could', 'should', 'may', 'do', 'does', 'did', 'so', 'if', 'no', 'new',
|
| 313 |
+
'based', 'using', 'which', 'into', 'such', 'than', 'then', 'these', 'those',
|
| 314 |
+
'propose', 'present', 'method', 'approach', 'framework', 'novel', 'model',
|
| 315 |
+
'learning', 'deep', 'via', 'et', 'al', 'all', 'we', 'you', 'they',
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
meaningful = [w for w in words if w not in stop_words and len(w) > 1]
|
| 319 |
+
|
| 320 |
+
bigrams = [f"{meaningful[i]} {meaningful[i+1]}" for i in range(len(meaningful) - 1)]
|
| 321 |
+
trigrams = [f"{meaningful[i]} {meaningful[i+1]} {meaningful[i+2]}" for i in range(len(meaningful) - 2)]
|
| 322 |
+
|
| 323 |
+
def _sample_diverse(items: list[str], n: int) -> list[str]:
|
| 324 |
+
if len(items) <= n:
|
| 325 |
+
return items
|
| 326 |
+
step = max(1, len(items) // n)
|
| 327 |
+
return [items[i] for i in range(0, len(items), step)][:n]
|
| 328 |
+
|
| 329 |
+
phrases = _sample_diverse(trigrams, 3) + _sample_diverse(bigrams, 4)
|
| 330 |
+
|
| 331 |
+
seen = set()
|
| 332 |
+
unique_phrases = []
|
| 333 |
+
for p in sorted(phrases, key=len, reverse=True):
|
| 334 |
+
if p not in seen:
|
| 335 |
+
seen.add(p)
|
| 336 |
+
unique_phrases.append(p)
|
| 337 |
+
|
| 338 |
+
qualifiers = [
|
| 339 |
+
"implementation pytorch",
|
| 340 |
+
"official code",
|
| 341 |
+
"pytorch github",
|
| 342 |
+
]
|
| 343 |
+
|
| 344 |
+
queries = []
|
| 345 |
+
for phrase in unique_phrases[:5]:
|
| 346 |
+
if len(phrase) > 5:
|
| 347 |
+
queries.append(f"{phrase} {qualifiers[0]}")
|
| 348 |
+
|
| 349 |
+
mid = len(meaningful) // 2
|
| 350 |
+
broad = " ".join(meaningful[max(0, mid-2):mid+2])
|
| 351 |
+
if len(broad) > 10:
|
| 352 |
+
queries.append(f"{broad} {qualifiers[2]}")
|
| 353 |
+
|
| 354 |
+
seen = set()
|
| 355 |
+
unique = []
|
| 356 |
+
for q in queries:
|
| 357 |
+
if q not in seen:
|
| 358 |
+
seen.add(q)
|
| 359 |
+
unique.append(q)
|
| 360 |
+
|
| 361 |
+
return unique[:10]
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
def _filter_repos(title: str, abstract: str, repos: list[dict]) -> list[dict]:
|
| 365 |
+
"""็จ LLM ๅฟซ้่ฟๆปคไธ็ธๅ
ณ็ไปๅบ๏ผๅชไฟ็ไธ่ฎบๆๆนๅ็ธๅ
ณ็ใ
|
| 366 |
+
|
| 367 |
+
ๅจ GitHub ๅ
ณ้ฎ่ฏๆ็ดขไนๅใAgent 1 ๅๆไนๅ่ฟ่กใ
|
| 368 |
+
ๅฆๆ่ฟๆปคๅไธบ็ฉบๆ LLM ่ฐ็จๅคฑ่ดฅ๏ผ่ฟๅๅๅงๅ่กจไฝไธบ้็บงๆนๆกใ
|
| 369 |
+
"""
|
| 370 |
+
if len(repos) <= 3:
|
| 371 |
+
return repos
|
| 372 |
+
|
| 373 |
+
# ่ถ
่ฟ 20 ไธชไปๅบๆถ๏ผๅชๅ top 20๏ผๆ stars๏ผ๏ผ้ฟๅ
JSON ่พๅบ่ฟ้ฟ
|
| 374 |
+
if len(repos) > 20:
|
| 375 |
+
repos_for_filter = sorted(repos, key=lambda r: r.get("stars", 0), reverse=True)[:20]
|
| 376 |
+
else:
|
| 377 |
+
repos_for_filter = repos
|
| 378 |
+
|
| 379 |
+
# ๆ้ ็ผฉ็ฅ็ไปๅบๆธ
ๅไพ LLM ๅคๆญ
|
| 380 |
+
repo_list_parts = []
|
| 381 |
+
for i, r in enumerate(repos_for_filter):
|
| 382 |
+
desc = (r.get("description") or "")[:120]
|
| 383 |
+
topics = ", ".join(r.get("topics", [])[:8])
|
| 384 |
+
repo_list_parts.append(
|
| 385 |
+
f"{i+1}. {r['full_name']} (Stars:{r.get('stars',0)})\n"
|
| 386 |
+
f" Description: {desc}\n"
|
| 387 |
+
f" Topics: {topics}"
|
| 388 |
+
)
|
| 389 |
+
repo_list_text = "\n".join(repo_list_parts)
|
| 390 |
+
|
| 391 |
+
system_prompt = """ไฝ ๆฏไธไธชๅญฆๆฏ่ฎบๆไธๅผๆบไปฃ็ ๅน้
๏ฟฝ๏ฟฝๅฎถใไปปๅกๆฏๅคๆญ GitHub ไปๅบๆฏๅฆไธ็ปๅฎ่ฎบๆๅฑไบๅไธ็ ็ฉถๆนๅใ
|
| 392 |
+
|
| 393 |
+
ๆ้คๆ ๅ๏ผๆปก่ถณไปปไธๅณๆ้ค๏ผ๏ผ
|
| 394 |
+
- ไปๅบ่งฃๅณ็ไธๅก้ฎ้ขไธ่ฎบๆๅฎๅ
จไธๅ๏ผๅฆ่ฎบๆๅๅทฅไธ็ผบ้ทๆฃๆต๏ผไปๅบๅๅปๅญฆๅพๅ/่ชๅจ้ฉพ้ฉถ/ไบบ่ธ่ฏๅซ๏ผ
|
| 395 |
+
- ไปๅบไฝฟ็จ็ๆ ธๅฟๆๆฏๆนๆณไธ่ฎบๆๅฎๅ
จๆ ๅ
ณ
|
| 396 |
+
- ไปๅบๆฏ้็จๆ็จ/่ฏพ็จไฝไธ/้ข่ฏ้ข้ๅ
|
| 397 |
+
|
| 398 |
+
ไฟ็ๆ ๅ๏ผๆปก่ถณไปปไธๅณไฟ็๏ผ๏ผ
|
| 399 |
+
- ไปๅบๅฎ็ฐ็ๆนๆณไธ่ฎบๆๆนๆณๅๅฑไธไธชๆๆฏ่ๅผ
|
| 400 |
+
- ไปๅบๅฏ็จไบ่ฏฅ่ฎบๆ็ๅฏนๆฏๅฎ้ช๏ผbaseline/comparison๏ผ
|
| 401 |
+
- ไปๅบๆฏ่ฏฅ้ขๅ็็ฅๅ benchmarking ๅบ
|
| 402 |
+
|
| 403 |
+
่พๅบไธฅๆ ผ JSON๏ผไธ่ฆ reasoning ๅญๆฎตไปฅ่็ token๏ผ๏ผ
|
| 404 |
+
{"relevant": ["owner/repo1", "owner/repo2"], "irrelevant": ["owner/repo3"]}"""
|
| 405 |
+
|
| 406 |
+
user_prompt = f"""## ่ฎบๆไฟกๆฏ
|
| 407 |
+
ๆ ้ข: {title[:200]}
|
| 408 |
+
ๆ่ฆ: {abstract[:500]}
|
| 409 |
+
|
| 410 |
+
## GitHub ไปๅบๆธ
ๅ๏ผๅ
ฑ {len(repos_for_filter)} ไธช๏ผ
|
| 411 |
+
{repo_list_text}
|
| 412 |
+
|
| 413 |
+
่ฏทๅคๆญๆฏไธชไปๅบๆฏๅฆไธ่ฏฅ่ฎบๆๆนๅ็ธๅ
ณใ"""
|
| 414 |
+
|
| 415 |
+
try:
|
| 416 |
+
raw = call_llm_json(system_prompt, user_prompt, temperature=0.1, max_tokens=4000)
|
| 417 |
+
data = parse_json_safe(raw, "filter_repos")
|
| 418 |
+
except Exception as e:
|
| 419 |
+
print(f" [WARN] ไปๅบ่ฟๆปคๅคฑ่ดฅ๏ผไฟ็ๅ
จ้จ: {e}")
|
| 420 |
+
return repos
|
| 421 |
+
|
| 422 |
+
relevant_set = set(data.get("relevant", []))
|
| 423 |
+
irrelevant = data.get("irrelevant", [])
|
| 424 |
+
|
| 425 |
+
if irrelevant:
|
| 426 |
+
print(f" [่ฟๆปค] ๅ้ค {len(irrelevant)} ไธชไธ็ธๅ
ณไปๅบ: {irrelevant}")
|
| 427 |
+
|
| 428 |
+
filtered = [r for r in repos if r["full_name"] in relevant_set]
|
| 429 |
+
|
| 430 |
+
if len(filtered) < 2:
|
| 431 |
+
print(f" [WARN] ่ฟๆปคๅไป
ๅฉ {len(filtered)} ไธชไปๅบ๏ผๅ้ๅฐๅๅง็ปๆ")
|
| 432 |
+
return repos
|
| 433 |
+
|
| 434 |
+
print(f" ่ฟๆปคๅไฟ็ {len(filtered)}/{len(repos)} ไธชไปๅบ")
|
| 435 |
+
return filtered
|
| 436 |
+
|
| 437 |
+
|
| 438 |
+
def _make_error_evaluation(error_msg: str) -> dict:
|
| 439 |
+
"""ๆ้ ไธไธช่กจ็คบ่ฏไผฐๅคฑ่ดฅ็ evaluation dict"""
|
| 440 |
+
return {
|
| 441 |
+
"reproducibility_score": 0,
|
| 442 |
+
"benchmark_fitness_score": 0,
|
| 443 |
+
"overall_score": 0,
|
| 444 |
+
"verdict": "error",
|
| 445 |
+
"env_score": 0,
|
| 446 |
+
"doc_score": 0,
|
| 447 |
+
"code_score": 0,
|
| 448 |
+
"community_score": 0,
|
| 449 |
+
"dep_score": 0,
|
| 450 |
+
"benchmark_score": 0,
|
| 451 |
+
"reasoning": f"่ฏไผฐๅคฑ่ดฅ: {error_msg[:100]}",
|
| 452 |
+
"risks": ["่ฏไผฐ่ฟ็จๅบ้๏ผ่ฏทๆๅจๆฃๆฅ่ฏฅไปๅบ"],
|
| 453 |
+
"benchmark_readiness": "not_ready",
|
| 454 |
+
"suggested_use": "่ฏไผฐๅคฑ่ดฅ๏ผ่ฏทๆๅจๆฃๆฅ",
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
|
| 458 |
+
# ============================================================
|
| 459 |
+
# ๅฝไปค่กๅ
ฅๅฃ
|
| 460 |
+
# ============================================================
|
| 461 |
+
if __name__ == "__main__":
|
| 462 |
+
# ไฟฎๅค Windows ็ป็ซฏ emoji ็ผ็ ้ฎ้ข
|
| 463 |
+
from llm_utils import fix_windows_encoding
|
| 464 |
+
fix_windows_encoding()
|
| 465 |
+
|
| 466 |
+
if len(sys.argv) < 2:
|
| 467 |
+
print("็จๆณ: python run.py <arxiv_url>")
|
| 468 |
+
print("็คบไพ: python run.py https://arxiv.org/abs/1706.03762")
|
| 469 |
+
print("็คบไพ: python run.py https://arxiv.org/abs/2011.08785")
|
| 470 |
+
sys.exit(1)
|
| 471 |
+
|
| 472 |
+
url = sys.argv[1]
|
| 473 |
+
result = run(url)
|
| 474 |
+
|
| 475 |
+
if result.get("error"):
|
| 476 |
+
print(f"\n{'='*60}")
|
| 477 |
+
print(f"่ฟ่กๆชๅฎๅ
จๆๅ")
|
| 478 |
+
print(f"{'='*60}")
|
| 479 |
+
print(f" {result['error']}")
|
| 480 |
+
|
| 481 |
+
if result.get("paper"):
|
| 482 |
+
print(f"\n ่ฎบๆไฟกๆฏๅทฒ่ทๅ: {result['paper'].get('title', '')[:80]}")
|
| 483 |
+
if result.get("direction"):
|
| 484 |
+
print(f" ๆนๅ่งฃๆๅทฒๅฎๆ: {result['direction'].get('subfield', '')}")
|
| 485 |
+
else:
|
| 486 |
+
from app import format_report
|
| 487 |
+
# ็จ utf-8 ็ผ็ ่พๅบ้ฟๅ
emoji ไนฑ็
|
| 488 |
+
report = format_report(result)
|
| 489 |
+
print(report.encode(sys.stdout.encoding or 'utf-8', errors='replace').decode(sys.stdout.encoding or 'utf-8', errors='replace'))
|
state.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# state.py
|
| 2 |
+
# ============================================================
|
| 3 |
+
# ็ฑปๅ๏ผๆฐๆฎๆจกๅๅฎไน๏ผไน่ด่ดฃ๏ผPPT ๅฑ็คบ็จ๏ผ
|
| 4 |
+
# ๅ่ฝ๏ผๅฎไนๆดไธช็ณป็ป็ๆ ธๅฟๆฐๆฎ็ปๆ
|
| 5 |
+
# ็จ้๏ผPPT ไธญๅฑ็คบๆถๆ่ฎพ่ฎก่ฝๅ๏ผไปฃ็ ไธญไธ้่ฆ import๏ผไป
ไฝไธบๅ่
|
| 6 |
+
# ============================================================
|
| 7 |
+
|
| 8 |
+
from dataclasses import dataclass, field
|
| 9 |
+
from typing import Optional
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
# ---- ็ฌฌไธๅฑ๏ผ็ ็ฉถๆนๅ ----
|
| 13 |
+
|
| 14 |
+
@dataclass
|
| 15 |
+
class MethodFamily:
|
| 16 |
+
"""ๆนๆณๆ"""
|
| 17 |
+
family_name: str # ๅฆ "Embedding-based Anomaly Detection"
|
| 18 |
+
description: str # ไธๅฅ่ฏๆ ธๅฟ็น็น
|
| 19 |
+
representative_work: str # ไปฃ่กจ่ฎบๆ๏ผๅฆ "PaDiM (2021)"
|
| 20 |
+
search_queries: list[str] # GitHub ๆ็ดข่ฏ
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
@dataclass
|
| 24 |
+
class DirectionAnalysis:
|
| 25 |
+
"""็ ็ฉถๆนๅ่งฃๆ็ปๆ๏ผAgent 1 ็่พๅบ๏ผ"""
|
| 26 |
+
subfield: str # ๅญ้ขๅๅ
|
| 27 |
+
subfield_trend: str # ๅฝๅ่ถๅฟ
|
| 28 |
+
method_families: list[MethodFamily]
|
| 29 |
+
broad_queries: list[str] # ๅฎฝๆณๆ็ดข่ฏ
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
# ---- ็ฌฌไบๅฑ๏ผๅ้ไปๅบ ----
|
| 33 |
+
|
| 34 |
+
@dataclass
|
| 35 |
+
class CandidateRepo:
|
| 36 |
+
"""ๅ้ไปๅบ๏ผ็ฒ็ Workflow ่พๅบ๏ผ"""
|
| 37 |
+
full_name: str # "openvinotoolkit/anomalib"
|
| 38 |
+
html_url: str
|
| 39 |
+
description: str
|
| 40 |
+
stars: int
|
| 41 |
+
language: str
|
| 42 |
+
updated_at: str
|
| 43 |
+
topics: list[str]
|
| 44 |
+
match_keyword: str # ๅฝไธญๅชไธชๆ็ดข่ฏ
|
| 45 |
+
method_family: str # ๅฝ็ฑปๅฐๅชไธชๆนๆณๆ๏ผๅฏไธบ็ฉบ๏ผ
|
| 46 |
+
readme: Optional[str] = None
|
| 47 |
+
dependencies: dict[str, str] = field(default_factory=dict)
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# ---- ็ฌฌไธๅฑ๏ผ่ฏไผฐ็ปๆ ----
|
| 51 |
+
|
| 52 |
+
@dataclass
|
| 53 |
+
class EvalResult:
|
| 54 |
+
"""ๅไธชไปๅบ็่ฏไผฐ็ปๆ๏ผAgent 2 ็่พๅบ๏ผ"""
|
| 55 |
+
reproducibility_score: int # ๅฏๅค็ฐๆงๆปๅ (0-80)
|
| 56 |
+
benchmark_fitness_score: int # ๅฏนๆฏๅฎ้ช้้
ๅบฆๆปๅ (0-20)
|
| 57 |
+
overall_score: int # ็ปผๅๆปๅ (0-100)
|
| 58 |
+
verdict: str # reproducible / partially / not_reproducible
|
| 59 |
+
env_score: int # 0-15
|
| 60 |
+
doc_score: int # 0-20
|
| 61 |
+
code_score: int # 0-20
|
| 62 |
+
community_score: int # 0-10
|
| 63 |
+
dep_score: int # 0-15
|
| 64 |
+
benchmark_score: int # 0-20
|
| 65 |
+
reasoning: str # ๅๆๆๆฌ
|
| 66 |
+
risks: list[str] # ้ฃ้ฉๅ่กจ
|
| 67 |
+
benchmark_readiness: str # ready / partial / not_ready
|
| 68 |
+
suggested_use: str # ๅปบ่ฎฎ็จ้
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
# ---- ้กถๅฑ๏ผๅฎๆด็ ๆฅ ----
|
| 72 |
+
|
| 73 |
+
@dataclass
|
| 74 |
+
class ResearchReport:
|
| 75 |
+
"""ๅฎๆด็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ๏ผrun.py ็ๆ็ป่พๅบ๏ผ"""
|
| 76 |
+
paper_info: dict
|
| 77 |
+
direction: DirectionAnalysis
|
| 78 |
+
repos: list[tuple[CandidateRepo, EvalResult]]
|
test_agents.py
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# test_agents.py
|
| 2 |
+
# ============================================================
|
| 3 |
+
# ็ฑปๅ๏ผๆต่ฏๅทฅๅ
ท๏ผไน่ด่ดฃ๏ผ
|
| 4 |
+
# ๅ่ฝ๏ผไธ้ฎ่ฟ่กไธคไธช Agent ็่ชๆต๏ผ้ช่ฏๅบ็กๅ่ฝๆญฃๅธธ
|
| 5 |
+
# ็จๆณ๏ผpython test_agents.py
|
| 6 |
+
# ============================================================
|
| 7 |
+
import sys
|
| 8 |
+
from llm_utils import fix_windows_encoding
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
# ๆจกๆ GitHub ๆ็ดข็ปๆ๏ผไพ Agent 1 ๆต่ฏไฝฟ็จ๏ผ
|
| 12 |
+
MOCK_REPOS = [
|
| 13 |
+
{
|
| 14 |
+
"full_name": "openvinotoolkit/anomalib",
|
| 15 |
+
"html_url": "https://github.com/openvinotoolkit/anomalib",
|
| 16 |
+
"description": "An anomaly detection library comprising state-of-the-art algorithms.",
|
| 17 |
+
"stars": 4000, "language": "Python",
|
| 18 |
+
"topics": ["anomaly-detection", "pytorch", "benchmarking"],
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"full_name": "hcw-00/PatchCore",
|
| 22 |
+
"html_url": "https://github.com/hcw-00/PatchCore",
|
| 23 |
+
"description": "Official implementation of PatchCore: Towards Total Recall in Industrial Anomaly Detection.",
|
| 24 |
+
"stars": 850, "language": "Python",
|
| 25 |
+
"topics": ["memory-bank", "anomaly-detection", "pytorch"],
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"full_name": "taikiinoue45/STFPM",
|
| 29 |
+
"html_url": "https://github.com/taikiinoue45/STFPM",
|
| 30 |
+
"description": "Student-Teacher Feature Pyramid Matching for Anomaly Detection (PyTorch).",
|
| 31 |
+
"stars": 320, "language": "Python",
|
| 32 |
+
"topics": ["teacher-student", "anomaly-detection"],
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"full_name": "VitjanZ/DRAEM",
|
| 36 |
+
"html_url": "https://github.com/VitjanZ/DRAEM",
|
| 37 |
+
"description": "DRAEM: Discriminatively trained reconstruction embedding for surface anomaly detection.",
|
| 38 |
+
"stars": 180, "language": "Python",
|
| 39 |
+
"topics": ["synthetic-defect", "anomaly-detection", "reconstruction"],
|
| 40 |
+
},
|
| 41 |
+
{
|
| 42 |
+
"full_name": "marugoto/CFLow",
|
| 43 |
+
"html_url": "https://github.com/marugoto/CFLow",
|
| 44 |
+
"description": "CFLow: Real-time unsupervised anomaly detection via conditional normalizing flows.",
|
| 45 |
+
"stars": 130, "language": "Python",
|
| 46 |
+
"topics": ["normalizing-flow", "anomaly-detection"],
|
| 47 |
+
},
|
| 48 |
+
{
|
| 49 |
+
"full_name": "someone/anomaly-tutorial",
|
| 50 |
+
"html_url": "https://github.com/someone/anomaly-tutorial",
|
| 51 |
+
"description": "A curated list of anomaly detection papers and resources.",
|
| 52 |
+
"stars": 45, "language": "Markdown",
|
| 53 |
+
"topics": ["awesome-list", "anomaly-detection"],
|
| 54 |
+
},
|
| 55 |
+
]
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def test_agent1():
|
| 59 |
+
"""ๆต่ฏ Agent 1๏ผdirection_analyzer๏ผๆฐ็โโๅบไบไปๅบๆฐๆฎๅฝ็บณ๏ผ"""
|
| 60 |
+
from direction_analyzer import analyze_direction
|
| 61 |
+
|
| 62 |
+
print("=" * 60)
|
| 63 |
+
print("Agent 1 ๆต่ฏ๏ผๅบไบ GitHub ไปๅบ็ๆนๆณๆๅฝ็บณ")
|
| 64 |
+
print("=" * 60)
|
| 65 |
+
|
| 66 |
+
test_cases = [
|
| 67 |
+
{
|
| 68 |
+
"name": "PaDiM + ็ๅฎไปๅบๆฐๆฎ",
|
| 69 |
+
"title": "PaDiM: a Patch Distribution Modeling Framework for Anomaly Detection and Localization",
|
| 70 |
+
"abstract": (
|
| 71 |
+
"We present a new framework for anomaly detection and localization based on "
|
| 72 |
+
"patch distribution modeling. PaDiM uses pretrained convolutional neural networks "
|
| 73 |
+
"to extract patch features and models their distribution using multivariate "
|
| 74 |
+
"Gaussian distributions. It achieves state-of-the-art results on MVTec AD and "
|
| 75 |
+
"STC datasets for industrial defect detection."
|
| 76 |
+
),
|
| 77 |
+
"repos": MOCK_REPOS,
|
| 78 |
+
"checks": [
|
| 79 |
+
("subfield ้็ฉบ", lambda r: bool(r.get("subfield"))),
|
| 80 |
+
("ๆ >= 2 ไธชๆนๆณๆ", lambda r: len(r.get("method_families", [])) >= 2),
|
| 81 |
+
("่ณๅฐ 1 ไธชๆนๆณๆๆ matched_repos", lambda r: any(
|
| 82 |
+
len(mf.get("matched_repos", [])) >= 1
|
| 83 |
+
for mf in r.get("method_families", [])
|
| 84 |
+
)),
|
| 85 |
+
("ๆ broad_queries", lambda r: len(r.get("broad_queries", [])) >= 1),
|
| 86 |
+
],
|
| 87 |
+
},
|
| 88 |
+
{
|
| 89 |
+
"name": "Transformer (้็บงๆจกๅผ๏ผๆ ไปๅบๆฐๆฎ)",
|
| 90 |
+
"title": "Attention Is All You Need",
|
| 91 |
+
"abstract": (
|
| 92 |
+
"The dominant sequence transduction models are based on complex recurrent "
|
| 93 |
+
"or convolutional neural networks... We propose a new simple network "
|
| 94 |
+
"architecture, the Transformer, based solely on attention mechanisms."
|
| 95 |
+
),
|
| 96 |
+
"repos": None, # ้็บงๆจกๅผ
|
| 97 |
+
"checks": [
|
| 98 |
+
("subfield ้็ฉบ", lambda r: bool(r.get("subfield"))),
|
| 99 |
+
("ๆ >= 3 ไธชๆนๆณๆ", lambda r: len(r.get("method_families", [])) >= 3),
|
| 100 |
+
("ๆ broad_queries", lambda r: len(r.get("broad_queries", [])) >= 1),
|
| 101 |
+
],
|
| 102 |
+
},
|
| 103 |
+
{
|
| 104 |
+
"name": "EfficientAD (่ฝป้ไปๅบๆฐๆฎ)",
|
| 105 |
+
"title": "EfficientAD: Accurate Visual Anomaly Detection at Millisecond-Level Latencies",
|
| 106 |
+
"abstract": (
|
| 107 |
+
"We propose EfficientAD, a lightweight anomaly detection method that achieves "
|
| 108 |
+
"millisecond-level latency. It uses a teacher-student architecture with a simple "
|
| 109 |
+
"student network that learns to mimic the teacher's features on normal images only."
|
| 110 |
+
),
|
| 111 |
+
"repos": MOCK_REPOS[:4], # ๅช็ป 4 ไธชไปๅบ
|
| 112 |
+
"checks": [
|
| 113 |
+
("subfield ้็ฉบ", lambda r: bool(r.get("subfield"))),
|
| 114 |
+
("ๆ subfield_trend", lambda r: len(r.get("subfield_trend", "")) >= 10),
|
| 115 |
+
("ๆนๆณๆๆ search_queries", lambda r: any(
|
| 116 |
+
len(mf.get("search_queries", [])) >= 1
|
| 117 |
+
for mf in r.get("method_families", [])
|
| 118 |
+
)),
|
| 119 |
+
],
|
| 120 |
+
},
|
| 121 |
+
]
|
| 122 |
+
|
| 123 |
+
passed = 0
|
| 124 |
+
failed = 0
|
| 125 |
+
for tc in test_cases:
|
| 126 |
+
print(f"\n [{tc['name']}]")
|
| 127 |
+
try:
|
| 128 |
+
result = analyze_direction(tc["title"], tc["abstract"], tc["repos"])
|
| 129 |
+
subfield = result.get("subfield", "?")
|
| 130 |
+
families = result.get("method_families", [])
|
| 131 |
+
print(f" ๅญ้ขๅ: {subfield}")
|
| 132 |
+
print(f" ๆนๆณๆ:")
|
| 133 |
+
for mf in families:
|
| 134 |
+
print(f" - {mf.get('family_name', '?')}: matched_repos={mf.get('matched_repos', [])}")
|
| 135 |
+
|
| 136 |
+
tc_failed = False
|
| 137 |
+
for check_name, check_fn in tc["checks"]:
|
| 138 |
+
if check_fn(result):
|
| 139 |
+
print(f" โ
{check_name}")
|
| 140 |
+
else:
|
| 141 |
+
print(f" โ {check_name}")
|
| 142 |
+
tc_failed = True
|
| 143 |
+
|
| 144 |
+
if tc_failed:
|
| 145 |
+
failed += 1
|
| 146 |
+
else:
|
| 147 |
+
passed += 1
|
| 148 |
+
except Exception as e:
|
| 149 |
+
print(f" โ ๅผๅธธ: {e}")
|
| 150 |
+
import traceback
|
| 151 |
+
traceback.print_exc()
|
| 152 |
+
failed += 1
|
| 153 |
+
|
| 154 |
+
return passed, failed
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def test_agent2():
|
| 158 |
+
"""ๆต่ฏ Agent 2๏ผrepo_evaluator"""
|
| 159 |
+
from repo_evaluator import evaluate_repo
|
| 160 |
+
|
| 161 |
+
print("\n" + "=" * 60)
|
| 162 |
+
print("Agent 2 ๆต่ฏ๏ผไปๅบ่ฏไผฐ")
|
| 163 |
+
print("=" * 60)
|
| 164 |
+
|
| 165 |
+
test_cases = [
|
| 166 |
+
{
|
| 167 |
+
"name": "anomalib (้ขๆ้ซๅ)",
|
| 168 |
+
"repo": {
|
| 169 |
+
"full_name": "openvinotoolkit/anomalib",
|
| 170 |
+
"html_url": "https://github.com/openvinotoolkit/anomalib",
|
| 171 |
+
"stars": 4000,
|
| 172 |
+
"description": "An anomaly detection library comprising state-of-the-art algorithms.",
|
| 173 |
+
"updated_at": "2026-01-15T00:00:00Z",
|
| 174 |
+
"language": "Python",
|
| 175 |
+
},
|
| 176 |
+
"readme": (
|
| 177 |
+
"# Anomalib\nA library for benchmarking anomaly detection.\n\n"
|
| 178 |
+
"## Installation\n```\npip install anomalib\n```\n\n"
|
| 179 |
+
"## Training\n```python\nfrom anomalib.engine import Engine\nengine = Engine()\nengine.train()\n```\n\n"
|
| 180 |
+
"## Supported Datasets\n- MVTec AD\n- BTAD\n\n"
|
| 181 |
+
"## Benchmarking\nUse `tools/benchmark.py` for standardized evaluation."
|
| 182 |
+
),
|
| 183 |
+
"deps": {"requirements.txt": "torch>=1.10\npytorch-lightning>=1.7\nopencv-python\nnumpy"},
|
| 184 |
+
"family": "Patch Distribution Modeling",
|
| 185 |
+
"checks": [
|
| 186 |
+
("overall_score >= 55", lambda r: r.get("overall_score", 0) >= 55),
|
| 187 |
+
("verdict ้ error", lambda r: r.get("verdict") in ("reproducible", "partially")),
|
| 188 |
+
("benchmark_readiness ้ not_ready", lambda r: r.get("benchmark_readiness") in ("ready", "partial")),
|
| 189 |
+
("reasoning ้็ฉบ", lambda r: len(r.get("reasoning", "")) >= 10),
|
| 190 |
+
],
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"name": "ๆจ็ Demo ้กน็ฎ (้ขๆไฝๅ)",
|
| 194 |
+
"repo": {
|
| 195 |
+
"full_name": "someone/anomaly-demo",
|
| 196 |
+
"html_url": "https://github.com/someone/anomaly-demo",
|
| 197 |
+
"stars": 15,
|
| 198 |
+
"description": "A simple demo of anomaly detection.",
|
| 199 |
+
"updated_at": "2024-03-01T00:00:00Z",
|
| 200 |
+
"language": "Python",
|
| 201 |
+
},
|
| 202 |
+
"readme": "# Anomaly Detection Demo\nJust a demo.\n\n```\npython demo.py --image path/to/image.jpg\n```\nPretrained weights: Google Drive link.",
|
| 203 |
+
"deps": {},
|
| 204 |
+
"family": "",
|
| 205 |
+
"checks": [
|
| 206 |
+
("overall_score < 50", lambda r: r.get("overall_score", 0) < 50),
|
| 207 |
+
("benchmark_readiness ไธบ not_ready", lambda r: r.get("benchmark_readiness") == "not_ready"),
|
| 208 |
+
("ๆ risks ๅ่กจ", lambda r: isinstance(r.get("risks"), list)),
|
| 209 |
+
],
|
| 210 |
+
},
|
| 211 |
+
{
|
| 212 |
+
"name": "ไธญ็ญ้กน็ฎ (้จๅๅฏๅค็ฐ)",
|
| 213 |
+
"repo": {
|
| 214 |
+
"full_name": "research-lab/anomaly-pytorch",
|
| 215 |
+
"html_url": "https://github.com/research-lab/anomaly-pytorch",
|
| 216 |
+
"stars": 200,
|
| 217 |
+
"description": "PyTorch implementation of anomaly detection methods.",
|
| 218 |
+
"updated_at": "2025-08-01T00:00:00Z",
|
| 219 |
+
"language": "Python",
|
| 220 |
+
},
|
| 221 |
+
"readme": (
|
| 222 |
+
"# Anomaly Detection in PyTorch\n\n"
|
| 223 |
+
"## Install\n```\npip install -r requirements.txt\n```\n\n"
|
| 224 |
+
"## Train\n```\npython train.py --config config.yaml\n```"
|
| 225 |
+
),
|
| 226 |
+
"deps": {"requirements.txt": "torch>=1.8\nnumpy\nopencv-python\nmatplotlib"},
|
| 227 |
+
"family": "Teacher-Student",
|
| 228 |
+
"checks": [
|
| 229 |
+
("overall_score ๅจ 40-85 ไน้ด", lambda r: 40 <= r.get("overall_score", 0) <= 85),
|
| 230 |
+
("verdict ้ error", lambda r: r.get("verdict") != "error"),
|
| 231 |
+
],
|
| 232 |
+
},
|
| 233 |
+
]
|
| 234 |
+
|
| 235 |
+
passed = 0
|
| 236 |
+
failed = 0
|
| 237 |
+
for tc in test_cases:
|
| 238 |
+
print(f"\n [{tc['name']}]")
|
| 239 |
+
try:
|
| 240 |
+
result = evaluate_repo(tc["repo"], tc["readme"], tc["deps"], tc["family"])
|
| 241 |
+
print(f" ็ปผๅ: {result.get('overall_score')}/100")
|
| 242 |
+
print(f" ๅฏๅค็ฐๆง: {result.get('reproducibility_score')}/80")
|
| 243 |
+
print(f" ้้
ๅบฆ: {result.get('benchmark_fitness_score')}/20")
|
| 244 |
+
print(f" ๅคๅฎ: {result.get('verdict')} | ๅฐฑ็ปช: {result.get('benchmark_readiness')}")
|
| 245 |
+
|
| 246 |
+
tc_failed = False
|
| 247 |
+
for check_name, check_fn in tc["checks"]:
|
| 248 |
+
if check_fn(result):
|
| 249 |
+
print(f" โ
{check_name}")
|
| 250 |
+
else:
|
| 251 |
+
print(f" โ {check_name}")
|
| 252 |
+
tc_failed = True
|
| 253 |
+
|
| 254 |
+
if tc_failed:
|
| 255 |
+
failed += 1
|
| 256 |
+
else:
|
| 257 |
+
passed += 1
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f" โ ๅผๅธธ: {e}")
|
| 260 |
+
import traceback
|
| 261 |
+
traceback.print_exc()
|
| 262 |
+
failed += 1
|
| 263 |
+
|
| 264 |
+
return passed, failed
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
# ============================================================
|
| 268 |
+
# ไธปๅ
ฅๅฃ
|
| 269 |
+
# ============================================================
|
| 270 |
+
if __name__ == "__main__":
|
| 271 |
+
fix_windows_encoding()
|
| 272 |
+
|
| 273 |
+
print("ResearchRadar ยท Agent ่ชๆฃๅฅไปถ")
|
| 274 |
+
print("=" * 60)
|
| 275 |
+
|
| 276 |
+
a1_pass, a1_fail = test_agent1()
|
| 277 |
+
a2_pass, a2_fail = test_agent2()
|
| 278 |
+
|
| 279 |
+
print("\n" + "=" * 60)
|
| 280 |
+
print("ๆต่ฏๆฑๆป")
|
| 281 |
+
print("=" * 60)
|
| 282 |
+
print(f" Agent 1 (ๆนๆณๆๅฝ็บณ): {a1_pass} ้่ฟ, {a1_fail} ๅคฑ่ดฅ")
|
| 283 |
+
print(f" Agent 2 (ไปๅบ่ฏไผฐ): {a2_pass} ้่ฟ, {a2_fail} ๅคฑ่ดฅ")
|
| 284 |
+
|
| 285 |
+
total_pass = a1_pass + a2_pass
|
| 286 |
+
total_fail = a1_fail + a2_fail
|
| 287 |
+
print(f" ๆป่ฎก: {total_pass} ้่ฟ, {total_fail} ๅคฑ่ดฅ")
|
| 288 |
+
|
| 289 |
+
if total_fail > 0:
|
| 290 |
+
print("\nโ ้จๅๆต่ฏๆช้่ฟ๏ผ่ฏทๆฃๆฅๅฏนๅบ Agent ็่พๅบใ")
|
| 291 |
+
sys.exit(1)
|
| 292 |
+
else:
|
| 293 |
+
print("\nโ
ๆๆๆต่ฏ้่ฟ๏ผ")
|
| 294 |
+
sys.exit(0)
|
ไน_ๅฎ็ฐๆป็ป.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ResearchRadar ยท ไนๅฎ็ฐๆป็ป
|
| 2 |
+
|
| 3 |
+
> ็ๆฌ๏ผv2.0 | ๆฅๆ๏ผ2026-05-04
|
| 4 |
+
|
| 5 |
+
## ไน็่ง่ฒ
|
| 6 |
+
|
| 7 |
+
ๅจ ResearchRadar ไธไบบๅๅทฅไธญ๏ผไน่ด่ดฃ**"ๆบ่ฝๅคๆญๅฑ + ่ฐๅบฆๅฑ + ็้ขๅฑ"**โโๅณๆๆ้่ฆ่ฐ็จ LLM ๅๅณ็ญ็ๆจกๅใไธฒ่ๅ
จๆต็จ็่ฐๅบฆๅจใไปฅๅ็จๆทไบคไบ็้ขใ
|
| 8 |
+
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
## ๅฎ็ฐไบไปไน
|
| 12 |
+
|
| 13 |
+
ๅ
ฑ **7 ไธชๆไปถ**๏ผ่ฆ็ไธไธชๅฑๆฌก๏ผ
|
| 14 |
+
|
| 15 |
+
### 1. ๅ
ฌๅ
ฑๅบ็ก่ฎพๆฝ โ `llm_utils.py`
|
| 16 |
+
|
| 17 |
+
ๆๆ Agent ็ๅ
ฑไบซๅบๅบง๏ผ่งฃๅณ LLM ่ฐ็จ็ไธไธชๆ ธๅฟ็็น๏ผ
|
| 18 |
+
|
| 19 |
+
| ่ฝๅ | ๅฎ็ฐ |
|
| 20 |
+
|------|------|
|
| 21 |
+
| **API ้งๆง** | `call_llm()` โ 3 ๆฌกๆๆฐ้้ฟ้่ฏ๏ผ2s โ 4s โ 8s๏ผ๏ผๆฏๆ `response_format` ๅผบๅถ JSON ๆจกๅผ |
|
| 22 |
+
| **JSON ๅฎน้** | `parse_json_safe()` โ 6 ็ง็ญ็ฅไพๆฌกๅฐ่ฏ๏ผ็ดๆฅ่งฃๆ โ ```json``` ไปฃ็ ๅ โ ้็จไปฃ็ ๅ โ ๆญฃๅๆๅ โ ๅฐพ้จ้ๅทไฟฎๅค โ ๅ
ณ้ฎ่ฏๅฎไฝ๏ผ |
|
| 23 |
+
| **่พๅบๅ
ๅบ** | `validate_direction_output()` / `validate_eval_output()` โ ็ผบๅคฑๅญๆฎต่ชๅจๅกซๅ
้ป่ฎคๅผ๏ผ็ฑปๅๆ ก้ช |
|
| 24 |
+
|
| 25 |
+
### 2. Agent 1๏ผๆนๆณๆๅฝ็บณ โ `direction_analyzer.py`
|
| 26 |
+
|
| 27 |
+
**่พๅ
ฅ**๏ผ่ฎบๆๆ ้ข + ๆ่ฆ + GitHub ๆ็ดข็ปๆ๏ผไปๅบๅ่กจ๏ผ
|
| 28 |
+
**่พๅบ**๏ผ็ ็ฉถๆนๅๅ
จๆฏ๏ผๅญ้ขๅใ่ถๅฟใๆนๆณๆ่ฐฑ็ณป + ๆฏไธชๆ็ๅฝๅฑไปๅบ๏ผ
|
| 29 |
+
|
| 30 |
+
- **ๆ ธๅฟ่ฎพ่ฎก**๏ผไธๅ่ฎฉ LLM ๅญ่ฎฐๅฟๅๅๆนๆณๆ๏ผ่ๆฏๅบไบๅฎ้
GitHub ไปๅบๆฐๆฎๅๅๆๅฝ็บณ
|
| 31 |
+
- ๆฏไธชๆนๆณๆ้ๅธฆ `matched_repos`โโๆ็กฎๆๅบๅชไบไปๅบๅฑไบ่ฏฅๆ
|
| 32 |
+
- ๆฏๆ้็บงๆจกๅผ๏ผๆ ไปๅบๆฐๆฎๆถๅบไบ LLM ่ช่บซ็ฅ่ฏ๏ผ
|
| 33 |
+
- ไฝฟ็จ `response_format: {"type": "json_object"}` + Few-Shot ็คบไพ
|
| 34 |
+
|
| 35 |
+
### 3. Agent 2๏ผไปๅบ่ฏไผฐ โ `repo_evaluator.py`
|
| 36 |
+
|
| 37 |
+
**่พๅ
ฅ**๏ผไปๅบๅ
ไฟกๆฏ + README + ไพ่ตๆไปถ + ๆนๆณๆ
|
| 38 |
+
**่พๅบ**๏ผๅ
ญ็ปดๅบฆ่ฏๅ๏ผๆปกๅ 100๏ผ
|
| 39 |
+
|
| 40 |
+
่ฏๅๆกๆถ๏ผ
|
| 41 |
+
- **ๅฏๅค็ฐๆง**๏ผ5 ็ปดๅบฆ๏ผ80 ๅ๏ผ๏ผ็ฏๅข้
็ฝฎ(15) + ๆๆกฃ่ดจ้(20) + ไปฃ็ ๅฏ็จๆง(20) + ็คพๅบๆดป่ทๅบฆ(10) + ไพ่ตๅฅๅบทๅบฆ(15)
|
| 42 |
+
- **ๅฏนๆฏๅฎ้ช้้
ๅบฆ**๏ผ1 ็ปดๅบฆ๏ผ20 ๅ๏ผ๏ผbenchmark ่ๆฌ + ้ข่ฎญ็ปๆ้ + ๆ ๅๅ่ฏไผฐ
|
| 43 |
+
- Few-Shot ่ฏๅ้ๅฎ็คบไพ๏ผ้ซๅ 93 / ไฝๅ 18๏ผ
|
| 44 |
+
|
| 45 |
+
### 4. ่ฐๅบฆๅจ โ `run.py`
|
| 46 |
+
|
| 47 |
+
**ๆฐๆต็จ๏ผๅ
ๆๅๅๆ๏ผ**๏ผ
|
| 48 |
+
|
| 49 |
+
```
|
| 50 |
+
arxiv URL
|
| 51 |
+
โ [1] paper_fetcher๏ผ่ทๅ่ฎบๆไฟกๆฏ๏ผ
|
| 52 |
+
โ [2] ๅ
ณ้ฎ่ฏๆๅ โ repo_searcher๏ผๅฎฝๆณๆ็ดข GitHub๏ผ
|
| 53 |
+
โ [3] direction_analyzer๏ผๅบไบไปๅบๆฐๆฎๅฝ็บณๆนๆณๆ๏ผ โ Agent 1
|
| 54 |
+
โ [4] repo_fetcher + repo_evaluator๏ผ่ทๅ่ฏฆๆ
+ ๅ
ญ็ปดๅบฆ่ฏๅ๏ผ โ Agent 2
|
| 55 |
+
โ [5] ๆฑๆป่พๅบ
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
- ไปๅบโๆนๆณๆๅฝๅฑ็ฑ Agent 1 ็ `matched_repos` ็ดๆฅ็ปๅบ๏ผไธๅ้่ฆๅ
ณ้ฎ่ฏๆ ๅฐ
|
| 59 |
+
- ็บฏ่งๅ็ๅ
ณ้ฎ่ฏๆๅ๏ผ`_extract_broad_queries`๏ผ๏ผไธ้ขๅคๆถ่ LLM ่ฐ็จ
|
| 60 |
+
|
| 61 |
+
### 5. ็้ขๅฑ โ `app.py`
|
| 62 |
+
|
| 63 |
+
Gradio Web ็้ข๏ผ
|
| 64 |
+
- ่พๅ
ฅๆก + 3 ไธช็คบไพไธ้ฎๅกซๅ
|
| 65 |
+
- `format_report()` ็ๆๅๆฎตๅผ Markdown ็ ๆฅ๏ผ
|
| 66 |
+
1. ่ฎบๆไฟกๆฏ
|
| 67 |
+
2. ็ ็ฉถๆนๅๅ
จๆฏ๏ผๅญ้ขๅ + ่ถๅฟ + ๆนๆณๆ่กจๆ ผ๏ผ
|
| 68 |
+
3. ๅผๆบๅฎ็ฐ่ฏไผฐๆๅ๏ผๆฏไธชไปๅบๅ
ญ็ปดๅบฆๆ็ป + ๅๆ + ้ฃ้ฉ็น๏ผ
|
| 69 |
+
4. ๅฏนๆฏๅฎ้ชๆจ่ๆป็ป๏ผๆ ready/partial/not_ready ๅ็ป๏ผ
|
| 70 |
+
|
| 71 |
+
### 6. ๆฐๆฎๆจกๅ โ `state.py`
|
| 72 |
+
|
| 73 |
+
5 ไธช dataclass ๅฎไน็ณป็ปๆ ธๅฟๆฐๆฎ็ปๆ๏ผ`MethodFamily` โ `DirectionAnalysis` โ `CandidateRepo` โ `EvalResult` โ `ResearchReport`
|
| 74 |
+
|
| 75 |
+
### 7. ่ชๆฃๆต่ฏ โ `test_agents.py`
|
| 76 |
+
|
| 77 |
+
ไธ้ฎ่ฟ่กไธคไธช Agent ็่ชๆต๏ผ6 ไธชๆต่ฏ็จไพ๏ผๆญ่จ + ๆฑๆป๏ผ้้ถ้ๅบ็ ใ
|
| 78 |
+
|
| 79 |
+
---
|
| 80 |
+
|
| 81 |
+
## ่ฎพ่ฎกๅๅ
|
| 82 |
+
|
| 83 |
+
- **ๆ ๆกๆถไพ่ต**๏ผAgent = Python ๅฝๆฐ + LLM ่ฐ็จ๏ผไธ็จ LangChain/LangGraph
|
| 84 |
+
- **ๆฐๆฎๆต็ฎๅ**๏ผdict ไผ ๅ๏ผif/else ๅๆฏ๏ผๆพๅผไผไบ้ๅผ
|
| 85 |
+
- **้่ฏฏไธๅดฉๆบ**๏ผLLM ่พๅบๅผๅธธ โ ๅกซๅ
้ป่ฎคๅผ๏ผAPI ๅคฑ่ดฅ โ 3 ๆฌก้่ฏ๏ผ่ฏไผฐๅคฑ่ดฅ โ ๆ ่ฎฐ error ็ปง็ปญ
|
| 86 |
+
- **ๆฅๅฃๅฅ็บฆๆธ
ๆฐ**๏ผไธ็ฒ็ๅฏนๆฅ้่ฟๅฝๆฐ็ญพๅ + dict ๅญๆฎตๅ็บฆๅฎ๏ผ่ฏฆ่ง `ไนโ็ฒ_ๅฏนๆฅๆๆกฃ.md`
|
| 87 |
+
|
| 88 |
+
---
|
| 89 |
+
|
| 90 |
+
## ๅทฒ็กฎ่ฎคๅฏ่ฟ่ก
|
| 91 |
+
|
| 92 |
+
```bash
|
| 93 |
+
python test_agents.py # 6/6 ้่ฟ
|
| 94 |
+
python direction_analyzer.py # 3 ็ฏ่ฎบๆ็ฌ็ซ่ชๆต
|
| 95 |
+
python repo_evaluator.py # 3 ไธชไปๅบๅบๆฏ็ฌ็ซ่ชๆต
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
---
|
| 99 |
+
|
| 100 |
+
## ็ฒๆจกๅๅทฒ้ๆ โ
|
| 101 |
+
|
| 102 |
+
็ฒ็ 3 ไธช Workflow ๆจกๅๅทฒไบคไปๅนถ้ๅฝๅไธบๆญฃๅผๆไปถๅ๏ผ
|
| 103 |
+
- `paper_fetcher.py` โ arxiv API ่ฎบๆไฟกๆฏ่ทๅ
|
| 104 |
+
- `repo_searcher.py` โ GitHub ไปๅบๆ็ดข๏ผๆฏๆๅป้ + Stars ๆๅบ + Token ่ฎค่ฏ๏ผ
|
| 105 |
+
- `repo_fetcher.py` โ GitHub ไปๅบ README + ไพ่ตๆไปถ่ทๅ
|
| 106 |
+
|
| 107 |
+
`python -c "import run"` ๅฏผๅ
ฅๆๅ๏ผๆฅไธๆฅๅฏ่ฟ่ก็ซฏๅฐ็ซฏ่่ฐๆต่ฏใ
|
ไนโ็ฒ_ๅฏนๆฅๆๆกฃ.md
ADDED
|
@@ -0,0 +1,772 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ResearchRadar ยท ไนโ็ฒ ๅฏนๆฅๆๆกฃ
|
| 2 |
+
|
| 3 |
+
> ็ๆฌ๏ผv1.0 | ๆฅๆ๏ผ2026-05-04 | ๆฐๅ๏ผไน
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
## ็ฎๅฝ
|
| 8 |
+
|
| 9 |
+
1. [ไนๅฎๆๆ
ๅตๆป่ง](#1-ไนๅฎๆๆ
ๅตๆป่ง)
|
| 10 |
+
2. [็ฒ้ไบคไป็3ไธชๆจกๅ๏ผAPIๅฅ็บฆ๏ผ](#2-็ฒ้ไบคไป็3ไธชๆจกๅapiๅฅ็บฆ)
|
| 11 |
+
- [2.1 paper_fetcher.py](#21-paper_fetcherpy)
|
| 12 |
+
- [2.2 repo_searcher.py](#22-repo_searcherpy)
|
| 13 |
+
- [2.3 repo_fetcher.py](#23-repo_fetcherpy)
|
| 14 |
+
3. [ๆฐๆฎๆตๅ
จๆฏๅพ](#3-ๆฐๆฎๆตๅ
จๆฏๅพ)
|
| 15 |
+
4. [ๅฏนๆฅๆญฅ้ชค๏ผๆๆฏ + ๆฒ้๏ผ](#4-ๅฏนๆฅๆญฅ้ชคๆๆฏ--ๆฒ้)
|
| 16 |
+
5. [ๅฏนๆฅๅๆๆ](#5-ๅฏนๆฅๅๆๆ)
|
| 17 |
+
6. [ๆ
้ๆๆฅๆๅ](#6-ๆ
้ๆๆฅๆๅ)
|
| 18 |
+
7. [ๅทฒ็ฅๅฑ้ไธๅ็ปญ่ฟญไปฃ](#7-ๅทฒ็ฅๅฑ้ไธๅ็ปญ่ฟญไปฃ)
|
| 19 |
+
|
| 20 |
+
---
|
| 21 |
+
|
| 22 |
+
## 1. ไนๅฎๆๆ
ๅตๆป่ง
|
| 23 |
+
|
| 24 |
+
### 1.1 ๅทฒๅฎๆ็7ไธชๆไปถ
|
| 25 |
+
|
| 26 |
+
| # | ๆไปถๅ | ็ฑปๅ | ๅ่ฝ | ็ถๆ |
|
| 27 |
+
|---|--------|------|------|------|
|
| 28 |
+
| 1 | `llm_utils.py` | ๅ
ฌๅ
ฑๅทฅๅ
ท | OpenAI ๅฎขๆท็ซฏใLLM่ฐ็จ๏ผ3ๆฌก้่ฏ๏ผใJSONๅฎๅ
จ่งฃๆ๏ผ6็ญ็ฅ๏ผใ่พๅบๆ ก้ช | โ
ๅฎๆ |
|
| 29 |
+
| 2 | `direction_analyzer.py` | Agent 1 | LLM่งฃๆ็ ็ฉถๆนๅโๅญ้ขๅ+ๆนๆณๆ+ๆ็ดข่ฏ | โ
ๅฎๆ |
|
| 30 |
+
| 3 | `repo_evaluator.py` | Agent 2 | LLMๅ
ญ็ปดๅบฆ่ฏๅ๏ผๅฏๅค็ฐๆง5็ปด80ๅ + ๅฏนๆฏๅฎ้ช้้
ๅบฆ1็ปด20ๅ๏ผ | โ
ๅฎๆ |
|
| 31 |
+
| 4 | `run.py` | ่ฐๅบฆๅจ | ไธฒ่3ๅฑๆถๆ๏ผๆฐๆฎไผ ้๏ผๆนๆณๆๅน้
๏ผ่ๆถ็ป่ฎก | โ
ๅฎๆ |
|
| 32 |
+
| 5 | `app.py` | UIๅฑ | Gradio็้ข + Markdown็ ๆฅๆ ผๅผๅ๏ผๅๆฎตๅผ๏ผ | โ
ๅฎๆ |
|
| 33 |
+
| 6 | `state.py` | ๆฐๆฎๆจกๅ | dataclassๅฎไน๏ผMethodFamily, DirectionAnalysis, CandidateRepo, EvalResult, ResearchReport๏ผ | โ
ๅฎๆ |
|
| 34 |
+
| 7 | `test_agents.py` | ๆต่ฏๅทฅๅ
ท | ไธ้ฎๆต่ฏไธคไธชAgent๏ผ6ไธชๆต่ฏ็จไพ๏ผๆญ่จ+ๆฑๆป | โ
ๅฎๆ |
|
| 35 |
+
|
| 36 |
+
### 1.2 ่ฏๅฎ่ฏไผฐ๏ผๅชไบๆฏ็ๆญฃๅฎๆ็๏ผๅชไบๆๅๆๆกไปถ
|
| 37 |
+
|
| 38 |
+
**ๅฏไปฅ100%็กฎ่ฎคๅฎๆ็๏ผ**
|
| 39 |
+
- Agent 1๏ผๆนๅ่งฃๆ๏ผ๏ผ็ฌ็ซๅฏ่ฟ่ก๏ผ3็ฏ่ฎบๆๆต่ฏ้่ฟใ่พๅ
ฅๆ ้ข+ๆ่ฆโ่พๅบ็ปๆๅ็็ ็ฉถๆนๅJSONใ
|
| 40 |
+
- Agent 2๏ผไปๅบ่ฏไผฐ๏ผ๏ผ็ฌ็ซๅฏ่ฟ่ก๏ผ3ไธชๅบๆฏๆต่ฏ้่ฟ๏ผ้ซๅ/ไฝๅ/ไธญ็ญ๏ผใ่พๅ
ฅไปๅบๅ
ไฟกๆฏ+README+ไพ่ตโ่พๅบๅ
ญ็ปดๅบฆ่ฏๅJSONใ
|
| 41 |
+
- ๅ
ฌๅ
ฑๅทฅๅ
ทๅฑ๏ผllm_utils.py๏ผ๏ผAPI้่ฏใJSON่งฃๆๅฎน้ใ่พๅบๆ ก้ชๅ
จ้จๅฐฑ็ปชใ
|
| 42 |
+
- ๆต่ฏๅฅไปถ๏ผtest_agents.py๏ผ๏ผไธ้ฎ่ฟ่ก๏ผ6/6้่ฟใ
|
| 43 |
+
|
| 44 |
+
**ไปฃ็ ๅทฒๅฎๆไฝ้็ฒไบคไปๅๆ่ฝ้ช่ฏ็๏ผ**
|
| 45 |
+
- `run.py`๏ผ่ฐๅบฆ้ป่พๅฎๆด๏ผๅซ่ๆถ็ป่ฎกใๆนๆณๆๅน้
๏ผไธญ่ฑๅ่ฏญๅ
ณ้ฎ่ฏ๏ผใ้่ฏฏๅค็้พ่ทฏใไฝ**ๆ ๆณ่ฟ่ก**โโๅฎไพ่ต็ฒ็3ไธชๆจกๅ๏ผๅฝๅๅฏผๅ
ฅๅณๆฅ้ใ
|
| 46 |
+
- `app.py`๏ผGradio็้ข + Markdownๆ ผๅผๅๅฎๆดใๅๆ ท**ๆ ๆณๅฏๅจ**โโๅฎๅฏผๅ
ฅ `run`๏ผ่ `run` ๅฏผๅ
ฅ็ฒ็ๆจกๅใ
|
| 47 |
+
|
| 48 |
+
**ๅทฒ็ฅๅฑ้๏ผ้bug๏ผๆฏMVP่ๅดๅ
็ๅ่๏ผ๏ผ**
|
| 49 |
+
- `_match_family` ไปๅบโๆนๆณๆๅน้
ๆฏๅ
ณ้ฎ่ฏ็บงๅซ็๏ผ้LLM่ฏญไนๅน้
ใๅฝLLM่ฟๅไธญๆๆนๆณๆๅ๏ผๅฆ"ๅบไบ้ๅปบ็ๆนๆณ"๏ผๆถ๏ผไพ่ตไธญ่ฑๅ่ฏญๅ
ณ้ฎ่ฏๆ ๅฐๆฅๅ
ๅบ๏ผไฝไธ่ฝไฟ่ฏ100%ๅ็กฎใๆญฃ็กฎ็ไผฐ่ฎก70-80%ใไปปๅกไนฆ่ฎกๅไธญ Week 3 ็จ LLM ๆฟๆขใ
|
| 50 |
+
- LLM่พๅบไพ่ตๆ็คบ่ฏ็บฆๆ๏ผๅถๆๆ ผๅผๅๅทฎใๅทฒ้่ฟ `parse_json_safe`๏ผ6็ง่งฃๆ็ญ็ฅ๏ผ+ `validate_*_output`๏ผๅญๆฎตๅกซๅ
้ป่ฎคๅผ๏ผๅ้ๅ
ๅบ๏ผ็กฎไฟไธๆธธไธๅดฉๆบใ
|
| 51 |
+
|
| 52 |
+
### 1.3 ่ชๆฃๅฝไปค
|
| 53 |
+
|
| 54 |
+
```bash
|
| 55 |
+
# ็ฒๆจกๅๅฐๆชไบคไปๆถ๏ผๅช่ฝ่ฟ่ก่ฟไธคไธช๏ผ
|
| 56 |
+
python direction_analyzer.py # ๆต่ฏ Agent 1๏ผ3็ฏ่ฎบๆ๏ผ
|
| 57 |
+
python repo_evaluator.py # ๆต่ฏ Agent 2๏ผ3ไธชไปๅบๅบๆฏ๏ผ
|
| 58 |
+
python test_agents.py # ไธ้ฎๆต่ฏไธคไธชAgent๏ผๆจ่๏ผ
|
| 59 |
+
|
| 60 |
+
# ็ฒๆจกๅไบคไปๅ๏ผ
|
| 61 |
+
python run.py https://arxiv.org/abs/2011.08785 # ๅฎๆด้พ่ทฏ
|
| 62 |
+
python app.py # ๅฏๅจ Gradio ็้ข
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
---
|
| 66 |
+
|
| 67 |
+
## 2. ็ฒ้ไบคไป็3ไธชๆจกๅ๏ผAPIๅฅ็บฆ๏ผ
|
| 68 |
+
|
| 69 |
+
> **้่ฆ**๏ผไปฅไธๅฅ็บฆๆฏๅๆนไปฃ็ ่ฝๅฏนๆฅ็**ๅฏไธๆฅๅฃๆ ๅ**ใๅฝๆฐๅใๅๆฐๅใ่ฟๅๅผ็ฑปๅใdict็keyๅ้ฝๅฟ
้กปไธฅๆ ผไธ่ดใๅฆๆๅๅจ๏ผๅฟ
้กปๅๆนๅๆญฅ็กฎ่ฎคใ
|
| 70 |
+
|
| 71 |
+
### 2.1 paper_fetcher.py
|
| 72 |
+
|
| 73 |
+
**่่ดฃ**๏ผๆ นๆฎ arxiv URL ่ทๅ่ฎบๆๅ
ไฟกๆฏใ
|
| 74 |
+
|
| 75 |
+
#### ๅฝๆฐ็ญพๅ
|
| 76 |
+
|
| 77 |
+
```python
|
| 78 |
+
def fetch_paper_info(arxiv_url: str) -> dict:
|
| 79 |
+
"""ไป arxiv URL ่ทๅ่ฎบๆไฟกๆฏใ
|
| 80 |
+
|
| 81 |
+
Args:
|
| 82 |
+
arxiv_url: arxiv ่ฎบๆ URL๏ผๅฆ "https://arxiv.org/abs/2011.08785"
|
| 83 |
+
|
| 84 |
+
Returns:
|
| 85 |
+
dict๏ผๅฟ
้กปๅ
ๅซไปฅไธๅญๆฎตใๅฆ่ทๅๅคฑ่ดฅ๏ผๆๅบ Exceptionใ
|
| 86 |
+
"""
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
#### ่ฟๅๅผ dict ๅญๆฎตๅฎไน
|
| 90 |
+
|
| 91 |
+
| ๅญๆฎตๅ | ็ฑปๅ | ๅฟ
้ | ่ฏดๆ | ็คบไพ |
|
| 92 |
+
|--------|------|------|------|------|
|
| 93 |
+
| `arxiv_id` | `str` | โ
ๅฟ
้ | arxiv ID | `"2011.08785"` |
|
| 94 |
+
| `title` | `str` | โ
ๅฟ
้ | ่ฎบๆๆ ้ข๏ผๅฎๆด๏ผไธ่ฆๆชๆญ๏ผ | `"PaDiM: a Patch Distribution Modeling..."` |
|
| 95 |
+
| `abstract` | `str` | โ
ๅฟ
้ | ่ฎบๆๆ่ฆ๏ผๅฎๆด๏ผ | `"We present a new framework..."` |
|
| 96 |
+
| `authors` | `list[str]` | โ
ๅฟ
้ | ไฝ่
ๅ่กจ | `["Thomas Defard", ...]` |
|
| 97 |
+
| `published` | `str` | ๆจ่ | ๅ่กจๆฅๆ๏ผISOๆ ผๅผๅญ็ฌฆไธฒๅณๅฏ๏ผ | `"2021-03-15"` ๆ `"2021-03-15T00:00:00Z"` |
|
| 98 |
+
| `categories` | `list[str]` | ๆจ่ | arxiv ๅ็ฑปๆ ็ญพ | `["cs.CV", "cs.LG"]` |
|
| 99 |
+
|
| 100 |
+
#### ไน็่ฐ็จไธไธๆ
|
| 101 |
+
|
| 102 |
+
```python
|
| 103 |
+
# run.py ็ฌฌ74่ก๏ผ
|
| 104 |
+
paper = fetch_paper_info(arxiv_url)
|
| 105 |
+
|
| 106 |
+
# ็ดงๆฅ็ไฝฟ็จ็ๅญๆฎต๏ผ็ฌฌ78-82่ก๏ผ๏ผ
|
| 107 |
+
title = paper.get("title", "")
|
| 108 |
+
abstract = paper.get("abstract", "")
|
| 109 |
+
# authors ๅ categories ไป
็จไบๆๅฐๆฅๅฟ
|
| 110 |
+
# app.py ้ขๅคไฝฟ็จ arxiv_id ๅ published ๆพ็คบๅจ็ ๆฅไธญ
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
#### ๅฎ็ฐๆ็คบ๏ผ็ป็ฒ๏ผ
|
| 114 |
+
|
| 115 |
+
- arxiv ๆๅ
ฌๅผ API๏ผ`https://export.arxiv.org/api/query?id_list={arxiv_id}`
|
| 116 |
+
- ่ฟๅ XML ๆ ผๅผ๏ผ้่ฆ่งฃๆ `<title>`, `<summary>`, `<author>`, `<published>`, `<category>` ็ญๆ ็ญพ
|
| 117 |
+
- ไนๅฏไปฅ็จ `arxiv` Python ๅ
๏ผ`pip install arxiv`๏ผ
|
| 118 |
+
- ๅฆๆ็ฝ็ปไธ้๏ผๅฏไปฅ็ดๆฅๆๅบๅผๅธธ๏ผrun.py ไผๆ่ทๅนถ่ฟๅ้่ฏฏไฟกๆฏ
|
| 119 |
+
- ๅปบ่ฎฎๅจ `__main__` ้ๅไธช่ชๆต๏ผ`python paper_fetcher.py` ๆๅฐไธ็ฏ่ฎบๆ็ไฟกๆฏ
|
| 120 |
+
|
| 121 |
+
---
|
| 122 |
+
|
| 123 |
+
### 2.2 repo_searcher.py
|
| 124 |
+
|
| 125 |
+
**่่ดฃ**๏ผๆ นๆฎๆ็ดขๆฅ่ฏขๅ่กจๅจ GitHub ไธๆ็ดขไปๅบ๏ผๅป้ๅ่ฟๅใ
|
| 126 |
+
|
| 127 |
+
#### ๅฝๆฐ็ญพๅ
|
| 128 |
+
|
| 129 |
+
```python
|
| 130 |
+
def search_repos(queries: list[str], max_per_keyword: int = 5) -> list[dict]:
|
| 131 |
+
"""ๅจ GitHub ๆ็ดขไปๅบใ
|
| 132 |
+
|
| 133 |
+
Args:
|
| 134 |
+
queries: ๆ็ดขๆฅ่ฏขๅญ็ฌฆไธฒๅ่กจ๏ผๅฆ ["padim anomaly detection pytorch", ...]
|
| 135 |
+
max_per_keyword: ๆฏไธชๆฅ่ฏขๆๅคไฟ็็ไปๅบๆฐ
|
| 136 |
+
|
| 137 |
+
Returns:
|
| 138 |
+
list[dict]: ๅ้ไปๅบๅ่กจ๏ผๆฏไธช dict ๅญๆฎต่งไธ่กจใๅทฒๅป้๏ผๆ full_name๏ผใ
|
| 139 |
+
"""
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
#### ่ฟๅๅผ list[dict] ๅญๆฎตๅฎไน
|
| 143 |
+
|
| 144 |
+
| ๅญๆฎตๅ | ็ฑปๅ | ๅฟ
้ | ่ฏดๆ | ็คบไพ |
|
| 145 |
+
|--------|------|------|------|------|
|
| 146 |
+
| `full_name` | `str` | โ
ๅฟ
้ | ไปๅบๅ
จๅ๏ผowner/repo๏ผ | `"openvinotoolkit/anomalib"` |
|
| 147 |
+
| `html_url` | `str` | โ
ๅฟ
้ | ไปๅบ URL | `"https://github.com/openvinotoolkit/anomalib"` |
|
| 148 |
+
| `description` | `str` | โ
ๅฟ
้ | ไปๅบๆ่ฟฐ๏ผๅฏไธบ็ฉบๅญ็ฌฆไธฒ๏ผ | `"An anomaly detection library..."` |
|
| 149 |
+
| `stars` | `int` | โ
ๅฟ
้ | Star ๆฐ้ | `4000` |
|
| 150 |
+
| `language` | `str` | โ
ๅฟ
้ | ไธป่ฆ่ฏญ่จ | `"Python"` |
|
| 151 |
+
| `updated_at` | `str` | โ
ๅฟ
้ | ๆๅๆดๆฐๆถ้ด๏ผISOๆ ผๅผ๏ผ | `"2026-01-15T00:00:00Z"` |
|
| 152 |
+
| `topics` | `list[str]` | โ
ๅฟ
้ | GitHub topics ๆ ็ญพ๏ผๅฏไธบ็ฉบๅ่กจ๏ผ | `["anomaly-detection", "pytorch"]` |
|
| 153 |
+
| `match_keyword` | `str` | ๆจ่ | ๅฝไธญไบๅชไธชๆ็ดขๆฅ่ฏข๏ผ็จไบ็ ๆฅๅฑ็คบ๏ผ | `"padim anomaly detection pytorch"` |
|
| 154 |
+
|
| 155 |
+
#### ไน็่ฐ็จไธไธๆ
|
| 156 |
+
|
| 157 |
+
```python
|
| 158 |
+
# run.py ็ฌฌ119่ก๏ผ
|
| 159 |
+
candidates = search_repos(all_queries, max_per_keyword=5)
|
| 160 |
+
# all_queries ็คบไพ๏ผ18ไธชๆ็ดข่ฏ๏ผ๏ผ
|
| 161 |
+
# ["patch distribution modeling anomaly detection pytorch",
|
| 162 |
+
# "padim implementation pytorch",
|
| 163 |
+
# "memory bank anomaly detection code",
|
| 164 |
+
# ...,
|
| 165 |
+
# "industrial anomaly detection pytorch", โ broad_queries
|
| 166 |
+
# "unsupervised anomaly localization github",
|
| 167 |
+
# "MVTec AD anomaly detection code"]
|
| 168 |
+
|
| 169 |
+
# ็ดงๆฅ็๏ผ็ฌฌ127่ก๏ผๅๅ top_n=5 ไธช๏ผ
|
| 170 |
+
candidates = candidates[:top_n]
|
| 171 |
+
|
| 172 |
+
# ็ถๅๅฏนๆฏไธช candidate ไฝฟ็จๅญๆฎต๏ผ็ฌฌ152-166่ก๏ผ๏ผ
|
| 173 |
+
full_name = repo["full_name"] # ็จไบๆๅ owner/name ๅๆพ็คบ
|
| 174 |
+
repo.get("html_url", "") # ็จไบ็ ๆฅ้พๆฅ
|
| 175 |
+
repo.get("description", "") # ็จไบๆนๆณๆๅน้
|
| 176 |
+
repo.get("stars", 0) # ็จไบ่ฏๅ่พๅ
ฅๅๆพ็คบ
|
| 177 |
+
repo.get("match_keyword", "") # ็จไบ็ ๆฅๅฑ็คบ
|
| 178 |
+
```
|
| 179 |
+
|
| 180 |
+
#### ้่ฆ็บฆๆ
|
| 181 |
+
|
| 182 |
+
- **ๅป้**๏ผๅไธไธช `full_name` ๅช่ฝๅบ็ฐไธๆฌกใๅคไธชๆ็ดขๆฅ่ฏขๅฏ่ฝๅฝไธญๅไธไธชไปๅบใ
|
| 183 |
+
- **ๆๅบ**๏ผๅปบ่ฎฎๆ `stars` ้ๅบๆๅๅๅๅป้๏ผ่ฟๆ ทไฟ็็ๆฏ star ๆ้ซ็็ๆฌใ
|
| 184 |
+
- **max_per_keyword**๏ผไนไผ 5๏ผๆๅณ็ๆฏไธชๆ็ดขๆฅ่ฏขๆๅค่ฟๅ5ไธชไปๅบใๅฆๆ `all_queries` ๆ18ไธช๏ผ็่ฎบๆๅค90ไธช๏ผๅป้ๅ้ๅธธๅฉ10-30ไธชใไนๅๆชๆญๅฐ5ไธชใ
|
| 185 |
+
- **GitHub API**๏ผๅฏไปฅ็จ `GET /search/repositories?q=...`๏ผๆช่ฎค่ฏ้ๅถ 10 req/min๏ผ่ฎค่ฏๅ 30 req/minใๅฆๆ18ไธชๆฅ่ฏขๅ
จ่ตฐAPIๅฏ่ฝ่งฆๅ้ๆตใๅปบ่ฎฎ๏ผๅฆๆๆ GitHub token๏ผๆพๅฐ header ้ใ
|
| 186 |
+
|
| 187 |
+
#### ๅฎ็ฐๆ็คบ๏ผ็ป็ฒ๏ผ
|
| 188 |
+
|
| 189 |
+
```python
|
| 190 |
+
# GitHub Search API ็คบไพ
|
| 191 |
+
import requests
|
| 192 |
+
url = "https://api.github.com/search/repositories"
|
| 193 |
+
params = {"q": query, "sort": "stars", "order": "desc", "per_page": max_per_keyword}
|
| 194 |
+
headers = {"Accept": "application/vnd.github.v3+json"}
|
| 195 |
+
# ๅฆๆๆ token: headers["Authorization"] = "token ghp_xxx"
|
| 196 |
+
response = requests.get(url, params=params, headers=headers)
|
| 197 |
+
data = response.json()
|
| 198 |
+
for item in data.get("items", []):
|
| 199 |
+
# ๆๅๅญๆฎตๆๅปบ dict
|
| 200 |
+
...
|
| 201 |
+
```
|
| 202 |
+
|
| 203 |
+
---
|
| 204 |
+
|
| 205 |
+
### 2.3 repo_fetcher.py
|
| 206 |
+
|
| 207 |
+
**่่ดฃ**๏ผ่ทๅๅไธชไปๅบ็ README ๅไพ่ตๆไปถๅ
ๅฎนใ
|
| 208 |
+
|
| 209 |
+
#### ๅฝๆฐ็ญพๅ
|
| 210 |
+
|
| 211 |
+
```python
|
| 212 |
+
def fetch_readme(owner: str, name: str) -> str | None:
|
| 213 |
+
"""่ทๅไปๅบ README ๆไปถๅ
ๅฎนใ
|
| 214 |
+
|
| 215 |
+
Args:
|
| 216 |
+
owner: ไปๅบๆๆ่
๏ผๅฆ "openvinotoolkit"
|
| 217 |
+
name: ไปๅบๅ๏ผๅฆ "anomalib"
|
| 218 |
+
|
| 219 |
+
Returns:
|
| 220 |
+
README ๆไปถๅ
จๆ๏ผๅญ็ฌฆไธฒ๏ผ๏ผ่ทๅๅคฑ่ดฅ่ฟๅ Noneใ
|
| 221 |
+
"""
|
| 222 |
+
|
| 223 |
+
def fetch_dependencies(owner: str, name: str) -> dict[str, str]:
|
| 224 |
+
"""่ทๅไปๅบ็ไพ่ตๆไปถใ
|
| 225 |
+
|
| 226 |
+
Args:
|
| 227 |
+
owner: ไปๅบๆๆ่
|
| 228 |
+
name: ไปๅบๅ
|
| 229 |
+
|
| 230 |
+
Returns:
|
| 231 |
+
dict: {ๆไปถๅ: ๆไปถๅ
ๅฎน}๏ผๅฆ {"requirements.txt": "torch>=1.10\n...", ...}
|
| 232 |
+
ๆพไธๅฐไปปไฝไพ่ตๆไปถๆถ่ฟๅ็ฉบ dict {}ใ
|
| 233 |
+
ๅธธ่ง็ฎๆ ๆไปถ๏ผrequirements.txt, environment.yml, setup.py, setup.cfg, Pipfile, pyproject.toml
|
| 234 |
+
"""
|
| 235 |
+
```
|
| 236 |
+
|
| 237 |
+
#### ไน็่ฐ็จไธไธๆ
|
| 238 |
+
|
| 239 |
+
```python
|
| 240 |
+
# run.py ็ฌฌ165-167่ก๏ผๅจ for ๅพช็ฏๅ
ๅฏนๆฏไธชไปๅบ่ฐ็จ๏ผ๏ผ
|
| 241 |
+
readme = fetch_readme(owner, name) # โ str | None
|
| 242 |
+
deps = fetch_dependencies(owner, name) # โ dict[str, str]
|
| 243 |
+
evaluation = evaluate_repo(repo, readme, deps, matched_family)
|
| 244 |
+
|
| 245 |
+
# repo_evaluator.py ๅ
้จ๏ผ็ฌฌ105่ก๏ผ๏ผ
|
| 246 |
+
readme_text = (readme or "README ๆชๆพๅฐ")[:2500] # ๆชๆญๅฐ 2500 ๅญ็ฌฆ
|
| 247 |
+
# deps ่ขซๆ ผๅผๅไธบๆๆฌๅๅๆ ทๆชๆญๆฏไธชๆไปถๅฐ 1000 ๅญ็ฌฆ
|
| 248 |
+
```
|
| 249 |
+
|
| 250 |
+
#### ้่ฆ็บฆๆ
|
| 251 |
+
|
| 252 |
+
- `fetch_readme`๏ผGitHub API ่ทฏๅพ `GET /repos/{owner}/{name}/readme`๏ผ่ฟๅ base64 ็ผ็ ๅ
ๅฎน๏ผ้่งฃ็ ใ
|
| 253 |
+
- `fetch_dependencies`๏ผ้่ฆ้ไธชๆฃๆฅไพ่ตๆไปถๆฏๅฆๅญๅจใGitHub API `GET /repos/{owner}/{name}/contents/{path}`ใ**ไธ่ฆ**ๆๆดไธชไปๅบ clone ไธๆฅโโMVP ้ถๆฎตไธไธช API ่ฐ็จๅณๅฏใ
|
| 254 |
+
- ไธคไธชๅฝๆฐ้ฝ**ไธ่ฝๆๅบๅผๅธธ**ใๅคฑ่ดฅๆถ่ฟๅ `None` ๆ `{}`ใไน็่ฐๅบฆๅจๅทฒ็ปๅฏนๆฏไธชไปๅบๅไบ try/except๏ผไฝๅฆๆๅฝๆฐๅ
้จๆๅบๅผๅธธ๏ผ่ฏไผฐๅพช็ฏๅฏ่ฝไผไธญๆญ๏ผๅฝๅๅชๆ่ทไบ่ฏไผฐๅคฑ่ดฅ๏ผๆชๆ่ท fetch ๅคฑ่ดฅโโ่ฟๆฏไธไธชไนๅทฒ็ฅ็้ฒๅพก็ผบๅฃ๏ผ่ง7.1่๏ผใ
|
| 255 |
+
|
| 256 |
+
#### ๅฎ็ฐๆ็คบ๏ผ็ป็ฒ๏ผ
|
| 257 |
+
|
| 258 |
+
```python
|
| 259 |
+
import requests
|
| 260 |
+
import base64
|
| 261 |
+
|
| 262 |
+
def fetch_readme(owner, name):
|
| 263 |
+
url = f"https://api.github.com/repos/{owner}/{name}/readme"
|
| 264 |
+
headers = {"Accept": "application/vnd.github.v3+json"}
|
| 265 |
+
resp = requests.get(url, headers=headers)
|
| 266 |
+
if resp.status_code != 200:
|
| 267 |
+
return None
|
| 268 |
+
content = resp.json().get("content", "")
|
| 269 |
+
return base64.b64decode(content).decode("utf-8", errors="replace")
|
| 270 |
+
|
| 271 |
+
def fetch_dependencies(owner, name):
|
| 272 |
+
target_files = ["requirements.txt", "environment.yml", "setup.py",
|
| 273 |
+
"setup.cfg", "Pipfile", "pyproject.toml"]
|
| 274 |
+
result = {}
|
| 275 |
+
for fname in target_files:
|
| 276 |
+
url = f"https://api.github.com/repos/{owner}/{name}/contents/{fname}"
|
| 277 |
+
resp = requests.get(url, headers={"Accept": "application/vnd.github.v3+json"})
|
| 278 |
+
if resp.status_code == 200:
|
| 279 |
+
content = resp.json().get("content", "")
|
| 280 |
+
result[fname] = base64.b64decode(content).decode("utf-8", errors="replace")
|
| 281 |
+
return result
|
| 282 |
+
```
|
| 283 |
+
|
| 284 |
+
---
|
| 285 |
+
|
| 286 |
+
## 3. ๆฐๆฎๆตๅ
จๆฏๅพ
|
| 287 |
+
|
| 288 |
+
```
|
| 289 |
+
็จๆท่พๅ
ฅ arxiv URL
|
| 290 |
+
โ
|
| 291 |
+
โผ
|
| 292 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 293 |
+
โ [1/5] paper_fetcher.py โ ็ฒ๏ผWorkflow๏ผ โ
|
| 294 |
+
โ fetch_paper_info(url) โ dict โ
|
| 295 |
+
โ {arxiv_id, title, abstract, authors, published, categories} โ
|
| 296 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 297 |
+
โ title, abstract
|
| 298 |
+
โผ
|
| 299 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 300 |
+
โ [2/5] direction_analyzer.py โ ไน๏ผAgent 1๏ผ โ
|
| 301 |
+
โ analyze_direction(title, abstract) โ dict โ
|
| 302 |
+
โ {subfield, subfield_trend, method_families, broad_queries} โ
|
| 303 |
+
โ โ
|
| 304 |
+
โ method_families: [ โ
|
| 305 |
+
โ {family_name, description, representative_work, โ
|
| 306 |
+
โ search_queries: ["...", "..."]} โ
|
| 307 |
+
โ ] โ
|
| 308 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 309 |
+
โ all_queries = flatten(search_queries) + broad_queries
|
| 310 |
+
โ ็บฆ 12-18 ไธชๆ็ดขๅญ็ฌฆไธฒ
|
| 311 |
+
โผ
|
| 312 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 313 |
+
โ [3/5] repo_searcher.py โ ็ฒ๏ผWorkflow๏ผ โ
|
| 314 |
+
โ search_repos(queries, max_per_keyword=5) โ list[dict] โ
|
| 315 |
+
โ [{full_name, html_url, description, stars, language, โ
|
| 316 |
+
โ updated_at, topics, match_keyword}] โ
|
| 317 |
+
โ โ
|
| 318 |
+
โ ๅป้ โ ๆชๆญ top_n=5 โ ไผ ็ปไธไธๆญฅ โ
|
| 319 |
+
โโโโโโโโโโโโโโ๏ฟฝ๏ฟฝโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 320 |
+
โ ๆฏไธชๅ้ไปๅบ: full_name โ owner/name
|
| 321 |
+
โผ
|
| 322 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 323 |
+
โ [4/5] ๅฏนๆฏไธชไปๅบๅนถ่ก๏ผ โ
|
| 324 |
+
โ โ
|
| 325 |
+
โ repo_fetcher.py โ ็ฒ๏ผWorkflow๏ผ โ
|
| 326 |
+
โ fetch_readme(owner, name) โ str | None โ
|
| 327 |
+
โ fetch_dependencies(owner, name) โ dict[str, str] โ
|
| 328 |
+
โ โ
|
| 329 |
+
โ run.py โ ไน๏ผ่ฐๅบฆๅจ๏ผ โ
|
| 330 |
+
โ _match_family(repo, families) โ str (ๆนๆณๆๅ or "") โ
|
| 331 |
+
โ โ
|
| 332 |
+
โ repo_evaluator.py โ ไน๏ผAgent 2๏ผ โ
|
| 333 |
+
โ evaluate_repo(repo, readme, deps, method_family) โ dict โ
|
| 334 |
+
โ {reproducibility_score, benchmark_fitness_score, โ
|
| 335 |
+
โ overall_score, verdict, env_score, doc_score, โ
|
| 336 |
+
โ code_score, community_score, dep_score, โ
|
| 337 |
+
โ benchmark_score, reasoning, risks, โ
|
| 338 |
+
โ benchmark_readiness, suggested_use} โ
|
| 339 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 340 |
+
โ ๆ overall_score ้ๅบๆๅ
|
| 341 |
+
โผ
|
| 342 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 343 |
+
โ [5/5] app.py โ ไน๏ผUI๏ผ โ
|
| 344 |
+
โ format_report(result) โ Markdown ็ ๆฅ โ
|
| 345 |
+
โ โ
|
| 346 |
+
โ ็ ๆฅ็ปๆ๏ผ โ
|
| 347 |
+
โ ไธใ่ฎบๆไฟกๆฏ๏ผarxiv_id, title, authors, categories๏ผ โ
|
| 348 |
+
โ ไบใ็ ็ฉถๆนๅๅ
จๆฏ๏ผๅญ้ขๅ + ่ถๅฟ + ๆนๆณๆ่ฐฑ็ณป่กจๆ ผ๏ผ โ
|
| 349 |
+
โ ไธใไปๅบ่ฏไผฐๆๅ๏ผๆฏไธชไปๅบๅ
ญ็ปดๅบฆๆ็ป + ๅๆ + ้ฃ้ฉ็น๏ผ โ
|
| 350 |
+
โ ๅใๅฏนๆฏๅฎ้ชๆจ่ๆป็ป๏ผๆ ready/partial/not_ready ๅ็ป๏ผ โ
|
| 351 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 352 |
+
```
|
| 353 |
+
|
| 354 |
+
### ๆฐๆฎ้็บงๅ่
|
| 355 |
+
|
| 356 |
+
| ้ถๆฎต | ่พๅ
ฅ | ่พๅบ | ้ข่ฎก่ๆถ |
|
| 357 |
+
|------|------|------|----------|
|
| 358 |
+
| 1. ่ฎบๆไฟกๆฏ | 1ไธชURL | 1ไธชdict | ~1s๏ผ็ฝ็ป๏ผ |
|
| 359 |
+
| 2. ๆนๅ่งฃๆ | ๆ ้ข+ๆ่ฆ | 1ไธชdict๏ผ3-6ๆนๆณๆ+3ๅฎฝๆณ๏ผ | ~5-15s๏ผLLM๏ผ |
|
| 360 |
+
| 3. ไปๅบๆ็ดข | ~15ไธชๆฅ่ฏข | ~5ไธชๅ้ไปๅบ | ~10-30s๏ผGitHub API ร 15๏ผ |
|
| 361 |
+
| 4. ไปๅบ่ฏไผฐ | 5ไธชไปๅบ ร (README+ไพ่ต) | 5ไธชevaluation dict | ~25-75s๏ผLLM ร 5๏ผ |
|
| 362 |
+
| **ๅ่ฎก** | | | **็บฆ40-120็ง** |
|
| 363 |
+
|
| 364 |
+
---
|
| 365 |
+
|
| 366 |
+
## 4. ๅฏนๆฅๆญฅ้ชค๏ผๆๆฏ + ๆฒ้๏ผ
|
| 367 |
+
|
| 368 |
+
### 4.1 ็ฒไบคไปๆไปถๆถ
|
| 369 |
+
|
| 370 |
+
็ฒๆฏๆฌกไบคไปไธไธชๆจกๅ๏ผไนๆนๆไปฅไธๆต็จ้ช่ฏใ
|
| 371 |
+
|
| 372 |
+
#### ้ถๆฎตA๏ผ็ฒไบคไป `paper_fetcher.py`
|
| 373 |
+
|
| 374 |
+
**็ฒ้็กฎไฟ๏ผ**
|
| 375 |
+
- [ ] ๆไปถๅ๏ผ`paper_fetcher.py`
|
| 376 |
+
- [ ] ๆพๅ
ฅ่ทฏๅพ๏ผ`D:\Desktop\AI_opencode_judging\paper_fetcher.py`
|
| 377 |
+
- [ ] ๆไปถๅ
ๅ
ๅซๅฝๆฐ `fetch_paper_info(arxiv_url: str) -> dict`
|
| 378 |
+
- [ ] ่ชๆตๅฏ่ฟ่ก๏ผ`python paper_fetcher.py` ่ฝๆๅฐไธ็ฏ่ฎบๆ็ไฟกๆฏ
|
| 379 |
+
- [ ] ่ฟๅๅผๅ
ๅซๆๆๅฟ
้ๅญๆฎต๏ผ่ง2.1่๏ผ
|
| 380 |
+
|
| 381 |
+
**ไน้ช่ฏๆญฅ้ชค๏ผ**
|
| 382 |
+
```bash
|
| 383 |
+
# 1. ็กฎ่ฎคๆไปถๅญๅจ
|
| 384 |
+
ls paper_fetcher.py
|
| 385 |
+
|
| 386 |
+
# 2. ๆฃๆฅๅฝๆฐ็ญพๅ
|
| 387 |
+
python -c "from paper_fetcher import fetch_paper_info; help(fetch_paper_info)"
|
| 388 |
+
|
| 389 |
+
# 3. ๆต่ฏๅฎ้
่ฐ็จ
|
| 390 |
+
python -c "
|
| 391 |
+
from paper_fetcher import fetch_paper_info
|
| 392 |
+
paper = fetch_paper_info('https://arxiv.org/abs/2011.08785')
|
| 393 |
+
for k in ['arxiv_id', 'title', 'abstract', 'authors']:
|
| 394 |
+
print(f'{k}: {str(paper.get(k))[:80]}...')
|
| 395 |
+
"
|
| 396 |
+
|
| 397 |
+
# 4. ็กฎ่ฎค run.py ไธๅๆฅ paper_fetcher ็ ImportError
|
| 398 |
+
python -c "import run" 2>&1 | head -5
|
| 399 |
+
# ้ขๆ๏ผไธๅๅบ็ฐ "็ผบๅฐๆจกๅ: paper_fetcher.py"๏ผ่ๆฏๆฅไธไธไธช็ผบๅคฑๆจกๅ
|
| 400 |
+
```
|
| 401 |
+
|
| 402 |
+
#### ้ถๆฎตB๏ผ็ฒไบคไป `repo_searcher.py`
|
| 403 |
+
|
| 404 |
+
**็ฒ้็กฎไฟ๏ผ**
|
| 405 |
+
- [ ] ๆไปถๅ๏ผ`repo_searcher.py`
|
| 406 |
+
- [ ] ๅฝๆฐ `search_repos(queries: list[str], max_per_keyword: int = 5) -> list[dict]`
|
| 407 |
+
- [ ] ่ชๆตๅฏ่ฟ่ก๏ผ็จๅ ไธชๆ้ ็ๆ็ดข่ฏ่ฐ็จ๏ผๆๅฐ่ฟๅ็ไปๅบๆฐ้ๅๅ็งฐ
|
| 408 |
+
- [ ] ๅป้ๅทฒๅฎ็ฐ๏ผๅไธ full_name ๅชๅบ็ฐไธๆฌก๏ผ
|
| 409 |
+
- [ ] ๆฏไธช dict ๅ
ๅซๆๆๅฟ
้ๅญๆฎต๏ผ่ง2.2่๏ผ
|
| 410 |
+
|
| 411 |
+
**ไน้ช่ฏๆญฅ้ชค๏ผ**
|
| 412 |
+
```bash
|
| 413 |
+
# 1. ็กฎ่ฎคๆ็ดขๅฏ็จ
|
| 414 |
+
python -c "
|
| 415 |
+
from repo_searcher import search_repos
|
| 416 |
+
repos = search_repos(['padim anomaly detection pytorch'], max_per_keyword=3)
|
| 417 |
+
print(f'ๆพๅฐ {len(repos)} ไธชไปๅบ')
|
| 418 |
+
for r in repos:
|
| 419 |
+
print(f' {r[\"full_name\"]} โญ{r[\"stars\"]} โ {r.get(\"match_keyword\", \"?\")}')
|
| 420 |
+
"
|
| 421 |
+
|
| 422 |
+
# 2. ็กฎ่ฎค run.py ไธๅๆฅ repo_searcher ็ ImportError
|
| 423 |
+
python -c "import run" 2>&1 | head -5
|
| 424 |
+
# ้ขๆ๏ผไธๅๅบ็ฐ "็ผบๅฐๆจกๅ: repo_searcher.py"๏ผ่ๆฏๆฅไธไธไธช็ผบๅคฑๆจกๅ
|
| 425 |
+
```
|
| 426 |
+
|
| 427 |
+
#### ้ถๆฎตC๏ผ็ฒไบคไป `repo_fetcher.py`
|
| 428 |
+
|
| 429 |
+
**็ฒ้็กฎไฟ๏ผ**
|
| 430 |
+
- [ ] ๆไปถๅ๏ผ`repo_fetcher.py`
|
| 431 |
+
- [ ] ๅฝๆฐ `fetch_readme(owner: str, name: str) -> str | None`
|
| 432 |
+
- [ ] ๅฝๆฐ `fetch_dependencies(owner: str, name: str) -> dict[str, str]`
|
| 433 |
+
- [ ] ่ชๆตๅฏ่ฟ่ก๏ผๅฏน anomalib ไปๅบ่ฐ็จไธคไธชๅฝๆฐ๏ผๆๅฐ็ปๆ
|
| 434 |
+
|
| 435 |
+
**ไน้ช่ฏๆญฅ้ชค๏ผ**
|
| 436 |
+
```bash
|
| 437 |
+
# 1. ็กฎ่ฎค่ฝ่ทๅ README
|
| 438 |
+
python -c "
|
| 439 |
+
from repo_fetcher import fetch_readme
|
| 440 |
+
readme = fetch_readme('openvinotoolkit', 'anomalib')
|
| 441 |
+
print(f'README ้ฟๅบฆ: {len(readme) if readme else 0} ๅญ็ฌฆ')
|
| 442 |
+
print((readme or '')[:200])
|
| 443 |
+
"
|
| 444 |
+
|
| 445 |
+
# 2. ็กฎ่ฎค่ฝ่ทๅไพ่ต
|
| 446 |
+
python -c "
|
| 447 |
+
from repo_fetcher import fetch_dependencies
|
| 448 |
+
deps = fetch_dependencies('openvinotoolkit', 'anomalib')
|
| 449 |
+
print(f'ๆพๅฐ {len(deps)} ไธชไพ่ตๆไปถ: {list(deps.keys())}')
|
| 450 |
+
for fname, content in deps.items():
|
| 451 |
+
print(f' {fname}: {len(content)} ๅญ็ฌฆ')
|
| 452 |
+
"
|
| 453 |
+
|
| 454 |
+
# 3. ็กฎ่ฎค run.py ไธๅๆฅไปปไฝ ImportError
|
| 455 |
+
python -c "import run; print('run.py ๅฏผๅ
ฅๆๅ๏ผ')"
|
| 456 |
+
# ้ขๆ๏ผrun.py ๅฏผๅ
ฅๆๅ๏ผ
|
| 457 |
+
```
|
| 458 |
+
|
| 459 |
+
### 4.2 ๅ
จ้จไบคไปๅ็่่ฐ
|
| 460 |
+
|
| 461 |
+
```bash
|
| 462 |
+
# ็ฌฌไธๆญฅ๏ผ็กฎไฟไน็ไธคไธช Agent ๆญฃๅธธ
|
| 463 |
+
python test_agents.py
|
| 464 |
+
# ้ขๆ๏ผ6/6 ้่ฟ
|
| 465 |
+
|
| 466 |
+
# ็ฌฌไบๆญฅ๏ผ็จไธ็ฏๅทฅไธ็ผบ้ทๆฃๆต่ฎบๆ่ทๅฎๆด้พ่ทฏ
|
| 467 |
+
python run.py https://arxiv.org/abs/2011.08785
|
| 468 |
+
# ้ขๆ๏ผ
|
| 469 |
+
# [1/5] ่ทๅ่ฎบๆไฟกๆฏ โ ๆพ็คบๆ ้ขใไฝ่
ใๅ็ฑปใ่ๆถ
|
| 470 |
+
# [2/5] ่งฃๆ็ ็ฉถๆนๅ โ ๆพ็คบๅญ้ขๅใ่ถๅฟใๆนๆณๆใ็ๆ็ๆ็ดข่ฏๆฐ
|
| 471 |
+
# [3/5] ๆ็ดข GitHub โ ๆพ็คบๅ้ไปๅบๅ่กจ๏ผๆๅค5ไธช๏ผ
|
| 472 |
+
# [4/5] ่ฏไผฐไปๅบ โ ้ไธชๆพ็คบ่ฏๅ
|
| 473 |
+
# [5/5] ๅฎๆ โ ๆๅฐๅฎๆด Markdown ็ ๆฅ
|
| 474 |
+
|
| 475 |
+
# ็ฌฌไธๆญฅ๏ผๅฏๅจ Gradio ็้ข
|
| 476 |
+
python app.py
|
| 477 |
+
# ๆต่งๅจๆๅผ http://127.0.0.1:7860
|
| 478 |
+
# ็ฒ่ดด arxiv URL๏ผ็นๅป Submit๏ผๆฅ็็ ๆฅ
|
| 479 |
+
```
|
| 480 |
+
|
| 481 |
+
### 4.3 ๅฏนๆฅๆถ็ๆฒ้่ฆ็น
|
| 482 |
+
|
| 483 |
+
1. **็ปไธๅผๅ็ฏๅข**
|
| 484 |
+
- Python ็ๆฌ๏ผ3.10+ ๏ผไนๅฝๅไฝฟ็จ 3.11+๏ผ`str | None` ็ฑปๅๆณจ่งฃ้่ฆ 3.10+๏ผ
|
| 485 |
+
- ไพ่ตๅฎ่ฃ
๏ผ`pip install -r requirements.txt`๏ผopenai, gradio, requests ๅทฒๅๅฅฝ๏ผ
|
| 486 |
+
- ็ฒๅฆ้ๆฐๅขไพ่ต๏ผ้ๅๆญฅๆดๆฐ `requirements.txt`
|
| 487 |
+
|
| 488 |
+
2. **GitHub API ้ๆต**
|
| 489 |
+
- ๆช่ฎค่ฏ๏ผ10 ๆฌก/ๅ้ใ18ไธชๆ็ดขๆฅ่ฏขไผ่ถ
้ใ
|
| 490 |
+
- ่ฎค่ฏ๏ผ30 ๆฌก/ๅ้ใๅปบ่ฎฎ็ฒ็ณ่ฏทไธไธช GitHub Personal Access Token๏ผๅ
่ดน๏ผSettings โ Developer settings โ Tokens๏ผ๏ผไธ้่ฆไปปไฝๆ้๏ผpublic repo ๅช่ฏปไธ้่ฆ scope๏ผใ
|
| 491 |
+
- Token ้
็ฝฎๆนๅผ๏ผ็ฒ่ช็ฑ้ๆฉ๏ผ็ฏๅขๅ้ `GITHUB_TOKEN`ใ้
็ฝฎๆไปถใๆ็กฌ็ผ็ โโไฝๅซๆไบคๅฐ git๏ผใ
|
| 492 |
+
|
| 493 |
+
3. **้่ฏฏๅค็็บฆๅฎ**
|
| 494 |
+
- Workflow ๅฝๆฐ๏ผ็ฒ็ๆจกๅ๏ผ๏ผๅฐฝ้ไธๆๅผๅธธใ่ทๅๅคฑ่ดฅ่ฟๅ `None`ใ`[]`ใ`{}` ็ญ็ฉบๅผใ
|
| 495 |
+
- Agent ๅฝๆฐ๏ผไน็ๆจกๅ๏ผ๏ผLLM ่งฃๆๅคฑ่ดฅๆ `ValueError`๏ผAPI ่ฐ็จๅคฑ่ดฅๆ `RuntimeError`ใ
|
| 496 |
+
- ่ฐๅบฆๅจ๏ผrun.py๏ผ๏ผๆ่ทๆๆๅผๅธธ๏ผ่ฝฌไธบ `{"error": "..."}` ๆ fallback ๅผ๏ผไฟ่ฏๆต็จไธๅดฉๆบใ
|
| 497 |
+
|
| 498 |
+
4. **Git ๅไฝๅปบ่ฎฎ**
|
| 499 |
+
```
|
| 500 |
+
D:\Desktop\AI_opencode_judging\
|
| 501 |
+
โโโ .gitignore โ ๅปบ่ฎฎๆทปๅ ๏ผ__pycache__/, .env, *.pyc
|
| 502 |
+
โโโ requirements.txt
|
| 503 |
+
โโโ state.py โ ๅๆนๅ
ฑไบซ็ๆฐๆฎๆจกๅๅ่
|
| 504 |
+
โโโ paper_fetcher.py โ ็ฒ
|
| 505 |
+
โโโ repo_searcher.py โ ็ฒ
|
| 506 |
+
โโโ repo_fetcher.py โ ็ฒ
|
| 507 |
+
โโโ llm_utils.py โ ไน
|
| 508 |
+
โโโ direction_analyzer.py โ ไน
|
| 509 |
+
โโโ repo_evaluator.py โ ไน
|
| 510 |
+
โโโ run.py โ ไน
|
| 511 |
+
โโโ app.py โ ไน
|
| 512 |
+
โโโ test_agents.py โ ไน
|
| 513 |
+
โโโ test_set/ โ ็ฒๆพ็ฝฎๆต่ฏๆฐๆฎ
|
| 514 |
+
```
|
| 515 |
+
|
| 516 |
+
---
|
| 517 |
+
|
| 518 |
+
## 5. ๅฏนๆฅๅๆๆ
|
| 519 |
+
|
| 520 |
+
### 5.1 ๅฎๆด็ ๆฅ็คบไพ๏ผ็ปๆๅฑ็คบ๏ผ
|
| 521 |
+
|
| 522 |
+
ๅฏนๆฅๅฎๆๅ๏ผ่พๅ
ฅ `https://arxiv.org/abs/2011.08785`๏ผPaDiM๏ผ๏ผ่พๅบ็ ๆฅ็ปๆๅฆไธ๏ผ
|
| 523 |
+
|
| 524 |
+
```markdown
|
| 525 |
+
# ResearchRadar ็ ็ฉถๆนๅๅ
จๆฏ็ ๆฅ
|
| 526 |
+
|
| 527 |
+
---
|
| 528 |
+
|
| 529 |
+
## ไธใ่ฎบๆไฟกๆฏ
|
| 530 |
+
|
| 531 |
+
| ้กน็ฎ | ๅ
ๅฎน |
|
| 532 |
+
|------|------|
|
| 533 |
+
| **ๆ ้ข** | PaDiM: a Patch Distribution Modeling Framework for Anomaly Detection and Localization |
|
| 534 |
+
| **arXiv** | [2011.08785](https://arxiv.org/abs/2011.08785) |
|
| 535 |
+
| **ไฝ่
** | Thomas Defard, Aleksandr Setkov, Angelique Loesch, Romaric Audigier |
|
| 536 |
+
| **ๅ่กจๆถ้ด** | 2021-03-15 |
|
| 537 |
+
| **ๅ็ฑป** | cs.CV, cs.LG |
|
| 538 |
+
|
| 539 |
+
---
|
| 540 |
+
|
| 541 |
+
## ไบใ็ ็ฉถๆนๅๅ
จๆฏ
|
| 542 |
+
|
| 543 |
+
### ๅญ้ขๅๅฎไฝ
|
| 544 |
+
|
| 545 |
+
**ๅทฅไธๅพๅๅผๅธธๆฃๆตไธๅฎไฝ**
|
| 546 |
+
|
| 547 |
+
### ๅฝๅ่ถๅฟ
|
| 548 |
+
|
| 549 |
+
2024-2025ๅนดไธปๆต่ถๅฟๅ
ๆฌๅฉ็จ้ข่ฎญ็ป่ง่งๆจกๅๆๅๅฑ้จ็นๅพ๏ผ็ปๅๆฆ็ๅปบๆจก่ฟ่กๆ ็็ฃๅผๅธธๆฃๆต๏ผๅผบ่ฐ้ซๆๆจ็ๅ็ป็ฒๅบฆๅฎไฝใ
|
| 550 |
+
|
| 551 |
+
### ๆนๆณๆ๏ฟฝ๏ฟฝ๏ฟฝ็ณป
|
| 552 |
+
|
| 553 |
+
| # | ๆนๆณๆ | ๆ ธๅฟ็น็น | ไปฃ่กจๅทฅไฝ |
|
| 554 |
+
|---|--------|----------|----------|
|
| 555 |
+
| 1 | **Patch Distribution Modeling** | ้ข่ฎญ็ปCNNๆๅpatch็นๅพ+้ซๆฏๅๅธๅปบๆจก | PaDiM (2021) |
|
| 556 |
+
| 2 | **Memory Bank-based Methods** | ๅญๅจๆญฃๅธธๆ ทๆฌ็นๅพๅฐ่ฎฐๅฟๅบ่ฟ่กๆฃ็ดข | PatchCore (2022) |
|
| 557 |
+
| 3 | **Knowledge Distillation Methods** | ๅธ็็ฝ็ป๏ผๅญฆ็ๅญฆไน ๆจกไปฟๆๅธ่พๅบ | STFPM (2021) |
|
| 558 |
+
| 4 | **Reconstruction-based Methods** | ่ช็ผ็ ๅจ้ๅปบๆญฃๅธธๆ ทๆฌ๏ผๅผๅธธ้ๅปบ่ฏฏๅทฎๅคง | AutoEncoder |
|
| 559 |
+
| 5 | **Synthetic Defect Methods** | ็ๆๅๆ็ผบ้ท็จไบ่ฎญ็ป | DRAEM (2021) |
|
| 560 |
+
|
| 561 |
+
---
|
| 562 |
+
|
| 563 |
+
## ไธใๅผๆบๅฎ็ฐ่ฏไผฐๆๅ
|
| 564 |
+
|
| 565 |
+
### 1. [openvinotoolkit/anomalib](https://github.com/openvinotoolkit/anomalib) `[Embedding-based]`
|
| 566 |
+
|
| 567 |
+
โ
**ๅฏๅค็ฐๆง: 80/80** | ๐ข **ๅฏนๆฏๅฎ้ช้้
ๅบฆ: 20/20** | **็ปผๅ: 100/100**
|
| 568 |
+
|
| 569 |
+
| ็ปดๅบฆ | ๅพๅ | ๆปกๅ | ่ฏดๆ |
|
| 570 |
+
|------|:----:|:----:|------|
|
| 571 |
+
| ็ฏๅข้
็ฝฎ | 15 | 15 | ไพ่ตๆไปถๅฎๆดๆง |
|
| 572 |
+
| ๆๆกฃ่ดจ้ | 20 | 20 | ๅฎ่ฃ
/่ฎญ็ป/ๆฐๆฎ่ฏดๆ |
|
| 573 |
+
| ไปฃ็ ๅฏ็จๆง | 20 | 20 | ่ฎญ็ป+ๆจ็่ๆฌ |
|
| 574 |
+
| ็คพๅบๆดป่ทๅบฆ | 10 | 10 | Star + ๆดๆฐ้ข็ |
|
| 575 |
+
| ไพ่ตๅฅๅบทๅบฆ | 15 | 15 | ไพ่ตๅ
ผๅฎนๆง |
|
| 576 |
+
| **ๅฏนๆฏๅฎ้ช** | **20** | **20** | **benchmark + ้ข่ฎญ็ปๆ้** |
|
| 577 |
+
|
| 578 |
+
โญ Star: 4000 | ๅน้
่ฏ: `anomaly detection library pytorch`
|
| 579 |
+
|
| 580 |
+
**ๅๆ**: anomalibๆไพไบๅฎๆด็benchmarkๆกๆถ๏ผๆฏๆMVTec AD็ญๆ ๅๆฐๆฎ้๏ผๆ้ข่ฎญ็ปๆ้ๅๆ ๅๅ่ฏไผฐ่ๆฌ๏ผๅฏไปฅ็ดๆฅ็จไบๅฏนๆฏๅฎ้ชใ
|
| 581 |
+
|
| 582 |
+
**ๅฏนๆฏๅฎ้ชๅปบ่ฎฎ**: ๅฏไปฅ็ดๆฅไฝไธบๅฏนๆฏๅฎ้ช baseline
|
| 583 |
+
|
| 584 |
+
---
|
| 585 |
+
|
| 586 |
+
### 2. [ๅ
ถไปไปๅบ...]
|
| 587 |
+
|
| 588 |
+
๏ผๆฏไธชไปๅบๅๆ ทๆ ผๅผ็ๅ
ญ็ปดๅบฆๆ็ป่กจ๏ผ
|
| 589 |
+
|
| 590 |
+
---
|
| 591 |
+
|
| 592 |
+
## ๅใๅฏนๆฏๅฎ้ชๆจ่ๆป็ป
|
| 593 |
+
|
| 594 |
+
### ๐ข ๅฏ็ดๆฅ็จไบๅฏนๆฏๅฎ้ช
|
| 595 |
+
|
| 596 |
+
- **[openvinotoolkit/anomalib](https://github.com/openvinotoolkit/anomalib)** โ ๅฏไปฅ็ดๆฅไฝไธบๅฏนๆฏๅฎ้ช baseline
|
| 597 |
+
|
| 598 |
+
### ๐ก ้่ฆๅฐ้ไฟฎๆนๅๅฏ็จ
|
| 599 |
+
|
| 600 |
+
- **[ๅ
ถไปไปๅบ...]** โ ้่ฆ้้
ๆฐๆฎ้ๆ ผๅผ
|
| 601 |
+
|
| 602 |
+
### ๐ด ไป
้ๅๅ่ไปฃ็ ๅฎ็ฐ
|
| 603 |
+
|
| 604 |
+
- **[ๅ
ถไปไปๅบ...]** โ ไป
ๆไพๆจ็demo๏ผๆ ่ฎญ็ป่ๆฌ...
|
| 605 |
+
|
| 606 |
+
---
|
| 607 |
+
|
| 608 |
+
> ResearchRadar ยท ่ฎบๆ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ + ๅฏนๆฏๅฎ้ชๆจ่
|
| 609 |
+
```
|
| 610 |
+
|
| 611 |
+
### 5.2 Gradio ็้ขๆๆ
|
| 612 |
+
|
| 613 |
+
ๆต่งๅจๆๅผ `http://127.0.0.1:7860`๏ผไผ็ๅฐ๏ผ
|
| 614 |
+
- ๆ ้ขๆ ๏ผResearchRadar โ ็ ็ฉถๆนๅๅ
จๆฏ + ๅผๆบไปฃ็ ่ฏไผฐ
|
| 615 |
+
- ่พๅ
ฅๆก๏ผ่ฎบๆ arxiv ้พๆฅ๏ผๅธฆ3ไธช็คบไพไธ้ฎๅกซๅ
๏ผ
|
| 616 |
+
- ่พๅบๅบ๏ผMarkdown ๆธฒๆ็ๅฎๆด็ ๆฅ๏ผๅฆ5.1่ๆ็คบ๏ผ
|
| 617 |
+
- ๅบ้จ็คบไพ๏ผPaDiM / Transformer / DRAEM ไธ็ฏ่ฎบๆๅฟซๆทๅ
ฅๅฃ
|
| 618 |
+
|
| 619 |
+
### 5.3 ๅฝไปค่ก่พๅบๆๆ
|
| 620 |
+
|
| 621 |
+
```
|
| 622 |
+
============================================================
|
| 623 |
+
[1/5] ๆญฃๅจ่ทๅ่ฎบๆไฟกๆฏ...
|
| 624 |
+
ๆ ้ข: PaDiM: a Patch Distribution Modeling Framework for Anomaly Detection and Localization
|
| 625 |
+
ไฝ่
: Thomas Defard, Aleksandr Setkov, Angelique Loesch
|
| 626 |
+
ๅ็ฑป: cs.CV, cs.LG
|
| 627 |
+
่ๆถ: 0.8s
|
| 628 |
+
|
| 629 |
+
[2/5] ๆญฃๅจ่งฃๆ็ ็ฉถๆนๅ๏ผAgent 1๏ผLLM ่ฐ็จ๏ผ...
|
| 630 |
+
ๅญ้ขๅ: ๅทฅไธๅพๅๅผๅธธๆฃๆตไธๅฎไฝ
|
| 631 |
+
่ถๅฟ: 2024-2025ๅนดไธปๆต่ถๅฟๅ
ๆฌๅฉ็จ้ข่ฎญ็ป่ง่งๆจกๅๆๅๅฑ้จ็นๅพ...
|
| 632 |
+
ๆนๆณๆ (5 ไธช):
|
| 633 |
+
- Patch Distribution Modeling: ้ข่ฎญ็ปCNNๆๅpatch็นๅพ+้ซๆฏๅๅธๅปบๆจก...
|
| 634 |
+
- Memory Bank-based Methods: ๅญๅจๆญฃๅธธๆ ทๆฌ็นๅพๅฐ่ฎฐๅฟๅบ...
|
| 635 |
+
- Knowledge Distillation Methods: ๅธ็็ฝ็ปๅญฆไน ๆจกไปฟ...
|
| 636 |
+
- Reconstruction-based Methods: ่ช็ผ็ ๅจ้ๅปบๆญฃๅธธๆ ทๆฌ...
|
| 637 |
+
- Synthetic Defect Methods: ็ๆๅๆ็ผบ้ท็จไบ่ฎญ็ป...
|
| 638 |
+
็ๆ 18 ไธชๆ็ดขๆฅ่ฏข
|
| 639 |
+
่ๆถ: 8.3s
|
| 640 |
+
|
| 641 |
+
[3/5] ๆญฃๅจๆ็ดข GitHub ไปๅบ๏ผ18 ไธชๆฅ่ฏข๏ผ...
|
| 642 |
+
ๅป้ๅ่ทๅพ 5 ไธชๅ้ไปๅบ
|
| 643 |
+
่ๆถ: 22.1s
|
| 644 |
+
ๅ้ๅ่กจ:
|
| 645 |
+
1. openvinotoolkit/anomalib โญ4000
|
| 646 |
+
2. hcw-00/PatchCore โญ850
|
| 647 |
+
3. taikiinoue45/STFPM โญ320
|
| 648 |
+
4. VitjanZ/DRAEM โญ180
|
| 649 |
+
5. xiahaifeng1995/PaDiM-Anomaly-Detection โญ150
|
| 650 |
+
|
| 651 |
+
[4/5] ๆญฃๅจ่ฏไผฐ 5 ไธชไปๅบ...
|
| 652 |
+
(1/5) ่ฏไผฐ openvinotoolkit/anomalib [Embedding-based]...
|
| 653 |
+
(2/5) ่ฏไผฐ hcw-00/PatchCore [Memory Bank]...
|
| 654 |
+
(3/5) ่ฏไผฐ taikiinoue45/STFPM [Teacher-Student]...
|
| 655 |
+
(4/5) ่ฏไผฐ VitjanZ/DRAEM [Synthetic Defect]...
|
| 656 |
+
(5/5) ่ฏไผฐ xiahaifeng1995/PaDiM-Anomaly-Detection [Embedding-based]...
|
| 657 |
+
่ฏไผฐ่ๆถ: 42.5s
|
| 658 |
+
|
| 659 |
+
[5/5] ๅฎๆ๏ผ
|
| 660 |
+
ๆ้ซๅ: openvinotoolkit/anomalib (100/100)
|
| 661 |
+
ๆป่ๆถ: 73.7s
|
| 662 |
+
============================================================
|
| 663 |
+
|
| 664 |
+
[ๆญคๅค่พๅบๅฎๆด Markdown ็ ๆฅ๏ผๅ5.1่]
|
| 665 |
+
```
|
| 666 |
+
|
| 667 |
+
---
|
| 668 |
+
|
| 669 |
+
## 6. ๆ
้ๆๆฅๆๅ
|
| 670 |
+
|
| 671 |
+
### 6.1 ็ฒๆจกๅๅฐๆชไบคไป
|
| 672 |
+
|
| 673 |
+
| ็็ถ | ๅๅ | ๅค็ |
|
| 674 |
+
|------|------|------|
|
| 675 |
+
| `python run.py ...` ๆฅ้ `็ผบๅฐๆจกๅ: paper_fetcher.py` | ็ฒๆชไบคไป | ็ญๅพ
็ฒ๏ผๆๅ
็จ `python test_agents.py` ้ช่ฏไน็้จๅ |
|
| 676 |
+
| `python app.py` ๆฅ้ `ๆ ๆณๅฏผๅ
ฅ run.py` | ๅไธ | ๅไธ |
|
| 677 |
+
|
| 678 |
+
### 6.2 API ็ธๅ
ณ
|
| 679 |
+
|
| 680 |
+
| ็็ถ | ๅๅ | ๅค็ |
|
| 681 |
+
|------|------|------|
|
| 682 |
+
| `LLM API ่ฐ็จๅคฑ่ดฅ๏ผๅทฒ้่ฏ 3 ๆฌก๏ผ` | DeepSeek API ไธๅฏ่พพๆๆฌ ่ดน | ๆฃๆฅ `llm_utils.py` ไธญ็ API Key ๆฏๅฆๆๆ๏ผๆฃๆฅ็ฝ็ป |
|
| 683 |
+
| GitHub API `403 rate limit exceeded` | GitHub ้ๆต | ็ฒ้ๆทปๅ GitHub Token๏ผๆๅๅฐๆ็ดขๆฅ่ฏขๆฐ |
|
| 684 |
+
| arxiv API ่ถ
ๆถ | arxiv ๆๅกๅจๆ
ข | ้่ฏ๏ผ็ฒๅฏๅ timeout ๅๆฐ |
|
| 685 |
+
|
| 686 |
+
### 6.3 ๆฐๆฎๆ ผๅผไธๅน้
|
| 687 |
+
|
| 688 |
+
| ็็ถ | ๅๅ | ๅค็ |
|
| 689 |
+
|------|------|------|
|
| 690 |
+
| `KeyError: 'full_name'` | ็ฒ็ `search_repos` ่ฟๅ็ dict ็ผบๅฐๅญๆฎต | ๅฏน็
งๆฌๆๆกฃ็ฌฌ2.2่็ๅญๆฎต่กจ่กฅ้ฝ |
|
| 691 |
+
| `ValueError: ๆ ๆณ่งฃๆ LLM ่ฟๅ็ JSON` | LLM ่ฟๅๆ ผๅผๅผๅธธ | ๆฅ็็ป็ซฏ่พๅบไธญ็"ๅๅง่ฟๅ๏ผๅ500ๅญ็ฌฆ๏ผ"๏ผ่็ณปไนไผๅ่งฃๆ้ป่พ |
|
| 692 |
+
| ็ ๆฅๆพ็คบ "N/A" ่ฟๅค | ็ฒ่ฟๅ็ dict ไธญๅฏ้ๅญๆฎต็ผบๅคฑ | ๆฃๆฅ paper dict ๆฏๅฆๅซ `published`, `categories` ็ญๅญๆฎต |
|
| 693 |
+
|
| 694 |
+
### 6.4 ่ฏๅๅผๅธธ
|
| 695 |
+
|
| 696 |
+
| ็็ถ | ๅๅ | ๅค็ |
|
| 697 |
+
|------|------|------|
|
| 698 |
+
| ๆๆไปๅบๅพๅ็ธ่ฟ | LLM ่ฏๅไธๅคๆๅบๅๅบฆ | ๆฃๆฅไผ ็ป LLM ็ README/deps ไฟกๆฏๆฏๅฆ่ถณๅคไธฐๅฏ |
|
| 699 |
+
| ๆๆพไผ่ดจไปๅบๅพๅๅพไฝ | `fetch_readme` ๆ `fetch_dependencies` ่ฟๅไบ็ฉบๅผ | ๆฃๆฅ API ่ฐ็จๆฏๅฆๆๅ๏ผ็ฝ็ปๆฏๅฆๅฏ่พพ |
|
| 700 |
+
| ๆๆไปๅบ `[ๆชๅฝ็ฑป]` | `_match_family` ไธญ่ฑๅ่ฏญๅน้
้ฝๆชๅฝไธญ | ๆฃๆฅ LLM ่ฟๅ็ๆนๆณๆๅๆฏๅฆ้ๅธธ่ง่กจ่ฟฐ๏ผๅฏๅจ `_DOMAIN_KEYWORDS` ่กฅๅ
ๅ
ณ้ฎ่ฏ |
|
| 701 |
+
|
| 702 |
+
---
|
| 703 |
+
|
| 704 |
+
## 7. ๅทฒ็ฅๅฑ้ไธๅ็ปญ่ฟญไปฃ
|
| 705 |
+
|
| 706 |
+
### 7.1 ไนๅทฒ่ฏๅซไฝๆชไฟฎๅค็้ฒๅพก็ผบๅฃ
|
| 707 |
+
|
| 708 |
+
1. **ไปๅบ่ฏไผฐๅพช็ฏไธญ็ๅผๅธธ็ฒๅบฆไธๅค็ป**๏ผ`run.py` ็ฌฌ164-170่ก๏ผ๏ผๅฝๅ `try/except` ๅ
่ฃนไบ `fetch_readme` + `fetch_dependencies` + `evaluate_repo` ็ๆดๆฎตใๅฆๆ `fetch_readme` ๆๅบๅผๅธธ๏ผ่ฝ็ถๅฎไธๅบ่ฏฅ๏ผ๏ผๆดไธชไปๅบ็่ฏไผฐ้ฝไผๆ ่ฎฐไธบ error๏ผไฝๆ ๆณ็ฅ้ๆฏ่ทๅๅคฑ่ดฅ่ฟๆฏ่ฏไผฐๅคฑ่ดฅใๆน่ฟๆนๅ๏ผๅๆญฅ try/exceptใ
|
| 709 |
+
|
| 710 |
+
2. **`_match_family` ไฝฟ็จๅ
ณ้ฎ่ฏๅน้
่้่ฏญไนๅน้
**๏ผๅทฒ้่ฟไธญ่ฑๅ่ฏญๅ
ณ้ฎ่ฏๆ ๅฐๅฐฝๅๆๅๅน้
็๏ผไฝๆญฃ็กฎ็ไป้100%ใไปปๅกไนฆ่ฎกๅ Week 3 ็จ LLM ๅ็ฒพๅๅฝ็ฑปใ
|
| 711 |
+
|
| 712 |
+
3. **`parse_json_safe` ็ญ็ฅ4๏ผๆๅคๅฑ `{...}`็่ดชๅฉชๅน้
๏ผ**๏ผๅฆๆ LLM ไธๆฌก่ฟๅไบๅคไธช JSON ๅฏน่ฑก๏ผๅฆๅ
่งฃ้ๅ็ป JSON๏ผ๏ผ็ญ็ฅ4็ `\{[\s\S]*\}` ไผไป็ฌฌไธไธช `{` ๅน้
ๅฐๆๅไธไธช `}`๏ผไบง็ไธไธช้ๆณ JSON ๅญ็ฌฆไธฒใๆญคๆ
ๅตๆๅฐๅบ็ฐ๏ผ็ญ็ฅ5๏ผๆธ
็ๅฐพ้จ้ๅท๏ผๅฏ่ฝไนไฟฎไธๅฅฝ๏ผๆ็ปไผ่งฆๅ็ญ็ฅ6๏ผๅ
ณ้ฎ่ฏๅฎไฝ๏ผๆๅคฑ่ดฅใๅฝๅ้่ฟ็บฆๆ Prompt๏ผ"ไธ่ฆไปปไฝ้ขๅคๆๅญ"๏ผๆฅ้ฟๅ
ใ
|
| 713 |
+
|
| 714 |
+
4. **ๆ ้่ฏๆบๅถๅจ GitHub API ๅฑ้ข**๏ผ`run.py` ๆฒกๆๅฏน็ฒ็ Workflow ๅฝๆฐๅ้่ฏใๅฆๆ GitHub API ไธดๆถ่ฟๅ 503๏ผไปๅบๆ็ดขๆ README ่ทๅไผ็ดๆฅๅคฑ่ดฅใๅปบ่ฎฎ็ฒๅจ่ชๅทฑ็ๅฝๆฐๅ
้จๅ ้่ฏ๏ผ1-2ๆฌกๅณๅฏ๏ผใ
|
| 715 |
+
|
| 716 |
+
### 7.2 MVP ๅๅปบ่ฎฎ่ฟญไปฃๆนๅ
|
| 717 |
+
|
| 718 |
+
| ไผๅ
็บง | ๅ
ๅฎน | ่ด่ดฃ | ้ข่ฎกๅทฅไฝ้ |
|
| 719 |
+
|--------|------|------|------------|
|
| 720 |
+
| P0 | ็ฒไบคไป3ไธชWorkflowๆจกๅ | ็ฒ | 2-3ๅคฉ |
|
| 721 |
+
| P0 | ่่ฐ + ็ซฏๅฐ็ซฏๆต่ฏ | ็ฒไนไธ่ตท | 1ๅคฉ |
|
| 722 |
+
| P1 | `_match_family` ๅ็บงไธบ LLM ่ฏญไนๅน้
| ไน | ๅๅคฉ |
|
| 723 |
+
| P1 | fetch_readme ๅคฑ่ดฅๆถไผ้
้็บง๏ผไธ้ปๆญ่ฏไผฐ๏ผ | ไน | 1ๅฐๆถ |
|
| 724 |
+
| P2 | ๆฏๆๆดๅค่ฎบๆๆบ๏ผไธไป
ๆฏ arxiv๏ผ | ็ฒ | 1ๅคฉ |
|
| 725 |
+
| P2 | ่ฏไผฐ็ปดๅบฆๆ้ๅฏ้
็ฝฎ | ไน | 2ๅฐๆถ |
|
| 726 |
+
| P3 | ็ผๅญ LLM ่ฏไผฐ็ปๆ๏ผ้ฟๅ
้ๅค่ฐ็จ่ฑ้ฑ๏ผ | ไน | ๅๅคฉ |
|
| 727 |
+
| P3 | ๆฏๆๆน้่ฎบๆ่พๅ
ฅ | ็ฒ+ไน | 1ๅคฉ |
|
| 728 |
+
|
| 729 |
+
---
|
| 730 |
+
|
| 731 |
+
## ้ๅฝA๏ผ่ชๆฃ Checklist๏ผไน็ไปฃ็ ๏ผ
|
| 732 |
+
|
| 733 |
+
ๅจ็ฒไบคไปๅ๏ผไนๅฏ็จๆญคๆธ
ๅ่ชๆฅ๏ผ
|
| 734 |
+
|
| 735 |
+
- [x] `python test_agents.py` โ 6/6 ้่ฟ
|
| 736 |
+
- [x] `python direction_analyzer.py` โ 3็ฏ่ฎบๆๆญฃๅธธ่พๅบ
|
| 737 |
+
- [x] `python repo_evaluator.py` โ 3ไธชๅบๆฏ่ฏๅๅ็
|
| 738 |
+
- [x] `llm_utils.py` โ call_llm ๆ3ๆฌก้่ฏใparse_json_safe ๆ6็ง็ญ็ฅ
|
| 739 |
+
- [x] `run.py` โ ๅฏผๅ
ฅๅคฑ่ดฅๆถๆๅบ ImportError ่้ sys.exit
|
| 740 |
+
- [x] `_DOMAIN_KEYWORDS` โ ไธญ่ฑๅ่ฏญๅ
ณ้ฎ่ฏๅทฒ่ฆ็6ๅคงๆนๆณๆ็ฑปๅซ
|
| 741 |
+
- [x] `app.py` โ ๅฏผๅ
ฅๅคฑ่ดฅๆๆ็กฎ้่ฏฏๆ็คบ
|
| 742 |
+
- [x] `state.py` โ ๆฐๆฎๆจกๅๅฎไนๅฎๆด
|
| 743 |
+
- [x] `requirements.txt` โ openai, gradio, requests ๅทฒๅๅบ
|
| 744 |
+
|
| 745 |
+
## ้ๅฝB๏ผ่ชๆฃ Checklist๏ผ็ฒ็3ไธชๆจกๅ๏ผ
|
| 746 |
+
|
| 747 |
+
็ฒไบคไปๆถ่ฏทๅฏน็
งๆญคๆธ
ๅ็กฎ่ฎค๏ผ
|
| 748 |
+
|
| 749 |
+
**paper_fetcher.py**
|
| 750 |
+
- [ ] `fetch_paper_info(arxiv_url)` ๅฝๆฐๅญๅจ
|
| 751 |
+
- [ ] ่ฟๅๅผๅ
ๅซ `arxiv_id`, `title`, `abstract`, `authors`๏ผๅฟ
้๏ผ
|
| 752 |
+
- [ ] ่ฟๅๅผๅ
ๅซ `published`, `categories`๏ผๆจ่๏ผ
|
| 753 |
+
- [ ] `python paper_fetcher.py` ่ชๆตๅฏ่ฟ่ก
|
| 754 |
+
|
| 755 |
+
**repo_searcher.py**
|
| 756 |
+
- [ ] `search_repos(queries, max_per_keyword=5)` ๅฝๆฐๅญๅจ
|
| 757 |
+
- [ ] ่ฟๅๅผๆฏไธช dict ๅ
ๅซๆๆๅฟ
้ๅญๆฎต๏ผ่ง2.2่๏ผ
|
| 758 |
+
- [ ] ๅทฒๆ `full_name` ๅป้
|
| 759 |
+
- [ ] ๅทฒๆ `stars` ้ๅบๆๅ
|
| 760 |
+
- [ ] ๅค็ไบ GitHub API ้ๆต๏ผๅ token ๆๅๅฐ่ฏทๆฑ้ข็๏ผ
|
| 761 |
+
- [ ] `python repo_searcher.py` ่ชๆตๅฏ่ฟ่ก
|
| 762 |
+
|
| 763 |
+
**repo_fetcher.py**
|
| 764 |
+
- [ ] `fetch_readme(owner, name)` ๅฝๆฐๅญๅจ๏ผๅคฑ่ดฅ่ฟๅ `None`
|
| 765 |
+
- [ ] `fetch_dependencies(owner, name)` ๅฝๆฐๅญๅจ๏ผๅคฑ่ดฅ่ฟๅ `{}`
|
| 766 |
+
- [ ] ่ฆ็ไบ `requirements.txt`, `environment.yml`, `setup.py`, `setup.cfg`, `Pipfile`, `pyproject.toml`
|
| 767 |
+
- [ ] ไธๆๅบๅผๅธธ
|
| 768 |
+
- [ ] `python repo_fetcher.py` ่ชๆตๅฏ่ฟ่ก
|
| 769 |
+
|
| 770 |
+
---
|
| 771 |
+
|
| 772 |
+
> ๆฌๆๆกฃ้ไปฃ็ ๅๆญฅ็ปดๆคใๅฆๆ็้ฎๆ้่ฆไฟฎๆนๅฅ็บฆ๏ผ่ฏท็ฒไนๅๆนๅฝ้ข็กฎ่ฎคๅๅๆนไปฃ็ ๏ผ้ฟๅ
ไฟกๆฏไธๅฏน็งฐใ
|
ๆต็จๆถๆๅพ.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ResearchRadar ๆต็จๆถๆๅพ
|
| 2 |
+
|
| 3 |
+
```
|
| 4 |
+
็จๆท่พๅ
ฅ arxiv URL
|
| 5 |
+
โ
|
| 6 |
+
โผ
|
| 7 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 8 |
+
โ [1/5] ่ฎบๆไฟกๆฏ่ทๅ (Workflow ยท ็ฒ) โ
|
| 9 |
+
โ paper_fetcher.fetch_paper_info() โ
|
| 10 |
+
โ โ arxiv API XML ่งฃๆ โ
|
| 11 |
+
โ โ {title, abstract, authors, categories, published} โ
|
| 12 |
+
โ ๅซ้่ฏ: 429/503 ่ชๅจ้้ฟ้่ฏ 3 ๆฌก โ
|
| 13 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 14 |
+
โ
|
| 15 |
+
โผ
|
| 16 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 17 |
+
โ [2/5] ๅฎฝๆณ GitHub ๆ็ดข (Workflow ยท ็ฒ) โ
|
| 18 |
+
โ โ
|
| 19 |
+
โ โ _extract_broad_queries(title, abstract) โ
|
| 20 |
+
โ โโ LLM ็ๆ 6-8 ไธช็ฒพๅ่ฑๆๆ็ดข่ฏ โ
|
| 21 |
+
โ (ๅคฑ่ดฅๅ้็บงไธบ่งๅๆๅ fallback) โ
|
| 22 |
+
โ โ
|
| 23 |
+
โ โก repo_searcher.search_repos(queries) โ
|
| 24 |
+
โ โโ GitHub API ๆ็ดข๏ผๆฏ่ฏๅ top 5 โ
|
| 25 |
+
โ โโ ๆ full_name ๅป้๏ผๆ stars ้ๅบ โ
|
| 26 |
+
โ โ 10~36 ไธชๅ้ไปๅบ โ
|
| 27 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 28 |
+
โ
|
| 29 |
+
โผ
|
| 30 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 31 |
+
โ [2.5] LLM ่ฟๆปคไธ็ธๅ
ณไปๅบ (ๆฐๅข ยท ไน) โ
|
| 32 |
+
โ _filter_repos(title, abstract, repos) โ
|
| 33 |
+
โ โโ >20 ไธชไปๅบ โ ๆ stars ๅ top 20 ้็ป LLM โ
|
| 34 |
+
โ โโ LLM ๅคๆญๆฏไธชไปๅบๆฏๅฆไธ่ฎบๆๆนๅ็ธๅ
ณ โ
|
| 35 |
+
โ โโ ๅ้คไธ็ธๅ
ณไปๅบ โ
|
| 36 |
+
โ โโ ่ฟๆปคๅ <2 ไธช โ ๅ้ๅฐๅๅง็ปๆ โ
|
| 37 |
+
โ โ 15~17 ไธช็ธๅ
ณไปๅบ โ
|
| 38 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 39 |
+
โ
|
| 40 |
+
โผ
|
| 41 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 42 |
+
โ [3/5] ๆนๆณๆๅฝ็บณ (Agent 1 ยท ไน) โ
|
| 43 |
+
โ direction_analyzer.analyze_direction() โ
|
| 44 |
+
โ ่พๅ
ฅ: ่ฎบๆ title + abstract + ่ฟๆปคๅ็ไปๅบๅ่กจ โ
|
| 45 |
+
โ LLM ๅๆไปๅบ description/topics/stars โ โ
|
| 46 |
+
โ ่พๅบ: โ
|
| 47 |
+
โ โโ subfield (ๅญ้ขๅๅฎไฝ) โ
|
| 48 |
+
โ โโ subfield_trend (่ถๅฟๅคๆญ) โ
|
| 49 |
+
โ โโ method_families[] โ
|
| 50 |
+
โ โ โโ family_name, description โ
|
| 51 |
+
โ โ โโ matched_repos[] โ ไปๅบๅฝๅฑๅชไธชๆนๆณๆ โ
|
| 52 |
+
โ โ โโ search_queries[] โ ่ฏฅๆ็ฒพๅๆ็ดข่ฏ โ
|
| 53 |
+
โ โโ broad_queries[] โ ๆช่ฆ็ๆนๅ็ๅฎฝๆณๆ็ดข่ฏ โ
|
| 54 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 55 |
+
โ
|
| 56 |
+
โผ
|
| 57 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 58 |
+
โ [4/5] ไปๅบ็ญ้ + ๆนๆณๆๆ ๅฐ (่ฐๅบฆๅจ ยท ไน) โ
|
| 59 |
+
โ โโ ไป Agent 1 ็ matched_repos ๅปบ็ซ โ
|
| 60 |
+
โ โ full_name โ family_name ๆ ๅฐ โ
|
| 61 |
+
โ โโ classified: ๆๆนๆณๆๅฝๅฑ็ไปๅบ (ๆ stars ๆๅบ) โ
|
| 62 |
+
โ โโ unclassified: ๆชๅฝ็ฑป็ไปๅบ (ๆ stars ๆๅบ) โ
|
| 63 |
+
โ โโ ๅ top 5 ไฝไธบๆ็ป่ฏไผฐๅ้ โ
|
| 64 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 65 |
+
โ
|
| 66 |
+
โผ
|
| 67 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 68 |
+
โ [5/5] ไปๅบ่ฏฆๆ
่ทๅ + ่ฏไผฐ (Agent 2 ยท ไน) [ๅนถ่ก] โ
|
| 69 |
+
โ โ
|
| 70 |
+
โ ๅฏน 5 ไธชๅ้ไปๅบ๏ผThreadPoolExecutor ๅนถ่กๆง่ก: โ
|
| 71 |
+
โ โ
|
| 72 |
+
โ โ repo_fetcher.fetch_readme(owner, name) โ
|
| 73 |
+
โ โโ GitHub Contents API๏ผbase64 ่งฃ็ โ
|
| 74 |
+
โ โ
|
| 75 |
+
โ โก repo_fetcher.fetch_dependencies(owner, name) โ
|
| 76 |
+
โ โโ ๆฃๆฅ 11 ็งไพ่ตๆไปถ็ฑปๅ โ
|
| 77 |
+
โ โ
|
| 78 |
+
โ โข repo_evaluator.evaluate_repo() โ
|
| 79 |
+
โ โโ LLM ๅ
ญ็ปดๅบฆ่ฏๅ (ๅฏๅค็ฐๆง 80 + ้้
ๅบฆ 20) โ
|
| 80 |
+
โ โโ ็ฏๅข้
็ฝฎ 0-15 โ
|
| 81 |
+
โ โโ ๆๆกฃ่ดจ้ 0-20 โ
|
| 82 |
+
โ โโ ไปฃ็ ๅฏ็จๆง 0-20 โ
|
| 83 |
+
โ โโ ็คพๅบๆดป่ทๅบฆ 0-10 โ
|
| 84 |
+
โ โโ ไพ่ตๅฅๅบทๅบฆ 0-15 โ
|
| 85 |
+
โ โโ ๅฏนๆฏๅฎ้ช้้
ๅบฆ 0-20 โ
|
| 86 |
+
โ โ
|
| 87 |
+
โ ๆ overall_score ้ๅบๆๅ โ
|
| 88 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 89 |
+
โ
|
| 90 |
+
โผ
|
| 91 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 92 |
+
โ ๆฑๆป โ format_report() (app.py) โ
|
| 93 |
+
โ โ
|
| 94 |
+
โ ็ๆ Markdown ็ ๆฅ๏ผๅ
ฑ 5 ้จๅ: โ
|
| 95 |
+
โ ไธใ่ฎบๆไฟกๆฏ (arXiv ้พๆฅใไฝ่
ใๅ็ฑป) โ
|
| 96 |
+
โ ไบใ็ ็ฉถๆนๅๅ
จๆฏ โ
|
| 97 |
+
โ โโ ๅญ้ขๅๅฎไฝ + ่ถๅฟ โ
|
| 98 |
+
โ โโ ๆนๆณๆ่ฐฑ็ณป่กจ โ
|
| 99 |
+
โ โโ ๆนๆณๆๅผๆบ่ฆ็ๅบฆ (ๅชไบๅทฒๆๅฎ็ฐ/ๅชไบๆฏ็ฉบ็ฝ) โ
|
| 100 |
+
โ ๅใๅผๆบๅฎ็ฐ่ฏไผฐๆๅ (ๅ
ญ็ปดๅบฆ่ฏๅๆ็ป) โ
|
| 101 |
+
โ ไบใๅฏนๆฏๅฎ้ชๆจ่ๆป็ป (๐ขๅฐฑ็ปช / ๐ก้ไฟฎๆน / ๐ดไป
ๅ่) โ
|
| 102 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
## ๆ ธๅฟ่ฎพ่ฎกๅณ็ญ
|
| 106 |
+
|
| 107 |
+
> **ๅ
ๆไปๅบ โ ๅๅบไบๅฎ้
ๆฐๆฎ่ฎฉ Agent ๅๆ**๏ผ่้่ฎฉ LLM ๅญ่ฎฐๅฟ็ผ้ ๆนๆณๆใ
|
| 108 |
+
> Agent ๆฏ"ๅๆๆด็ๅทฅๅ
ท"๏ผไธๆฏ"็ฅ่ฏๅบ"ใ
|
| 109 |
+
|
| 110 |
+
## ๆจกๅๅๅทฅ
|
| 111 |
+
|
| 112 |
+
| ๆจกๅ | ่ด่ดฃ | ็ฑปๅ | ่ฏดๆ |
|
| 113 |
+
|------|:----:|:----:|------|
|
| 114 |
+
| `paper_fetcher.py` | ็ฒ | Workflow | arxiv API ่ทๅ่ฎบๆๅ
ไฟกๆฏ๏ผๅซ้่ฏ้ป่พ |
|
| 115 |
+
| `repo_searcher.py` | ็ฒ | Workflow | GitHub API ๅ
ณ้ฎ่ฏๆ็ดข๏ผๅป้ๆๅบ |
|
| 116 |
+
| `repo_fetcher.py` | ็ฒ | Workflow | ่ทๅไปๅบ README + 11 ็งไพ่ตๆไปถ |
|
| 117 |
+
| `direction_analyzer.py` | ไน | Agent 1 | LLM ๅบไบไปๅบๆฐๆฎๅฝ็บณๆนๆณๆ่ฐฑ็ณป |
|
| 118 |
+
| `repo_evaluator.py` | ไน | Agent 2 | LLM ๅ
ญ็ปดๅบฆ่ฏๅ (ๅฏๅค็ฐๆง + ้้
ๅบฆ) |
|
| 119 |
+
| `run.py` | ไน | ่ฐๅบฆๅจ | ไธฒ่ๅ
จๆต็จ [1/5]โ[5/5] + ๅ
ณ้ฎ่ฏ็ๆ + ่ฟๆปค |
|
| 120 |
+
| `app.py` | ไน | ็้ข | Gradio Web UI + Markdown ็ ๆฅๆ ผๅผๅ |
|
| 121 |
+
| `llm_utils.py` | ไน | ๅ
ฌๅ
ฑ | DeepSeek API ๅฎขๆท็ซฏ + JSON ๅฎๅ
จ่งฃๆ + ่พๅบๆ ก้ช |
|
| 122 |
+
|
| 123 |
+
## ็ ๆฅ่พๅบ็ปๆ
|
| 124 |
+
|
| 125 |
+
1. **่ฎบๆไฟกๆฏ** โ ๆ ้ขใarXiv ้พๆฅใไฝ่
ใๅ่กจๆถ้ดใๅ็ฑป
|
| 126 |
+
2. **็ ็ฉถๆนๅๅ
จๆฏ** โ ๅญ้ขๅๅฎไฝใๅฝๅ่ถๅฟใๆนๆณๆ่ฐฑ็ณป่กจใๅผๆบ่ฆ็ๅบฆ
|
| 127 |
+
3. **ๆนๆณๆๅผๆบ่ฆ็ๅบฆ** โ ๅชไบๆนๆณๆๅทฒๆๅฎ็ฐใๅชไบๆฏ็ ็ฉถ็ฉบ็ฝ
|
| 128 |
+
4. **ๅผๆบๅฎ็ฐ่ฏไผฐๆๅ** โ ๆฏไธชไปๅบๅ
ญ็ปดๅบฆ่ฏๅๆ็ป + ้ฃ้ฉ็น + ๅฏนๆฏๅฎ้ชๅปบ่ฎฎ
|
| 129 |
+
5. **ๅฏนๆฏๅฎ้ชๆจ่ๆป็ป** โ ๐ขๅฏ็ดๆฅไฝฟ็จ / ๐ก้ๅฐ้ไฟฎๆน / ๐ดไป
้ๅๅ่
|