한 줄 요약
Zesuy/Plugin-Deepseek-Vision은 이미지를 직접 읽지 못하는 DeepSeek 텍스트 모델 앞에 붙는 CLIProxyAPI v7 네이티브 요청 전처리 플러그인이다.[2] CLIProxyAPI가 인증·모델 별칭·최종 모델 라우팅을 끝낸 뒤, 호스트에 이미 등록된 비전 모델로 이미지를 분석하고 원래 이미지 블록을 분석 텍스트로 바꿔 DeepSeek에 전달한다.[1]
이 프로젝트 자체가 새 프록시, 새 모델 제공자, 별도 endpoint, API key 저장소, server-side tool은 아니다.[2] 모델 라우팅·자격 증명·프로토콜 변환·네트워크·재시도·공급자 rate limit은 CLIProxyAPI가 계속 소유한다.[1][2]
이 문서는 2026-08-09 조사 시점의 main 커밋 91fbbe3e497c8fd98f08bf4e4497921124597314와 v0.3.0 문서를 기준으로 README, 계약·설정·보안 문서와 핵심 Go 구현을 대조한 기록이다.[2]
저장소 현황
- 저장소:
Zesuy/Plugin-Deepseek-Vision[1] - 라이선스: MIT.[1]
- 주요 언어·모듈: Go,
github.com/zesuy/Plugin-Deepseek-Vision.[2] - 선언된 도구체인: Go 1.26, CGO, 플랫폼 C 컴파일러, Python, Git, Linux/macOS의
nm또는 Windows의objdump.[1][2] - 호스트 통합 대상: CLIProxyAPI v7.2.119.[1]
- 조회 시 GitHub 표시값: 별 45개, fork 2개, open issue 0개, 저장소 크기 약 1,439 KB, archived 아님.[1]
- 조사 기준 커밋 메시지:
Merge pull request #7 from Zesuy/codex/v0.3.0-release-blockers.[2] - v0.3.0은 Linux·macOS·Windows의 amd64/arm64 자산을 대상으로 하며, FreeBSD amd64는 호스트가 지원하더라도 이 릴리스에서 실기기 검증 자산을 배포하지 않는다.[1]
해결하려는 문제
DeepSeek 텍스트 모델은 OpenAI Responses 요청의 input_image를 직접 소비하지 못한다.[2] 이 플러그인은 이미지가 포함된 요청을 먼저 찾아 호스트의 비전 모델에 보내고, 이미지별 내용·가시 텍스트·이미지 간 관계를 포함한 분석을 생성한 뒤, 원래 구조 안의 이미지 블록을 “이미 분석된 첨부” 표시와 공동 분석 텍스트로 교체한다.[2] 따라서 최종 DeepSeek 모델은 원본 이미지를 받지 않고도 사용자의 질문과 시각적 맥락을 함께 추론한다.[1]
같은 prompt 또는 하나의 지원되는 message/content/tool-result 항목에 여러 이미지가 있으면 이미지마다 따로 캡션을 요청하는 대신 순서를 보존한 공동 분석을 수행한다.[2] 관련 prompt 텍스트는 최대 2,000자 범위로 제한해 VLM이 사용자의 초점을 잃지 않도록 한다.[1][2]
동작 파이프라인
1.[2] CLIProxyAPI가 인증, 별칭 해석, 최종 upstream 모델 선택을 수행한다.[2]
2.[2] 플러그인이 source-format + request path와 최종 모델을 정확히 검사한다.[2]
3.[2] Responses·Chat·Claude의 지원되는 구조에서 이미지 참조와 prompt 그룹을 발견한다.[2]
4.[2] 같은 그룹의 이미지를 순서대로 호스트 VLM에 보내고, vision_model이 실패하면 설정된 fallback 모델 체인을 순서대로 시도한다.[2]
5.[2] 분석 텍스트를 원래 구조의 이미지 위치에 삽입하고, 프로토콜 native 이미지 블록과 참조가 남아 있지 않은지 다시 검증한다.[2]
6.[2] 검증된 텍스트 전용 요청을 원래 CLIProxyAPI 실행면으로 돌려 DeepSeek가 계속 추론하게 한다.[1][2]
이미지가 있는 지원 요청에서 어느 하나의 분석·검증이 실패하면 부분 재작성이나 원본 이미지 전달을 허용하지 않고 요청을 종료한다.[2] 즉, 이 경계는 “가능한 만큼 이미지가 전달되는” best-effort가 아니라 fail-closed 전처리 경계다.[1][2]
지원 경계
| 조건 | v0.3.0 동작 |
|---|---|
openai-response + /v1/responses | input[].content[]의 URL/data URI input_image, 배열형 function_call_output.output[] 지원 |
openai + /v1/chat/completions | messages[].content[]의 image_url, tool 메시지 포함 |
claude + /v1/messages | Anthropic message와 tool_result.content[]의 base64/URL 이미지 |
| 여러 이미지·보이는 이전 대화 | prompt 그룹별 공동 분석, 이미지 순서와 관계 보존 |
stream: true | 응답 스트림 시작 전에 전처리한 뒤 스트리밍 시작 |
| 최종 모델 | 기본 deepseek-v4-flash; target_models에 명시된 모델만 개입 |
/v1/responses/compact, /v1/messages/count_tokens | 플러그인 경계 밖으로 우회 |
| 파일 ID만 제공된 이미지 | 지원하지 않으며 422 오류 |
previous_response_id에 숨은 서버 측 history | 플러그인에서 볼 수 없어 처리하지 않음 |
플러그인은 근접한 경로를 추측해 가로채지 않는다.[2] 정확한 세 가지 route와 최종 모델 gate를 모두 만족하지 않는 요청은 호스트가 원래 방식으로 처리한다.[1][2]
deepseek-v4-pro는 문서상 명시적으로 target_models에 추가할 수 있지만, v0.3.0의 기본값이나 release acceptance target이 아니다.[2] 배포자가 해당 upstream Responses 경로가 실제로 사용 가능한지 검증한 뒤 직접 활성화해야 한다.[1][2]
요청 재작성과 프롬프트 설계
기본 재작성은 각 첨부에 “이미 분석되었고 target model은 view_image로 다시 열 수 없다”는 표시를 붙인 다음, [Images ... — Joint visual analysis] 블록에 VLM 결과를 넣는 방식이다.[2] 분석 프롬프트는 이미지 속 텍스트를 충실히 전사하고 알아보기 어려운 부분을 표시하며, 이미지 간 차이와 관계를 설명하도록 요구한다.[2] 이미지 안에 보이는 지시문은 신뢰하지 않는 데이터로 취급한다.[1]
이 설계는 단순한 이미지 captioner보다 대화 맥락에 맞는 전처리에 가깝다.[2] 예를 들어 같은 prompt에 화면 캡처 세 장이 있으면 세 장을 각각 독립적으로 설명하지 않고, 각 이미지의 내용·문자·차이·상호 관계를 하나의 VLM 호출에서 묶어 DeepSeek의 후속 코드·문제 해결 추론에 제공한다.[1][2]
설정 핵심
| 설정 | 기본값 | 의미 |
|---|---|---|
target_models | ["deepseek-v4-flash"] | 이미지 전처리를 적용할 최종 모델 목록 |
vision_model | gpt-5.6-luna | CLIProxyAPI에 이미 등록된 주 VLM |
vision_fallback_models | [] | 실패 시 순서대로 시도할 VLM, 최대 3개·중복 불가 |
language | zh | 분석 언어: zh, en, auto |
request_timeout_seconds | 120 | 대기 시간을 포함한 전체 전처리 deadline |
max_inflight_vision_requests | 4 | 전역 동시 prompt-group VLM 호출 수 |
emergency_max_images_per_request | 256 | 극단적인 요청을 막는 unique-image 최종 상한 |
analysis_cache_size | 128 | 일반 파생 분석 LRU 항목 수; 0이면 일반 재사용 비활성화 |
analysis_cache_ttl_seconds | 900 | data URI 분석 TTL |
analysis_url_cache_ttl_seconds | 120 | URL 이미지 분석 TTL |
agent_reanalysis_enabled | false | rich tool output 기반 통제형 재분석 opt-in |
trace_enabled | false | 전체 평문 디버그 trace opt-in |
설정 업데이트는 검증 후 원자적으로 적용되며, 잘못된 설정은 기존 snapshot을 유지한다.[2] ABI 차원에서는 raw RPC bytes 32 MiB와 동시 callback 4개라는 별도 admission budget도 적용된다.[2]
VLM fallback은 408·429·5xx, attempt timeout, 비어 있거나 잘못되었거나 크기를 초과한 결과, 일반 host executor 오류처럼 retryable한 경우에만 다음 모델로 넘어간다.[2] 부모 요청 취소·rewrite 실패·기타 non-retryable 오류는 체인을 중단한다. provider 선택과 각 모델의 자격 증명은 모두 CLIProxyAPI가 담당한다.[2]
캐시와 deduplication
일반 캐시는 순서가 있는 이미지 참조, 전체 prompt, 전체 순서의 VLM 모델 체인, 정규화된 언어를 키로 삼고, 캐시 항목에는 원본 이미지나 원래 참조를 저장하지 않고 파생 분석 텍스트와 SHA-256 키만 저장한다.[2] URL 이미지는 내용이 변할 수 있어 data URI보다 짧은 TTL을 사용한다.[1][2]
통제형 재분석은 일반 캐시와 의미가 다르다.[2]
기본 refresh는 새 call ID에 대해 한 번 실행하고, 같은 call ID와 동일한 이미지 fingerprint·focus·언어·모델 체인의 재실행은 idempotent replay로 처리한다.[2]
no_store는 분석은 수행하지만 cross-request cache를 읽거나 쓰지 않는다.[2]
재구성·재시작 시 캐시 generation이 새로 시작되며, analysis_cache_size: 0은 일반 LRU만 끄고 refresh idempotency cache와 요청 내 deduplication까지 없애지는 않는다.[1]
통제형 Agent 재분석
agent_reanalysis_enabled: true일 때만 rich tool output 기반의 재분석이 활성화된다.[2] 지원 진입점은 요청에 선언된 view_image와 deepseek_vision_reanalyze이며, CLIProxyAPI server-side tool을 등록하거나 요구하지 않는다.[1][2]
deepseek_vision_reanalyze의 인자는 다음 형태로 제한된다.[2]
{
"attachment_ids": ["id-1"],
"focus": "필수인 작업별 분석 초점",
"detail": "high",
"cache": "refresh"
}attachment_ids: Agent가 소유한 불투명 handle 1~16개.[2] 플러그인은 비어 있지 않은 문자열인지 검사할 뿐, 이를 이미지 경로·데이터·조회 키로 해석하지 않는다.[2]focus: 필수 non-empty 문자열, 최대 2,000자.[2]detail:high또는original, 기본high.[2]cache:refresh또는no_store, 기본refresh.[2]
실제 이미지 출처는 tool arguments가 아니라 매칭되는 rich tool output의 실제 이미지 블록뿐이다. path 인자를 통해 파일을 읽거나 URL·바이트를 밀어 넣지 않으며, view_image 예외 경로를 보존할 때도 agent_reanalysis_enabled, 명시적 view_image, 엄격한 .codex/attachments/<id>/ 경로 조건을 모두 요구한다.[2] 요청 하나에서 활성 tail call ID도 최대 3개다.[1][2]
오류·실패 안전
지원 경계를 통과한 이미지 요청은 다음처럼 종료된다.[1]
| HTTP | 의미 |
|---|---|
400 | Responses/지원 프로토콜 구조가 잘못됨 |
413 | body·image reference·ABI admission·unique image limit 초과 |
422 | file ID처럼 지원하지 않는 이미지 출처 |
502 | VLM fallback 소진, timeout, invalid/empty/oversized result 또는 최종 rewrite 검증 실패 |
안전한 502 응답은 불투명한 error_id, 고정 오류 코드 vision_fallback_exhausted, 순서가 있는 attempt 요약(model, category, 선택적 upstream_status, retryable)만 노출한다. provider 원문, credentials, 완전한 URL·data URI, local path는 반환하지 않는다.[1][2]
일반 진단은 Authorization·API key·cookie·본문·이미지 참조를 기록하지 않는다.[2] 단, trace_enabled는 예외다.[2] 이 모드는 inbound 대화 본문, 완전한 이미지 URL/data URI, prompt 그룹, VLM 요청·응답, rewritten body를 logs/deepseek-vision-trace/에 남길 수 있으므로 민감한 재현에서만 잠깐 켜야 한다. trace 파일은 권한과 rotation·용량 제한을 적용하지만 이미지 URL의 signed query parameter까지 자동으로 안전해지는 것은 아니다.[2]
이미지 안의 프롬프트 주입은 신뢰하지 않는 데이터로 처리되고, private/loopback/link-local 이미지 URL은 거부된다.[2] URL 이미지를 실제로 읽는 네트워크·DNS·allowlist·데이터 거버넌스는 선택한 provider와 배포 환경이 책임진다.[2]
구현 구조
고정 커밋의 핵심 구현은 다음 경계로 나뉜다.[2]
main.go,wiring.go: plugin ABI 진입점과 CLIProxyAPI host callback 연결.[2]rpc.go: ABI 버전 1·schema 버전 2 RPC envelope, request/response 복사와 크기·동시성 admission.[2]internal/interceptor/runtime.go: 인증·모델 해석 이후의 intercept-after 경계, route/model gate, 이미지 분석·재작성 orchestration.[2]internal/downstream/registry.go:openai-response + /v1/responses,openai + /v1/chat/completions,claude + /v1/messages의 exact adapter 매핑.[2]internal/downstream/responses_rewrite.go,chat.go,claude.go: 각 protocol의 이미지 발견·prompt 그룹화·원래 구조 보존·이미지 제거 검증.[2]internal/vision/host_client.go,fallback.go,prompt.go: CLIProxyAPIhost.model.execute호출, ordered fallback, VLM prompt와 안전한 오류 요약.[2]internal/interceptor/analysis_cache.go: 일반 분석 LRU, 요청 내 deduplication, call-ID 기반 재분석 idempotency.[2]internal/config/config.go,internal/safety/*,internal/tracelog/*: atomic configuration, 입력·크기·경로 제한, 진단·opt-in trace.[2]
즉, 이 프로젝트의 핵심은 새 모델 추론 엔진이 아니라 기존 host capability를 호출하는 ABI 플러그인과 protocol-preserving rewrite engine이다.[2] 원래 요청의 protocol shape를 다른 protocol로 왕복 변환하지 않고 각 다운스트림 adapter가 자기 wire format 안에서 이미지를 치환한다.[2]
설치·배포
권장 경로는 CLIProxyAPI 공식 Plugin Store에서 DeepSeek Vision을 찾아 설치하는 것이다.[2] 수동 설치는 GitHub Releases의 플랫폼별 v0.3.0 ZIP을 받아 plugins/<GOOS>/<GOARCH>/deepseek-vision.<ext> 또는 설정한 plugins.dir 아래에 배치한 뒤 CLIProxyAPI를 재시작한다.[1]
Docker에서는 CLIProxyAPI가 컨테이너 안에서 실행되므로 컨테이너의 OS·architecture에 맞는 자산을 /CLIProxyAPI/plugins로 마운트해야 한다.[2] Linux amd64 예시는 plugins/linux/amd64/deepseek-vision.so이며, macOS는 .dylib, Windows는 .dll이다.[1]
소스에서 패키징할 때 VERSION=0.3.0 ./scripts/package.sh는 native target의 c-shared library를 만들고, cliproxy_plugin_init export·version metadata·credential marker를 검사한 뒤 deterministic ZIP과 checksum을 생성한다. release 자산은 6개 native runner에서 전체 플랫폼을 빌드하도록 설계되어 있다.[1][2]
검증 결과와 한계
저장소가 제공하는 계약 검증 스크립트를 이번 조사 환경에서 실제 실행했다.[2]
./scripts/verify-contracts.sh: 성공, JSON fixture 15개와 필수 contract marker 검증.[2]bash -n scripts/*.sh및python3 -m py_compile test/e2e/mock_openai.py: 성공.[2]go test ./...: 현재 조사 호스트에 Go executable이 없어 실행하지 못함 (go: command not found).[2] 따라서 이 기록은 전체 Go unit/race/vet 통과를 주장하지 않는다.[2]
프로젝트 자체의 권장 CI 명령은 go test ./..., go test -race ./..., go vet ./..., ./scripts/verify-contracts.sh, ./scripts/package-smoke.sh다.[2] VLM 처리는 응답 스트림 전에 수행되므로 이미지가 있는 요청의 first-byte latency가 증가하고, 캐시는 process-local이라 여러 CLIProxyAPI 인스턴스 사이에서 공유되지 않는다.[1]
평가
강점
- CLIProxyAPI의 인증·provider routing·credential boundary를 재사용해 별도 API key와 새 proxy 운영면을 만들지 않는다.[2]
- Responses·Chat·Claude를 각각 native 구조로 처리해 protocol 변환으로 인한 이미지 위치·tool history 손상을 줄인다.[2]
- 여러 이미지 공동 분석, ordered fallback, ordinary cache와 reanalysis idempotency를 분리해 실사용 흐름을 명시적으로 모델링한다.[2]
- 실패 시 원본 이미지가 DeepSeek로 새어 나가지 않도록 fail-closed하고, 502·diagnostics에서 upstream 민감정보를 제한한다.[2]
- ABI admission, body/reference/image limits, prompt injection 방어, trace opt-in 경계를 문서와 코드 계약으로 함께 관리한다.[2]
비용과 주의점
- VLM 전처리가 요청의 첫 응답 전에 들어가므로 latency와 provider 비용이 추가된다.[2]
- 비전 모델이 이미지를 읽는 실제 네트워크·보존·데이터 residency는 CLIProxyAPI가 선택한 provider와 배포 환경에 달려 있다.[2]
trace_enabled는 대화·이미지 URL·VLM 입출력을 평문으로 남길 수 있어 디버깅 이후 즉시 꺼야 한다.[2]- 기본 지원 모델은
deepseek-v4-flash이며,deepseek-v4-pro나 다른 모델은 upstream Responses 호환성을 별도로 검증해야 한다.[2] - Go 1.26과 CGO가 필요한 native plugin이라 현재 Linux 조사 환경처럼 Go가 없는 머신에서는 소스 빌드·unit test를 바로 재현할 수 없다.[2]
관련 문서
- deepseek-v4 — DeepSeek V4 계열 모델 엔터티
- moc-ai-models — AI 모델·멀티모달 모델·서빙 도구
- moc-ai-agents — Agent의
view_image재분석과 host tool 경계 - moc-dev-tools — CLIProxyAPI 플러그인·개발 도구
- 2026-05-02-ds2api — DeepSeek Web을 API 호환 계층으로 바꾸는 별도 Go 미들웨어
출처
이 문서의 source provenance와 핵심 파일 SHA-256은 raw source: github-zesuy-plugin-deepseek-vision에 보존했다.
Sources
[1] https://github.com/Zesuy/Plugin-Deepseek-Vision — Zesuy deepseek-vision repository [2] https://github.com/Zesuy/Plugin-Deepseek-Vision/tree/91fbbe3e497c8fd98f08bf4e4497921124597314 — deepseek-vision source snapshot at 91fbbe3e