# ask.py

[![PyPI version](https://badge.fury.io/py/ask-py-cli.svg)](https://badge.fury.io/py/ask-py-cli)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

[English](README_EN.md) | 简体中文 | [日本語](README_JA.md)

基于 LangChain 的终端 LLM 问答工具，支持多模型、角色记忆和 MCP 工具调用。

## 特性

- 🚀 快速终端问答，直接 `ask "问题"` 即可
- ⚡ 流式输出，实时显示回答（默认启用）
- 🔧 多模型配置，支持任意 OpenAI 兼容接口
- 🎭 角色系统，自定义 System Prompt
- 🧠 三层记忆系统（短期/中期/长期），自动压缩淘汰
- 🔌 MCP（Model Context Protocol）工具支持
- 📁 文件内容分析，支持 `-f` 参数读取文件
- 📊 错误日志分析，支持从 stdin 读取
- 🌍 上下文感知，自动注入工作目录、环境变量等

## 快速开始

### 1. 安装

```bash
# 使用 pipx（推荐）
pipx install ask-py-cli

# 或使用 uv tool
uv tool install ask-py-cli
```

### 2. 开始使用

安装后即可直接使用，首次运行会自动创建默认配置：

```bash
# 直接提问（使用默认的 public 模型）
ask "什么是 Python？"
```

> ⚠️ **重要提示**: 
> - 默认的 `public(glm-4-flash)` 模型仅用于**快速体验**，有 **IP 维度频次限制**（动态调整）
> - **长期使用建议配置自己的 API 密钥**，避免频次限制影响使用
> - 支持任何 OpenAI 兼容接口：OpenAI、Azure OpenAI、DeepSeek、智谱 GLM、Ollama 等

#### 添加自己的模型

```bash
ask model add openai \
    -b https://api.openai.com/v1 \
    -k $OPENAI_API_KEY \
    -m gpt-4 \
    --set-default
```

### 3. 开始使用

```bash
# 基础问答（默认流式输出，实时显示）
ask "什么是量子计算？"
ask "解释 Python 的装饰器"

# 分析代码文件
ask -f main.py "解释这个文件的功能"
ask "优化这段代码" -f utils.py
ask -f config.yaml "检查配置是否正确"

# 分析错误和日志
cat error.log | ask "分析这个错误" --stdin
python script.py 2>&1 | ask "解释这个错误" --stdin
tail -n 100 app.log | ask "找出性能问题" --stdin

# 使用角色（带记忆功能）
ask role add shell -s "你是一个系统管理员助手。当用户询问系统相关问题（如文件操作、进程管理、系统信息查询等）时，优先使用 shell 命令解决，而不是使用其他编程语言代码实现。" --set-default
ask "列出当前目录下所有大于 100MB 的文件"
ask "找出占用 CPU 最高的进程"  # 自动记忆上下文，无需重复说明

# 使用工具模式
ask -t "现在几点了？"  # 使用 time 工具
ask --mcp shell "列出当前目录的 Python 文件"  # 使用 shell 工具

# 组合使用
ask -r shell -f script.sh "优化这个脚本"
ask -f main.py "添加错误处理" --no-stream  # 禁用流式输出
```

## 命令参考

### 提问

```bash
ask [OPTIONS] "问题"

选项:
  -m, --model TEXT   指定模型
  -s, --system TEXT  临时系统提示词
  -r, --role TEXT    使用指定角色
  -t, --tools        启用 MCP 工具
  --mcp NAME         指定 MCP 服务器（可多次使用）
  --no-stream        禁用流式输出（一次性显示完整结果）
  -f, --file TEXT    读取文件内容并分析
  --stdin            从标准输入读取内容（用于错误分析等）
```

### 使用示例

#### 日常问答
```bash
# 快速提问（流式输出，实时显示）
ask "什么是 Python 的生成器？"
ask "解释 RESTful API 设计原则"
```

#### 代码分析
```bash
# 分析单个文件
ask -f main.py "解释这个文件的功能"
ask "优化这段代码的性能" -f utils.py

# 分析配置文件
ask -f docker-compose.yml "检查配置是否正确"
ask -f package.json "解释依赖关系"
```

#### 错误诊断
```bash
# 分析错误日志
cat error.log | ask "分析这个错误" --stdin
python script.py 2>&1 | ask "解释这个错误" --stdin

# 分析应用日志
tail -n 100 app.log | ask "找出性能瓶颈" --stdin
journalctl -u myapp -n 50 | ask "分析服务问题" --stdin
```

#### 系统管理辅助
```bash
# 使用 shell 角色进行系统管理对话
ask role add shell -s "你是一个系统管理员助手。当用户询问系统相关问题（如文件操作、进程管理、系统信息查询等）时，优先使用 shell 命令解决，而不是使用其他编程语言代码实现。" --set-default
ask "找出占用磁盘空间最大的目录"
ask "列出所有正在监听的端口"  # 自动记忆上下文

# 系统问题诊断
ask -r shell "清理 /tmp 目录下超过 7 天的文件"
ask -r shell "检查系统负载并找出原因"
```

#### 工具集成
```bash
# 使用 MCP 工具
ask -t "现在几点了？"  # 查询时间
ask --mcp shell "列出当前目录的 Python 文件"

# 组合使用
ask -f requirements.txt "检查依赖冲突" --no-stream | tee analysis.txt
```

### 模型管理

```bash
ask model add NAME -b API_BASE -k API_KEY [-m MODEL] [--set-default]
ask model list
ask model default NAME
ask model remove NAME
```

### 角色管理

```bash
ask role add NAME -s "提示词" [-m MODEL] [--set-default]
ask role list
ask role show NAME
ask role edit NAME -s "新提示词"
ask role default [NAME]      # 设置/清除默认角色
ask role remove NAME
ask role memory NAME         # 查看记忆
ask role clear-memory NAME --confirm
```

## 配置文件

配置存储在 `~/.config/ask/` 目录：

```
~/.config/ask/
├── config.yaml    # 模型配置
├── roles.yaml     # 角色配置
├── mcp.json       # MCP 服务器配置
└── memory/        # 记忆存储
```

### config.yaml 示例

首次运行会自动创建默认配置：

```yaml
default: public
lang: zh-cn  # 语言设置: en, zh-cn, zh-tw (默认根据系统 $LANG 自动检测)
models:
  public:
    api_base: https://ask.appsvc.net/v1
    api_key: <自动生成的密钥>
    model: glm-4-flash
    temperature: 0.7
```

> ⚠️ **重要提示**: 
> - `public(glm-4-flash)` 模型仅用于快速体验，有 IP 维度频次限制（动态调整）
> - 长期使用建议添加自己的模型配置，使用自己的 API 密钥
> - 可以添加多个模型，通过 `ask model default <name>` 切换默认模型

添加自己的模型后：

```yaml
default: openai
default_role: shell
lang: zh-cn
models:
  public:
    api_base: https://ask.appsvc.net/v1
    api_key: <自动生成的密钥>
    model: glm-4-flash
    temperature: 0.7
  openai:
    api_base: https://api.openai.com/v1
    api_key: sk-xxx
    model: gpt-4
    temperature: 0.7
```

### 多语言支持

支持语言：
- `en` - English
- `zh-cn` - 简体中文
- `zh-tw` - 繁體中文
- `ja` - 日本語

语言检测优先级：
1. 配置文件中的 `lang` 设置
2. 环境变量 `$LANG`
3. 默认使用英文

## 核心功能

### 流式输出

默认启用流式输出，实时显示回答内容，提升响应感知：

```bash
ask "解释量子计算原理"  # 实时显示，无需等待完整响应
ask "详细说明" --no-stream  # 禁用流式，一次性显示完整结果
```

### 上下文感知

自动注入当前环境信息，让回答更贴合实际场景：

- 当前工作目录
- 操作系统和 Python 版本
- 重要环境变量（PATH, HOME, USER, SHELL, LANG 等）

无需手动配置，系统自动识别并添加到上下文中。

### 文件内容分析

直接分析代码文件、配置文件等，支持多种文件格式：

```bash
# 分析代码文件
ask -f main.py "解释这个文件的功能"
ask "优化这段代码的性能" -f utils.py
ask -f app.js "找出潜在的 bug"

# 分析配置文件
ask -f config.yaml "检查配置是否正确"
ask -f docker-compose.yml "解释服务配置"
ask -f package.json "分析依赖关系"

# 分析日志文件
ask -f access.log "分析访问模式"
ask -f error.log "找出常见错误"
```

文件内容会自动添加到问题上下文中，LLM 可以基于实际代码进行分析。

### 错误日志分析

从标准输入读取错误信息进行分析，非常适合调试场景：

```bash
# 分析错误日志文件
cat error.log | ask "分析这个错误" --stdin
tail -n 100 app.log | ask "找出问题原因" --stdin

# 分析命令输出
python script.py 2>&1 | ask "解释这个错误" --stdin
npm run build 2>&1 | ask "分析构建失败原因" --stdin

# 分析系统日志
journalctl -u myapp -n 50 | ask "分析服务问题" --stdin
dmesg | tail -n 20 | ask "解释这些内核消息" --stdin

# 分析测试输出
pytest -v 2>&1 | ask "分析测试失败原因" --stdin
```

结合上下文感知功能，LLM 可以基于当前环境信息提供更准确的诊断。

## 记忆系统

角色支持三层分层记忆，自动管理对话历史：

| 层级 | 说明 | 策略 |
|------|------|------|
| 短期 | 最近完整对话 | 保留 10 轮 |
| 中期 | 早期对话摘要 | LLM 压缩生成 |
| 长期 | 整体精炼总结 | 多摘要合并 |

## MCP 工具支持

MCP（Model Context Protocol）让 LLM 能够调用外部工具。

> ⚠️ **注意**: 工具模式需要启动外部进程，响应速度较慢，建议仅在需要时使用 `-t` 参数。

### 默认配置

首次运行自动创建 `~/.config/ask/mcp.json`，会自动检测系统中的 `uvx` 或 `pipx` 命令：

```json
{
  "mcpServers": {
    "time": {
      "command": "uvx",
      "args": ["mcp-server-time"]
    },
    "shell": {
      "command": "uvx",
      "args": ["mcp-shell-server"],
      "env": {
        "ALLOW_COMMANDS": "ls,cat,head,tail,find,grep,wc,pwd,echo,mkdir,cp,mv,touch,date,whoami,hostname,ps,du"
      }
    }
  },
  "enabled": ["time"]
}
```

- `time`: 查询时间（默认启用）
- `shell`: 执行系统命令（通过 `ALLOW_COMMANDS` 限制可用命令，默认不启用）
- 自动检测：优先使用 `uvx`，不存在则使用 `pipx`

> ⚠️ **注意**: `shell` 服务器由于执行准确性问题，默认不启用。如需使用，请通过 `--mcp shell` 手动指定，或编辑配置文件在 `enabled` 中添加 `"shell"`。

### 添加更多服务器

```json
{
  "mcpServers": {
    "time": { "command": "uvx", "args": ["mcp-server-time"] },
    "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] },
    "fetch": { "command": "uvx", "args": ["mcp-server-fetch"] }
  },
  "enabled": ["time", "filesystem"]
}
```

> MCP 工具通过 `uvx` 或 `npx` 动态调用，需安装 [uv](https://docs.astral.sh/uv/) 或 Node.js。

### 使用工具

```bash
ask mcp list              # 查看服务器
ask mcp tools shell       # 查看 shell 工具详情
ask -t "现在几点？"        # 使用默认启用的工具（time）
ask -t "列出 /tmp 目录文件"          # 需要手动启用 shell 服务器
ask --mcp shell "列出当前目录文件"  # 手动指定使用 shell 服务器
```

> ⚠️ **注意**: `shell` 服务器由于执行准确性问题，默认不启用。如需使用，请通过 `--mcp shell` 手动指定，或编辑配置文件启用。

### 角色级 MCP

```yaml
# ~/.config/ask/roles.yaml
shell:
  system_prompt: "你是一个系统管理员助手。当用户询问系统相关问题（如文件操作、进程管理、系统信息查询等）时，优先使用 shell 命令解决，而不是使用其他编程语言代码实现。"
  mcp: ["shell"]  # 启用 shell 服务器以执行命令
```

## 支持的模型

任何 OpenAI 兼容接口：OpenAI、Azure OpenAI、DeepSeek、智谱 GLM、Ollama、vLLM、LM Studio 等。

## 开发

```bash
# 克隆并安装
git clone https://github.com/tiancheng91/ask.py
cd ask.py
uv sync

# 运行
uv run ask "问题"

# 测试
uv run pytest test_ask.py -v

# 构建发布
uv build
uv publish
```

### 从源码安装

```bash
pipx install git+https://github.com/tiancheng91/ask.py
# 或
uv tool install git+https://github.com/tiancheng91/ask.py
# 或从 PyPI 安装
pipx install ask-py-cli
```

## License

MIT
