mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-19 11:06:18 +00:00
* fix(models): make request admission enqueue atomic * test(models): cover atomic request admission FIFO entry * docs(models): record atomic admission FIFO invariant * fix(models): address request-admission review follow-ups
5.0 KiB
5.0 KiB
Model Factory (packages/harness/deerflow/models/factory.py)
Request-admission waits follow the next scheduled admission and configured
interval, capped at 50 ms; the cap must not become a minimum poll interval that
limits high-RPM throughput. Local AdmissionError is structurally non-retriable
in LLM error handling regardless of its message text. Immediate admission and
joining the blocking FIFO are one lock-protected decision: do not split the
fast-path permit check from queue insertion, or an older caller can be overtaken
while handing off to the wait queue.
create_chat_model(name, thinking_enabled)instantiates LLM from config via reflection- Supports
thinking_enabledflag with per-modelwhen_thinking_enabledoverrides - Supports vLLM-style thinking toggles via
when_thinking_enabled.extra_body.chat_template_kwargs.enable_thinkingfor Qwen reasoning models, while normalizing legacythinkingconfigs for backward compatibility - A per-request
reasoning_effortkwarg (the regular, non-bootstrap lead-agent build passes it even whenNone) is popped fromkwargsand layered likemodel_overrides: a non-Nonevalue replaces the profile's, and the thinking transforms applied afterwards (when_thinking_enabled,when_thinking_disabled, theextra_body.thinkingdisable path) still decide the final value. Never let a key reach the constructor through bothkwargsand the profile settings — Python raisesgot multiple values for keyword argumentand the lead agent cannot be built for that model. Codex checks the requested level itself. Pinned bytests/test_model_factory.pyandtests/test_lead_agent_model_resolution.py - Supports
supports_visionflag for image understanding models - Config values starting with
$resolved as environment variables - Missing provider modules surface actionable install hints from reflection resolvers (for example
uv add langchain-google-genai) - Optional
models[].request_admissionattaches a process-sharedBaseRateLimiterat the model factory. Identical explicit groups share one FIFO across model instances, threads and event loops; implicit groups use the configured model name. Policies are immutable once registered and conflicting settings fail construction. A monotonic minimum interval spaces requests without idle-time burst credit; bounded waiters poll without occupying executor threads and unregister infinally. The factory strips the policy from provider kwargs and sets exposed SDKmax_retries=0so middleware retries re-enter admission. This limits model invocations, not tokens or a distributed provider account; custom providers bypassing BaseChatModel hooks are outside the contract. Tests:test_model_request_admission.pyandtest_model_request_admission_fifo_atomic.py.
Claude Code Credentials (packages/harness/deerflow/models/credential_loader.py)
ClaudeChatModel.model_post_initcallsload_claude_code_credential()for every instance, andcreate_chat_modelbuilds fresh instances per run (lead agent, title, summarization, subagents)$CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTORis a one-shot handoff: a pipe returns EOF and a file keeps its advanced offset._read_secret_from_file_descriptortherefore caches a non-empty secret per(env_var, fd)under a lock held across the read. Do not drop the cache or the lock — later instances would get no credential, and the Anthropic SDK raisesTypeError: Could not resolve authentication methodbefore sending. Empty reads andOSErrorare not cached. The key is the descriptor number on purpose — a closed handoff keeps serving its token, and a secret placed on a recycled number in-process is not re-read unless the cache is cleared. The cache is per process, so a new process (e.g. a uvicorn--reloadworker) cannot recover a drained descriptor. Pinned bytests/test_credential_loader.py, including a two-instanceClaudeChatModeltest
vLLM Provider (packages/harness/deerflow/models/vllm_provider.py)
VllmChatModelsubclasseslangchain_openai:ChatOpenAIfor vLLM 0.19.0 OpenAI-compatible endpoints- Preserves vLLM's non-standard assistant
reasoningfield on full responses, streaming deltas, and follow-up tool-call turns - Designed for configs that enable thinking through
extra_body.chat_template_kwargs.enable_thinkingon vLLM 0.19.0 Qwen reasoning models, while accepting the olderthinkingalias cumulative_stream_usageis an opt-in model setting (defaultfalse) for endpoints that repeat cumulative token totals on each streaming chunk. The provider converts snapshots to deltas only when a stable completion id is present, isolates interleaved streams by id, and leaves the original usage untouched otherwise. Per-model tracking is lock-protected and cleared on the trailing empty-choicesframe whether or not that frame carries usage. A soft cap of 1024 ids evicts only entries idle for at least one hour; active streams may temporarily exceed the cap so eviction cannot corrupt their deltas. Regression coverage lives intests/test_vllm_provider.py.