Download Game! Currently 99 players. Last logged in:XothSolvikAnakinUntapped

Blitzer's Blog >> 72645

Back to blogs index
Posted: 21 Sep 2026 08:16 [ permalink ]
Loistava lisC$ys! TC$mC$ nostaa Valvomo-proxyn tC$ysin uudelle tasolle. Nyt
jC$rjestelmC$stC$ saadaan tC$ysin joustava: se voi toimia tC$ysin
manuaalisesti (ihminen hyvC$ksyy kaiken), tC$ysin automaattisesti tai
C$lykkC$C$sti niin, ettC$ rutiininomaiset ja turvalliset promptit livahtavat
lC$pi automaattisesti, kun taas epC$ilyttC$vC$t tai uudet tilanteet
pysC$htyvC$t tarkastettavaksi ja kuratoitavaksi.
 
 TC$ssC$ on pC$ivitetty, entistC$kin kovempi versio `valvomo_proxy.py`-tiedosto
sta, joka sisC$ltC$C$ kaikkien nC$iden uusien vaatimusten hallinnan:
 
 ### PC$ivitetty Valvomo Proxy (`valvomo_proxy.py`)
 
 ```python
 from fastapi import FastAPI, HTTPException
 from pydantic import BaseModel
 import json
 import os
 import time
 import requests
 import re
 
 app = FastAPI(title="Valvomo LLM Proxy with HITL & Dynamic Routing")
 
 STATE_FILE = "valvomo_state.json"
 
 def load_state():
     if not os.path.exists(STATE_FILE):
         return {
             "prompts": {},
             "responses": {},
             "llm_endpoints": {
                 "default": "http://localhost:11434/v1/chat/completions"
             },
             "mode": "manual",  # "manual" (kaikki jonoon), "all" (kaikki
lC$pi), "regex" (ehtojen mukaan lC$pi)
             "approval_regex": ""
         }
     with open(STATE_FILE, "r", encoding="utf-8") as f:
         return json.load(f)
 
 def save_state(state):
     with open(STATE_FILE, "w", encoding="utf-8") as f:
         json.dump(state, f, indent=4, ensure_ascii=False)
 
 class ChatCompletionRequest(BaseModel):
     model: str = "default"
     messages: list
     temperature: float = 0.7
 
 class ModeRequest(BaseModel):
     mode: str # "manual", "all", "regex"
     regex_pattern: str = ""
 
 class LLMEndpointRequest(BaseModel):
     name: str
     url: str
 
 # ==========================================
 # APUPROSESSI: LLM-KUTSU JA OHJAUS
 # ==========================================
 def process_prompt_to_llm(prompt_id: str, state: dict, target_llm_name: str =
None):
     p = state["prompts"][prompt_id]
     p["status"] = "approved"
     
     # Valitaan kC$ytettC$vC$ LLM-pC$C$tepiste (oletus tai kC$yttC$jC$n
override)
     llm_endpoints = state["llm_endpoints"]
     if not target_llm_name or target_llm_name not in llm_endpoints:
         target_llm_name = list(llm_endpoints.keys())[0]  # Otetaan
ensimmC$inen jos ei mC$C$ritelty
     
     target_url = llm_endpoints[target_llm_name]
     p["assigned_llm"] = target_llm_name
 
     # LC$hetetC$C$n pyyntC6 eteenpC$in valitulle LLM:lle
     try:
         llm_resp = requests.post(target_url, json=p["request"], timeout=60)
         llm_data = llm_resp.json()
         # Tuetaan OpenAI/Ollama yhteensopivaa vastausrakennetta
         llm_content = llm_data["choices"][0]["message"]["content"]
     except Exception as e:
         llm_content = f"[VIRHE LLM-KUTSUSSA ({target_llm_name})]: {str(e)}"
 
     # Tallennetaan vastaus ulosmenevien vastausten jonoon (Outbound Queue)
kuratointia varten
     state["responses"][prompt_id] = {
         "id": prompt_id,
         "status": "pending_response_approval",
         "content": llm_content,
         "source": target_llm_name
     }
     save_state(state)
 
 # ==========================================
 # 1. CLIENT-RAJAPINTA (Matkii LLM API:ta)
 # ==========================================
 @app.post("/v1/chat/completions")
 def intercept_prompt(req: ChatCompletionRequest):
     state = load_state()
     prompt_id = str(int(time.time() * 1000))
     
     # YhdistetC$C$n viestit yhdeksi merkkijonoksi regex-tarkistusta varten
     full_prompt_text = " ".join([m.get("content", "") for m in req.messages])
     
     prompt_data = {
         "id": prompt_id,
         "status": "pending_approval",
         "request": req.dict(),
         "created_at": time.time(),
         "manual_response": None,
         "assigned_llm": "default"
     }
     
     mode = state.get("mode", "manual")