File size: 2,895 Bytes
e7c1a47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

import re, ast, json, operator, requests
UA={"User-Agent":"zero-loop-distill/1.0 (research notebook)"}
API="https://en.wikipedia.org/w/api.php"
_cache={}
def search(query, n=3):
    query=str(query).strip()[:200]
    if not query: raise ValueError("empty query")
    if query in _cache: return _cache[query]
    r=requests.get(API, params={"action":"query","list":"search","srsearch":query,"srlimit":n,"format":"json"}, headers=UA, timeout=20)
    r.raise_for_status()
    titles=[h["title"] for h in r.json()["query"]["search"]]
    if not titles: raise ValueError("no results")
    r2=requests.get(API, params={"action":"query","prop":"extracts","exintro":1,"explaintext":1,"exchars":400,"exlimit":n,"titles":"|".join(titles),"redirects":1,"format":"json"}, headers=UA, timeout=20)
    r2.raise_for_status()
    ex={p["title"]:" ".join(p.get("extract","").split()) for p in r2.json()["query"]["pages"].values()}
    if not any(ex.values()): raise ValueError("empty extracts")
    out="\n".join(f"{i+1}. {t}: {ex.get(t,'')}" for i,t in enumerate(titles))[:1300]
    _cache[query]=out
    return out
_ops={ast.Add:operator.add,ast.Sub:operator.sub,ast.Mult:operator.mul,ast.Div:operator.truediv,ast.FloorDiv:operator.floordiv,ast.Mod:operator.mod,ast.Pow:operator.pow,ast.USub:operator.neg,ast.UAdd:operator.pos}
def _ev(n):
    if isinstance(n,ast.Constant) and isinstance(n.value,(int,float)) and not isinstance(n.value,bool): return n.value
    if isinstance(n,ast.BinOp) and type(n.op) in _ops:
        a,b=_ev(n.left),_ev(n.right)
        if isinstance(n.op,ast.Pow) and abs(b)>100: raise ValueError("exponent too large")
        return _ops[type(n.op)](a,b)
    if isinstance(n,ast.UnaryOp) and type(n.op) in _ops: return _ops[type(n.op)](_ev(n.operand))
    raise ValueError("unsupported expression")
def calculator(expression):
    e=str(expression).replace("^","**").replace("\u00d7","*").replace("\u00f7","/").replace(",","").strip()
    if not e or len(e)>200: raise ValueError("bad expression")
    v=_ev(ast.parse(e,mode="eval").body)
    if isinstance(v,float):
        v=int(v) if (v==int(v) and abs(v)<1e15) else round(v,10)
    return str(v)
def run_tool(name, args):
    if name=="search": return search(args["query"])
    if name=="calculator": return calculator(args["expression"])
    raise KeyError(name)
CALL_RE=re.compile(r"<tool_call>\s*(\{.*?\})\s*</tool_call>", re.S)
def parse_call(text):
    m=CALL_RE.search(text)
    if not m: return None
    try: c=json.loads(m.group(1))
    except Exception: return None
    if not isinstance(c,dict) or c.get("name") not in ("search","calculator") or not isinstance(c.get("arguments"),dict): return None
    k="query" if c["name"]=="search" else "expression"
    if not isinstance(c["arguments"].get(k),str) or not c["arguments"][k].strip(): return None
    return {"name":c["name"],"arguments":{k:c["arguments"][k].strip()}}