๐ aimirror
AI ๆถไปฃ็ไธ่ฝฝ้ๅๅ ้ๅจ โโ ่ขซๆ ข้็ฝ็ป้ผ็ฏ็ๅทฅ็จๅธ็่ชๆๅทฅๅ ท
ไธไธชๆๅก = PyPI + Docker Hub + CRAN + HuggingFace ๅ จๅ ้๏ผ่ฟ่ฝไปปๆๆฉๅฑๆดๅคๆบ
๐ก ้กน็ฎ่ๆฏ
ไฝไธบไธๅ AI ๅทฅ็จๅธ๏ผๆฏๅคฉ็ๅทฅไฝ็ฆปไธๅผ๏ผ
pip install torchโโ ๅ ็พ MB ็ wheel ๅ ไธ่ฝฝๅฐๅฐ่ๅคฉ่docker pull nvidia/cudaโโ ๅ ไธช GB ็้ๅๅฑๅๅคไธ่ฝฝhuggingface-cli downloadโโ ๆจกๅๆไปถไป HuggingFace ่็่ฌ็ฌ่ฟๆฅ
ๅ ฌๅธๅ ็ฝๆไปฃ็๏ผไฝๅ็บฟ็จไธ่ฝฝๅคงๆไปถไพ็ถๆ ขๅพ่ฎฉไบบๅดฉๆบใ้ๅคไธ่ฝฝ็ธๅ็ๅ ๏ผไธๅญๅจ็็ผๅญใๅฟๆ ๅฏๅฟ๏ผไบๆฏๅไบ่ฟไธชๅทฅๅ ทใ
aimirror = ๆบ่ฝ่ทฏ็ฑ + ๅนถ่กๅ็ไธ่ฝฝ + ๆฌๅฐ็ผๅญ๏ผ่ฎฉไธ่ฝฝ้ๅบฆ้ฃ่ตทๆฅใ
โจ ๅ่ฝ็นๆง
- โก ๅนถ่กไธ่ฝฝ โโ HTTP Range ๅ็๏ผๅค็บฟ็จๅนถๅ๏ผๆฆจๅนฒๅธฆๅฎฝ
- ๐พ ๆบ่ฝ็ผๅญ โโ ๅบไบๆไปถ digest ๅป้๏ผLRU ่ชๅจๆทๆฑฐ
- ๐ฏ ๅจๆ่ทฏ็ฑ โโ ๅฐๆไปถ็ดๆฅไปฃ็๏ผๅคงๆไปถ่ชๅจๅนถ่ก
- ๐ ๅคๆบๆฏๆ โโ Docker HubใPyPIใCRANใHuggingFace ๅผ็ฎฑๅณ็จ
- ๐ ไปปๆๆฉๅฑ โโ ๅช่ฆๆฏ HTTP ไธ่ฝฝ๏ผ้ ็ฝฎไธๆก่งๅๅณๅฏๅ ๅๅๅ ้
- ๐ ๅ ๅฎนๆนๅ โโ ่ชๅจๆนๅ HTML/JSON ๅๅบไธญ็้พๆฅ๏ผๆ ็ผไปฃ็
- ๐๏ธ ็นๆฎๅค็ โโ ๆฏๆ่ชๅฎไน Handler ๅค็ๅคๆๅบๆฏ๏ผๅฆ Docker Registry๏ผ
- ๐ฆ ๅนถๅๆงๅถ โโ ๅ จๅฑไธ่ฝฝๅนถๅ้ๅถ๏ผ้ฒๆญข่ตๆบ่ๅฐฝ
- ๐ ่ทฏๅพ้ๅ โโ ็ตๆดป็่ทฏๅพๆฟๆข่งๅ๏ผ้้ ๅ็ง API ๅทฎๅผ
- ๐ ็ผๅญไผๅ โโ ๆฏๆๅๅง URL ไฝไธบ็ผๅญ key๏ผ่งฃๅณไธดๆถ็ญพๅ้ฎ้ข
๐ฅ ๆง่ฝๅฎๆต
PyPI ๅ ๅฎ่ฃ ๅ ้ๅฏนๆฏ
ไฝฟ็จ uv pip install ๅฎ่ฃ
148 ไธชไพ่ตๅ
๏ผๅซ torchใtransformers ็ญๅคงๅ
๏ผ๏ผ
| ๆจกๅผ | ่งฃๆไพ่ต | ๅๅคๅ | ๆป่ๆถ | ๅ ้ๆฏ |
|---|---|---|---|---|
| โ ไป ไปฃ็ (900KB/s) | 17m 04s | 14m 20s | ~31 ๅ้ | 1x |
| โ aimirror (170MB/s) | 34.78s | 45.81s | ~80 ็ง | 23x |
๐ก ๅฎๆต็ฏๅข: ๅ ฌๅธๅ ็ฝไปฃ็๏ผๅธฆๅฎฝ็ถ้ขๆๆพใไฝฟ็จ aimirror ๅไป 900KB/s ้ฃๅ่ณ 170MB/s๏ผๆ้่ฟ 200 ๅ๏ผ
็ผๅญๆๆ
| ๅบๆฏ | ่ๆถ | ้ๅบฆ | ่ฏดๆ |
|---|---|---|---|
| ้ฆๆฌกไธ่ฝฝ | 80s | 170MB/s | ๅนถ่กไธ่ฝฝ + ๅๅ ฅ็ผๅญ |
| ็ผๅญๅฝไธญ | <1s | 3000+ MB/s | ไธๅ ๅ ็ฝๅฎๆต๏ผๆฌๅฐ SSD ๆดๅฟซ๏ผ็ฌๅผ |
ๅคๆบๅๆถๅ ้
ไธไธช aimirror ๆๅก๏ผๅๆถๅ ้ๅค็งๅ ็ฎก็ๅจ๏ผ
| ๅ ็ฎก็ๅจ | ้ ็ฝฎๆนๅผ | ๅ ้ๆๆ |
|---|---|---|
| pip/uv | export HTTPS_PROXY=http://localhost:8081 ๆ pip install -i http://localhost:8081/simple |
PyPI ๅ 23x ๅ ้ |
| docker | /etc/docker/daemon.json ไธญ่ฎพ็ฝฎ registry-mirrors |
้ๅๆๅๅนถ่กๅ็ |
| R CRAN | options(repos = c(CRAN = "http://localhost:8081")) |
R ๅ ไธ่ฝฝๅ ้ |
| huggingface-cli | export HF_ENDPOINT=http://localhost:8081 |
ๆจกๅๆไปถ็งไธ |
| conda | .condarc ไธญ้
็ฝฎ channels |
ๅ็ๅฏๆฉๅฑ |
| npm/maven | ้ ็ฝฎ registry ๆๅ aimirror | ไปปๆ HTTP ๆบๅๅฏ |
๐ ๆฉๅฑ่ฝๅ: ๅช่ฆๆฏ HTTP ไธ่ฝฝ๏ผๅจ
config.yamlไธญๆทปๅ ไธๆก่งๅๅณๅฏๆฅๅ ฅๅ ้๏ผๆ ้ๅฏๅจๅคไธชๆๅกใ
๐๏ธ ๆถๆ
flowchart LR
subgraph Client["ๅฎขๆท็ซฏ"]
PIP[pip install]
DOCKER[docker pull]
HF[huggingface-cli]
R[R install.packages]
end
subgraph aimirror["aimirror ๆๅก"]
ROUTER[่ทฏ็ฑๅน้
ๅจ<br/>router.py]
HANDLER[็นๆฎๅค็ๅจ<br/>handlers/]
PROXY[็ดๆฅไปฃ็<br/>proxy]
DOWNLOADER[ๅนถ่กไธ่ฝฝๅจ<br/>downloader.py]
CACHE[็ผๅญ็ฎก็ๅจ<br/>cache.py]
REWRITE[ๅ
ๅฎนๆนๅ<br/>content_rewrite]
end
subgraph UpstreamProxy["ไธๆธธไปฃ็ (ๅฏ้)"]
COMPANY_PROXY[ๅ
ฌๅธไปฃ็]
end
subgraph Upstream["ไธๆธธๆๅก"]
PYPI[PyPI]
DOCKER_HUB[Docker Hub]
HF_HUB[HuggingFace]
CRAN[CRAN]
end
PIP --> ROUTER
DOCKER --> ROUTER
HF --> ROUTER
R --> ROUTER
ROUTER -->|ๅน้
handler| HANDLER
ROUTER -->|ๅฐๆไปถ/ไปฃ็็ญ็ฅ| PROXY
ROUTER -->|ๅคงๆไปถ/ๅนถ่ก็ญ็ฅ| DOWNLOADER
HANDLER --> PROXY
PROXY -->|้่ฆๆนๅ| REWRITE
REWRITE --> Client
PROXY -->|็ดๆฅ่ฟๅ| Client
DOWNLOADER --> CACHE
CACHE -->|ๅฝไธญ| Client
CACHE -->|ๆชๅฝไธญ| UpstreamProxy
PROXY --> UpstreamProxy
UpstreamProxy -.->|ๅฏ้| Upstream
UpstreamProxy -->|็ด่ฟ| Upstream
DOCKER_HUB -->|่ฟๅๆไปถ| CACHE
PYPI -->|่ฟๅๆไปถ| CACHE
HF_HUB -->|่ฟๅๆไปถ| CACHE
CRAN -->|่ฟๅๆไปถ| CACHE
๐ ๅฟซ้ๅผๅง
ๆนๅผไธ๏ผpip ๅฎ่ฃ ๏ผๆจ่๏ผ
# ๅฎ่ฃ
pip install aimirror
# ๅฏๅจ
aimirror
# ไฝฟ็จ
curl http://localhost:8081/healthๆนๅผไบ๏ผๆบ็ ๅฎ่ฃ
# ๅ
้ไปๅบ
git clone https://github.com/livehl/aimirror.git
cd aimirror
# ๅฎ่ฃ
ไพ่ต
pip install -r requirements.txt
# ๅฏๅจ
python main.py
# ไฝฟ็จ
curl http://localhost:8081/health๐ง ๅฎขๆท็ซฏ้ ็ฝฎ
pip / uv
# ไธดๆถไฝฟ็จ๏ผๅๆฌกๅฎ่ฃ
๏ผ
pip install torch --index-url http://localhost:8081/simple --trusted-host localhost:8081
# ๅ
จๅฑ้
็ฝฎ๏ผๆจ่๏ผ
pip config set global.index-url http://localhost:8081/simple
pip config set global.trusted-host localhost:8081
# ไฝฟ็จ uv๏ผ้ๅบฆๆดๅฟซ๏ผ
uv pip install torch --index-url http://localhost:8081/simple
# ๆไฝฟ็จ็ฏๅขๅ้
export HTTPS_PROXY=http://localhost:8081
pip install torchDocker
# ้
็ฝฎ daemon.json
sudo tee /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["http://localhost:8081"]
}
EOF
sudo systemctl restart docker
# ๆไธดๆถๆๅ
docker pull --registry-mirror=http://localhost:8081 nginx
โ ๏ธ ้่ฆๆ็คบ๏ผDocker ้ๅๅฑๆไปถ้ๅธธๅพๅคง๏ผGB ็บงๅซ๏ผ๏ผๅปบ่ฎฎๅฐchunk_size่ฎพ็ฝฎไธบ0๏ผ่ชๅจๆจกๅผ๏ผใ่ชๅจๆจกๅผไธ๏ผ
chunk_size = ๆไปถๆปๅคงๅฐ / concurrency๏ผ่ฟๆ ทๅฏไปฅ๏ผ
- ้ฟๅ ๅบๅฎๅฐๅ็ๅฏผ่ดๅ็ๆฐ้่ฟๅค
- ๅๅฐ Docker Registry token ๅ ่ถ ๆถๅคฑๆ็ๆฆ็
- ไฟๆๅนถๅๆฐไธๅ๏ผๅๆถไผๅๅ็ๅคงๅฐ
้ ็ฝฎ็คบไพ่ง
config.yamlไธญ็docker-blob่งๅใ
HuggingFace (huggingface-cli)
# ่ฎพ็ฝฎ็ฏๅขๅ้
export HF_ENDPOINT=http://localhost:8081
# ไธ่ฝฝๆจกๅ๏ผๆฏๆๆๆๆไปถ็ฑปๅ๏ผ.gguf, .bin, .safetensors, .json ็ญ๏ผ
huggingface-cli download TheBloke/Llama-2-7B-GGUF llama-2-7b.Q4_K_M.gguf
# ไธ่ฝฝๆดไธชไปๅบ
huggingface-cli download meta-llama/Llama-2-7b-hf --local-dir ./modelsๆไฝฟ็จ Python:
import os
os.environ["HF_ENDPOINT"] = "http://localhost:8081"
from huggingface_hub import hf_hub_download, snapshot_download
# ไธ่ฝฝๅไธชๆไปถ
hf_hub_download(repo_id="TheBloke/Llama-2-7B-GGUF", filename="llama-2-7b.Q4_K_M.gguf")
# ไธ่ฝฝๆดไธชไปๅบ
snapshot_download(repo_id="meta-llama/Llama-2-7b-hf", local_dir="./models")R (CRAN)
# ๅจ R ๆงๅถๅฐไธญ่ฎพ็ฝฎ
options(repos = c(CRAN = "http://localhost:8081"))
# ๆๅจ .Rprofile ไธญๆฐธไน
้
็ฝฎ
cat('options(repos = c(CRAN = "http://localhost:8081"))\n', file = "~/.Rprofile")Conda
# ไฟฎๆน .condarc
cat >> ~/.condarc <<EOF
channels:
- http://localhost:8081/conda-forge
- http://localhost:8081/bioconda
EOFnpm / yarn
# ไธดๆถไฝฟ็จ
npm install --registry http://localhost:8081/registry/npm
# ๅ
จๅฑ้
็ฝฎ
npm config set registry http://localhost:8081/registry/npm
yarn config set registry http://localhost:8081/registry/npm๐ API
ไปฃ็็ซฏ็น
| ่ทฏๅพ | ๆนๆณ | ่ฏดๆ |
|---|---|---|
/{full_path:path} |
GET/HEAD/POST/PUT/DELETE | ้็จไปฃ็ๅ ฅๅฃ๏ผๆ นๆฎ่ทฏ็ฑ่งๅ่ฝฌๅๅฐๅฏนๅบไธๆธธ |
็ฎก็็ซฏ็น
| ่ทฏๅพ | ๆนๆณ | ่ฏดๆ | ๅๅบ็คบไพ |
|---|---|---|---|
/health |
GET | ๅฅๅบทๆฃๆฅ | {"status": "ok", "active_downloads": 0, "downloads": []} |
/stats |
GET | ็ผๅญ็ป่ฎกไฟกๆฏ | {"cache": {"total_size_mb": 1024, "file_count": 100}} |
ๅฅๅบทๆฃๆฅๅๅบ่ฏฆๆ
curl http://localhost:8081/healthๅๅบๅญๆฎต่ฏดๆ๏ผ
status: ๆๅก็ถๆ๏ผok่กจ็คบๆญฃๅธธ่ฟ่กactive_downloads: ๅฝๅๆญฃๅจ่ฟ่ก็ไธ่ฝฝไปปๅกๆฐdownloads: ๆญฃๅจไธ่ฝฝ็ๆไปถๅ่กจ๏ผ็ผๅญ key๏ผ
็ผๅญ็ป่ฎกๅๅบ่ฏฆๆ
curl http://localhost:8081/stats | jqๅๅบๅ ๅซ็ผๅญ็ฎๅฝ็ๆปๅคงๅฐใๆไปถๆฐ้็ญไฟกๆฏใ
๐ ๅฟซ้ๅผๅง
ๆนๅผไธ๏ผpip ๅฎ่ฃ ๏ผๆจ่๏ผ
# ๅฎ่ฃ
pip install aimirror
# ๅฏๅจ
aimirror
# ไฝฟ็จ
curl http://localhost:8081/healthๆนๅผไบ๏ผๆบ็ ๅฎ่ฃ
# ๅ
้ไปๅบ
git clone https://github.com/livehl/aimirror.git
cd aimirror
# ๅฎ่ฃ
ไพ่ต
pip install -r requirements.txt
# ๅฏๅจ
python main.py
# ไฝฟ็จ
curl http://localhost:8081/health๐ณ Docker ้จ็ฝฒ
ไฝฟ็จ GitHub Container Registry
# ๆๅ้ๅ
docker pull ghcr.io/livehl/aimirror:latest
# ่ฟ่ก๏ผๅบ็ก็๏ผ
docker run -d -p 8081:8081 \
-v $(pwd)/cache:/data/fast_proxy/cache \
ghcr.io/livehl/aimirror:latest
# ่ฟ่ก๏ผๅธฆ่ชๅฎไน้
็ฝฎ๏ผ
docker run -d -p 8081:8081 \
-v $(pwd)/config.yaml:/app/config.yaml \
-v $(pwd)/cache:/data/fast_proxy/cache \
ghcr.io/livehl/aimirror:latestDocker Compose ็คบไพ
version: '3.8'
services:
aimirror:
image: ghcr.io/livehl/aimirror:latest
container_name: aimirror
ports:
- "8081:8081"
volumes:
- ./config.yaml:/app/config.yaml
- ./cache:/data/fast_proxy/cache
- ./logs:/data/fast_proxy
restart: unless-stoppedๆณจๆ๏ผไธๆธธไปฃ็่ฏทๅจ
config.yamlไธญ้ ็ฝฎserver.upstream_proxy๏ผไธๆฏๆ็ฏๅขๅ้ๆนๅผใ
โ๏ธ ้ ็ฝฎ็คบไพ
# fast_proxy ้
็ฝฎๆไปถ
server:
host: "0.0.0.0"
port: 8081
upstream_proxy: "" # ไธๆธธไปฃ็๏ผ้ป่ฎค็ฉบ่กจ็คบ็ด่ฟ
public_host: "127.0.0.1:8081" # ๅฏนๅค่ฎฟ้ฎๅฐๅ๏ผ็จไบ HTML ้พๆฅๆนๅ
max_concurrent_downloads: 100 # ๅ
จๅฑๆๅคงๅนถๅไธ่ฝฝๆฐ๏ผ่ถ
่ฟๅๆ้
cache:
dir: "/data/fast_proxy/cache"
max_size_gb: 100
lru_enabled: true
rules:
# Docker Registry ไปฃ็๏ผ/v2/ ๅ /v2/auth ๅจไปฃ็ ไธญ็นๆฎๅค็๏ผ
- name: docker-blob
pattern: "/v2/.*/blobs/sha256:[a-f0-9]+"
upstream: "https://registry-1.docker.io"
strategy: parallel
min_size: 1 # all
concurrency: 20
chunk_size: 0 # ่ชๅจๆจกๅผ๏ผๆปๅคงๅฐ/concurrency๏ผ้ฟๅ
่ถ
ๅคงๆไปถๅ็่ฟๅคๅฏผ่ด token ่ถ
ๆถ
- name: docker-registry
pattern: "/v2/.*"
upstream: "https://registry-1.docker.io"
strategy: proxy
handler: handlers.docker # ็นๆฎๅค็ๆจกๅ่ทฏๅพ
- name: pip-packages
pattern: "/packages/.+\\.(whl|tar\\.gz|zip)$"
upstream: "https://pypi.org"
strategy: parallel
min_size: 1 # all
concurrency: 20
chunk_size: 5242880 # 5MB per chunk
- name: r-package
pattern: "/src/contrib/.*"
upstream: "https://cran.r-project.org"
strategy: parallel
min_size: 102400 # 100K
concurrency: 20
chunk_size: 5242880
- name: huggingface-files
pattern: '/.*/(blob|resolve)/[^/]+/.+'
upstream: "https://huggingface.co"
strategy: parallel
min_size: 102400 #100k
concurrency: 20
chunk_size: 10485760 # 10MB per chunk
cache_key_source: original # ไฝฟ็จๅๅง URL ไฝไธบ็ผๅญ key๏ผ้ฟๅ
ไธดๆถ็ญพๅๅฝฑๅ็ผๅญๅฝไธญ๏ผ
path_rewrite:
- search: "/blob/"
replace: "/resolve/"
# HEAD ่ฏทๆฑๆถ้่ฆ้ขๅคไฟ็็ๅๅบๅคด๏ผ็จไบๅ
ๆฐๆฎ่ทๅ๏ผ
head_meta_headers:
- "x-repo-commit"
- "x-linked-etag"
- "x-linked-size"
- "etag"
- name: huggingface-api
pattern: '/api/models/.*'
upstream: "https://huggingface.co"
strategy: proxy
# ็คบไพ๏ผๅ
ถไปไฝฟ็จไธดๆถ็ญพๅ URL ็็ซ็น
# - name: example-signed-url
# pattern: '/signed-download/.*'
# upstream: "https://example.com"
# strategy: parallel
# min_size: 10485760
# concurrency: 10
# cache_key_source: original # ไฝฟ็จๅๅง URL ไฝไธบ็ผๅญ key
- name: default
pattern: ".*"
upstream: "https://pypi.org"
strategy: proxy
content_rewrite: # ๅๅบๅ
ๅฎนๆนๅ้
็ฝฎ
content_types: # ๅน้
็ Content-Type๏ผHTML ๅ JSON๏ผ
- "text/html"
- "application/json"
- "application/vnd.pypi.simple"
targets: # ่ฆๆฟๆข็็ฎๆ host ๅ่กจ
- "https://files.pythonhosted.org"
logging:
level: "INFO"
file: "/data/fast_proxy/fast_proxy.log"้ ็ฝฎ่ฏดๆ
Server ้ ็ฝฎ
| ๅญๆฎต | ่ฏดๆ | ้ป่ฎคๅผ |
|---|---|---|
server.host |
ๆๅก็ๅฌๅฐๅ | "0.0.0.0" |
server.port |
ๆๅก็ๅฌ็ซฏๅฃ | 8081 |
server.upstream_proxy |
ไธๆธธไปฃ็ๅฐๅ๏ผ็ฉบๅญ็ฌฆไธฒ่กจ็คบ็ด่ฟ | "" |
server.public_host |
ๅฏนๅค่ฎฟ้ฎๅฐๅ๏ผ็จไบ HTML ้พๆฅๆนๅ | "127.0.0.1:8081" |
server.max_concurrent_downloads |
ๅ จๅฑๆๅคงๅนถๅไธ่ฝฝๆฐ๏ผ่ถ ่ฟๅๆ้ | 100 |
Cache ้ ็ฝฎ
| ๅญๆฎต | ่ฏดๆ | ้ป่ฎคๅผ |
|---|---|---|
cache.dir |
็ผๅญ็ฎๅฝ่ทฏๅพ | "./cache" |
cache.max_size_gb |
็ผๅญๆๅคงๅฎน้๏ผGB๏ผ | 100 |
cache.lru_enabled |
ๆฏๅฆๅฏ็จ LRU ่ชๅจๆทๆฑฐ | true |
Rules ้ ็ฝฎ
| ๅญๆฎต | ่ฏดๆ | ็คบไพ |
|---|---|---|
rules[].name |
่งๅๅ็งฐ | "docker-blob" |
rules[].pattern |
URL ๅน้ ๆญฃๅ่กจ่พพๅผ | "/v2/.*/blobs/sha256:[a-f0-9]+" |
rules[].upstream |
ไธๆธธๆบ base URL | "https://registry-1.docker.io" |
rules[].strategy |
ไธ่ฝฝ็ญ็ฅ๏ผproxy ็ดๆฅไปฃ็ / parallel ๅนถ่กไธ่ฝฝ |
"parallel" |
rules[].min_size |
ๆๅฐๆไปถๅคงๅฐ๏ผๅญ่๏ผ๏ผๅฐไบๆญคๅผไฝฟ็จไปฃ็ | 1048576 |
rules[].concurrency |
ๅนถ่กไธ่ฝฝ็บฟ็จๆฐ | 20 |
rules[].chunk_size |
ๆฏไธชๅ็ๅคงๅฐ๏ผๅญ่๏ผ๏ผโค0 ่กจ็คบ่ชๅจ่ฎก็ฎ๏ผๆปๅคงๅฐ/concurrency๏ผ | 10485760 |
rules[].cache_key_source |
็ผๅญ key ๆฅๆบ๏ผoriginal ไฝฟ็จๅๅงURL๏ผfinal ไฝฟ็จๆ็ปURL |
"original" |
rules[].path_rewrite |
่ทฏๅพ้ๅ่งๅๆฐ็ป | [{search: "/blob/", replace: "/resolve/"}] |
rules[].content_rewrite |
ๅๅบๅ ๅฎนๆนๅ้ ็ฝฎ๏ผ็จไบ HTML/JSON ไธญ็้พๆฅๆฟๆข๏ผ | ่ง default ่งๅ |
rules[].handler |
็นๆฎๅค็ๆจกๅ่ทฏๅพ | "handlers.docker" |
rules[].head_meta_headers |
HEAD ่ฏทๆฑๆถ้ขๅคไฟ็็ๅๅบๅคดๅ่กจ | ["etag", "x-repo-commit"] |
Logging ้ ็ฝฎ
| ๅญๆฎต | ่ฏดๆ | ้ป่ฎคๅผ |
|---|---|---|
logging.level |
ๆฅๅฟ็บงๅซ๏ผDEBUG/INFO/WARNING/ERROR |
"INFO" |
logging.file |
ๆฅๅฟๆไปถ่ทฏๅพ | "/tmp/fast_proxy.log" |
้ซ็บง้ ็ฝฎ็คบไพ
่ชๅฎไน Handler
ๅๅปบ handlers/custom.py๏ผ
async def exec_path(request, full_path, config, http_client):
"""
่ชๅฎไน่ฏทๆฑๅค็ๅจ
Args:
request: FastAPI Request ๅฏน่ฑก
full_path: ่ฏทๆฑ่ทฏๅพ
config: ๅ
จๅฑ้
็ฝฎๅญๅ
ธ
http_client: httpx.AsyncClient ๅฎไพ
Returns:
(handled, response):
- handled: bool๏ผๆฏๅฆๅทฒๅค็
- response: ๅฆๆ handled=True๏ผ่ฟๅ Response ๅฏน่ฑก
"""
if full_path.startswith('/custom/'):
# ๅค็่ชๅฎไน้ป่พ
return True, Response(content="Custom response")
# ๆชๅค็๏ผ็ปง็ปญๅ็ปญๆต็จ
return False, Noneๅจ config.yaml ไธญ้
็ฝฎ๏ผ
rules:
- name: custom-handler
pattern: "/custom/.*"
upstream: "https://example.com"
strategy: proxy
handler: handlers.customๆฉๅฑ็คบไพ๏ผๆทปๅ GitHub Releases ไธ่ฝฝๅ ้
rules:
- name: github-releases
pattern: '/.*/releases/download/.+'
upstream: "https://github.com"
strategy: parallel
min_size: 1048576 # 1MB ไปฅไธๅฏ็จๅนถ่ก
concurrency: 16
chunk_size: 10485760 # 10MB ๅ็ๆฉๅฑ็คบไพ๏ผๆทปๅ ่ชๅฎไน่ฝฏไปถๆบ
rules:
- name: my-company-repo
pattern: '/artifacts/.+\.(jar|war|zip)$'
upstream: "https://artifacts.mycompany.com"
strategy: parallel
min_size: 10485760 # 10MB ไปฅไธๅฏ็จๅนถ่ก
concurrency: 10
chunk_size: 20971520 # 20MB ๅ็
cache_key_source: original๐งช ๆต่ฏ
่ฟ่กๆต่ฏ
# ่ฟ่ก็ฎๅๆต่ฏ๏ผๆ ้ pytest๏ผ
python test_simple.py
# ่ฟ่กๅฎๆดๆต่ฏๅฅไปถ๏ผ้่ฆ pytest๏ผ
pytest test_proxy.py -vๆๅจ้ช่ฏ
ๆต่ฏ PyPI ไปฃ็
curl -o /dev/null "http://localhost:8081/packages/fb/d7/71b982339efc4fff3c622c6fefecddfd3e0b35b60c5f822872d5b806bb71/torch-1.0.0-cp27-cp27m-manylinux1_x86_64.whl" \
-w "HTTP: %{http_code}, Size: %{size_download}, Time: %{time_total}s\n"ๆต่ฏ HuggingFace ไปฃ็
export HF_ENDPOINT=http://localhost:8081
# ๆต่ฏไธ่ฝฝ GGUF ๆจกๅๆไปถ
huggingface-cli download TheBloke/Llama-2-7B-GGUF llama-2-7b.Q4_K_M.gguf
# ๆต่ฏไธ่ฝฝ safetensors ๆ ผๅผๆจกๅ
huggingface-cli download meta-llama/Llama-2-7b-hf model-00001-of-00002.safetensors
# ๆต่ฏไธ่ฝฝๆดไธชไปๅบ
huggingface-cli download sentence-transformers/all-MiniLM-L6-v2 --local-dir ./test-modelๆต่ฏ Docker Registry ไปฃ็
# ่ทๅ token
TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/nginx:pull" \
| grep -o '"token":"[^"]*"' | cut -d'"' -f4)
# ไธ่ฝฝ blob
curl -o /dev/null "http://localhost:8081/v2/library/nginx/blobs/sha256:abc123" \
-H "Authorization: Bearer $TOKEN" \
-w "HTTP: %{http_code}, Size: %{size_download}, Time: %{time_total}s\n"้ช่ฏ็ผๅญๅฝไธญ
# ็ฌฌไธๆฌกไธ่ฝฝ๏ผๅนถ่กไธ่ฝฝ๏ผ
time curl -o /tmp/test1.gguf "http://localhost:8081/unsloth/model/resolve/main/file.gguf"
# ็ฌฌไบๆฌกไธ่ฝฝ๏ผ็ผๅญๅฝไธญ๏ผๅบ่ฏฅๅฟซๅพๅค๏ผ
time curl -o /tmp/test2.gguf "http://localhost:8081/unsloth/model/resolve/main/file.gguf"
# ๆฅ็็ผๅญ็ป่ฎก
curl http://localhost:8081/stats | jq๐ License
MIT