• DeepSuck-深度求嗦

    America.gov

    America.gov

    Find answers from official government sources and clear next steps for the services you need with America.gov.

    感觉风格好像是Gemini 不会中文

    主楼
  • 路边一条狗

    快点来一名中国开发者反代出来,将程序上传github

    #1
  • syxing0270
    #!/usr/bin/env python3
    """america_proxy.py — america.gov 聊天机器人 → OpenAI 兼容反向代理(单文件,只依赖 curl_cffi)。
    
    运行:python america_proxy.py [--once "问题"]
    端点:POST /v1/chat/completions(stream 可选)、GET /v1/models、GET /health
    实测两个坑:① Cloudflare 只看 TLS/HTTP2 指纹 —— curl_cffi 伪装 safari 零 cookie 即 200,
    curl/httpx/urllib 一律 403,且不能强制 HTTP/1.1;② 上游校验历史签名(historyInvalid),
    不接受自造的 assistant 消息,所以多轮一律压平成一条 prompt。
    """
    import argparse, json, sys, time, uuid
    from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
    
    try:
        from curl_cffi import requests as cr
    except ImportError:
        sys.exit("缺少依赖:pip install curl_cffi")
    
    URL, MODEL = "https://america.gov/api/chat", "america-gov"
    HDRS = {"content-type": "application/json", "accept": "*/*",
            "origin": "https://america.gov", "referer": "https://america.gov/"}
    FPS = ["safari", "safari_17_2_1", "safari_17_0", "chrome", "edge101"]  # 仅 safari 实测通过
    LANG, TIMEOUT, FP, SESS = "en", 120.0, None, {}
    class Gone(Exception): pass  # 客户端断开哨兵(curl_cffi 的异常也是 OSError,不能直接 except OSError)
    
    def err(m, c): e = Exception(m); e.code = c; raise e  # 带 HTTP 状态码的异常
    
    def upstream(b):
        """指纹轮换,首次成功后固定;返回上游 SSE 行迭代器。"""
        global FP
        tried = []
        for fp in [FP] if FP else FPS:
            r = SESS.setdefault(fp, cr.Session(impersonate=fp)).post(
                URL, json=b, headers=HDRS, stream=True, timeout=TIMEOUT, allow_redirects=False)
            if r.status_code == 200 and "text/event-stream" in (r.headers.get("content-type") or ""):
                FP = fp
                return r.iter_lines()
            tried.append(f"{fp}->{r.status_code}")
            if r.status_code != 403 or r.headers.get("x-america-chat-error"):
                err(f"上游 {r.status_code} ({r.headers.get('x-america-chat-error')}): {r.text[:200]}", r.status_code)
        err("Cloudflare 拦截,已试过 " + ", ".join(tried) + ";可能出口 IP 被限流", 502)
    
    def parse(lines, cb=None):
        """UIMessageStream:正文取 text-delta,官方来源取 data-search,其余事件内容已加密无用。"""
        txt, src = [], {}
        for raw in lines:
            line = raw.decode("utf-8", "replace") if isinstance(raw, bytes) else raw
            if line[:5] != "data:": continue
            try:
                ev = json.loads(line[5:])
            except Exception:
                continue
            t = ev.get("type") if isinstance(ev, dict) else None
            if t == "text-delta":
                d = ev.get("delta") or ""
                txt.append(d)
                if cb: cb(d)
            elif t == "data-search":
                for g in (ev.get("data") or {}).get("groundings") or []:
                    if g.get("url"): src[g["url"]] = g
        return "".join(txt), list(src.values())
    
    def body(ms, lang):
        """OpenAI messages → 上游单条 user 消息(多轮压平成 transcript)。"""
        def t(m):
            c = m.get("content")
            return c if isinstance(c, str) else "".join((p or {}).get("text", "") for p in c or [])
        ts = [("User" if m["role"] == "user" else "Assistant") + ": " + t(m)
              for m in ms if m.get("role") in ("user", "assistant") and t(m)]
        if not ts or not ts[-1].startswith("User: "): err("最后一条必须是用户提问", 400)
        text = ts[-1][6:] if len(ts) == 1 else "Answer using this transcript.\n" + "\n".join(ts)
        return {"messages": [{"id": uuid.uuid4().hex[:16], "role": "user",
                              "parts": [{"type": "text", "text": text}]}],
                "trigger": "submit", "language": lang}
    
    class H(BaseHTTPRequestHandler):
        protocol_version = "HTTP/1.1"
    
        def log_message(s, *a): pass
    
        def out(s, c, o):
            b = json.dumps(o, ensure_ascii=False).encode()
            s.send_response(c)
            s.send_header("content-type", "application/json; charset=utf-8")
            s.send_header("content-length", str(len(b)))
            s.end_headers()
            s.wfile.write(b)
    
        def do_GET(s):
            if s.path == "/v1/models":
                return s.out(200, {"object": "list", "data": [{"id": MODEL, "object": "model"}]})
            return s.out(200, {"status": "ok", "upstream": URL, "fingerprint": FP})
    
        def do_POST(s):
            try:
                p = json.loads(s.rfile.read(int(s.headers.get("content-length") or 0)) or b"{}")
            except Exception as e:
                return s.out(400, {"error": {"message": f"请求体无效: {e}"}})
            try:
                lines = upstream(body(p.get("messages") or [], LANG))
            except Exception as e:
                return s.out(getattr(e, "code", 502), {"error": {"message": str(e)}})
            mid, ts, mdl = "chatcmpl-" + uuid.uuid4().hex[:20], int(time.time()), p.get("model") or MODEL
            if p.get("stream") is not True:
                txt, src = parse(lines)
                return s.out(200, {"id": mid, "object": "chat.completion", "created": ts, "model": mdl,
                                   "choices": [{"index": 0, "message": {"role": "assistant", "content": txt},
                                                "finish_reason": "stop"}],
                                   "usage": dict(prompt_tokens=0, completion_tokens=0, total_tokens=0),
                                   "x_sources": src})
            s.send_response(200)
            s.send_header("content-type", "text/event-stream; charset=utf-8")
            s.send_header("cache-control", "no-store")
            s.send_header("connection", "close")
            s.end_headers()
    
            def w(o):
                try:
                    s.wfile.write(f"data: {json.dumps(o, ensure_ascii=False)}\n\n".encode())
                    s.wfile.flush()
                except OSError:
                    raise Gone
    
            def pk(d, fr=None):
                w({"id": mid, "object": "chat.completion.chunk", "created": ts, "model": mdl,
                   "choices": [{"index": 0, "delta": d, "finish_reason": fr}]})
            try:
                pk({"role": "assistant"})
                _, src = parse(lines, lambda d: pk({"content": d}))
                pk({}, "stop")
                if src: w({"id": mid, "created": ts, "x_sources": src})
                s.wfile.write(b"data: [DONE]\n\n")
            except Gone:
                pass
    
    def main():
        ap = argparse.ArgumentParser(description="america.gov 聊天机器人反向代理(OpenAI 兼容)")
        for flag, tp, dflt, hlp in [("--host", str, "127.0.0.1", "监听地址"), ("--port", int, 8787, "监听端口"),
                                    ("--language", str, "en", "en | es | fr"), ("--timeout", float, 120.0, "上游超时秒"),
                                    ("--once", str, None, "只问一次,不启动服务")]:
            ap.add_argument(flag, type=tp, default=dflt, help=hlp)
        a = ap.parse_args()
        global LANG, TIMEOUT
        LANG, TIMEOUT = a.language, a.timeout
        if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(encoding="utf-8")  # Windows 控制台
        if a.once:
            try:
                _, src = parse(upstream(body([{"role": "user", "content": a.once}], LANG)),
                               lambda d: (sys.stdout.write(d), sys.stdout.flush()))
            except Exception as e:
                return print(f"错误:{e}", file=sys.stderr) or 1
            print()
            for g in src[:10]: print(f"  - {g.get('title')}\n    {g.get('url')}", file=sys.stderr)
            return 0
        srv = ThreadingHTTPServer((a.host, a.port), H)
        print(f'america-proxy: http://{a.host}:{a.port}  model="{MODEL}"', file=sys.stderr)
        try:
            srv.serve_forever()
        except KeyboardInterrupt:
            return 0
    
    if __name__ == "__main__": sys.exit(main())
    #2

发表回复

登录后回复