Skip to content

feat: add cloud-based LLM support and robust error recovery - #41

Open
amaynez wants to merge 1 commit into
nikmcfly:mainfrom
amaynez:feat/cloud-llm-support
Open

feat: add cloud-based LLM support and robust error recovery#41
amaynez wants to merge 1 commit into
nikmcfly:mainfrom
amaynez:feat/cloud-llm-support

Conversation

@amaynez

@amaynez amaynez commented May 3, 2026

Copy link
Copy Markdown

This pull request introduces comprehensive support for cloud-based LLM providers like OpenRouter, significantly expanding the accessibility of MiroFish-Offline.

The primary objective of these changes is to democratize access to the platform. By allowing users to offload the heavy lifting of model inference to cloud providers, we enable participation from a much broader user base. This includes individuals who lack the high performance hardware typically required for sufficiently intelligent local inference.

Key Enhancements:

  1. Cloud Provider Integration: Users can now choose between local Ollama instances and cloud-based OpenAI-compatible endpoints. This flexibility ensures that the system remains functional even on resource-constrained devices.
  2. Robust JSON Repair: A new multi-phase JSON repair logic has been implemented. This ensures that the system can recover from truncated or malformed responses, which are common when dealing with complex structured extractions or low-latency cloud endpoints.
  3. Modular LLM Configuration: The internal architecture now supports separate configurations for different tasks. For example, users can use a lighter model for general interactions while utilizing a more powerful model specifically for graph extraction and ontology generation.
  4. Optimized Deployment: Docker Compose configurations have been updated to make the Ollama service optional. This simplifies the initial setup for cloud-centric users while maintaining full offline capabilities for those with the necessary hardware.
  5. Improved Error Visibility: The frontend now extracts and displays backend error messages more effectively, providing a better debugging experience for developers and a clearer interface for users.

By incorporating these changes, the project transitions from a hardware-dependent tool to a versatile platform that adapts to the user's environment. This strategy not only increases the potential user base but also improves the overall reliability and professional polish of the codebase.

nocode-ananas added a commit to nocode-ananas/polylop that referenced this pull request Jun 6, 2026
…kept FAST patch, kept 24h timeout, kept ollama out of compose)
nocode-ananas added a commit to nocode-ananas/polylop that referenced this pull request Jul 24, 2026
…j connection guards, 0-entities => FAILED

- llm_client.py: retry loop (429/5xx, Retry-After, exp. backoff 2-60s) merged
  onto Polylop base (24h timeout, JSON repair, for_graph_extraction kept)
- neo4j_storage.py: health_check + _verify_connection guards, louder
  embedding-failure log
- api/graph.py: build task with 0 extracted entities now marked FAILED
  instead of completed
- embedding_service.py part of PR nikmcfly#50 NOT taken: Polylop already has the
  better implementation (Bearer token + index sort) from PR nikmcfly#41 backport
- verified: 4 fault-injection tests in container (retry, exhaustion,
  non-retryable, backoff timing)
nocode-ananas added a commit to nocode-ananas/polylop that referenced this pull request Jul 24, 2026
Fixes the simulation lifecycle bugs from the 2026-06-13 audit (section B).
No upstream PR covers these — nikmcfly nikmcfly#30/nikmcfly#41/nikmcfly#50/nikmcfly#51 are already backported
and address other areas.

Every finding was reproduced against the unpatched code before fixing, using
backend/tests/test_simulation_lifecycle.py: 11/31 checks pass on the baseline,
31/31 with this patch.

Stop had no effect on reconnected simulations
  stop_simulation only ever looked at cls._processes, which is empty after a
  backend restart. The status flipped to 'stopped' while the process kept
  running — and kept calling the LLM API, costing real money. Added a PID-based
  termination path (SIGTERM, then SIGKILL) for simulations we have no Popen
  handle for.

Manually stopped runs were reported as failed/completed
  The monitor thread woke up to the SIGTERM exit code and overwrote the stop
  with 'failed'; the orphan monitor could report 'completed'. An explicit stop
  is now recorded and wins over the exit-code verdict. stop_simulation also
  waits for the monitor instead of racing it.

Double start was possible
  Nothing serialized check-and-spawn, so concurrent /start requests (the axios
  interceptor retries POSTs up to 3x) each spawned a process into the same
  directory. Added a per-simulation lock, and a liveness check so a start is
  refused while the real process is alive even if the status file claims
  otherwise.

state.json and run_state.json drifted apart
  Nothing wrote the terminal status into state.json when a simulation ended on
  its own, so finished runs kept showing as running (live: sim_cb2ebb78e07a,
  run_state 'completed' vs state.json 'running'). The runner now mirrors its
  terminal status into state.json through one shared, atomic writer. /stop
  records STOPPED instead of PAUSED — the process is terminated, not suspended,
  no view renders 'paused', and PAUSED overwrote the runner's own status.

PID reuse could adopt an unrelated process
  os.kill(pid, 0) only proves some process holds that PID. The start command
  line is now recorded and verified before a process is adopted or signalled;
  an unverifiable PID closes the run instead of hanging it on 'running'
  forever. psutil is not in the runtime image, so this is stdlib only
  (/proc, with a ps fallback for macOS).

Also in this change
  - run_state.json is written atomically; concurrent readers used to see
    truncated JSON (40008 corrupted reads in a 2s test on the old code)
  - a 'running' state with no PID no longer hangs forever on reconnect
  - failed runs get a completed_at timestamp like every other terminal state
  - the orphan reconnect is skipped in the Flask reloader's parent process:
    with DEBUG on, create_app runs twice, and two monitor threads in two
    processes were writing the same run_state.json

Not touched on purpose: FLASK_HOST/DEBUG/NEO4J_PASSWORD hardening, declined
2026-07-15. The reloader guard above makes the lifecycle robust against debug
mode instead of turning it off.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant