Skill: chenkun-nuaa/ck-rag-skill (version 1.0.0)

--- name: ragflow-kb description: RAGFlow知识库问答与操作指导。调用RAGFlow知识库API进行智能问答，并基于知识库返回结果提供agent操作建议。支持流式输出，耐心等待完整响应生成。当用户提出技术问题、故障排查、操作指导或需要知识库检索时触发此技能。适用于容器/Docker问题、系统运维、开发相关问题等场景。 --- # RAGFlow知识库问答Skill ## 概述 此skill通过调用RAGFlow知识库API，为用户提供智能问答和操作指导。**API使用流式输出（Stream）方式返回结果，需要耐心等待完整响应生成**（通常5-10秒）。 ## 工作流程 ### 步骤1: 识别问题类型 判断用户的问题是否适合通过知识库查询： - 技术问题（容器、Docker、Kubernetes等） - 系统运维问题 - 故障排查 - 操作指导 - 其他需要专业知识库的场景 ### 步骤2: 调用RAGFlow API 使用`scripts/query_ragflow.py`脚本查询知识库： **标准查询**（适合正常使用）： ```bash python3 /home/onestack/.openclaw/workspace/ragflow-kb/scripts/query_ragflow.py "用户的问题" ``` **调试模式**（查看详细信息）： ```bash python3 /home/onestack/.openclaw/workspace/ragflow-kb/scripts/query_ragflow.py "用户的问题" -v # 或 python3 /home/onestack/.openclaw/workspace/ragflow-kb/scripts/query_ragflow.py "用户的问题" --verbose ``` ### 步骤3: 等待流式响应 **重要提示**： - RAGFlow API使用流式输出，响应需要时间生成 - 无新数据超时：**15秒**（给流式生成足够时间） - 最大总超时：**60秒** - 请求超时：**120秒** - 通常5-10秒能完成，复杂问题可能更久 脚本会显示进度点（`.`）表示正在接收数据，请耐心等待。 ### 步骤4: 处理返回结果 API返回结果包含： - **助手回复**：完整的AI生成答案 - **引用文档**：知识库中相关的文档来源 - **统计信息**：处理行数、数据块数量、耗时 ### 步骤5: 总结和操作建议 根据返回结果： - **直接回答**: 如果是简单问题，直接总结答案 - **操作指导**: 如果问题涉及具体操作（如容器挂了），提供步骤化的操作建议 - **建议执行agent操作**: 如果建议使用其他agent工具，明确指出 ## API配置 **基本信息**: - API地址: `http://172.28.20.46:30001/v1/conversation/completion` - 认证方式: Bearer token + Cookie session - 输出方式: **Server-Sent Events (SSE) 流式输出** **请求格式**: - 方法: POST - Content-Type: application/json **关键参数**: - `conversation_id`: 会话ID（使用固定ID保持对话上下文） - `messages`: 对话历史数组，每个消息包含： - `role`: "user" 或 "assistant" - `content`: 消息内容 - `id`: 消息唯一标识 ## 使用示例 ### 示例1: 容器故障排查 ``` 用户: 容器挂了怎么办 → 调用API查询"容器挂了怎么办" → 等待约6秒，接收完整流式响应（94行数据） → 返回故障排查步骤并引用文档 → 总结操作建议：直接删除容器，重新创建并加版本号 ``` **实际执行**： ```bash python3 /home/onestack/.openclaw/workspace/ragflow-kb/scripts/query_ragflow.py "容器挂了怎么办" # 输出： [查询] 容器挂了怎么办 ......................................................................... # 完整答案 如果容器挂了，你需要直接删除这个容器，然后重新创建一个新的容器， 并且给新容器的名字后缀加上一个版本号[ID:0]。 [引用文档] - 运维测试文档.doc -------------------------------------------------------------------------------- [成功] 查询完成 (耗时: 6.19秒) ``` ### 示例2: 技术知识查询 ``` 用户: Docker网络模式有哪些？ → 调用API查询"Docker网络模式" → 等待流式响应 → 返回bridge、host、overlay等模式的说明 → 总结并简要说明各模式特点 → 如果知识库没相关内容，返回"知识库中未找到您要的答案！" ``` ### 示例3: 需要执行agent操作 ``` 用户: 怎么查看容器日志？ → 调用API查询"查看容器日志" → API返回使用docker logs命令的方法 → 总结：使用`docker logs <container_name>`查看日志 → 建议用户提供容器名称，使用exec工具执行命令 ``` ## 超时配置说明 脚本已针对流式输出优化超时配置： | 参数 | 值 | 说明 | |------|-----|------| | `STREAM_NO_DATA_TIMEOUT` | 15秒 | 无新数据则认为完成（给流式生成足够时间） | | `STREAM_MAX_TIMEOUT` | 60秒 | 最大总等待时间（防止无限等待） | | 请求超时 | 120秒 | HTTP连接超时 | **如果超时**： 1. 使用调试模式（-v）查看详细信息 2. 检查网络连接到RAGFlow服务器 3. 确认API服务状态 ## 调试模式 使用`-v`或`--verbose`参数获取详细调试信息： ```bash python3 /home/onestack/.openclaw/workspace/ragflow-kb/scripts/query_ragflow.py "测试问题" -v ``` 调试信息包括： - 完整的请求URL和参数 - 响应状态码 - 数据接收过程 - 处理的行数、数据块数量、耗时 - 完整的JSON响应 ## 注意事项 1. **流式输出等待**: RAGFlow使用流式输出，需要耐心等待，不要提前终止 2. **会话管理**: conversation_id可以复用，保持对话上下文 3. **错误处理**: 如果API调用失败，检查网络连接和API服务状态 4. **结果总结**: 不要只是复制返回结果，要进行总结和提炼 5. **操作建议**: 当API返回包含操作步骤时，转化为可执行的命令或明确指引 6. **安全性**: API认证信息已固化在脚本中，注意不要泄露 ## 扩展使用 对于需要agent执行的命令： - 明确告知用户可以执行的命令 - 如果用户确认，使用exec工具执行 - 反馈执行结果 对于需要多次查询的复杂问题： - 拆分为多个子问题 - 逐步查询和确认 - 最后整合完整答案 ## 故障排查 ### API请求失败 ```bash # 测试连接 curl -I http://172.28.20.46:30001/v1/conversation/completion # 查看详细错误 python3 scripts/query_ragflow.py "测试" -v ``` ### 认证失败 - 检查Authorization token是否过期 - 检查session cookie是否有效 - 查看HTTP状态码（401/403表示权限问题） ### 返回"知识库中未找到" - 知识库确实没有相关内容 - 或者检索关键词匹配不上 - 尝试更换问题描述方式

path: scripts/query_ragflow.py
content: #!/usr/bin/env python3
"""
RAGFlow知识库查询脚本

使用方法:
    python3 query_ragflow.py "你的问题"

示例:
    python3 query_ragflow.py "容器挂了怎么办"

选项:
    -v, --verbose: 显示详细调试信息
"""

import sys
import json
import requests
from time import time, time as timestamp

# RAGFlow API配置
API_URL = "http://172.28.20.46:30001/v1/conversation/completion"
AUTHORIZATION = "IjQxYThhZGYyMDZlYjExZjFhZDE1ODJkYzljOWQ1YmJmIg.aYvfEw.ElppYHks0F5ETowUlvqA1Th-XHE"
COOKIE = "session=.elxVyzOegCAMAMC_dHagCgh8hIDaRleQyfh3jYmD4w13Qh5dWt4ZEizixBmNxgsbKkbknKkcxcy43siB/MyNqkb5CONuTR2yyWQKbarxVe7a9dNywRHnEaYvfEw66dir-0J0wYtii0IOGJ11861RtRtxp4"

# 固定的conversation_id，保持对话上下文
CONVERSATION_ID = "0e18393f0b6042f2bbf6b391c82835d1"

# 流式输出配置
STREAM_NO_DATA_TIMEOUT = 15.0    # 15秒无新数据则认为完成（给流式生成足够时间）
STREAM_MAX_TIMEOUT = 60.0        # 最大总等待时间60秒


def query_ragflow(question, verbose=False):
    """
    查询RAGFlow知识库

    Args:
        question (str): 用户问题
        verbose (bool): 是否输出调试信息

    Returns:
        dict: API响应结果
    """
    # 构建请求体
    payload = {
        "conversation_id": CONVERSATION_ID,
        "messages": [
            {
                "content": "你好！ 我是你的助理，有什么可以帮到你的吗？",
                "role": "assistant"
            },
            {
                "id": f"msg_{int(timestamp())}",
                "content": question,
                "role": "user",
                "files": [],
                "conversationId": CONVERSATION_ID
            }
        ]
    }

    # 请求头
    headers = {
        "Authorization": AUTHORIZATION,
        "Content-Type": "application/json",
        "Cookie": COOKIE
    }

    if verbose:
        print(f"[调试] 发送请求到: {API_URL}")
        print(f"[调试] 请求体: {json.dumps(payload, ensure_ascii=False, indent=2)}")

    try:
        # 发送POST请求（启用流式传输，设置较长超时）
        response = requests.post(
            API_URL,
            json=payload,
            headers=headers,
            stream=True,
            timeout=120  # 120秒连接超时
        )
        response.raise_for_status()

        if verbose:
            print(f"[调试] 响应状态码: {response.status_code}")
            print("[调试] 开始接收流式数据...")
            print("[调试] 等待完整响应生成，请稍候...")

        # 解析SSE流
        full_answer = ""
        references = []
        message_id = None
        last_answer_length = 0
        last_activity_time = time()
        start_time = time()
        line_count = 0
        chunk_count = 0

        for line in response.iter_lines(decode_unicode=True):
            line_count += 1

            # 检查是否超过最大超时时间
            if time() - start_time > STREAM_MAX_TIMEOUT:
                if verbose:
                    print(f"\n[调试] 达到最大超时时间 ({STREAM_MAX_TIMEOUT}秒)")
                break

            # 更新活动时间
            last_activity_time = time()

            if line.startswith('data:'):
                try:
                    # 去掉"data:"前缀并解析JSON
                    json_str = line[5:].strip()
                    if json_str and json_str != '[DONE]':  # 跳过结束标记
                        data = json.loads(json_str)

                        # 确保data是dict类型
                        if not isinstance(data, dict):
                            continue

                        # 提取答案
                        if "data" in data and isinstance(data["data"], dict) and "answer" in data["data"]:
                            # 只在第一次出现消息ID时记录
                            if message_id is None and "id" in data["data"]:
                                message_id = data["data"]["id"]
                                if verbose:
                                    print(f"[调试] 消息ID: {message_id}")

                            # 累积答案内容（流式输出）
                            answer_chunk = data["data"]["answer"]
                            full_answer += answer_chunk
                            chunk_count += 1

                            # 打印进度（每100个字符打印一个点）
                            if len(full_answer) - last_answer_length > 100:
                                print(f".", end="", flush=True)
                                last_answer_length = len(full_answer)

                        # 提取引用
                        if "data" in data and isinstance(data["data"], dict) and "reference" in data["data"]:
                            chunks = data["data"]["reference"].get("chunks", [])
                            if isinstance(chunks, list):
                                references.extend(chunks)

                except (json.JSONDecodeError, TypeError) as e:
                    if verbose:
                        print(f"\n[调试] 跳过无效数据行: {e}")
                    continue

            # 检查是否超时（长时间无新数据）
            if time() - last_activity_time > STREAM_NO_DATA_TIMEOUT:
                if verbose:
                    print(f"\n[调试] {STREAM_NO_DATA_TIMEOUT}秒无新数据，接收完成")
                break

        # 如果有点没换行，换行
        if len(full_answer) - last_answer_length > 0:
            print()

        if verbose:
            print(f"[调试] 共处理 {line_count} 行数据，{chunk_count} 个数据块")
            print(f"[调试] 总耗时: {time() - start_time:.2f}秒")
            print(f"[调试] 答案长度: {len(full_answer)} 字符")

        return {
            "error": False,
            "answer": full_answer,
            "references": references,
            "message_id": message_id,
            "stats": {
                "lines": line_count,
                "chunks": chunk_count,
                "duration": time() - start_time
            }
        }

    except requests.exceptions.Timeout as e:
        return {
            "error": True,
            "message": f"API请求超时: {str(e)}"
        }
    except requests.exceptions.RequestException as e:
        return {
            "error": True,
            "message": f"API请求失败: {str(e)}"
        }


def format_response(result, verbose=False):
    """
    格式化API响应结果

    Args:
        result (dict): API响应结果
        verbose (bool): 是否输出调试信息

    Returns:
        str: 格式化后的文本
    """
    if result.get("error"):
        print(f"[错误] {result['message']}")
        return None

    # 返回答案
    answer = result.get("answer", "")

    # 如果有引用，显示引用信息
    references = result.get("references", [])
    if references and references[0]:  # 确保引用列表不为空
        answer += "\n\n[引用文档]"
        for ref in references:
            if isinstance(ref, dict):
                doc_name = ref.get("doc_name", "未知文档")
                answer += f"\n- {doc_name}"

    return answer if answer.strip() else None


def main():
    """主函数"""
    # 检查参数
    verbose = "--verbose" in sys.argv or "-v" in sys.argv

    # 提取问题（跳过-v选项）
    args = [arg for arg in sys.argv[1:] if arg not in ["--verbose", "-v"]]

    if not args:
        print("使用方法: python3 query_ragflow.py \"你的问题\" [选项]")
        print("示例:")
        print("  python3 query_ragflow.py \"容器挂了怎么办\"")
        print("  python3 query_ragflow.py \"容器挂了怎么办\" -v")
        sys.exit(1)

    question = " ".join(args)

    print(f"[查询] {question}")
    print("-" * 80)

    # 查询RAGFlow
    result = query_ragflow(question, verbose)

    # 格式化输出
    answer = format_response(result, verbose)

    if answer:
        print(answer)
        print("-" * 80)
        stats = result.get("stats", {})
        duration = stats.get("duration", 0)
        print(f"[成功] 查询完成 (耗时: {duration:.2f}秒)")
    else:
        print("[失败] 未获取到有效回答")

    # 输出完整响应（调试用）
    if verbose:
        print("\n[完整响应]")
        print(json.dumps(result, indent=2, ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/quick_test.py
content: #!/usr/bin/env python3
"""
RAGFlow API 快速测试脚本
用于诊断API连接和基本功能
"""

import sys
import json
import requests
from time import time

# RAGFlow API配置
API_URL = "http://172.28.20.46:30001/v1/conversation/completion"
AUTHORIZATION = "IjQxYThhZGYyMDZlYjExZjFhZDE1ODJkYzljOWQ1YmJmIg.aYvfEw.ElppYHks0F5ETowUlvqA1Th-XHE"
COOKIE = "session=.elxVyzOegCAMAMC_dHagCgh8hIDaRleQyfh3jYmD4w13Qh5dWt4ZEizixBmNxgsbKkbknKkcxcy43siB/MyNqkb5CONuTR2yyWQKbarxVe7a9dNywRHnEaYvfEw66dir-0J0wYtii0IOGJ11861RtRtxp4"
CONVERSATION_ID = "0e18393f0b6042f2bbf6b391c82835d1"

def test_connection():
    """测试API连接"""
    print("=" * 60)
    print("测试1: API连接性")
    print("=" * 60)

    try:
        response = requests.head(API_URL, timeout=5)
        print(f"✓ API可达")
        print(f"  状态码: {response.status_code}")
        print(f"  Server: {response.headers.get('Server', 'N/A')}")
        return True
    except requests.exceptions.Timeout:
        print(f"✗ API连接超时 (>5秒)")
        return False
    except requests.exceptions.ConnectionError as e:
        print(f"✗ API连接失败")
        print(f"  错误: {e}")
        return False
    except Exception as e:
        print(f"✗ 未知错误: {e}")
        return False

def test_simple_query():
    """测试简单查询（预期快速响应）"""
    print("\n" + "=" * 60)
    print("测试2: 简单查询 '你好'")
    print("=" * 60)

    payload = {
        "conversation_id": CONVERSATION_ID,
        "messages": [
            {
                "content": "你好",
                "role": "user"
            }
        ]
    }

    headers = {
        "Authorization": AUTHORIZATION,
        "Content-Type": "application/json",
        "Cookie": COOKIE
    }

    start_time = time()

    try:
        response = requests.post(
            API_URL,
            json=payload,
            headers=headers,
            stream=True,
            timeout=60
        )

        print(f"  状态码: {response.status_code}")
        print(f"  开始接收数据...")

        lines_count = 0
        chunks = 0
        for line in response.iter_lines(decode_unicode=True):
            lines_count += 1
            if line.startswith('data:'):
                chunks += 1
                print(f".", end="", flush=True)

            # 10秒后中断
            if time() - start_time > 10:
                print(f"\n  警告: 10秒超时，停止接收")
                break

        duration = time() - start_time
        print(f"\n  完成! 耗时: {duration:.2f}秒, 处理行数: {lines_count}, 数据块: {chunks}")
        return True

    except Exception as e:
        print(f"\n  ✗ 查询失败: {e}")
        return False

def test_network():
    """测试网络延迟"""
    print("\n" + "=" * 60)
    print("测试3: 网络延迟")
    print("=" * 60)

    import socket

    try:
        host = "172.28.20.46"
        port = 30001
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(2)

        start_time = time()
        result = sock.connect_ex((host, port))
        duration = (time() - start_time) * 1000

        sock.close()

        if result == 0:
            print(f"✓ 端口连接成功")
            print(f"  延迟: {duration:.1f}ms")
            return True
        else:
            print(f"✗ 端口连接失败 (错误码: {result})")
            return False

    except socket.timeout:
        print(f"✗ 连接超时 (>2秒)")
        return False
    except Exception as e:
        print(f"✗ 网络测试失败: {e}")
        return False

def main():
    print("\n🔍 RAGFlow API 诊断工具")
    print("")

    results = []

    # 运行测试
    results.append(("API连接", test_connection()))
    results.append(("网络延迟", test_network()))
    results.append(("简单查询", test_simple_query()))

    # 汇总
    print("\n" + "=" * 60)
    print("测试汇总")
    print("=" * 60)

    for name, result in results:
        status = "✅ 通过" if result else "❌ 失败"
        print(f"{name:15s} {status}")

    # 建议
    all_passed = all(r[1] for r in results)
    print("\n" + "=" * 60)
    if all_passed:
        print("✅ 所有测试通过！API工作正常。")
    else:
        print("❌ 存在问题，建议检查：")
        failed_tests = [r[0] for r in results if not r[1]]
        for test in failed_tests:
            if test == "API连接":
                print("  - 检查RAGFlow服务是否启动")
                print("  - 检查防火墙规则")
                print("  - 确认API地址正确")
            elif test == "网络延迟":
                print("  - 检查网络连接")
                print("  - 尝试ping服务器")
            elif test == "简单查询":
                print("  - 检查认证信息（token/cookie）")
                print("  - 查看RAGFlow服务日志")

if __name__ == "__main__":
    main()


path: scripts/test_api.sh
content: #!/bin/bash
# RAGFlow API测试脚本

echo "=== RAGFlow API 连接测试 ==="
echo ""

# 测试1: 检查API是否可达
echo "测试1: API连接性"
curl -I http://172.28.20.46:30001/v1/conversation/completion --connect-timeout 5 -s -o /dev/null -w "HTTP状态码: %{http_code}\n"
echo ""

# 测试2: 检查网络延迟
echo "测试2: 网络延迟"
ping -c 3 172.28.20.46
echo ""

# 测试3: 快速查询（简单问题）
echo "测试3: 快速查询 - '你好'"
python3 /home/onestack/.openclaw/workspace/ragflow-kb/scripts/query_ragflow.py "你好"
echo ""
echo "=== 测试完成 ==="


path: TROUBLESHOOTING.md
content: # RAGFlow Skill 故障排查指南

## 快速诊断

```bash
# 运行快速诊断工具
python3 /home/onestack/.openclaw/workspace/ragflow-kb/scripts/quick_test.py
```

---

## 常见问题与解决方案

### 问题1: 查询一直不结束（流式输出持续输出点）

**症状**：
```
[查询] Docker的基本概念
..............................................................................
(一直输出，长时间不结束)
```

**原因**：
- RAGFlow正在生成较长的回答
- 话题复杂，知识库匹配内容多
- 正常现象，但可能超过60秒最大超时

**解决方案**：

**方案1：使用简单问题**
```bash
# 建议：使用更具体、简短的问题
python3 scripts/query_ragflow.py "容器挂了怎么办"  # ✅ 快速
python3 scripts/query_ragflow.py "Docker基本概念"   # ⚠️ 可能很慢
```

**方案2：调整超时时间**
```bash
# 编辑脚本，找到这一行（约第26行）：
STREAM_MAX_TIMEOUT = 60.0  # 改为 120.0 或更长

# 或者
STREAM_NO_DATA_TIMEOUT = 15.0  # 改为 30.0
```

**方案3：手动中断**
```bash
# 按 Ctrl+C 手动停止
# 检查是否已经收到部分答案
```

---

### 问题2: API连接失败

**症状**：
```
[错误] API请求失败: Connection refused
或
[错误] API请求失败: Timeout
```

**诊断**：
```bash
# 测试网络连通性
curl -I http://172.28.20.46:30001

# 运行诊断工具
python3 scripts/quick_test.py
```

**解决方案**：

1. **检查API服务启动**
```bash
# 在RAGFlow服务器上检查服务
systemctl status ragflow
# 或
docker ps | grep ragflow
```

2. **检查防火墙**
```bash
# 测试端口开放
telnet 172.28.20.46 30001

# 或
nc -zv 172.28.20.46 30001
```

3. **检查网络**
```bash
ping 172.28.20.46
traceroute 172.28.20.46
```

---

### 问题3: 认证失败

**症状**：
```
[错误] API请求失败: 401 Client Error: Unauthorized
或
[错误] API请求失败: 403 Client Error: Forbidden
```

**原因**：
- Token或Cookie过期
- 认证信息错误

**解决方案**：

1. **更新认证信息**
```bash
# 编辑脚本，找到第10-12行：
AUTHORIZATION = "你的新token"
COOKIE = "session=你的新cookie"
```

2. **重新登录获取认证信息**
- 登录RAGFlow Web界面
- 打开浏览器开发者工具（F12）
- Network 标签查找API请求
- 复制请求头中的 Authorization 和 Cookie

---

### 问题4: 返回"知识库中未找到您要的答案！"

**原因**：
- 知识库确实没有相关内容
- 关键词匹配不上

**解决方案**：

1. **尝试不同的问法**
```bash
# 原问题
python3 scripts/query_ragflow.py "Docker网络模式"

# 改用更口语化
python3 scripts/query_ragflow.py "Docker有哪些网络"
```

2. **使用调试模式查看匹配过程**
```bash
python3 scripts/query_ragflow.py "你的问题" -v
# 查看是否检索到相关文档
```

3. **更新知识库**
- 在RAGFlow中上传更全面的文档
- 确保文档包含你关心的内容

---

### 问题5: 代码错误

**症状**：
```
Traceback (most recent call last):
  ...
ModuleNotFoundError: No module named 'requests'
```

**解决方案**：

```bash
# 安装依赖
pip3 install requests

# 验证安装
python3 -c "import requests; print(requests.__version__)"
```

---

## 调试技巧

### 1. 使用调试模式

```bash
# 查看详细的请求/响应信息
python3 scripts/query_ragflow.py "测试问题" -v

# 或
python3 scripts/query_ragflow.py "测试问题" --verbose
```

### 2. 检查原始响应

```bash
# 使用curl直接测试（不处理流式）
curl -X POST http://172.28.20.46:30001/v1/conversation/completion \
  -H "Authorization: 你的token" \
  -H "Content-Type: application/json" \
  -H "Cookie: session=你的cookie" \
  -d '{"conversation_id":"0e18393f0b6042f2bbf6b391c82835d1","messages":[{"role":"user","content":"测试"}]}'
```

### 3. 查看网络抓包

```bash
# 监控API调用
tcpdump -i any host 172.28.20.46 and port 30001
```

---

## 性能优化建议

### 1. 简化问题

**不好**：
```bash
python3 scripts/query_ragflow.py "详细解释Docker的架构、组件、工作原理、网络模式、存储驱动以及容器生命周期管理"
```

**好**：
```bash
python3 scripts/query_ragflow.py "Docker容器生命周期管理"
```

### 2. 使用关键词

**不好**：
```bash
python3 scripts/query_ragflow.py "如果我的程序运行的时候出问题了怎么办"
```

**好**：
```bash
python3 scripts/query_ragflow.py "容器挂了怎么处理"
```

### 3. 分步骤查询

对于复杂问题，拆分成多个简单查询：

```bash
# 步骤1
python3 scripts/query_ragflow.py "Docker网络有几种模式"

# 步骤2
python3 scripts/query_ragflow.py "bridge网络模式特点"
```

---

## 超时配置说明

脚本中有3个超时参数可根据需要调整：

| 参数 | 位置 | 默认值 | 说明 |
|------|------|--------|------|
| `STREAM_MAX_TIMEOUT` | 第26行 | 60秒 | 最大总等待时间 |
| `STREAM_NO_DATA_TIMEOUT` | 第25行 | 15秒 | 无新数据超时 |
| 请求超时 | 第102行 | 120秒 | HTTP连接超时 |

**修改示例**：
```python
# 编辑 scripts/query_ragflow.py

# 等待更长的时间（适合复杂问题）
STREAM_MAX_TIMEOUT = 120.0
STREAM_NO_DATA_TIMEOUT = 30.0

# 或快速失败（适合简单问题）
STREAM_MAX_TIMEOUT = 30.0
STREAM_NO_DATA_TIMEOUT = 5.0
```

---

## 获取帮助

### 1. 查看脚本说明

```bash
python3 scripts/query_ragflow.py --help
```

### 2. 运行完整诊断

```bash
# 运行全套诊断
python3 scripts/quick_test.py

# 或使用bash脚本
bash scripts/test_api.sh
```

### 3. 查看日志

```bash
# 启用详细日志
python3 scripts/query_ragflow.py "测试" -v > debug.log 2>&1

# 查看日志
cat debug.log
```

---

## 总结

| 问题类型 | 诊断工具 | 解决方案 |
|----------|----------|----------|
| 查询太慢 | `quick_test.py` | 简化问题或调整超时 |
| 连接失败 | `curl -I` | 检查API服务和网络 |
| 认证失败 | 查看HTTP状态码 | 更新token/cookie |
| 无相关答案 | 调试模式 | 更改问法或更新知识库 |
| 代码错误 | 查看错误信息 | 安装依赖 |

---

**记住**：
1. 先用 `quick_test.py` 快速诊断
2. 简单问题响应更快
3. 复杂问题可以拆分查询
4. 使用 `-v` 调试模式查看详情


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)