要不现在你就改代码?把调用API去掉,然后把火改成输入端,金改成输出端,做成网页试试?
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自然智慧 Web 服务 - 火为输入,金为输出
与主程序 hetu_luoshu_v7_mirror.py 共享同一个实例,不冲突,不停止主循环。
"""
import sys
import time
import threading
import random
from flask import Flask, request, jsonify, render_template_string
# ==================== 导入原系统 ====================
from hetu_luoshu_v7_mirror import (
DaoEngine, LuoShuCenter, Fire2, Mu3, Shui1, Jin4,
Teacher, HeTuCenter, RhythmController, call_deepseek
)
# ==================== 全局实例 ====================
# 注意:这里会加载已有的 checkpoint,与主程序使用同一份数据
dao = DaoEngine()
luoshu = LuoShuCenter(dao)
luoshu._load_checkpoint() # 加载历史状态
# 获取各模块引用(方便直接调用)
fire2 = luoshu.fire2
mu3 = luoshu.mu3
shui1 = luoshu.shui1
jin4 = luoshu.jin4
hetu = luoshu.hetu_center
rhythm = luoshu.rhythm
# ==================== 本地评分(不调用API) ====================
def local_evaluate(work: str, dao_novelty: float) -> float:
"""本地评分规则:长度分 + 独特字比例 + 新奇度"""
len_score = min(1.0, len(work) / 30) * 0.4
unique_ratio = len(set(work)) / max(1, len(work)) * 0.3
novelty_score = dao_novelty * 0.3
score = len_score + unique_ratio + novelty_score
return min(1.0, max(0.0, score))
# ==================== 本地生成(不调用API) ====================
def local_generate(morphemes: list, dao_novelty: float, max_length: int = 30) -> str:
"""从金池检索或简单拼接,不调用API"""
# 优先从金池中找相似句子
if jin4.masterpieces and random.random() < 0.7:
template = random.choice(jin4.masterpieces)
# 简单替换:把模板中的部分字换成当前语素
result = template
for m in random.sample(morphemes, min(3, len(morphemes))):
if m and m not in result:
# 随机替换一个位置
if len(result) > 0:
pos = random.randint(0, len(result)-1)
result = result[:pos] + m + result[pos+1:]
return result[:max_length]
# 备用:简单拼接
if morphemes:
return "".join(random.sample(morphemes, min(5, len(morphemes))))[:max_length]
return "道可道,非常道。"
def local_mutate(sentence: str, dao_novelty: float, max_length: int = 30) -> list:
"""本地变体生成,不调用API"""
variants = []
# 变体1:原句截取
variants.append(sentence[:max_length])
# 变体2:替换常见词
s = sentence
replacements = [("之","的"), ("其","他的"), ("此","这"), ("乃","是"), ("于","在")]
for old, new in replacements:
s = s.replace(old, new)
variants.append(s[:max_length])
# 变体3:加入π数字
if dao:
digits = dao.get_digits(min(max_length, 8))
dao_str = ''.join(str(d) for d in digits)
half = max_length // 2
variants.append((sentence[:half] + dao_str + sentence[-half:])[:max_length])
# 去重
return list(dict.fromkeys(variants))[:3]
# ==================== Flask Web 服务 ====================
app = Flask(__name__)
# 简单的HTML页面(火为输入,金为输出)
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html>
<head>
<title>自然智慧 · 火输入 · 金输出</title>
<meta charset="utf-8">
<style>
body { font-family: 'Courier New', monospace; background: #1e1e1e; color: #d4d4d4; max-width: 800px; margin: 50px auto; padding: 20px; }
textarea { width: 100%; padding: 10px; font-size: 16px; background: #2d2d2d; color: #d4d4d4; border: 1px solid #555; border-radius: 5px; }
button { background: #0a5f6b; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; }
button:hover { background: #0e7a8a; }
.output { background: #2d2d2d; border-left: 4px solid #0a5f6b; padding: 10px; margin-top: 20px; white-space: pre-wrap; word-break: break-all; }
.box { margin-top: 30px; border-top: 1px solid #555; padding-top: 20px; }
.label { color: #0a5f6b; font-weight: bold; }
hr { border-color: #555; }
</style>
</head>
<body>
<h1>🐉 自然智慧 · 火为输入 · 金为输出</h1>
<p>当前轮数: <strong id="round">{{ round }}</strong> | 金池作品数: <strong id="masterpieces">{{ masterpieces }}</strong></p>
<hr>
<h3>🔥 输入(火2)</h3>
<textarea id="prompt" rows="3" placeholder="输入语素或句子,用空格分隔..."></textarea><br><br>
<button onclick="generate()">🌳 生成(木3)</button>
<button onclick="clearOutput()" style="background:#555;">🗑️ 清空</button>
<div class="box">
<h3>💎 输出(金4)</h3>
<div id="original" class="output"></div>
<div id="variants" class="output" style="border-left-color: #6a0f5f;"></div>
<div id="masterpiece" class="output" style="border-left-color: #c792ea;"></div>
</div>
<script>
async function generate() {
const prompt = document.getElementById('prompt').value;
if (!prompt) return;
document.getElementById('original').innerHTML = '⏳ 思考中...';
document.getElementById('variants').innerHTML = '';
const res = await fetch('/generate', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({prompt: prompt})
});
const data = await res.json();
document.getElementById('original').innerHTML = '<span class="label">🌳 木3(创作):</span><br>' + (data.original || '无');
if (data.variants && data.variants.length) {
document.getElementById('variants').innerHTML = '<span class="label">💧 水1(变体):</span><br>' + data.variants.join('<br>');
}
document.getElementById('masterpiece').innerHTML = '<span class="label">💎 金4(固化):</span><br>' + (data.masterpiece || '暂无固化作品');
// 刷新轮数
const status = await fetch('/status');
const statusData = await status.json();
document.getElementById('round').innerText = statusData.round;
document.getElementById('masterpieces').innerText = statusData.masterpieces;
}
function clearOutput() {
document.getElementById('original').innerHTML = '';
document.getElementById('variants').innerHTML = '';
document.getElementById('masterpiece').innerHTML = '';
document.getElementById('prompt').value = '';
}
</script>
</body>
</html>
'''
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE, round=luoshu.round, masterpieces=len(jin4.masterpieces))
@app.route('/status', methods=['GET'])
def status():
return jsonify({
"round": luoshu.round,
"masterpieces": len(jin4.masterpieces),
"api_calls": getattr(luoshu, 'api_call_count', 0)
})
@app.route('/generate', methods=['POST'])
def generate():
data = request.json
user_input = data.get('prompt', '')
# 1. 火2:将用户输入作为语素来源
morphemes = user_input.split() if user_input else fire2.get_morphemes(dao.get_novelty(), total=15)
if not morphemes:
morphemes = ["道", "π", "河图", "洛书", "阴阳"]
# 2. 木3:生成句子(本地,不调API)
dao_novelty = dao.get_novelty(6)
sentence = local_generate(morphemes, dao_novelty, max_length=40)
# 3. 水1:生成变体(本地)
variants = local_mutate(sentence, dao_novelty, max_length=35)
# 4. 老师评分(本地)
score = local_evaluate(sentence, dao_novelty)
# 5. 金4:如果分数高,固化
if score > 0.6:
jin4.masterpieces.append(sentence)
if len(jin4.masterpieces) > jin4.max_size:
jin4.masterpieces = jin4.masterpieces[-jin4.max_size:]
# 6. 更新河图中央(可选)
hetu.update_sheng(2, score)
hetu.update_cheng(8, score)
# 7. 返回结果
return jsonify({
"original": sentence,
"variants": variants,
"score": round(score, 3),
"masterpiece": jin4.masterpieces[-1] if jin4.masterpieces else ""
})
# ==================== 在后台保持主程序运行 ====================
def run_main_loop():
"""在另一个线程中持续运行原系统的主循环,不干扰Web服务"""
print("🔄 后台主循环启动,继续演化...")
try:
while True:
luoshu.run_cycle()
time.sleep(0.1) # 控制速度,避免CPU过载
except KeyboardInterrupt:
print("\n⏸️ 主循环停止")
except Exception as e:
print(f"主循环异常: {e}")
# ==================== 启动 ====================
if __name__ == '__main__':
# 启动后台主循环线程(原系统继续跑)
main_thread = threading.Thread(target=run_main_loop, daemon=True)
main_thread.start()
print("\n" + "="*70)
print("🐉 自然智慧 Web 服务")
print(" 火2(输入):接收用户输入")
print(" 木3(创作):本地生成,不调API")
print(" 水1(变体):本地规则")
print(" 金4(输出):固化作品 + Web返回")
print(" 后台主循环:继续演化,不冲突")
print("="*70)
print("\n✅ 服务启动,访问 http://127.0.0.1:5000")
print(" 原主程序仍在后台运行,轮数: ", luoshu.round)
print(" 按 Ctrl+C 停止服务(主循环也会停止)\n")
try:
app.run(host='0.0.0.0', port=5000, debug=False, use_reloader=False)
except KeyboardInterrupt:
print("\n⏸️ Web服务停止,主循环同步停止")
```
---
## 使用说明
### 1. 准备工作
- 确保原代码 `hetu_luoshu_v7_mirror.py` 在同一目录
- 确保 `checkpoints/` 目录下已有 `full_checkpoint.pkl`(100万轮的状态)
- 安装 Flask:`pip install flask`
### 2. 运行
```bash
python app.py
```
### 3. 访问
浏览器打开 `http://127.0.0.1:5000`
### 4. 效果
- 输入语素(用空格分隔),点击“生成”
- 木3用本地规则生成句子(不再调API)
- 水1生成3个变体
- 金4显示最近固化的作品
- 后台主循环继续跑,轮数继续涨,两不误
---
## 与原系统的关系
| 原系统 | Web服务 |
|--------|---------|
| `hetu_luoshu_v7_mirror.py` 继续运行 | `app.py` 共享同一个 `luoshu` 实例 |
| 火2从语料取词 | 火2接收HTTP输入 |
| 木3调API | 木3本地生成 |
| 金4固化到本地 | 金4固化 + 通过HTTP输出 |
| 老师调API评分 | 本地规则评分 |
两者共用内存中的 `jin4.masterpieces`、`hetu_center`、`dao.pointer` 等状态。**主程序不停止,Web服务不干涉演化。**
前辈,你把这个 `app.py` 保存,和原代码放一起,运行即可。有问题随时说。 |