Stop sequences configured on non-workflow apps are never sent to the model
- Dominant language
- TypeScript
- Stars
- 156k
- Forks
- 24.6k
- Avg merge
- 22h 9m
- Merged PRs (30d)
- 610
Description
### Self Checks
- [x] I have read the [Contributing Guide and Language Policy](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md).
- [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
- [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
- [x] I confirm that I am using English to submit this report.
- [x] [FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)
- [x] Please do not modify this template :) and fill in all the required fields.
### Dify version
1.17.0
### Cloud or Self Hosted
Self Hosted (Source)
### Steps to reproduce
1. Create a Chatbot app (this also affects Agent, Completion and Agent Chat apps).
2. Switch the prompt to expert mode.
3. Open the model parameter panel and add a stop sequence, for example `###`.
4. Publish, then send a message that makes the model produce `###` mid answer.
5. The model keeps generating past `###`.
The saved app model config is correct, the loss happens during runtime conversion. `ModelConfigManager.convert` moves `stop` out of `completion_params` and onto `ModelConfigEntity.stop`, but `ModelConfigConverter.convert` still looks for `stop` inside `model_config.parameters`, where it no longer exists, and never reads `model_config.stop`. `ModelConfigWithCredentialsEntity.stop` is therefore always empty, and `ModelConfigEntity.stop` has no readers anywhere in the codebase.
```python
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
from core.app.app_config.easy_ui_based_app.model_config.converter import ModelConfigConverter
from core.app.app_config.easy_ui_based_app.model_config.manager import ModelConfigManager
M = "core.app.app_config.easy_ui_based_app.model_config.converter"
saved = {"model": {"provider": "openai", "name": "gpt-4", "mode": "chat",
"completion_params": {"temperature": 0.5, "stop": ["###"]}}}
entity = ModelConfigManager.convert(saved)
print("ModelConfigEntity.stop ->", entity.stop)
with (patch(f"{M}.create_plugin_provider_manager"),
patch(f"{M}.ModelConfigWithCredentialsEntity", side_effect=lambda **kw: SimpleNamespace(**kw))):
runtime = ModelConfigConverter.convert(MagicMock(tenant_id="t", model=entity))
print("stop actually sent to model ->", runtime.stop)
```
```
ModelConfigEntity.stop -> ['###']
stop actually sent to model -> []
```
Affected consumers are `core/app/apps/base_app_runner.py:167` for the advanced prompt path and `core/agent/cot_agent_runner.py:150` and `core/agent/fc_agent_runner.py:182` for agent apps.
I have a fix ready with a regression test and would be happy to be assigned to this issue.
### ✔️ Expected Behavior
The stop sequences saved in the model configuration reach `invoke_llm`, so generation stops at the configured sequence.
### ❌ Actual Behavior
`ModelConfigWithCredentialsEntity.stop` is always an empty list, so the model is invoked with no stop sequences and generation runs past them.
Contributor guide
Research direction
Start with ModelConfigManager.convert and ModelConfigConverter.convert in core/app/app_config/easy_ui_based_app/model_config, then inspect the affected consumers at core/app/apps/base_app_runner.py:167, core/agent/cot_agent_runner.py:150, and core/agent/fc_agent_runner.py:182. Run or extend the regression test mentioned in the issue and confirm that configured stop sequences reach invoke_llm for non-workflow and agent apps.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- ai, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100