cb535d033c
## Description Fixes #4631. With a local provider and `LLM_TEMPERATURE` unset, cognee sends no `temperature` at all, so extraction runs at whatever the model itself defaults to. For several Ollama models that is `1.0`. `docs/ollama_models.md` already tells users extraction wants `0.0`, but nothing in the default path does it. **Why the gate exists, and why it is too wide.** `fold_sampling_params_into_llm_args` only folds `llm_temperature` when it is in `model_fields_set`, and its docstring gives the reason: the default gpt-5 family rejects any temperature other than the provider default, so an unset field must not silently send `0.0`. That reason is real, but it is a property of the hosted OpenAI reasoning models, not of every provider. The gate applies to all of them, so Ollama, llama.cpp and LM Studio inherit a workaround for a restriction they do not have. `llm_temperature` already defaults to `0.0`, so the value was there the whole time; only the gate stopped it. **The fix** is one condition, reusing the predicate this file already has: ```python if "llm_temperature" in self.model_fields_set or is_local_llm( self.llm_provider, self.llm_model ): folded["temperature"] = self.llm_temperature ``` `is_local_llm` is not new here. The validator immediately below, `default_local_rate_limit_budget`, already uses it to give local servers a different default for the same class of reason: a default shaped for cloud endpoints being wrong for local ones. This follows that precedent rather than adding a new axis, and it runs after `infer_provider_from_model`, the same precondition that validator documents. **Two things I deliberately did not do.** I did not invert the gate to "everything except gpt-5", which is arguably the more principled shape since gpt-5 is the actual constraint named in the docstring. It would start sending `0.0` to every Anthropic, Gemini, Mistral and Bedrock user who never asked for it, which is a far larger behaviour change than this bug justifies. I did not widen `is_local_llm`. It excludes vLLM because vLLM batches like a cloud endpoint, and that exclusion was written for rate limiting rather than for temperature, so a vLLM endpoint would in fact accept the field. I kept the existing predicate anyway: a vLLM user setting `LLM_TEMPERATURE` explicitly already works today, and splitting the two meanings apart is a bigger change than this bug needs. Happy to split it if you would rather. **Docs.** The change makes two existing statements wrong, so both are updated here. `.env.template` said an unset value uses the provider's default, now qualified for local servers. `docs/ollama_models.md` troubleshooting item 2 told users to set `LLM_TEMPERATURE=0.0` themselves, which is now the default, so the item became a check rather than an instruction. This is option (a) from the issue; it is not an alternative to the code change, it is required by it. ## Acceptance Criteria - A local provider with `LLM_TEMPERATURE` unset sends `temperature: 0.0`; hosted providers, vLLM included, are unchanged. - Explicit configuration still wins: `LLM_TEMPERATURE` at any value is folded as before, and a `temperature` key in `LLM_ARGS` still takes precedence over the dedicated field. - Added to `cognee/tests/unit/infrastructure/llm/test_llm_config.py`, beside the existing sampling-param tests: - `test_local_provider_folds_unset_temperature` (ollama, llama_cpp, lm_studio) — the bug - `test_non_local_provider_still_omits_unset_temperature` (gpt-5, two vLLM spellings) — pins the boundary - `test_explicit_temperature_wins_on_local_provider` - `test_llm_args_temperature_wins_over_local_default` - Verified fail-first by reverting only `config.py` and keeping the tests: exactly the three `test_local_provider_folds_unset_temperature` cases fail. The other four pass either way, since they pin behaviour this change does not alter. - The existing `test_unset_temperature_is_not_folded_into_llm_args` builds a default config, which is the gpt-5 path, and still passes untouched. - `unit/infrastructure/llm/` + `unit/modules/retrieval/` run like for like against `dev`: the failure sets diff identical, with +8 passes for the tests added. The 10 failures in that set are pre-existing on `dev`. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Code refactoring - [ ] Other (please specify): ## Screenshots See the attached run. ## Pre-submission Checklist - [x] **I have tested my changes thoroughly before submitting this PR** (See `CONTRIBUTING.md`) - [x] **This PR contains minimal changes necessary to address the issue/feature** - [x] My code follows the project's coding standards and style guidelines - [x] I have added tests that prove my fix is effective or that my feature works - [x] I have added necessary documentation (if applicable) - [x] All new and existing tests pass — with the caveat noted above, that 10 tests in `unit/modules/retrieval/` already fail on `dev` in my environment and are unchanged by this PR - [x] I have searched existing PRs to ensure this change hasn't been submitted already - [x] I have linked any relevant issues in the description - [x] My commits have clear and descriptive messages ## DCO Affirmation I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin. Signed-off-by: Chinmay V <chinmayv095@gmail.com>