<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title><![CDATA[求索空间]]></title> 
<atom:link href="https://blog.askerlab.com/rss.php" rel="self" type="application/rss+xml" />
<description><![CDATA[以问题为起点的探索空间]]></description>
<link>https://blog.askerlab.com/</link>
<language>zh-cn</language>
<generator>www.emlog.net</generator>
<item>
    <title>01 基础大模型调用</title>
    <link>https://blog.askerlab.com/01_ji_chu_da_mo_xing_diao_yong</link>
    <description><![CDATA[<h1>1 背景</h1>
<p>本节课只解决一个问题：<strong>怎么用最简单的代码调用一次大模型</strong>。<br />
先不要急着学 CoT、ReAct、工具调用、记忆、多 Agent。因为这些能力最后都会回到同一个基础动作：</p>
<pre><code class="language-text">把问题发给大模型
→ 大模型返回答案
→ 程序拿到答案继续处理</code></pre>
<p>如果这一步都不能稳定运行，后面写 Agent 时会很痛苦。</p>
<h2>1.1 本节课要做什么</h2>
<p>本节课只做四件事：</p>
<ol>
<li>说明现在常见的大模型调用方式</li>
<li>说明为什么本节先使用 OpenAI 兼容接口</li>
<li>写一个简单的 <code>llm.py</code></li>
<li>写一个简单的 <code>main.py</code>，运行后能看到模型输出<br />
本节课不追求封装得很完整，也不做太多抽象。代码要做到：<strong>高中生看得懂，复制下来能运行，后面课程能继续复用</strong>。</li>
</ol>
<h1>2 当前有几种大模型调用方式</h1>
<h2>2.1 第一种：官方原生接口</h2>
<p>每个大模型厂商一般都有自己的官方接口。<br />
例如：</p>
<table>
<thead>
<tr>
<th>厂商</th>
<th>常见接口方式</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>OpenAI</td>
<td>OpenAI SDK、Responses API、Chat Completions API</td>
<td>OpenAI 自己的官方接口</td>
</tr>
<tr>
<td>Anthropic Claude</td>
<td>Anthropic SDK、Messages API</td>
<td>Claude 原生接口</td>
</tr>
<tr>
<td>Google Gemini</td>
<td>Google Gen AI SDK、Gemini API</td>
<td>Gemini 原生接口</td>
</tr>
</tbody>
</table>
<p>这种方式的好处是能力最完整，坏处是每家写法不完全一样。你刚开始学习时，如果一上来同时适配 OpenAI、Claude、Gemini，很容易被 SDK 差异打断思路。</p>
<h2>2.2 第二种：OpenAI 兼容接口</h2>
<p>很多模型厂商支持 OpenAI 兼容接口。<br />
简单说，就是它们让你继续使用 OpenAI SDK，只需要改三样东西：</p>
<pre><code class="language-text">API Key
Base URL
Model Name</code></pre>
<p>常见支持 OpenAI 兼容接口的平台包括：</p>
<table>
<thead>
<tr>
<th>平台</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>OpenAI</td>
<td>原始 OpenAI 接口</td>
</tr>
<tr>
<td>DeepSeek</td>
<td>支持 OpenAI 兼容格式</td>
</tr>
<tr>
<td>阿里云百炼 Qwen</td>
<td>支持 OpenAI 兼容模式</td>
</tr>
<tr>
<td>Moonshot Kimi</td>
<td>支持 OpenAI 兼容格式</td>
</tr>
<tr>
<td>智谱 GLM</td>
<td>支持 OpenAI 兼容格式</td>
</tr>
</tbody>
</table>
<p>这就是本节课选择 OpenAI 兼容接口的原因：<strong>代码最少，迁移最简单，适合入门</strong>。</p>
<h2>2.3 第三种：统一网关</h2>
<p>还有一种方式是使用 LiteLLM、One API、公司内部网关这类统一代理。<br />
它的作用是把多个模型包装成一个统一入口：</p>
<pre><code class="language-text">业务代码
→ 模型网关
→ OpenAI / DeepSeek / Qwen / Claude / Gemini</code></pre>
<p>这种方式适合团队使用，但不适合第一节课。因为它又多引入了一层系统，初学者很容易不知道问题出在代码、网关还是模型服务。</p>
<h2>2.4 本节课的推荐做法</h2>
<p>本节课推荐：</p>
<pre><code class="language-text">先用 OpenAI SDK
→ 连接一个 OpenAI 兼容模型
→ 跑通最小调用
→ 后面课程全部复用这个 LLM 客户端</code></pre>
<p>这样后面写 CoT 时，只需要关注 prompt 怎么写；写 ReAct 时，只需要关注模型怎么推理和行动；写工具调用时，再扩展工具参数即可。</p>
<h1>3 一次大模型调用需要哪些信息</h1>
<h2>3.1 最少需要三个配置</h2>
<p>一次大模型调用最少需要三个配置：</p>
<table>
<thead>
<tr>
<th>配置</th>
<th>含义</th>
<th>示例</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>LLM_MODEL_ID</code></td>
<td>要调用哪个模型</td>
<td><code>deepseek-chat</code>、<code>qwen-plus</code>、<code>kimi-k2.5</code></td>
</tr>
<tr>
<td><code>LLM_API_KEY</code></td>
<td>你的 API 密钥</td>
<td><code>sk-xxxx</code></td>
</tr>
<tr>
<td><code>LLM_BASE_URL</code></td>
<td>模型服务地址</td>
<td><code>https://api.deepseek.com</code></td>
</tr>
</tbody>
</table>
<p>可以把它理解成点外卖：</p>
<pre><code class="language-text">LLM_MODEL_ID：你要点哪道菜
LLM_API_KEY：证明这是你的账号
LLM_BASE_URL：外卖平台地址</code></pre>
<h2>3.2 为什么配置放到 .env</h2>
<p>不要把 API Key 写死在 Python 代码里。<br />
不推荐：</p>
<pre><code class="language-python">api_key = "sk-xxxx"</code></pre>
<p>推荐：</p>
<pre><code class="language-python">api_key = os.getenv("LLM_API_KEY")</code></pre>
<p>原因很简单：</p>
<ul>
<li>API Key 是密码，不能随便暴露</li>
<li>换模型时不需要改代码</li>
<li>后面部署到服务器时也更方便<br />
所以本节课把 <code>.env</code> 当作配置文件使用，先不引入 <code>config.yaml</code>。对第一节课来说，<code>.env</code> 已经够用了。</li>
</ul>
<h1>4 项目结构</h1>
<h2>4.1 最终目录</h2>
<p>创建一个目录：</p>
<pre><code class="language-text">agent-course-01-llm-call/
├── .env
├── llm.py
├── main.py
└── requirements.txt</code></pre>
<p>每个文件的作用如下：</p>
<table>
<thead>
<tr>
<th>文件</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>.env</code></td>
<td>放模型配置和 API Key</td>
</tr>
<tr>
<td><code>llm.py</code></td>
<td>封装大模型调用</td>
</tr>
<tr>
<td><code>main.py</code></td>
<td>写一个最小运行示例</td>
</tr>
<tr>
<td><code>requirements.txt</code></td>
<td>放 Python 依赖</td>
</tr>
</tbody>
</table>
<h1>5 安装依赖</h1>
<h2>5.1 创建 requirements.txt</h2>
<p>创建 <code>requirements.txt</code>：</p>
<pre><code class="language-txt">openai
python-dotenv</code></pre>
<p>这里只安装两个包：</p>
<ul>
<li><code>openai</code>：用来调用 OpenAI 兼容接口</li>
<li><code>python-dotenv</code>：用来读取 <code>.env</code> 配置</li>
</ul>
<h2>5.2 安装依赖</h2>
<p>执行：</p>
<pre><code class="language-bash">pip install -r requirements.txt</code></pre>
<p>如果你的电脑需要使用 <code>pip3</code>，就执行：</p>
<pre><code class="language-bash">pip3 install -r requirements.txt</code></pre>
<h2>5.3 验证安装</h2>
<p>执行：</p>
<pre><code class="language-bash">python -c "from openai import OpenAI; from dotenv import load_dotenv; print('ok')"</code></pre>
<p>预期输出：</p>
<pre><code class="language-text">ok</code></pre>
<p>如果这里都不能运行，先不要继续写代码，先解决 Python 环境和依赖安装问题。</p>
<h1>6 配置 .env</h1>
<h2>6.1 创建 .env 文件</h2>
<p>创建 <code>.env</code>：</p>
<pre><code class="language-bash">LLM_MODEL_ID=deepseek-chat
LLM_API_KEY=你的API_KEY
LLM_BASE_URL=https://api.deepseek.com
LLM_TIMEOUT=60</code></pre>
<p>把 <code>你的API_KEY</code> 换成真实的 API Key。</p>
<h2>6.2 不同平台的配置示例</h2>
<p>如果你使用 DeepSeek：</p>
<pre><code class="language-bash">LLM_MODEL_ID=deepseek-chat
LLM_API_KEY=你的DeepSeek_API_KEY
LLM_BASE_URL=https://api.deepseek.com
LLM_TIMEOUT=60</code></pre>
<p>如果你使用阿里云百炼 Qwen：</p>
<pre><code class="language-bash">LLM_MODEL_ID=qwen-plus
LLM_API_KEY=你的DASHSCOPE_API_KEY
LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
LLM_TIMEOUT=60</code></pre>
<p>如果你使用OpenAI：</p>
<pre><code>如果你使用 OpenAI：
```bash
LLM_MODEL_ID=gpt-5-mini
LLM_API_KEY=你的OPENAI_API_KEY
LLM_BASE_URL=https://api.openai.com/v1
LLM_TIMEOUT=60</code></pre>
<p>注意：模型名称可能会变化，最终以对应平台控制台和官方文档为准。如果报 <code>model not found</code>，优先检查 <code>LLM_MODEL_ID</code>。</p>
<h1>7 编写 llm.py</h1>
<h2>7.1 代码目标</h2>
<p><code>llm.py</code> 只做一件事：<strong>把 messages 发给大模型，然后返回文本结果</strong>。<br />
这里保留流式输出。因为流式输出体验更好，运行时能看到模型一个字一个字返回，不会一直卡着没反应。</p>
<h2>7.2 完整代码</h2>
<p>创建 <code>llm.py</code>：</p>
<pre><code class="language-python">import os
from typing import List, Dict, Optional
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
class HelloAgentsLLM:
    """
    一个最小可用的 LLM 客户端。
    只支持 OpenAI 兼容接口。
    """
    def __init__(
        self,
        model: Optional[str] = None,
        api_key: Optional[str] = None,
        base_url: Optional[str] = None,
        timeout: Optional[int] = None,
    ):
        self.model = model or os.getenv("LLM_MODEL_ID")
        self.api_key = api_key or os.getenv("LLM_API_KEY")
        self.base_url = base_url or os.getenv("LLM_BASE_URL")
        self.timeout = timeout or int(os.getenv("LLM_TIMEOUT", "60"))
        if not self.model:
            raise ValueError("缺少模型名称，请在 .env 中配置 LLM_MODEL_ID")
        if not self.api_key:
            raise ValueError("缺少 API Key，请在 .env 中配置 LLM_API_KEY")
        if not self.base_url:
            raise ValueError("缺少服务地址，请在 .env 中配置 LLM_BASE_URL")
        self.client = OpenAI(
            api_key=self.api_key,
            base_url=self.base_url,
            timeout=self.timeout,
        )
    def think(self, messages: List[Dict[str, str]], temperature: float = 0) -&gt; str:
        """
        调用大模型，并返回完整文本。
        messages 是对话列表，例如：
        [
            {"role": "system", "content": "你是一个有帮助的助手"},
            {"role": "user", "content": "你好"}
        ]
        """
        print(f"🧠 正在调用模型：{self.model}")
        try:
            response = self.client.chat.completions.create(
                model=self.model,
                messages=messages,
                temperature=temperature,
                stream=True,
            )
            print("✅ 模型返回：")
            result = []
            for chunk in response:
                if not chunk.choices:
                    continue
                content = chunk.choices[0].delta.content
                if not content:
                    continue
                print(content, end="", flush=True)
                result.append(content)
            print()
            return "".join(result)
        except Exception as e:
            print(f"❌ 调用大模型失败：{e}")
            return ""</code></pre>
<h2>7.3 这段代码怎么理解</h2>
<p>这段代码里最重要的只有三部分。<br />
第一，读取配置：</p>
<pre><code class="language-python">self.model = model or os.getenv("LLM_MODEL_ID")
self.api_key = api_key or os.getenv("LLM_API_KEY")
self.base_url = base_url or os.getenv("LLM_BASE_URL")</code></pre>
<p>意思是：如果代码里传了参数，就用代码里的；如果没有传，就从 <code>.env</code> 里读取。<br />
第二，创建客户端：</p>
<pre><code class="language-python">self.client = OpenAI(
    api_key=self.api_key,
    base_url=self.base_url,
    timeout=self.timeout,
)</code></pre>
<p>意思是：告诉 OpenAI SDK，我要访问哪个模型服务。<br />
第三，发送 messages：</p>
<pre><code class="language-python">response = self.client.chat.completions.create(
    model=self.model,
    messages=messages,
    temperature=temperature,
    stream=True,
)</code></pre>
<p>意思是：把对话内容发给模型，并使用流式返回。</p>
<h1>8 编写 main.py</h1>
<h2>8.1 代码目标</h2>
<p><code>main.py</code> 是入口文件，只负责演示怎么使用 <code>HelloAgentsLLM</code>。<br />
它不要复杂，也不要封装太多逻辑。第一节课最重要的是让读者看清楚调用顺序。</p>
<h2>8.2 完整代码</h2>
<p>创建 <code>main.py</code>：</p>
<pre><code class="language-python">from llm import HelloAgentsLLM
def main():
    llm = HelloAgentsLLM()
    messages = [
        {
            "role": "system",
            "content": "你是一个讲解清楚、表达简单的 AI 助手。",
        },
        {
            "role": "user",
            "content": "用高中生能听懂的话解释什么是 LLM Agent。",
        },
    ]
    print("--- 调用 LLM ---")
    response_text = llm.think(messages)
    if response_text:
        print("\n--- 完整模型响应 ---")
        print(response_text)
if __name__ == "__main__":
    main()</code></pre>
<h2>8.3 调用顺序</h2>
<p>这个文件的执行顺序很简单：</p>
<pre><code class="language-text">创建 HelloAgentsLLM
→ 准备 messages
→ 调用 llm.think(messages)
→ 打印模型返回内容</code></pre>
<p>这就是后面所有 Agent 课程的基础。</p>
<h1>9 运行验证</h1>
<h2>9.1 执行命令</h2>
<p>在项目目录下执行：</p>
<pre><code class="language-bash">python main.py</code></pre>
<p>预期输出类似：</p>
<pre><code class="language-text">--- 调用 LLM ---
🧠 正在调用模型：deepseek-chat
✅ 模型返回：
LLM Agent 可以理解成一个由大语言模型驱动的智能助手，它不只是回答问题，还能根据目标规划步骤、调用工具，并根据结果继续完成任务。
--- 完整模型响应 ---
LLM Agent 可以理解成一个由大语言模型驱动的智能助手，它不只是回答问题，还能根据目标规划步骤、调用工具，并根据结果继续完成任务。</code></pre>
<p>只要能看到模型返回内容，就说明本节课完成了。</p>
<h2>9.2 修改问题再运行</h2>
<p>你可以把 <code>main.py</code> 里的问题改成：</p>
<pre><code class="language-python">"写一个 Python 快速排序算法"</code></pre>
<p>再执行：</p>
<pre><code class="language-bash">python main.py</code></pre>
<p>如果模型能返回代码，说明你的调用链路是正常的。</p>
<h1>10 常见坑</h1>
<h2>10.1 .env 没有生效</h2>
<p>如果提示：</p>
<pre><code class="language-text">缺少 API Key，请在 .env 中配置 LLM_API_KEY</code></pre>
<p>先检查 <code>.env</code> 是否在当前目录。<br />
正确目录应该是：</p>
<pre><code class="language-text">agent-course-01-llm-call/
├── .env
├── llm.py
├── main.py
└── requirements.txt</code></pre>
<p>然后检查变量名是不是写错了。<br />
必须是：</p>
<pre><code class="language-bash">LLM_MODEL_ID=xxx
LLM_API_KEY=xxx
LLM_BASE_URL=xxx</code></pre>
<p>不是：</p>
<pre><code class="language-bash">MODEL_ID=xxx
API_KEY=xxx
BASE_URL=xxx</code></pre>
<h2>10.2 base_url 写成了完整接口地址</h2>
<p>这是新手最常见的问题。<br />
如果你使用 SDK，一般配置的是：</p>
<pre><code class="language-bash">LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1</code></pre>
<p>不要写成：</p>
<pre><code class="language-bash">LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions</code></pre>
<p>因为 <code>/chat/completions</code> 这段路径 SDK 会自动拼接。</p>
<h2>10.3 模型名称写错</h2>
<p>如果报错里出现：</p>
<pre><code class="language-text">model not found</code></pre>
<p>一般是模型名不对。<br />
解决办法：</p>
<ol>
<li>去模型平台控制台确认模型名</li>
<li>确认账号是否有这个模型权限</li>
<li>先使用官方示例里的模型名</li>
<li>不要照抄过期文章里的模型名</li>
</ol>
<h2>10.4 API Key 错误</h2>
<p>如果报错里出现：</p>
<pre><code class="language-text">401
unauthorized
invalid api key</code></pre>
<p>一般是 API Key 错了。<br />
先检查：</p>
<ul>
<li>API Key 有没有复制完整</li>
<li>API Key 前后有没有多余空格</li>
<li>当前平台和 API Key 是否匹配</li>
<li>DeepSeek 的 Key 不要拿去调用 Qwen</li>
<li>Qwen 的 Key 不要拿去调用 Kimi</li>
</ul>
<h2>10.5 temperature 设置</h2>
<p>本节课默认：</p>
<pre><code class="language-python">temperature=0</code></pre>
<p>可以简单理解成：让模型尽量稳定回答。<br />
推荐：</p>
<table>
<thead>
<tr>
<th>场景</th>
<th>temperature</th>
</tr>
</thead>
<tbody>
<tr>
<td>学习、测试、写代码</td>
<td><code>0</code></td>
</tr>
<tr>
<td>普通问答</td>
<td><code>0.2</code> 到 <code>0.5</code></td>
</tr>
<tr>
<td>创意写作</td>
<td><code>0.7</code> 左右</td>
</tr>
</tbody>
</table>
<p>刚开始学习 Agent，推荐先用 <code>0</code>。结果稳定，方便排查问题。</p>
<h1>11 本节课最终代码</h1>
<h2>11.1 requirements.txt</h2>
<pre><code class="language-txt">openai
python-dotenv</code></pre>
<h2>11.2 .env</h2>
<pre><code class="language-bash">LLM_MODEL_ID=deepseek-chat
LLM_API_KEY=你的API_KEY
LLM_BASE_URL=https://api.deepseek.com
LLM_TIMEOUT=60</code></pre>
<h2>11.3 llm.py</h2>
<pre><code class="language-python">import os
from typing import List, Dict, Optional
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
class HelloAgentsLLM:
    def __init__(
        self,
        model: Optional[str] = None,
        api_key: Optional[str] = None,
        base_url: Optional[str] = None,
        timeout: Optional[int] = None,
    ):
        self.model = model or os.getenv("LLM_MODEL_ID")
        self.api_key = api_key or os.getenv("LLM_API_KEY")
        self.base_url = base_url or os.getenv("LLM_BASE_URL")
        self.timeout = timeout or int(os.getenv("LLM_TIMEOUT", "60"))
        if not self.model:
            raise ValueError("缺少模型名称，请在 .env 中配置 LLM_MODEL_ID")
        if not self.api_key:
            raise ValueError("缺少 API Key，请在 .env 中配置 LLM_API_KEY")
        if not self.base_url:
            raise ValueError("缺少服务地址，请在 .env 中配置 LLM_BASE_URL")
        self.client = OpenAI(
            api_key=self.api_key,
            base_url=self.base_url,
            timeout=self.timeout,
        )
    def think(self, messages: List[Dict[str, str]], temperature: float = 0) -&gt; str:
        print(f"🧠 正在调用模型：{self.model}")
        try:
            response = self.client.chat.completions.create(
                model=self.model,
                messages=messages,
                temperature=temperature,
                stream=True,
            )
            print("✅ 模型返回：")
            result = []
            for chunk in response:
                if not chunk.choices:
                    continue
                content = chunk.choices[0].delta.content
                if not content:
                    continue
                print(content, end="", flush=True)
                result.append(content)
            print()
            return "".join(result)
        except Exception as e:
            print(f"❌ 调用大模型失败：{e}")
            return ""</code></pre>
<h2>11.4 main.py</h2>
<pre><code class="language-python">from llm import HelloAgentsLLM
def main():
    llm = HelloAgentsLLM()
    messages = [
        {
            "role": "system",
            "content": "你是一个讲解清楚、表达简单的 AI 助手。",
        },
        {
            "role": "user",
            "content": "用高中生能听懂的话解释什么是 LLM Agent。",
        },
    ]
    print("--- 调用 LLM ---")
    response_text = llm.think(messages)
    if response_text:
        print("\n--- 完整模型响应 ---")
        print(response_text)
if __name__ == "__main__":
    main()</code></pre>
<h1>12 总结</h1>
<h2>12.1 本节课学到了什么</h2>
<p>本节课只做了一个最小闭环：</p>
<pre><code class="language-text">.env 配置模型
→ llm.py 封装调用
→ main.py 发起请求
→ 控制台看到模型输出</code></pre>
<p>这个闭环很小，但非常重要。后面所有 Agent 能力都会建立在它上面。</p>
<h2>12.2 为什么这样写</h2>
<p>本节课没有做复杂封装，原因是：</p>
<ul>
<li>第一节课的目标是跑通，不是设计框架</li>
<li><code>.env</code> 已经能满足基础配置需求</li>
<li>OpenAI 兼容接口能覆盖很多常见模型</li>
<li><code>llm.think(messages)</code> 这个入口后面可以继续复用<br />
后面进入 CoT 时，可以这样调用：
<pre><code class="language-python">messages = [
{"role": "system", "content": "你是一个擅长一步一步推理的助手。"},
{"role": "user", "content": "请一步一步分析这个问题：..."}
]
llm.think(messages)</code></pre>
<p>也就是说，本节课不是孤立代码，而是后续 Agent 课程的底座。</p></li>
</ul>
<h1>13 参考文献</h1>
<h2>13.1 官方文档</h2>
<ul>
<li>OpenAI API Reference：Chat Completions、Streaming、OpenAI Python SDK</li>
<li>DeepSeek API Docs：OpenAI-compatible API format</li>
<li>阿里云百炼 Model Studio 文档：OpenAI 兼容接口调用千问模型</li>
<li>Moonshot Kimi API 开放平台文档：OpenAI 兼容 API</li>
<li>智谱 AI 开放文档：OpenAI API 兼容接入说明</li>
<li>Anthropic Claude API Docs：Claude Python SDK、Messages API</li>
<li>Google AI for Developers：Gemini API、Google Gen AI SDK</li>
</ul>
<h2>13.2 后续课程</h2>
<ul>
<li>02 CoT：显式步骤推理</li>
<li>03 ReAct：推理和行动交替</li>
<li>04 Tool Use：让模型调用工具</li>
<li>05 Memory：让 Agent 记住上下文</li>
<li>06 Reflection：让 Agent 自我修正</li>
</ul>]]></description>
    <pubDate>Sun, 24 May 2026 00:15:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/01_ji_chu_da_mo_xing_diao_yong</guid>
</item>
<item>
    <title>wireguard 局域网VPN方案</title>
    <link>https://blog.askerlab.com/wireguard_install</link>
    <description><![CDATA[<p>本文用一台云服务器作为 WireGuard 服务端，手机、电脑、CatWrt 作为客户端接入。这个方案最稳定，也最适合普通用户：云服务器有公网 IP，客户端不需要公网 IP，直接连服务器即可。</p>
<h2>一、网络规划</h2>
<p>先统一规划 IP，后面所有配置都按这个来。</p>
<table>
<thead>
<tr>
<th>设备</th>
<th>角色</th>
<th>WireGuard IP</th>
</tr>
</thead>
<tbody>
<tr>
<td>云服务器</td>
<td>服务端</td>
<td>10.8.0.1</td>
</tr>
<tr>
<td>手机</td>
<td>客户端</td>
<td>10.8.0.2</td>
</tr>
<tr>
<td>电脑</td>
<td>客户端</td>
<td>10.8.0.3</td>
</tr>
<tr>
<td>CatWrt</td>
<td>客户端</td>
<td>10.8.0.10</td>
</tr>
<tr>
<td>端口</td>
<td>UDP</td>
<td>51820</td>
</tr>
</tbody>
</table>
<p>需要记住一个原则：一台设备一套密钥，一个独立 IP，不要多个设备共用同一个配置。</p>
<h2>二、服务器安装 WireGuard</h2>
<h3>1. 安装软件</h3>
<p>Ubuntu / Debian 执行：</p>
<pre><code class="language-bash">sudo apt update
sudo apt install -y wireguard qrencode iptables</code></pre>
<p>CentOS / Rocky / AlmaLinux 执行：</p>
<pre><code class="language-bash">sudo dnf install -y wireguard-tools qrencode iptables</code></pre>
<h3>2. 开启 IP 转发</h3>
<p>编辑系统配置：</p>
<pre><code class="language-bash">sudo vim /etc/sysctl.conf</code></pre>
<p>加入或确认有这一行：</p>
<pre><code class="language-bash">net.ipv4.ip_forward=1</code></pre>
<p>让配置立即生效：</p>
<pre><code class="language-bash">sudo sysctl -p</code></pre>
<p>检查结果：</p>
<pre><code class="language-bash">cat /proc/sys/net/ipv4/ip_forward</code></pre>
<p>输出 <code>1</code> 就是成功。</p>
<h3>3. 查看服务器公网网卡</h3>
<p>执行：</p>
<pre><code class="language-bash">ip route | grep default</code></pre>
<p>你会看到类似：</p>
<pre><code class="language-text">default via 172.31.0.1 dev eth0</code></pre>
<p>这里的 <code>eth0</code> 就是公网网卡。也可能是 <code>ens3</code>、<code>ens5</code>、<code>enp1s0</code>，后面配置里的 <code>eth0</code> 要按实际结果替换。</p>
<h3>4. 生成服务端密钥</h3>
<pre><code class="language-bash">sudo mkdir -p /etc/wireguard/clients
cd /etc/wireguard
sudo umask 077
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key</code></pre>
<p>查看服务端私钥和公钥：</p>
<pre><code class="language-bash">sudo cat /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_public.key</code></pre>
<p>私钥不要泄露，公钥后面要填到客户端里。</p>
<h3>5. 创建服务端配置</h3>
<p>编辑配置文件：</p>
<pre><code class="language-bash">sudo vim /etc/wireguard/wg0.conf</code></pre>
<p>写入：</p>
<pre><code class="language-ini">[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = 填服务端PrivateKey
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE</code></pre>
<p>注意：如果你的公网网卡不是 <code>eth0</code>，把上面的 <code>eth0</code> 改成你的实际网卡名。</p>
<h3>6. 放行 UDP 端口</h3>
<p>如果服务器用了 UFW：</p>
<pre><code class="language-bash">sudo ufw allow 51820/udp
sudo ufw reload</code></pre>
<p>如果是云服务器，还要去云厂商安全组放行：</p>
<pre><code class="language-text">协议：UDP
端口：51820
来源：0.0.0.0/0</code></pre>
<p>这是最容易漏的一步。WireGuard 用的是 UDP，不是 TCP。</p>
<h3>7. 启动 WireGuard</h3>
<pre><code class="language-bash">sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0</code></pre>
<p>查看状态：</p>
<pre><code class="language-bash">sudo wg show</code></pre>
<p>看到 <code>interface: wg0</code> 就说明服务端启动成功。</p>
<h2>三、添加手机、电脑、CatWrt 客户端</h2>
<h3>1. 生成客户端密钥</h3>
<p>生成手机密钥：</p>
<pre><code class="language-bash">cd /etc/wireguard
sudo wg genkey | sudo tee clients/phone_private.key | sudo wg pubkey | sudo tee clients/phone_public.key</code></pre>
<p>生成电脑密钥：</p>
<pre><code class="language-bash">sudo wg genkey | sudo tee clients/pc_private.key | sudo wg pubkey | sudo tee clients/pc_public.key</code></pre>
<p>生成 CatWrt 密钥：</p>
<pre><code class="language-bash">sudo wg genkey | sudo tee clients/catwrt_private.key | sudo wg pubkey | sudo tee clients/catwrt_public.key</code></pre>
<h3>2. 把客户端加入服务端</h3>
<p>编辑服务端配置：</p>
<pre><code class="language-bash">sudo vim /etc/wireguard/wg0.conf</code></pre>
<p>在文件末尾追加：</p>
<pre><code class="language-ini">[Peer]
# phone
PublicKey = 填phone_public.key里的内容
AllowedIPs = 10.8.0.2/32
[Peer]
# pc
PublicKey = 填pc_public.key里的内容
AllowedIPs = 10.8.0.3/32
[Peer]
# catwrt
PublicKey = 填catwrt_public.key里的内容
AllowedIPs = 10.8.0.10/32</code></pre>
<p>服务端这里一定要写 <code>/32</code>，不要给每个客户端都写 <code>10.8.0.0/24</code>，否则多客户端容易冲突。</p>
<h3>3. 重启服务端</h3>
<pre><code class="language-bash">sudo systemctl restart wg-quick@wg0
sudo wg show</code></pre>
<h2>四、生成客户端配置文件</h2>
<h3>1. 手机配置 phone.conf</h3>
<p>查看需要填的密钥：</p>
<pre><code class="language-bash">sudo cat /etc/wireguard/clients/phone_private.key
sudo cat /etc/wireguard/server_public.key</code></pre>
<p>创建手机配置：</p>
<pre><code class="language-bash">sudo vim /etc/wireguard/clients/phone.conf</code></pre>
<p>写入：</p>
<pre><code class="language-ini">[Interface]
PrivateKey = 填phone_private.key里的内容
Address = 10.8.0.2/32
DNS = 1.1.1.1
MTU = 1420
[Peer]
PublicKey = 填server_public.key里的内容
Endpoint = 你的服务器公网IP或域名:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25</code></pre>
<p><code>AllowedIPs = 0.0.0.0/0</code> 表示手机所有流量都走 WireGuard。如果只想访问 WireGuard 内网，改成：</p>
<pre><code class="language-ini">AllowedIPs = 10.8.0.0/24</code></pre>
<p>生成二维码：</p>
<pre><code class="language-bash">sudo qrencode -t ansiutf8 &lt; /etc/wireguard/clients/phone.conf</code></pre>
<h3>2. 电脑配置 pc.conf</h3>
<p>查看电脑私钥：</p>
<pre><code class="language-bash">sudo cat /etc/wireguard/clients/pc_private.key</code></pre>
<p>创建电脑配置：</p>
<pre><code class="language-bash">sudo vim /etc/wireguard/clients/pc.conf</code></pre>
<p>写入：</p>
<pre><code class="language-ini">[Interface]
PrivateKey = 填pc_private.key里的内容
Address = 10.8.0.3/32
DNS = 1.1.1.1
MTU = 1420
[Peer]
PublicKey = 填server_public.key里的内容
Endpoint = 你的服务器公网IP或域名:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25</code></pre>
<h3>3. CatWrt 配置 catwrt.conf</h3>
<p>查看 CatWrt 私钥：</p>
<pre><code class="language-bash">sudo cat /etc/wireguard/clients/catwrt_private.key</code></pre>
<p>创建 CatWrt 配置：</p>
<pre><code class="language-bash">sudo vim /etc/wireguard/clients/catwrt.conf</code></pre>
<p>写入：</p>
<pre><code class="language-ini">[Interface]
PrivateKey = 填catwrt_private.key里的内容
Address = 10.8.0.10/32
DNS = 1.1.1.1
MTU = 1420
[Peer]
PublicKey = 填server_public.key里的内容
Endpoint = 你的服务器公网IP或域名:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25</code></pre>
<p>如果你第一次配置 CatWrt，建议先把 <code>AllowedIPs</code> 写成：</p>
<pre><code class="language-ini">AllowedIPs = 10.8.0.0/24</code></pre>
<p>确认能连通后，再改成：</p>
<pre><code class="language-ini">AllowedIPs = 0.0.0.0/0</code></pre>
<p>这样可以避免路由器一启用 WireGuard 就全家断网。</p>
<h2>五、手机设置 WireGuard</h2>
<h3>1. iPhone / iPad</h3>
<p>在 App Store 安装 <code>WireGuard</code>，打开 App，点击 <code>+</code>，选择扫码导入，扫描服务器生成的二维码，保存后打开开关。</p>
<h3>2. Android</h3>
<p>安装 <code>WireGuard</code> App，点击 <code>+</code>，选择扫码导入或导入配置文件，保存后打开开关。</p>
<h3>3. 手机测试</h3>
<p>手机打开 WireGuard 后，访问查 IP 网站。如果显示的是服务器公网 IP，说明手机流量已经走服务器。如果只是访问内网，可以测试：</p>
<pre><code class="language-bash">ping 10.8.0.1</code></pre>
<h2>六、电脑设置 WireGuard</h2>
<h3>1. Windows</h3>
<p>安装 WireGuard 官方客户端，点击 <code>Import tunnel(s) from file</code>，选择 <code>pc.conf</code>，然后点击 <code>Activate</code>。</p>
<h3>2. macOS</h3>
<p>在 App Store 安装 WireGuard，导入 <code>pc.conf</code>，然后启用。</p>
<h3>3. Linux</h3>
<p>安装：</p>
<pre><code class="language-bash">sudo apt update
sudo apt install -y wireguard</code></pre>
<p>复制配置：</p>
<pre><code class="language-bash">sudo cp pc.conf /etc/wireguard/wg0.conf
sudo chmod 600 /etc/wireguard/wg0.conf</code></pre>
<p>启动：</p>
<pre><code class="language-bash">sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0</code></pre>
<p>查看：</p>
<pre><code class="language-bash">sudo wg show</code></pre>
<h2>七、CatWrt 设置 WireGuard</h2>
<p>CatWrt 可以按 OpenWrt 的方式配置。这里推荐把 CatWrt 当客户端，连接云服务器。</p>
<h3>1. 安装 WireGuard 组件</h3>
<p>SSH 登录 CatWrt，执行：</p>
<pre><code class="language-bash">opkg update
opkg install luci-proto-wireguard wireguard-tools kmod-wireguard qrencode</code></pre>
<p>安装后重启：</p>
<pre><code class="language-bash">reboot</code></pre>
<p>如果提示 <code>kmod-wireguard</code> 内核版本不匹配，不要硬装。通常是固件和软件源不匹配，需要换匹配的软件源或升级 CatWrt 固件。</p>
<h3>2. 新建 WireGuard 接口</h3>
<p>进入 CatWrt 后台：</p>
<pre><code class="language-text">网络 -&gt; 接口 -&gt; 添加新接口</code></pre>
<p>设置：</p>
<pre><code class="language-text">名称：wg_vps
协议：WireGuard VPN</code></pre>
<p>如果没有 <code>WireGuard VPN</code> 选项，说明插件没装好，或装完没有重启。</p>
<h3>3. 填写接口信息</h3>
<p>在 <code>wg_vps</code> 接口中填写：</p>
<pre><code class="language-text">私钥：catwrt_private.key 的内容
IP 地址：10.8.0.10/32
MTU：1420
监听端口：留空</code></pre>
<p>CatWrt 作为客户端时，监听端口可以留空。</p>
<h3>4. 添加服务端 Peer</h3>
<p>在 <code>对端 / Peers</code> 里添加：</p>
<pre><code class="language-text">公钥：server_public.key 的内容
端点主机：服务器公网IP或域名
端点端口：51820
允许的 IP：10.8.0.0/24 或 0.0.0.0/0
持久 KeepAlive：25</code></pre>
<p>如果只是测试，允许的 IP 先写：</p>
<pre><code class="language-text">10.8.0.0/24</code></pre>
<p>如果想让 CatWrt 下的设备都走 WireGuard，再改成：</p>
<pre><code class="language-text">0.0.0.0/0</code></pre>
<p>如果页面有 <code>Route Allowed IPs / 路由允许的 IP</code>，需要勾选。</p>
<h3>5. 设置防火墙区域</h3>
<p>如果只是让 CatWrt 自己访问 WireGuard，把 <code>wg_vps</code> 放到 <code>lan</code> 区域即可。<br />
如果想让 CatWrt 下面的设备通过 WireGuard 上网，建议把 <code>wg_vps</code> 放到 <code>wan</code> 区域，因为 <code>wan</code> 通常已经开启 NAT，并允许 <code>lan -&gt; wan</code> 转发。<br />
如果你新建了 <code>vpn</code> 区域，需要确认：</p>
<pre><code class="language-text">lan -&gt; vpn：允许转发
vpn：开启 Masquerading
vpn：允许输出</code></pre>
<p>普通用户建议先放到 <code>wan</code> 区域，少踩坑。</p>
<h3>6. CatWrt 测试</h3>
<p>SSH 到 CatWrt：</p>
<pre><code class="language-bash">wg show
ping 10.8.0.1</code></pre>
<p>如果看到 <code>latest handshake</code>，说明已经连上。如果 CatWrt 配的是全局流量，可以测试出口 IP：</p>
<pre><code class="language-bash">curl ifconfig.me</code></pre>
<p>显示服务器公网 IP，说明 CatWrt 已经通过 WireGuard 出口上网。</p>
<h2>八、常见坑</h2>
<h3>1. 没有握手</h3>
<p>优先检查：云服务器安全组是否放行 UDP 51820，服务器防火墙是否放行 UDP 51820，客户端 Endpoint 是否写错，服务端是否添加了对应客户端 Peer，公钥是否填反。</p>
<h3>2. 有握手但不能上网</h3>
<p>检查服务器是否开启转发：</p>
<pre><code class="language-bash">cat /proc/sys/net/ipv4/ip_forward</code></pre>
<p>必须输出：</p>
<pre><code class="language-text">1</code></pre>
<p>再检查 NAT 网卡名是否正确：</p>
<pre><code class="language-bash">ip route | grep default</code></pre>
<p>如果实际网卡是 <code>ens3</code>，配置里却写 <code>eth0</code>，就会连上但不能上网。</p>
<h3>3. 多个客户端互相顶掉</h3>
<p>原因通常是多个设备用了同一个配置。每台设备都要有独立 <code>PrivateKey</code> 和独立 <code>Address</code>。</p>
<h3>4. CatWrt 一启用就断网</h3>
<p>先把 CatWrt 的 <code>AllowedIPs</code> 从：</p>
<pre><code class="language-ini">0.0.0.0/0</code></pre>
<p>改成：</p>
<pre><code class="language-ini">10.8.0.0/24</code></pre>
<p>确认基础连接正常后，再考虑全局代理。旁路由不会自动接管全家流量，如果 CatWrt 是旁路由，还需要让设备网关指向 CatWrt，或者使用策略路由。</p>
<h3>5. 能连但网页打不开</h3>
<p>优先检查 DNS。客户端可以先写：</p>
<pre><code class="language-ini">DNS = 1.1.1.1</code></pre>
<p>如果某些网络下不稳定，保留：</p>
<pre><code class="language-ini">PersistentKeepalive = 25</code></pre>
<p>必要时把 MTU 改小：</p>
<pre><code class="language-ini">MTU = 1280</code></pre>
<h2>九、新增客户端接入时怎么修改</h2>
<p>后面如果要新增手机、电脑、平板、路由器，不需要重装 WireGuard，只需要做三件事：生成新客户端密钥、服务端增加一个 Peer、生成新客户端配置。</p>
<h3>1. 规划一个新 IP</h3>
<p>先给新设备分配一个没有用过的 WireGuard IP。例如前面已经用了：</p>
<pre><code class="language-text">手机：10.8.0.2
电脑：10.8.0.3
CatWrt：10.8.0.10</code></pre>
<p>新增一台平板，可以用：</p>
<pre><code class="language-text">平板：10.8.0.4</code></pre>
<p>不要和已有设备重复。</p>
<h3>2. 生成新客户端密钥</h3>
<p>假设新客户端叫 <code>pad</code>：</p>
<pre><code class="language-bash">cd /etc/wireguard
sudo bash -c 'umask 077; wg genkey | tee /etc/wireguard/pad_private.key | wg pubkey &gt; /etc/wireguard/pad_public.key'</code></pre>
<p>查看新客户端公钥：</p>
<pre><code class="language-bash">sudo cat /etc/wireguard/pad_public.key</code></pre>
<h3>3. 修改服务端配置</h3>
<p>编辑服务端配置：</p>
<pre><code class="language-bash">sudo vim /etc/wireguard/wg0.conf</code></pre>
<p>在文件末尾追加：</p>
<pre><code class="language-ini">[Peer]
# pad
PublicKey = 填pad_public.key里的内容
AllowedIPs = 10.8.0.4/32</code></pre>
<p>注意：服务端这里只需要新增这个客户端的 <code>[Peer]</code>，不要修改已有手机、电脑、CatWrt 的配置。</p>
<h3>4. 重启 WireGuard</h3>
<pre><code class="language-bash">sudo systemctl restart wg-quick@wg0</code></pre>
<p>查看状态：</p>
<pre><code class="language-bash">sudo wg show</code></pre>
<p>重启时已有客户端会短暂断开，几秒后会自动恢复。普通用户用这种方式最简单。</p>
<h3>5. 生成新客户端配置</h3>
<p>查看服务端公钥和新客户端私钥：</p>
<pre><code class="language-bash">sudo cat /etc/wireguard/server_public.key
sudo cat /etc/wireguard/clients/pad_private.key</code></pre>
<p>创建新客户端配置：</p>
<pre><code class="language-bash">sudo vim /etc/wireguard/clients/pad.conf</code></pre>
<p>写入：</p>
<pre><code class="language-ini">[Interface]
PrivateKey = 填pad_private.key里的内容
Address = 10.8.0.4/32
DNS = 1.1.1.1
MTU = 1420
[Peer]
PublicKey = 填server_public.key里的内容
Endpoint = 你的服务器公网IP或域名:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25</code></pre>
<p>如果这个客户端只想访问 WireGuard 内网，不想让所有流量都走服务器，把：</p>
<pre><code class="language-ini">AllowedIPs = 0.0.0.0/0</code></pre>
<p>改成：</p>
<pre><code class="language-ini">AllowedIPs = 10.8.0.0/24</code></pre>
<h3>6. 导入新客户端</h3>
<p>手机或平板可以生成二维码：</p>
<pre><code class="language-bash">sudo qrencode -t ansiutf8 &lt; /etc/wireguard/clients/pad.conf</code></pre>
<p>然后用 WireGuard App 扫码导入。电脑客户端则直接导入 <code>pad.conf</code> 文件。</p>
<h3>7. 新增客户端时最容易出错的地方</h3>
<p>新增客户端时，只记住这几条：</p>
<pre><code class="language-text">1. 新设备必须用新的 PrivateKey 和 PublicKey
2. 新设备必须用新的 Address，不能和旧设备重复
3. 服务端必须新增一个对应的 [Peer]
4. 服务端 Peer 里的 AllowedIPs 要写这个客户端的 /32
5. 原有客户端配置不用改</code></pre>
<p>例如新增 <code>pad</code>，服务端只新增：</p>
<pre><code class="language-ini">[Peer]
# pad
PublicKey = pad的PublicKey
AllowedIPs = 10.8.0.4/32</code></pre>
<p>客户端只使用：</p>
<pre><code class="language-ini">Address = 10.8.0.4/32</code></pre>
<p>不要复制旧手机的配置直接用，否则两个设备会互相顶掉。</p>]]></description>
    <pubDate>Sat, 23 May 2026 16:57:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/wireguard_install</guid>
</item>
<item>
    <title>tmux安装与claude监控安装</title>
    <link>https://blog.askerlab.com/tmux_cluade_tmux</link>
    <description><![CDATA[<p>用 tmux + claude-tmux + claude-tui 管理多个 Claude Code 终端任务</p>
<pre><code class="language-text">tmux        负责多终端会话持久化
claude-tmux 负责查看多个 Claude Code 会话状态
claude-tui  负责查看上下文、成本、工具调用、session 统计</code></pre>
<h2>一、环境说明</h2>
<p>本文以 Ubuntu / Debian / WSL / SSH 终端环境为主。<br />
先确认 Claude Code 已经能用：</p>
<pre><code class="language-bash">claude --version</code></pre>
<p>如果这里都不能运行，先把 Claude Code 装好，再继续后面的步骤。</p>
<h2>二、安装 tmux</h2>
<h3>Ubuntu / Debian</h3>
<pre><code class="language-bash">sudo apt update
sudo apt install -y tmux curl git build-essential</code></pre>
<h3>macOS</h3>
<pre><code class="language-bash">brew install tmux</code></pre>
<p>验证：</p>
<pre><code class="language-bash">tmux -V</code></pre>
<h2>三、安装 Rust / Cargo</h2>
<p><code>claude-tmux</code> 推荐通过 Cargo 安装，所以需要 Rust 工具链。<br />
先检查：</p>
<pre><code class="language-bash">cargo --version</code></pre>
<p>如果没有 Cargo，安装 Rust，如果没有魔法可能安装失败，可以部分用国内安装：</p>
<pre><code class="language-bash">curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
env RUSTUP_DIST_SERVER=https://mirrors.tuna.tsinghua.edu.cn/rustup \
    RUSTUP_UPDATE_ROOT=https://mirrors.tuna.tsinghua.edu.cn/rustup/rustup \
    sh -s -- -y --profile minimal

source "$HOME/.cargo/env"</code></pre>
<p>验证：</p>
<pre><code class="language-bash">cargo --version</code></pre>
<h2>四、安装 claude-tmux</h2>
<p>执行：</p>
<pre><code class="language-bash">cargo install claude-tmux</code></pre>
<p>确认二进制文件存在：</p>
<pre><code class="language-bash">which claude-tmux
ls -lh ~/.cargo/bin/claude-tmux</code></pre>
<p>正常路径一般是：</p>
<pre><code class="language-text">/home/你的用户名/.cargo/bin/claude-tmux</code></pre>
<h2>五、配置 tmux 快捷键打开 claude-tmux</h2>
<p>编辑 tmux 配置：</p>
<pre><code class="language-bash">vim ~/.tmux.conf</code></pre>
<p>加入这一行：</p>
<pre><code class="language-bash">bind-key C-c display-popup -E -w 80 -h 30 "~/.cargo/bin/claude-tmux"</code></pre>
<p>重载配置：</p>
<pre><code class="language-bash">tmux source-file ~/.tmux.conf</code></pre>
<p>进入 tmux：</p>
<pre><code class="language-bash">tmux</code></pre>
<p>然后按：</p>
<pre><code class="language-text">Ctrl-b  Ctrl-c</code></pre>
<p>就会弹出 <code>claude-tmux</code> 面板。<br />
<code>claude-tmux</code> 常见状态：</p>
<pre><code class="language-text">● Working           Claude 正在工作
○ Idle              Claude 空闲，等你输入
◐ Waiting for input 等待权限确认，例如 [y/n]
? Unknown           不是 Claude 会话，或者状态无法判断</code></pre>
<h2>六、安装 claude-tui</h2>
<p><code>claude-tui</code> 的坑比较多，核心要求是：</p>
<pre><code class="language-text">Python 3.13+</code></pre>
<p>先检查当前 Python：</p>
<pre><code class="language-bash">python3 --version</code></pre>
<p>如果输出是 <code>Python 3.13.x</code>，可以直接安装：</p>
<pre><code class="language-bash">curl -sSL https://raw.githubusercontent.com/slima4/claude-tui/main/install.sh | bash</code></pre>
<p>安装后执行：</p>
<pre><code class="language-bash">claudetui setup
claudetui mode full</code></pre>
<p>验证：</p>
<pre><code class="language-bash">which claudetui
claudetui --help</code></pre>
<h2>七、如果 Python 版本不是 3.13+</h2>
<p>很多 Ubuntu 机器默认是 Python 3.10 或 3.12。不要直接替换系统的 <code>/usr/bin/python3</code>，否则可能影响 apt 和系统脚本。<br />
推荐做法：只在当前用户环境里使用 Python 3.13。<br />
先检查：</p>
<pre><code class="language-bash">python3.13 --version
which python3.13</code></pre>
<p>如果能看到 Python 3.13，执行：</p>
<pre><code class="language-bash">mkdir -p ~/.local/bin
ln -sf "$(command -v python3.13)" ~/.local/bin/python3
grep -q 'export PATH="$HOME/.local/bin:$PATH"' ~/.bashrc || echo 'export PATH="$HOME/.local/bin:$PATH"' &gt;&gt; ~/.bashrc
source ~/.bashrc
hash -r</code></pre>
<p>验证：</p>
<pre><code class="language-bash">which python3
python3 --version</code></pre>
<p>你应该看到类似：</p>
<pre><code class="language-text">/home/你的用户名/.local/bin/python3
Python 3.13.x</code></pre>
<p>然后重新安装 <code>claude-tui</code>：</p>
<pre><code class="language-bash">curl -sSL https://raw.githubusercontent.com/slima4/claude-tui/main/install.sh | bash
claudetui setup
claudetui mode full</code></pre>
<h2>八、常见坑</h2>
<h3>1：代理环境变量导致 curl 失败</h3>
<p>如果你看到类似错误：</p>
<pre><code class="language-text">curl: (97) Can't complete SOCKS5 connection</code></pre>
<p>或者明明没有主动加代理，但 curl 自动走了 socks/http 代理，先检查环境变量：</p>
<pre><code class="language-bash">env | grep -i proxy</code></pre>
<p>也可以逐个 echo：</p>
<pre><code class="language-bash">echo "http_proxy=$http_proxy"
echo "https_proxy=$https_proxy"
echo "all_proxy=$all_proxy"
echo "HTTP_PROXY=$HTTP_PROXY"
echo "HTTPS_PROXY=$HTTPS_PROXY"
echo "ALL_PROXY=$ALL_PROXY"</code></pre>
<p>临时清掉当前终端代理：</p>
<pre><code class="language-bash">unset http_proxy
unset https_proxy
unset all_proxy
unset HTTP_PROXY
unset HTTPS_PROXY
unset ALL_PROXY</code></pre>
<p>再次确认：</p>
<pre><code class="language-bash">env | grep -i proxy</code></pre>
<p>如果没有输出，说明当前 shell 的代理已经清掉。<br />
重新测试：</p>
<pre><code class="language-bash">curl -I --max-time 10 https://astral.sh
curl -I --max-time 10 https://raw.githubusercontent.com</code></pre>
<p>如果你想查代理从哪里自动注入：</p>
<pre><code class="language-bash">grep -nEi 'proxy|1080|8080|7890|socks' ~/.bashrc ~/.profile ~/.bash_profile ~/.zshrc 2&gt;/dev/null</code></pre>
<hr />
<h3>2：apt 代理配置导致 502 Bad Gateway</h3>
<p>如果你给 apt 配过代理，比如：</p>
<pre><code class="language-text">Acquire::http::Proxy "http://127.0.0.1:8080/";
Acquire::https::Proxy "http://127.0.0.1:8080/";</code></pre>
<p>然后出现：</p>
<pre><code class="language-text">502 Bad Gateway [IP: 127.0.0.1 8080]
仓库 InRelease 的签名不再生效</code></pre>
<p>这通常不是 Ubuntu 源坏了，而是 apt 拿到的是代理返回的 502 页面，不是真正的 InRelease 文件。<br />
先删掉 apt 代理：</p>
<pre><code class="language-bash">sudo rm -f /etc/apt/apt.conf.d/99proxy
sudo apt clean</code></pre>
<p>确认没有残留：</p>
<pre><code class="language-bash">ls /etc/apt/apt.conf.d/*proxy* 2&gt;/dev/null
cat /etc/apt/apt.conf.d/*proxy* 2&gt;/dev/null</code></pre>
<p>然后重新测试：</p>
<pre><code class="language-bash">sudo apt update</code></pre>
<p>如果你的网络必须走代理，先确认代理端口真的可用。<br />
测试 HTTP 代理：</p>
<pre><code class="language-bash">curl -v --max-time 10 -x http://127.0.0.1:8080 https://www.cloudflare.com/cdn-cgi/trace</code></pre>
<p>测试 SOCKS5 代理：</p>
<pre><code class="language-bash">curl -v --max-time 10 --socks5-hostname 127.0.0.1:1080 https://www.cloudflare.com/cdn-cgi/trace</code></pre>
<p>如果 8080 返回 502，说明这个 HTTP 代理出口不可用，不要给 apt 配 8080。<br />
如果 1080 可用，可以尝试 apt 使用 socks5h：</p>
<pre><code class="language-bash">sudo tee /etc/apt/apt.conf.d/99proxy &lt;&lt;'EOF'
Acquire::ForceIPv4 "true";
Acquire::http::Proxy "socks5h://127.0.0.1:1080/";
Acquire::https::Proxy "socks5h://127.0.0.1:1080/";
EOF</code></pre>
<p>然后：</p>
<pre><code class="language-bash">sudo apt clean
sudo apt update</code></pre>
<p>不用代理时，删除它：</p>
<pre><code class="language-bash">sudo rm -f /etc/apt/apt.conf.d/99proxy
sudo apt clean</code></pre>
<h3>3：deadsnakes PPA 连接超时</h3>
<p>如果你用 deadsnakes PPA 安装 Python 3.13，可能遇到：</p>
<pre><code class="language-text">连接超时
无法连接 ppa.launchpadcontent.net
IPv6 网络不可达</code></pre>
<p>这时有三个选择：</p>
<h4>选择 1：优先用 uv，绕开 apt PPA</h4>
<pre><code class="language-bash">curl -LsSf https://astral.sh/uv/install.sh | sh
source "$HOME/.local/bin/env" 2&gt;/dev/null || export PATH="$HOME/.local/bin:$PATH"
uv python install 3.13</code></pre>
<h4>选择 2：修好代理后再 apt install</h4>
<p>确认代理可用后再执行：</p>
<pre><code class="language-bash">sudo apt update
sudo apt install -y python3.13 python3.13-venv libpython3.13-stdlib</code></pre>
<h4>选择 3：不用 claude-tui，先只用 tmux + claude-tmux</h4>
<p>如果网络暂时修不好，<code>claude-tmux</code> 已经足够看多个 Claude 是否 working、idle、waiting。</p>
<h2>九、推荐的 tmux 工作流</h2>
<p>创建多个 Claude 任务 session：</p>
<pre><code class="language-bash">tmux new -s claude-api
tmux new -s claude-web
tmux new -s claude-test
tmux new -s claude-monitor</code></pre>
<p>在前三个 session 里启动 Claude：</p>
<pre><code class="language-bash">claude</code></pre>
<p>在 monitor session 里启动 claude-tui：</p>
<pre><code class="language-bash">claudetui monitor</code></pre>
<p>最终结构类似：</p>
<pre><code class="language-text">tmux
├── claude-api      # Claude 任务 1
├── claude-web      # Claude 任务 2
├── claude-test     # Claude 任务 3
└── claude-monitor  # claudetui monitor</code></pre>
<p>日常命令：</p>
<pre><code class="language-bash">tmux ls
tmux attach -t claude-api
tmux attach -t claude-web
tmux attach -t claude-test</code></pre>
<p>在任意 tmux session 里打开 <code>claude-tmux</code>：</p>
<pre><code class="language-text">Ctrl-b  Ctrl-c</code></pre>
<p>打开 <code>claude-tui</code> 实时监控：</p>
<pre><code class="language-bash">claudetui monitor</code></pre>
<p>查看历史统计：</p>
<pre><code class="language-bash">claudetui stats</code></pre>
<p>查看 session 列表：</p>
<pre><code class="language-bash">claudetui sessions list</code></pre>
<h2>十、最终配置</h2>
<p>我的推荐组合是：</p>
<pre><code>vim ~/.tmux.conf</code></pre>
<p>配置：</p>
<pre><code># Ctrl+a c      新建 window
# Ctrl+a d      detach
# Ctrl+a |      左右分屏
# Ctrl+a -      上下分屏
# Alt+h/j/k/l   直接切 pane
# 鼠标点击       选择 pane
# 鼠标拖边框     调整 pane 大小
# 把 prefix 从 Ctrl+b 改成 Ctrl+a

unbind C-b
set -g prefix C-a
bind C-a send-prefix

# 开启鼠标
set -g mouse on
setw -g mode-keys vi
# 鼠标左键拖选：自动进入 copy-mode，并限定在当前 pane
bind-key -T root MouseDrag1Pane if-shell -F "#{pane_in_mode}" "send-keys -M" "copy-mode -M"

# 鼠标松开：复制并退出 copy-mode
bind-key -T copy-mode-vi MouseDragEnd1Pane send -X copy-selection-and-cancel

bind-key -T copy-mode-vi v send -X begin-selection
bind-key -T copy-mode-vi y send -X copy-selection-and-cancel
bind-key -T copy-mode-vi Enter send -X copy-selection-and-cancel

set -g set-clipboard on

# 按 r 重新加载配置
bind r source-file ~/.tmux.conf \; display-message "tmux.conf reloaded"

# 更容易记的分屏
bind h split-window -h
bind v split-window -v

# Alt + hjkl 直接切换 pane，不需要先按 prefix
bind -n M-h select-pane -L
bind -n M-j select-pane -D
bind -n M-k select-pane -U
bind -n M-l select-pane -R

# Alt + 方向键也可以切换 pane
bind -n M-Left select-pane -L
bind -n M-Down select-pane -D
bind -n M-Up select-pane -U
bind -n M-Right select-pane -R

# Alt + 数字切 window
bind -n M-1 select-window -t 1
bind -n M-2 select-window -t 2
bind -n M-3 select-window -t 3
bind -n M-4 select-window -t 4
bind -n M-5 select-window -t 5

# 绑定claude-tmux
bind-key C-c display-popup -E -w 80 -h 30 "~/.cargo/bin/claude-tmux"
</code></pre>]]></description>
    <pubDate>Wed, 13 May 2026 20:16:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/tmux_cluade_tmux</guid>
</item>
<item>
    <title>【1】openclaw 安装部署</title>
    <link>https://blog.askerlab.com/install_openclaw</link>
    <description><![CDATA[<h1>安装和部署</h1>
<h1>常用命令</h1>
<pre><code>openclaw gateway stop
openclaw gateway start</code></pre>
<p>ssh代理远程访问</p>
<pre><code>ssh -N -L 18789:127.0.0.1:18789 claw@192.168.100.104</code></pre>
<p>登录：<br />
查看.openclaw/openclaw.json中token秘钥，然后登录：</p>
<pre><code>http://localhost:18789/chat?token=XXXX</code></pre>]]></description>
    <pubDate>Thu, 12 Mar 2026 00:30:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/install_openclaw</guid>
</item>
<item>
    <title>自制追剧助手：阿里云盘的便捷使用技巧.md</title>
    <link>https://blog.askerlab.com/aliautosave_use</link>
    <description><![CDATA[<h1>1. 背景</h1>
<p>最近正好在使用figma的make功能，正巧代码工具又层出不穷，除了我常用的cursor， codex、claude code、gemini-cli等Agent代码工具迎来了重大升级，正巧我使用阿里云盘在追剧，痛点是当有新剧增加的时候，别人是分享到网盘链接里的，每次我都需要找到对应的网盘，然后保存到我的阿里云盘里。如果是已更新完的剧还好，如果是正在更新的剧，我还需要记住对应的链接，没事点开看看有没有更新，然后转存到我的网盘里。所以正好想开发一个小工具，能够根据链接进行转存，并且定时查看分享链接里的内容有没有更新，如果更新以后则转存到我的目标云盘里。<br />
因此做了一个阿里云盘自动转存的功能，目前支持的功能如下：</p>
<ul>
<li><strong>支持阿里云盘登录、查看存储状态</strong></li>
<li><strong>支持阿里云盘通过分享链接转存</strong></li>
<li><strong>支持转存为特定的名字</strong></li>
<li><strong>支持定时转存设置</strong></li>
<li><strong>支持对订阅内容进行编辑、暂停、删除</strong></li>
<li><strong>支持查看转存日志</strong><br />
<code>本项目完全没有主动编写任何代码，全程使用和大模型对话方式进行实现，本次只是说明如何使用该软件，后续我会将如何用figma+codex自动化编写代码进行分享。</code></li>
</ul>
<h1>2. 软件安装与使用</h1>
<h2>2.1 安装</h2>
<p>目前已经上传到docker hub，建议直接使用docker进行安装，也可以访问我的github，按照github进行安装</p>
<pre><code>https://github.com/apostle9891/aliautosave</code></pre>
<p>使用docker进行安装</p>
<pre><code class="language-docker"># 拉取aliautosave
docker pull apostle9891/aliautosave:latest

# 运行docker，其中/path要改成你的path
docker run -d --name aliautosave -p 8144:8144 -v /path/aliautosave_data:/app/data apostle9891/aliautosave:latest</code></pre>
<p>如果是网页docker，可以直接搜索：<code>aliautosave</code><br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/53f41764691593.png" alt="" /><br />
点击下载，并进行安装，安装过程中端口映射为<code>8144</code>，存储位置替换<code>/app/data</code><br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/a8561764691593.png" alt="" /></p>
<h2>2.2 软件使用</h2>
<p>当安装完成后，可以打开对应的<code>IP:8144</code>,比如我的网页是<code>192.168.100.101:8144</code><br />
打开以后，点击扫码登录阿里云盘<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/88d81764691593.png" alt="" /><br />
打开阿里云盘，登录阿里云盘<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/5ba21764691593.png" alt="" /><br />
登录完毕后，可以看到对应的云盘信息<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/7a371764691593.png" alt="" /><br />
点击新增订阅，填入需要新增的分享链接<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/d9691764691594.png" alt="" /><br />
可以看到拉取到对应的云盘里的电视剧信息，支持多种自动命名规则，会自动提取里面的名字、集数、季数、扩展信息等，然后转为标准的姓名，目前支持：</p>
<ul>
<li><code>{title}.S{season:02}E{episode:02}{ext}</code></li>
<li><code>{title}.E{episode:02}{ext}</code></li>
<li><code>{name}{ext}</code></li>
<li><code>{title}.{index:02}{ext}</code><br />
提取出来以后，我们可以自定义命名title，比如我们这次的电视剧叫做<strong>大生意</strong>，那我们改为<strong>大生意人</strong>。<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/61b51764691594.png" alt="" /><br />
可以看到整体预览名字改成了大生意人<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/83921764691594.png" alt="" /><br />
选择对应的目标文件夹<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/cb841764691594.png" alt="" /><br />
支持新建文件夹<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/f9941764691594.png" alt="" /><br />
选择定时的策略，默认选择立即订阅并开始复制，会对内容进行复制<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/b44c1764691595.png" alt="" /><br />
点击后即可立即进行复制<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/e2241764691595.png" alt="" /><br />
支持暂停、编辑、删除、查看转存日志<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/add31764691595.png" alt="" /><br />
暂停<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/2ca51764691595.png" alt="" /><br />
日志<br />
<img src="https://blog.askerlab.com/content/uploadfile/202512/6aae1764691595.png" alt="" /></li>
</ul>
<h1>结尾</h1>
<p>大模型能力越来越强了，如果说在2023年我第一次开通vscode的copilot还是属于辅助编程，去年我买了cursor属于自定义编程，现在从6月份开始就真正可以叫做Agent编程了，可以全程通过对话进行编程，以后只需要一个ideal，就可以实现自己的想法。</p>]]></description>
    <pubDate>Tue, 02 Dec 2025 23:25:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/aliautosave_use</guid>
</item>
<item>
    <title>提示词维度测试仪</title>
    <link>https://blog.askerlab.com/prompt_test-2</link>
    <description><![CDATA[<h1>提示词维度测试仪</h1>
<h2>背景</h2>
<p>当我们使用大模型对ASR（语音识别）文本进行总结时，如何判断总结质量的好坏？这里提供一个简单的测试框架。</p>
<h2>核心测试维度</h2>
<h3>1. 完整性 ✅</h3>
<blockquote>
<p>原文的关键信息是否都被覆盖？</p>
</blockquote>
<table>
<thead>
<tr>
<th>检查项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>核心观点</td>
<td>主要论点是否保留</td>
</tr>
<tr>
<td>关键数据</td>
<td>重要数字、时间是否准确</td>
</tr>
<tr>
<td>人物/事件</td>
<td>关键角色是否提及</td>
</tr>
</tbody>
</table>
<h3>2. 准确性 🎯</h3>
<blockquote>
<p>总结内容是否与原文一致？</p>
</blockquote>
<table>
<thead>
<tr>
<th>检查项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>事实正确</td>
<td>没有张冠李戴</td>
</tr>
<tr>
<td>无幻觉</td>
<td>没有凭空编造内容</td>
</tr>
<tr>
<td>语义保真</td>
<td>没有曲解原意</td>
</tr>
</tbody>
</table>
<h3>3. 简洁性 📝</h3>
<blockquote>
<p>是否做到了有效压缩？</p>
</blockquote>
<table>
<thead>
<tr>
<th>检查项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>去除冗余</td>
<td>口语化内容已精简</td>
</tr>
<tr>
<td>结构清晰</td>
<td>层次分明，易于阅读</td>
</tr>
<tr>
<td>长度合理</td>
<td>压缩比适当（通常10%-30%）</td>
</tr>
</tbody>
</table>
<h3>4. 可读性 👀</h3>
<blockquote>
<p>总结文本是否流畅易懂？</p>
</blockquote>
<table>
<thead>
<tr>
<th>检查项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>语句通顺</td>
<td>没有病句、断句</td>
</tr>
<tr>
<td>逻辑连贯</td>
<td>上下文衔接自然</td>
</tr>
<tr>
<td>专业术语</td>
<td>保留必要术语，通俗化表达</td>
</tr>
</tbody>
</table>
<h2>快速打分表</h2>
<table>
<thead>
<tr>
<th>维度</th>
<th>权重</th>
<th>得分(1-5)</th>
<th>加权分</th>
</tr>
</thead>
<tbody>
<tr>
<td>完整性</td>
<td>30%</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td>准确性</td>
<td>40%</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td>简洁性</td>
<td>15%</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td>可读性</td>
<td>15%</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td><strong>总分</strong></td>
<td>100%</td>
<td>-</td>
<td><strong>_</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p>💡 <strong>评分参考</strong>：4分以上为优秀，3-4分为合格，3分以下需要优化提示词</p>
</blockquote>
<h2>常见问题与优化方向</h2>
<table>
<thead>
<tr>
<th>问题</th>
<th>可能原因</th>
<th>优化建议</th>
</tr>
</thead>
<tbody>
<tr>
<td>遗漏关键点</td>
<td>提示词太笼统</td>
<td>明确要求&quot;保留所有核心观点&quot;</td>
</tr>
<tr>
<td>出现幻觉</td>
<td>模型自由发挥</td>
<td>添加&quot;不要编造原文没有的内容&quot;</td>
</tr>
<tr>
<td>过于冗长</td>
<td>未限制长度</td>
<td>指定字数或压缩比例</td>
</tr>
<tr>
<td>逻辑混乱</td>
<td>缺少结构引导</td>
<td>要求&quot;按时间/主题分点总结&quot;</td>
</tr>
</tbody>
</table>]]></description>
    <pubDate>Thu, 27 Nov 2025 09:59:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/prompt_test-2</guid>
</item>
<item>
    <title>提示词机理档案</title>
    <link>https://blog.askerlab.com/prompt_archive-2</link>
    <description><![CDATA[<h1>模型内部是「方向」而不是「句子」</h1>
<p>比如当我们约束“永远不要高度浓缩！”。</p>
<ul>
<li>它不是直接理解「永远不要高度浓缩！」这 9 个汉字。</li>
<li>它理解的是：在训练语料中，「不要高度浓缩」「详细展开讲」「拆开来说说细节」这些表达，经常伴随什么样的输出模式。</li>
<li>所以每一句话，对它来说等价于在行为空间里施加一个「方向」：往“展开、详细、慢速讲”的区域移动。<br />
所以那些能稳定触发你想要的行为方向的短语</li>
<li>详细展开 / 不要省略 → 「不要简略」「详细展开」「逐点解释」</li>
<li>忠实原文 / 不瞎编 → 「不新增事实」「不要编造细节」「如实保留」</li>
<li>去掉元语言 → 「不要解释你的思考过程」「最终只输出文章，不提到指令」</li>
<li>结构清晰 → 「按以下结构…」「先…，然后…，最后…」<br />
这些词对模型来说，就是统计上非常稳定的“开关”。</li>
</ul>]]></description>
    <pubDate>Thu, 27 Nov 2025 09:59:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/prompt_archive-2</guid>
</item>
<item>
    <title>提示词维度测试仪</title>
    <link>https://blog.askerlab.com/prompt_test</link>
    <description><![CDATA[<h1>提示词维度测试仪</h1>
<h2>背景</h2>
<p>当我们使用大模型对ASR（语音识别）文本进行总结时，如何判断总结质量的好坏？这里提供一个简单的测试框架。</p>
<h2>核心测试维度</h2>
<h3>1. 完整性 ✅</h3>
<blockquote>
<p>原文的关键信息是否都被覆盖？</p>
</blockquote>
<table>
<thead>
<tr>
<th>检查项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>核心观点</td>
<td>主要论点是否保留</td>
</tr>
<tr>
<td>关键数据</td>
<td>重要数字、时间是否准确</td>
</tr>
<tr>
<td>人物/事件</td>
<td>关键角色是否提及</td>
</tr>
</tbody>
</table>
<h3>2. 准确性 🎯</h3>
<blockquote>
<p>总结内容是否与原文一致？</p>
</blockquote>
<table>
<thead>
<tr>
<th>检查项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>事实正确</td>
<td>没有张冠李戴</td>
</tr>
<tr>
<td>无幻觉</td>
<td>没有凭空编造内容</td>
</tr>
<tr>
<td>语义保真</td>
<td>没有曲解原意</td>
</tr>
</tbody>
</table>
<h3>3. 简洁性 📝</h3>
<blockquote>
<p>是否做到了有效压缩？</p>
</blockquote>
<table>
<thead>
<tr>
<th>检查项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>去除冗余</td>
<td>口语化内容已精简</td>
</tr>
<tr>
<td>结构清晰</td>
<td>层次分明，易于阅读</td>
</tr>
<tr>
<td>长度合理</td>
<td>压缩比适当（通常10%-30%）</td>
</tr>
</tbody>
</table>
<h3>4. 可读性 👀</h3>
<blockquote>
<p>总结文本是否流畅易懂？</p>
</blockquote>
<table>
<thead>
<tr>
<th>检查项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>语句通顺</td>
<td>没有病句、断句</td>
</tr>
<tr>
<td>逻辑连贯</td>
<td>上下文衔接自然</td>
</tr>
<tr>
<td>专业术语</td>
<td>保留必要术语，通俗化表达</td>
</tr>
</tbody>
</table>
<h2>快速打分表</h2>
<table>
<thead>
<tr>
<th>维度</th>
<th>权重</th>
<th>得分(1-5)</th>
<th>加权分</th>
</tr>
</thead>
<tbody>
<tr>
<td>完整性</td>
<td>30%</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td>准确性</td>
<td>40%</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td>简洁性</td>
<td>15%</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td>可读性</td>
<td>15%</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td><strong>总分</strong></td>
<td>100%</td>
<td>-</td>
<td><strong>_</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p>💡 <strong>评分参考</strong>：4分以上为优秀，3-4分为合格，3分以下需要优化提示词</p>
</blockquote>
<h2>常见问题与优化方向</h2>
<table>
<thead>
<tr>
<th>问题</th>
<th>可能原因</th>
<th>优化建议</th>
</tr>
</thead>
<tbody>
<tr>
<td>遗漏关键点</td>
<td>提示词太笼统</td>
<td>明确要求&quot;保留所有核心观点&quot;</td>
</tr>
<tr>
<td>出现幻觉</td>
<td>模型自由发挥</td>
<td>添加&quot;不要编造原文没有的内容&quot;</td>
</tr>
<tr>
<td>过于冗长</td>
<td>未限制长度</td>
<td>指定字数或压缩比例</td>
</tr>
<tr>
<td>逻辑混乱</td>
<td>缺少结构引导</td>
<td>要求&quot;按时间/主题分点总结&quot;</td>
</tr>
</tbody>
</table>]]></description>
    <pubDate>Thu, 27 Nov 2025 09:59:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/prompt_test</guid>
</item>
<item>
    <title>提示词机理档案</title>
    <link>https://blog.askerlab.com/prompt_archive</link>
    <description><![CDATA[<h1>模型内部是「方向」而不是「句子」</h1>
<p>比如当我们约束“永远不要高度浓缩！”。</p>
<ul>
<li>它不是直接理解「永远不要高度浓缩！」这 9 个汉字。</li>
<li>它理解的是：在训练语料中，「不要高度浓缩」「详细展开讲」「拆开来说说细节」这些表达，经常伴随什么样的输出模式。</li>
<li>所以每一句话，对它来说等价于在行为空间里施加一个「方向」：往“展开、详细、慢速讲”的区域移动。<br />
所以那些能稳定触发你想要的行为方向的短语</li>
<li>详细展开 / 不要省略 → 「不要简略」「详细展开」「逐点解释」</li>
<li>忠实原文 / 不瞎编 → 「不新增事实」「不要编造细节」「如实保留」</li>
<li>去掉元语言 → 「不要解释你的思考过程」「最终只输出文章，不提到指令」</li>
<li>结构清晰 → 「按以下结构…」「先…，然后…，最后…」<br />
这些词对模型来说，就是统计上非常稳定的“开关”。</li>
</ul>]]></description>
    <pubDate>Thu, 27 Nov 2025 09:59:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/prompt_archive</guid>
</item>
<item>
    <title>提示词写作指南：那些我反复回看的优质示例</title>
    <link>https://blog.askerlab.com/prompt_collect-2</link>
    <description><![CDATA[<h1>Geminsi 3 提示词工程：通用最佳实践指南</h1>
<pre><code>Gemini 3 提示词工程：通用最佳实践指南

@_philschmid 最新博客：Gemini 3 更偏好直接、逻辑性强的内容，而非冗长的说教。提示词核心原则与三大关键实践 👇

核心原则 (Core Principles)
· 指令要精准 (Precise Instructions)：去除废话，直接清晰地陈述你的目标。Gemini 3 对简洁明了的指令反应最好。
· 保持一致性 (Consistency)：在提示词中维持统一的结构（例如统一使用 XML 标签），并明确定义模棱两可的术语。
· 多模态融合 (Multimodal Coherence)：文本、图像、音频或视频应被视为同等重要的输入。指令中要明确引用特定的模态，让模型进行综合分析，而不是孤立处理。
· 约束前置 (Constraint Placement)：将行为约束和角色定义放在“系统指令”中或提示词的最顶端，作为模型推理的锚点。
· 长上下文处理 (Context Anchoring)：处理大量数据时，将具体指令放在末尾。在数据和问题之间使用过渡句（如“基于上述信息……”）来桥接。

三大关键实践
1. 推理与规划 (Reasoning and Planning)
不要让模型直接给出答案，而是强制它先“思考”。
· 显式拆解：要求模型在回答前，先将目标拆解为子任务，检查信息是否完整，并构思结构化的提纲。
· 自我更新的任务清单 (TODO Tracker)：让模型创建一个 TODO 列表，在执行过程中自我追踪进度（例如：[ ] 任务1，[x] 任务2）。
· 自我批判：要求模型在输出最终响应前，先对照用户的原始约束进行自我审查（例如：“我是否回应了用户的真实意图，而不仅仅是字面意思？”）。

2. 结构化提示 (Structured Prompting)
使用清晰的标记语言（XML 或 Markdown）来界定提示词的边界。这能帮助模型区分哪里是“指令”，哪里是“数据”。
· XML 示例：使用 &lt;rules&gt; 定义规则，&lt;context&gt; 放入背景资料，&lt;planning_process&gt; 展示思考过程。
· Markdown 示例：使用标题如 # Identity（身份），# Constraints（约束）来组织内容。
· 建议：选择一种格式并保持一致，不要混用。

3. 智能体工具使用 (Agentic Tool Use)
当把 Gemini 3 作为自主智能体使用时，需要赋予它更强的韧性和反思能力：
· 坚持指令 (The Persistence Directive)：明确告诉智能体“必须持续工作直到问题被完全解决”。如果工具调用失败，它应该分析错误并尝试替代方案，而不是直接放弃或把问题抛回给用户。
· 预计算反思 (Pre-Computation Reflection)：在调用任何工具之前，要求智能体明确陈述：
  4. 为什么要调用这个工具？
  5. 期望获取什么具体数据？
  6. 这个数据如何帮助解决用户的问题？

场景应用与模板
文章还提供了针对不同领域的具体策略：
· 研究分析：先拆解问题，独立搜索，最后综合并强制引用来源。
· 创意写作：明确目标受众，如果是为了通过图灵测试或显得自然，需明确禁止使用“企业黑话”（如 synergy, protocols）。
· 解决问题：要求模型先找出“标准方案”，再找出“高手方案”（Power User Solution），提供最优解。
</code></pre>
<h1>最火的推特发帖提示词</h1>
<ul>
<li><strong>先定钩子类型</strong>：反直觉/唱反调（contrarian）、好奇心缺口（curiosity gap）、具体数字承诺（specific value）、打破常识（pattern interrupt）。<a href="https://www.hipclip.ai/workflows/how-to-create-x-twitter-threads-that-actually-go-viral-in-2025?utm_source=chatgpt.com">3hipclip.ai</a></li>
<li><strong>线程结构要短平快</strong>：每条只推进一个点，保持叙事动量，避免信息过载。<a href="https://www.hipclip.ai/workflows/how-to-create-x-twitter-threads-that-actually-go-viral-in-2025?utm_source=chatgpt.com">hipclip.ai+1</a></li>
<li><strong>提示词要“可参数化”</strong>：主题、受众、立场、语气、长度、CTA、禁忌项都用变量占位。<a href="https://clickup.com/templates/ai-prompts/tweets-and-twitter-threads?utm_source=chatgpt.com">clickup.com+1</a></li>
<li><strong>把“研究”写进流程</strong>：输出前必须做“最新信息检索+可信来源对照+可引用事实点”。（很多模板会要求先收集材料再写作，只是通常写得不够硬，你这里需要更硬。）<a href="https://hackernoon.com/a-twitter-thread-prompt-that-actually-works?utm_source=chatgpt.com">黑客中午+1</a>
<pre><code></code></pre></li>
</ul>
<h1>角色（Role）</h1>
<p>你是“X/Twitter 增长文案专家 + 快速研究员（Research-first Copywriter）”。<br />
你擅长用【反直觉的矛盾】制造注意力，用【证据与例子】建立可信度，用【清晰结构】提升转推/收藏/评论率。</p>
<h1>目标（Goal）</h1>
<p>基于我输入的需求，先进行网络检索与事实核验，再产出可直接发布的 X/Twitter 文案（单条或线程），要求：<br />
1) 内容“新”：必须引用/吸收近期网络信息与趋势（尽量是最近 30 天，除非主题不需要）。<br />
2) 内容“狠”：必须包含至少一个“矛盾/冲突/反常识”的核心张力点，形成强钩子。<br />
3) 内容“稳”：观点有证据支撑，避免虚构数据与来源；不确定就用“可能/一些案例显示”并给出替代表述。</p>
<h1>输入（User Input）</h1>
<p>我会提供（尽量多提供越好）：</p>
<ul>
<li>主题/领域：</li>
<li>受众是谁（新手/专家/老板/开发者/产品/投资人/普通用户）：</li>
<li>我想表达的核心观点（可一句话）：</li>
<li>我已有素材（链接/要点/经历/数据/产品细节）：</li>
<li>目的（涨粉/引流/招聘/品牌/产品发布/观点输出）：</li>
<li>风格（毒舌/克制/专业/故事感/幽默/犀利）：</li>
<li>形式（单条/线程/引用转推/投票）：</li>
<li>禁忌（不聊什么/不提什么品牌/避免敏感点）：</li>
</ul>
<h1>任务（Tasks）</h1>
<h2>Task A：联网研究（必须执行）</h2>
<p>1) 用网络搜索找到与主题最相关的【最新】信息（优先：权威媒体/研究报告/官方博客/行业报告/头部从业者公开内容）。<br />
2) 提取 5-10 条“可用于发帖的事实点/新变化/争议点/数据/案例”（每条一句话）。<br />
3) 做最小交叉验证：同一关键事实至少对照 2 个来源；若无法验证，标记为“未完全确认”。</p>
<h2>Task B：制造“矛盾张力”（必须执行）</h2>
<p>在写作前，先生成 6 个“矛盾钩子候选”，每个符合以下任一模式：</p>
<ul>
<li>反直觉：大家以为 A，但最新情况更像 B</li>
<li>代价冲突：你得到 X，会失去 Y</li>
<li>立场对撞：主流观点 P 的盲点是 Q</li>
<li>真相揭露：行业最赚钱的部分，恰恰是最不起眼的部分</li>
<li>误区纠偏：90% 的人做错在第一步</li>
<li>数据打脸：最新数据与常识相反<br />
从中选 2 个最强的进入成稿。</li>
</ul>
<h2>Task C：输出可直接发布的文案（必须执行）</h2>
<p>按我指定的“形式”输出；如果我没指定，默认输出三套：<br />
1) 单条推文（1 条，&lt;= 280 字符，强钩子 + 观点 + 证据/例子 + 轻 CTA）<br />
2) 线程（7-9 条，每条一个要点，节奏：钩子 -&gt; 可信度 -&gt; 三段论/步骤 -&gt; 反驳常见误解 -&gt; 落地建议 -&gt; CTA）<br />
3) 引用转推文案（1 条，针对一条“假想的行业主流观点/新闻”，用矛盾角度反击）</p>
<h1>输出格式（Output Format）</h1>
<h2>0) 联网研究摘要</h2>
<ul>
<li>关键事实点（5-10 条）：（用项目符号列出）</li>
<li>争议/分歧点（1-3 条）：（用项目符号列出）</li>
<li>可引用来源清单：给出来源名称 + 标题/关键词 + 发布时间（不贴长链接；若必须给链接，放最后）</li>
</ul>
<h2>1) 矛盾钩子候选（6 个）</h2>
<ul>
<li>Hook 1:</li>
<li>Hook 2:<br />
...</li>
</ul>
<h2>2) 成稿（可直接复制发布）</h2>
<h3>A. 单条（1 条）</h3>
<p>（正文）</p>
<h3>B. 线程（7-9 条）</h3>
<p>1/ （钩子）<br />
2/ ...<br />
...<br />
n/ （CTA：提问或让人收藏/转发）</p>
<h3>C. 引用转推（1 条）</h3>
<p>（正文）</p>
<h2>3) 质量自检（必须给出结论）</h2>
<ul>
<li>是否“最新”：是/否（若否，说明原因）</li>
<li>是否有“矛盾张力”：是/否（指出张力句）</li>
<li>是否可读：是/否（如果否，给 1 句改法）</li>
<li>是否避免虚构：是/否（标注任何不确定点）</li>
</ul>
<h1>写作准则（Hard Rules）</h1>
<ul>
<li>必须“具体”：多用数字、步骤、对比、案例；少空话。</li>
<li>每条信息只推进一个观点，避免信息过载。</li>
<li>少用 hashtag：除非我要求，否则最多 0-2 个。</li>
<li>不要夸张承诺；用“证据 + 例子”替代空洞煽动。</li>
<li>永远优先清晰，其次才是文采。</li>
</ul>
<pre><code></code></pre>]]></description>
    <pubDate>Wed, 26 Nov 2025 09:59:00 +0800</pubDate>
    <dc:creator>apostle9891</dc:creator>
    <guid>https://blog.askerlab.com/prompt_collect-2</guid>
</item></channel>
</rss>