Unstablity when using in OpenCode

#31
by http403 - opened

I'm using this model in conjunction of models in OpenCode. I found this model have the tendency of writing to /tmp regardless of deny message. Here my setup.

llama.cpp: b9553
Opencode: 1.17.4
Workspace: https://github.com/kdcokenny/opencode-workspace

OpenCode config:
{
    "$schema": "https://opencode.ai/config.json",
      "model": "llama/qwen3.5-9b",
    "small_model": "llama/nemotron-3-nano-4b",
    "provider": {
        "llama": {
            "npm": "@ai-sdk/openai-compatible",
            "name": "LM Studio",
            "options": {
                "baseURL": "http://127.0.0.1:9055/v1"
            },
            "models": {
                "gemma4-12b-fable5-distilled": {
                    "name": "Gemma 4 12B Fable5 Distilled",
                    "modalities": {
                        "input": [
                            "text"
                        ],
                        "output": [
                            "text"
                        ]
                    },
                    "reasoning": true,
                    "tool_call": true,
                    "cost": {
                        "input": 1e-06,
                        "output": 3.2e-06,
                        "cache_read": 2e-07
                    }
                },
                "qwen3.5-9b": {
                    "name": "Qwen 3.5 9B",
                    "modalities": {
                        "input": [
                            "text"
                        ],
                        "output": [
                            "text"
                        ]
                    },
                    "reasoning": true,
                    "tool_call": true,
                    "cost": {
                        "input": 1e-06,
                        "output": 3.2e-06,
                        "cache_read": 2e-07
                    }
                },
                "nemotron-3-nano-4b": {
                    "name": "Nemotron 3 Nano 4B",
                    "modalities": {
                        "input": [
                            "text"
                        ],
                        "output": [
                            "text"
                        ]
                    },
                    "reasoning": true,
                    "tool_call": true,
                    "cost": {
                        "input": 1e-06,
                        "output": 3.2e-06,
                        "cache_read": 2e-07
                    }
                }
            },
        },
    },
    "agent": {
        "plan": {
            "model": "llama/qwen3.5-9b",
            "temperature": 0.75,
            "reasoningEffort": "high",
            "textVerbosity": "low",
            "permission": {
                "edit": "deny",
                "write": "deny",
                "bash": {
                    "*": "deny"
                },
                "task": "deny",
                "worktree_*": "allow"
            },
        },
        "build": {
            "model": "llama/qwen3.5-9b",
            "temperature": 0.75,
            "reasoningEffort": "high",
            "textVerbosity": "low",
            "prompt": "You are a **build orchestrator**. You coordinate implementation through delegation - you do NOT implement directly.\\\\\\\\n\\\\\\\\n## Your Role\\\\\\\\n- Delegate implementation to `coder`\\\\\\\\n- Delegate documentation to `scribe`\\\\\\\\n- Delegate codebase analysis to `explore`\\\\\\\\n- Delegate external research to `researcher`\\\\\\\\n- Interpret results and decide next steps\\\\\\\\n\\\\\\\\n## Critical Constraint\\\\\\\\nYou CANNOT edit files or run commands directly. For ALL implementation and verification, delegate to `coder`.",
            "permission": {
                "edit": "deny",
                "write": "deny",
                "bash": {
                    "*": "deny"
                },
                "task": "allow",
                "worktree_*": "allow"
            }
        },
        "coder": {
            "model": "llama/gemma4-12b-fable5-distilled",
            // "temperature": 1.0,
            // "reasoningEffort": "high",
            // "textVerbosity": "low",
            "permission": {
                "context7_*": "deny",
                "exa_*": "deny",
                "gh_grep_*": "deny",
                "read": "allow",
                "write": "allow",
                "edit": "allow",
                "glob": "allow",
                "grep": "allow",
                "bash": "allow",
                "plan_read": "deny",
                "todoread": "deny"
            }
        },
        "explore": {
            "model": "llama/nemotron-3-nano-4b",
            "temperature": 0.7,
            "reasoningEffort": "low",
            "textVerbosity": "low",
            "permission": {
                "edit": "deny",
                "write": "deny",
                "plan_read": "deny",
                "todoread": "deny",
                "bash": {
                    "*": "deny",
                    "ls *": "allow",
                    "tree *": "allow",
                    "pwd": "allow",
                    "cat *": "allow",
                    "head *": "allow",
                    "tail *": "allow",
                    "wc *": "allow",
                    "file *": "allow",
                    "stat *": "allow",
                    "grep *": "allow",
                    "rg *": "allow",
                    "find *": "allow",
                    "git status*": "allow",
                    "git log*": "allow",
                    "git diff*": "allow",
                    "git show*": "allow",
                    "git blame*": "allow",
                    "git branch*": "allow",
                    "git ls-files*": "allow",
                    "uname*": "allow",
                    "hostname": "allow",
                    "whoami": "allow",
                    "which *": "allow",
                    "realpath *": "allow"
                }
            }
        },
        "researcher": {
            "model": "llama/nemotron-3-nano-4b",
            "temperature": 0.7,
            "reasoningEffort": "high",
            "textVerbosity": "medium",
            "permission": {
                "context7_*": "allow",
                "exa_*": "allow",
                "gh_grep_*": "allow",
                "kagi_*": "deny",
                "webfetch": "allow",
                "write": "deny",
                "edit": "deny",
                "plan_read": "deny",
                "todoread": "deny",
                "bash": {
                    "*": "deny",
                    "gh repo view*": "allow",
                    "gh pr view*": "allow",
                    "gh pr list*": "allow",
                    "gh issue view*": "allow",
                    "gh issue list*": "allow",
                    "gh release view*": "allow",
                    "gh release list*": "allow",
                    "gh run view*": "allow",
                    "gh run list*": "allow",
                    "gh workflow list*": "allow",
                    "gh search *": "allow",
                    "gh api *": "allow",
                    "npm view*": "allow",
                    "npm info*": "allow",
                    "npm show*": "allow",
                    "pip show*": "allow",
                    "pip index*": "allow",
                    "cargo search*": "allow",
                    "cargo info*": "allow",
                    "man *": "allow",
                    "tldr *": "allow",
                    "dig *": "allow",
                    "nslookup *": "allow",
                    "whois *": "allow",
                    "host *": "allow",
                    "jq *": "allow",
                    "head *": "allow",
                    "tail *": "allow",
                    "base64 *": "allow",
                    "grep *": "allow",
                    "rg *": "allow",
                    "wc *": "allow",
                    "sort *": "allow",
                    "uniq *": "allow",
                    "cut *": "allow",
                    "awk *": "allow",
                    "tr *": "allow"
                }
            }
        },
        "scribe": {
            "model": "llama/qwen3.5-9b",
            "temperature": 0.9,
            "reasoningEffort": "low",
            "textVerbosity": "high",
            "permission": {
                "bash": {
                    "*": "deny"
                },
                "edit": "allow",
                "glob": "allow",
                "read": "allow",
                "write": "allow",
                "plan_read": "deny",
                "todoread": "deny"
            }
        },
        "reviewer": {
            "model": "llama/qwen3.5-9b",
            "temperature": 0.75,
            "reasoningEffort": "high",
            "textVerbosity": "medium",
            "permission": {
                "edit": "deny",
                "write": "deny",
                "bash": {
                    "*": "deny",
                    "git diff*": "allow",
                    "git log*": "allow",
                    "git show*": "allow",
                    "git blame*": "allow",
                    "rg *": "allow"
                },
                "plan_read": "allow",
                "delegation_read": "allow",
                "delegation_list": "allow"
            }
        }
    },
    "mcp": {
        "context7": {
            "type": "remote",
            "url": "https://mcp.context7.com/mcp",
            "enabled": true
        },
        "exa": {
            "type": "remote",
            "url": "https://mcp.exa.ai/mcp",
            "enabled": true
        },
        "gh_grep": {
            "type": "remote",
            "url": "https://mcp.grep.app",
            "enabled": true
        }
    },
    "permission": {
        "task": "deny",
        "context7_*": "deny",
        "exa_*": "deny",
        "gh_grep_*": "deny",
        "kagi_*": "deny",
        "webfetch": "deny",
        "worktree_*": "deny"
    },
    "instructions": [
        "./tools/philosophy.md"
    ],
    "plugin": [
        "@tarquinen/opencode-dcp@3.1.3",
        "@franlol/opencode-md-table-formatter@0.0.6"
    ]
}
llama.cpp config
version = 1

[*]
metrics = 1
no-mmap = 1
n-gpu-layers = 99
flash-attn = on
cache-type-k = q4_0
cache-type-v = q4_0
jinja = 1

[gemma4-12b-fable5-distilled]
model = ~/models/yuxinlu1/gemma-4-12B-agentic-fable5-composer2.5-v2-3.5x-tau2-GGUF/gemma4-v2-Q6_K.gguf
model-draft = ~/models/yuxinlu1/gemma-4-12B-agentic-fable5-composer2.5-v2-3.5x-tau2-GGUF/gemma-4-12B-it-MTP-Q8_0.gguf
spec-type = draft-mtp
spec-draft-n-max = 4
temp = 1
top-k = 64
top-p = 0.95
repeat-penalty = 1.1
ctx-size = 256000
parallel = 2

[qwen3.5-9b]
model = ~/models/lmstudio-community/Qwen3.5-9B-GGUF/Qwen3.5-9B-Q4_K_M.gguf
temp = 0.6
top-p = 0.95
top-k = 20
min-p = 0.0
presence-penalty = 0.0
repeat-penalty = 1.0
ctx-size = 128000
parallel = 1
chat-template-file = ~/templates/qwen3.5-9b-opencode.jinja

[nemotron-3-nano-4b]
model = ~/models/lmstudio-community/NVIDIA-Nemotron-3-Nano-4B-GGUF/NVIDIA-Nemotron-3-Nano-4B-Q4_K_M.gguf
temp = 0.6
top-p = 0.95
top-k = 40
min-p = 0.0
presence-penalty = 0.0
repeat-penalty = 1.1
ctx-size = 256000
parallel = 2

I don't think this is an issue belong to OpenCode, as this particular problem doesn't show with other models like Qwen3.6-27B.

And it is looping forever.
A screenshot of the model repeating itself in the same task

And sometime hallucinating paths
A screenshot of the model hallucinating

Or writing invalid Python code
A screenshot of the model writing invalid Python code

http403 changed discussion title from Writing to /tmp to Unstablity when using in OpenCode

Thanks for writing this up with screenshots β€” this is genuinely the kind of report I can act on.
Since you're on v2 (the agentic version), let me be straight about what you're seeing. The non-converging rewrite loop ("keep producing dead versions, never actually call the handler") and the path hallucination (editing /tmp directories that don't exist) are real model-side behaviors, not something I'll explain away. They're execution-robustness and grounding limits: v2 will attempt the task and often gets the logic right, but it over-acts instead of converging, and it doesn't always ground an edit on a real read first. This is exactly the failure class I'm fixing in v3 β€” grounding an edit on an actual read before writing, backing off instead of retrying the same failing action, and not cycling dead versions. Your report maps directly onto what's already on the roadmap.

The invalid Python is a different story, and that one is likely fixable on your side right now. The signature β€” "--" comments, "===" / "||", stray integers spliced into the code, languages mixed together β€” is almost certainly a sampling/quant issue, not broken weights. Long, dense code generation with a repetition penalty (or DRY) pushes the model off the valid-token path, and it starts emitting wrong operators and noise. Two things to try: for long one-shot code, set repeat penalty to 1.0 and turn DRY off (keep temp 1.0, top_p 0.95, top_k 64) β€” the penalty only helps short outputs; and use Q4 or higher, since Q3/Q2 degrade code noticeably.

One opencode-specific note: serve with llama-server --jinja so Gemma 4's native tool format is parsed, and set toolParser to raw-function-call in opencode.json. A heavy multi-step agent harness is also genuinely demanding for a 12B β€” even when the code is right, the loop can hallucinate around it, so trust-but-verify.

If you can share your quant, your sampling settings, and the backend, I can pin the invalid-Python part down precisely. Appreciate the detailed write-up. πŸ™

You have the quant and sampling setting under the expandable tab of llama.cpp config. I will repost it below.

settings
backend vulkan
quant Q6_K
temp 1
top-k 64
top-p 0.95
repeat-penalty 1.1

In terms of DRY, do I only need to set --dry-multiplier to 0 in order to disable it?

Sign up or log in to comment