Repository navigation
Conversation
load_plugins() registered every module with a SLUG and a run() unconditionally, so the executecode plugin - which runs Python from user requests and LLM responses in a live Jupyter kernel with no sandboxing - was active in all deployments by default. With no optillm_api_key set, any unauthenticated request could reach full code execution on the host (issue algorithmicsuperintelligence#302). - Add UNSAFE_DEFAULT_DISABLED_PLUGINS and skip such plugins during load_plugins() with a warning that names the exact flag to re-enable - Opt back in via --enable-unsafe-plugins (CLI), OPTILLM_ENABLE_UNSAFE_PLUGINS (env) or server_config; comma-separated slugs, same three-part pattern as --readurls-allow-internal - Reload plugins after parse_args() in main() so the opt-in (and --plugins-dir) apply to the loaded set; the pre-parse load is kept for --approach choices. With the env var set even the first load includes the plugin, so --approach keeps working - README: mark the executecode row as disabled by default and add a code-execution security section mirroring the readurls one - No sandboxing in this change (nsjail/gVisor-style isolation is out of scope); pure stdlib, no new dependencies Note: this is an intentional default behavior change - deployments that rely on executecode must now set the flag or env var. Fixes algorithmicsuperintelligence#302
Watch the model's reasoning as it is generated and inject a hint from a memory bank when it hesitates or moves to a new step. Generation runs in segments so it works with every client, including the local inference server. Retrieval is TF-IDF over a bundled JSON hint bank, with no new dependencies. The RL-trained retriever is left as follow-up work. Fixes algorithmicsuperintelligence#206
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gins by default Fixes algorithmicsuperintelligence#302 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
o-series and gpt-5 models reject max_tokens, so pass-through requests that used max_completion_tokens failed with a 400. Keep the copy for approaches that read max_tokens, but do not forward it from the none approach or the proxy plugin. The local inference client only read max_tokens, so it now honors max_completion_tokens too. Fixes algorithmicsuperintelligence#350 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The MCP plugin wrote configured env and header values, which hold API keys, to ~/.optillm/logs/mcp_plugin.log at debug level, the level it starts at before the config is loaded. Log only the names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run the MCP tests on pull requests, where the one test that needs a token skips itself on forks, and add the test files that no CI job ran. Stop hiding test_api_compatibility failures and fix its test_utils import, which stopped it running under pytest. Make the entropy sampling test independent of how tied tokens are ordered, which differs by platform. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove emojis, consolidate the security and MCP sections, and collapse older benchmarks. Correct the MCTS flag names and a broken reference link, and list the compact plugin. Add docs/llm-gateway.md on using the proxy plugin for routing and optimization together. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
executecode is now disabled by default, which changes behavior for deployments that rely on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
streaming_hintsplugin. It watches the model's reasoning as it is generated and injects a hint from a memory bank when the model hesitates ("wait", "not sure", "let me check") or moves to a new step. This is the inference half of #206. The RL-trained retriever is left for a follow-up, and the README in the plugin folder says so.Changes
optillm/plugins/streaming_hints/memory_bank.pyholdsHintandHintMemoryBank. Retrieval is TF-IDF cosine over hint text plus keywords (keywords count double), in pure Python, so there is no new dependency.search(query, k, exclude)is the interface an embedding-backed bank could implement later.retriever.pyholdsStreamingHintRetriever. It consumes reasoning incrementally, sentence by sentence, across chunk boundaries. A sentence is an injection point whenmin_gap_charshave passed since the last hint and it carries an uncertainty signal or ends a paragraph. At that point it queries the bank with the problem plus the last 600 characters of reasoning and returns the best unused hint abovehint_threshold.streaming_hints.pyis the driver. It generates in segments ofsegment_tokens, feeds each segment to the retriever, cuts the segment at the injection point, appends<hint>...</hint>and continues from the cut. It stops when the model finishes, atmax_segments, or whenmax_tokensis spent across segments.hints.jsonis a bundled bank of 20 general hints (math, coding, reasoning).hints_pathpoints to a custom one.README.mdcovers how it works, config, the custom hint format and future work.optillm/plugins/streaming_hints_plugin.py, theSLUG = "streaming_hints"entry point.pyproject.tomlshipshints.jsonas package data (checked in a built wheel).tests/test_plugins.pylists, and the new test file added to the unit-test step intest.yml.Usage follows the issue:
By default the response is the model text only.
show_hints: truereturns it with the<hint>tags.Testing
tests/test_streaming_hints.pyadds 11 tests with a fake client. They cover ranking in the bundled bank, exclusion, injection only at an uncertainty signal after the gap, a sentence split across two chunks, the threshold andmax_hints, cutting and continuing (the discarded tail never reaches the next prompt),show_hints, continuation after a length cut-off, themax_tokensbudget across segments, and the plugin entry point.The unit-test step from
test.yml, run locally on Python 3.12:test_reasoning_simple.pyandtest_batching.pyfailed locally onmainas well, withpyarrow has no attribute PyExtensionTypefrom an olddatasetsthat my resolver picked. CI onmainis green, so this is my environment.End to end through the server with local inference (
OPTILLM_API_KEY=optillm,Qwen/Qwen2.5-0.5B-Instruct,segment_tokens=100,min_gap_chars=80,max_tokens=300,show_hints=true), on "A train travels 120 km in 1.5 hours. What is its speed in meters per second?":I have no benchmark numbers. That needs an API budget and is listed as future work.
Notes for reviewers
optillm/streaming_hints/likeautothink/.autothinkis a local-decoding approach, while this one only needs the OpenAI client, so a plugin (with its package underplugins/likedeepthink/) works with every provider and needs no change toserver.py. Happy to move it if you prefer the core layout.stream=True, so the driver generates in segments, and up to one segment of text after an injection point is generated and then discarded. Feeding token deltas from a real stream and cancelling it would avoid that for providers that stream. The retriever already takes arbitrary deltas, so only the driver would change.finish_reason: "stop", so a segment that used its whole token budget is also treated as cut off.<reasoning_so_far>and the model is asked to continue. That works on every provider, but where a segment was cut by the token limit mid-sentence, a small model sometimes starts a new sentence instead of finishing it (visible as "120,Next" in the live run). Assistant-prefill continuation would be smoother on providers that support it.Hint.usesis counted as a first usage statistic.Fixes #206