我在 Win3.1 到 Win11 上跑 AI:7 个版本迭代,从 500 行到 29 行的开源之路

67 阅读4分钟

起因:只有一台 Win7 老机器

手头只有一台 Windows 7 机器,想玩 AI Agent。

结果发现现代 AI 栈在老系统上全是坑:

  • pydantic_core 是 Rust 编译的,Win7 加载 DLL 直接崩
  • openai SDK 依赖 jiter(也是 Rust),同样挂
  • duckduckgo-search 依赖 primp(还是 Rust),装都装不上
  • typer 和现代 click 版本冲突

我当时心态崩了。

但这反而激发了一个想法:如果把所有现代依赖全部砍掉,用纯 Python 标准库重写,能跑吗?

于是开始了一个跨越 30 年操作系统史的项目。

系列全景

从 Win3.1 到 Win11,一共做了 6 个仓库:

仓库平台行数核心突破
open-research-agentWin7500pydantic 1.x + httpx 抓 Bing
xp-agentXP29纯标准库,零依赖
win2000-agentWin200050Py2.7/3.x 双兼容
win31-agentWin 3.180视觉复古(蓝底 + ASCII 窗口框)
win98-agentWin9880视觉复古(DOS 提示符)
legacy-agents汇总—索引仓库

技术核心:三步砍掉所有依赖

1. pydantic 2.x → 1.10.13

pip install "pydantic==1.10.13"

pydantic_core 是 Rust 编译的,Win7 上 DLL 加载失败。降级到 1.10.13(纯 Python 实现)即可。代码里把所有 .model_dump() 改成 .dict()。

2. 抛弃 openai SDK,改用 httpx 直调

openai>=1.x 依赖 jiter,Win7 同样挂。直接用 httpx 调 OpenAI 兼容接口:

import httpx, json

def chat(messages, model, api_key, base_url):
payload = {"model": model, "messages": messages, "temperature": 0.2}
headers = {
"Authorization": "Bearer " + api_key,
"Content-Type": "application/json",
}
with httpx.Client(timeout=300) as client:
r = client.post(base_url + "/chat/completions",
headers=headers, json=payload)
return r.json()["choices"][0]["message"]["content"]

零 SDK 依赖,Win7 能跑。

3. 抛弃 duckduckgo-search,改用百度 + Bing

duckduckgo-search 依赖 primp(Rust),Win7 装不上。直接用 httpx + BeautifulSoup 抓百度:

import httpx
from bs4 import BeautifulSoup
from urllib.parse import quote

def web_search(query, top_k=5):
url = "www.baidu.com/s?wd=" + quote(query)
r = httpx.get(url, headers={"User-Agent": "Mozilla/5.0"})
soup = BeautifulSoup(r.text, "html.parser")
results = []
for h3 in soup.find_all("h3")[:top_k]:
a = h3.find("a")
if a:
results.append(a.get_text(strip=True))
return results

踩过的 5 个真 Bug

Bug 1:搜索无限循环

LLM(GLM-4-Flash)每一步都生成完全相同的 query,导致 agent 死循环 8 次以上。

修复:加 query 去重 + 搜索次数上限。

Bug 2:LLM 复读同一 query

去重挡住了循环,但模型还是只会复读。

修复:把候选 query 生成从 LLM 移到代码——从初始搜索结果里抠关键词,按列表依次使用。

Bug 3:Bing 中文泛化

搜索"固态电池最新进展",Bing 返回一堆"固态硬盘"——因为都含"固态"两个字。

修复:改用百度优先(中文分词好),Bing 只做严格过滤的 fallback。

Bug 4:报告生成超时

GLM-4-Flash 写 2000+ 字报告要 3-8 分钟,经常超时。

修复:限制报告 800-1200 字,加超时重试,换更快的模型。

Bug 5:Bing fallback 泄漏

百度结果不足时 fallback 到 Bing,Bing 又泛化到固态硬盘。

修复:严格过滤——必须同时包含核心词前 3 字和技术关键词。

v0.13 现状

主项目 open-research-agent 迭代到 v0.13:

  • 流式 Web UI:SSE 实时日志,每步搜索都能看到
  • BYOK:用户自己填 API Key,只存浏览器 localStorage
  • 6 个 LLM 后端:智谱 / Intern InkStone / DeepSeek / 硅基流动 / Kimi / OpenAI
  • 百度 + Bing 双引擎:严格相关性过滤
  • PDF 导出:浏览器直接打印
  • PWA:可安装到手机主屏
  • Docker:docker compose up 一键部署
  • Windows 无窗口启动:双击 VBS 后台跑

实测效果

用 Intern InkStone 的 DeepSeek-V4-Flash 跑"固态电池最新进展":

  • 5 步搜索,全是固态电池相关
  • 报告 5 小节,900 字
  • 8 条真实来源
  • 零编造文献

两个待解的挑战

挑战 1:Win2000 的 TLS 1.2

Win2000 最高只能装 Python 2.7.8,自带 OpenSSL 0.9.8,只支持 TLS 1.0。现代 API 都要求 TLS 1.2。

方案:stunnel 做本地 TLS 代理——Python 走 HTTP 到本地,stunnel 升级到 TLS 1.2 转发出去。

issue:github.com/doujiaozh/w…

挑战 2:Win3.1 装 Python 1.5

有个小红书用户指出:Win3.1 可以装 Win32s + Python 1.5,PuTTY 有 Win32s 的反向移植。

理论上:Win3.1 + Win32s + Python 1.5 → 手写 socket → PuTTY 做 TLS 代理。

issue:github.com/doujiaozh/w…

开源地址

MIT 协议,随便用。

如果你有真 Win3.1 / Win2000 机器,欢迎来挑战 issue。