一、引言

在人工智能时代,智能助手已经成为我们日常生活和工作中的重要工具。今天,我将为大家解析一个名为 EVA 的智能助手项目,这是一个基于 LLM(大语言模型)的自主代理系统,具有执行命令、管理会话、进化学习等强大功能。

EVA 不仅是一个实用的工具,更是学习 Python 高级编程、LLM 集成和系统设计的优秀案例。通过深入分析其代码结构和实现原理,我们可以了解如何构建一个功能完整的 AI 代理系统。

二、项目概览

EVA 是一个用 Python 编写的智能助手,主要特点包括:

  • 基于 LLM:集成 DeepSeek 等思考型模型
  • 跨平台支持:兼容 Windows 和 Linux 系统
  • 自主代理:能够执行系统命令、管理文件
  • 会话管理:自动保存和加载会话状态
  • 记忆管理:智能记忆压缩和线索保存
  • 进化能力:能够保存知识和技能,持续改进

三、核心模块解析

3.1 导入模块

EVA 使用了多个 Python 核心模块和第三方库,构建了完整的功能体系:

1
2
3
4
5
6
7
8
9
10
import os
import re
import json
import subprocess
import sys
import requests
import traceback
import argparse
import platform
from pathlib import Path

这些模块各自负责不同的功能:

  • os:操作系统接口,处理环境变量和文件操作
  • re:正则表达式,用于文本处理
  • json:JSON 数据处理,用于会话保存和 API 交互
  • subprocess:执行系统命令
  • requests:HTTP 请求,调用 LLM API
  • argparse:命令行参数解析
  • platform:平台信息获取,实现跨平台兼容
  • Path:路径操作,提供更便捷的文件路径处理

3.2 LLM 配置与模型检测

EVA 通过环境变量配置 LLM 参数,并提供了模型长度检测功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# LLM配置区
EVA_BASE_URL = os.environ.get("EVA_BASE_URL", "https://api.deepseek.com/v1")
EVA_MODEL_NAME = os.environ.get("EVA_MODEL_NAME", "deepseek-reasoner")
EVA_API_KEY = os.environ.get("EVA_API_KEY", "sk-这里填你的deepseek API key")

def detect_model_len():
url = f"{EVA_BASE_URL}/models"
headers = {"Authorization": f"Bearer {EVA_API_KEY}"}
try:
resp = requests.get(url, headers=headers, timeout=10)
except UnicodeEncodeError:
print(f"错误:EVA_API_KEY ({EVA_API_KEY}) 包含非法字符,请检查 EVA_API_KEY 配置。")
sys.exit(1)
# ... 后续代码

这个设计非常巧妙,它:

  1. 通过环境变量提供配置灵活性
  2. 自动检测模型的最大上下文长度
  3. 提供详细的错误处理和用户提示

3.3 跨平台兼容性设计

EVA 实现了良好的跨平台支持,通过条件判断适配不同操作系统:

1
2
3
4
5
6
# 跨平台配置区
IS_WINDOWS = platform.system() == "Windows"
OS_NAME = "Windows" if IS_WINDOWS else "Linux"
SHELL = "powershell.exe" if IS_WINDOWS else "bash"
SHELL_FLAG = "-Command" if IS_WINDOWS else "-c"
ENCODING = "utf-8"

这种设计确保了 EVA 在不同系统上都能正常工作,为用户提供一致的体验。

3.4 环境探针

EVA 会自动收集环境信息,为 LLM 提供上下文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def collect_env_info():
cmds = {
"Linux": [
"uname -a",
"for t in python3 python node npm git docker curl wget; do command -v $t >/dev/null 2>&1 && echo \"$t: $(${t} --version 2>&1 | head -1)\" || echo \"$t: 未安装\"; done",
"ls -1A | grep -v '^\\.$' | grep -v '^\\..$' | while IFS= read -r f; do if [ -d \"$f\" ]; then echo \"[目录] $f\"; else echo \"[文件] $f\"; fi; done",
],
"Windows": [
"[System.Environment]::OSVersion.VersionString",
"foreach ($t in @('python','node','git','docker','curl.exe')) { $cmd = Get-Command $t -ErrorAction SilentlyContinue; if ($cmd) { $v = & $t --version 2>&1 | Select-Object -First 1; $name = $t -replace '\\.exe$',''; Write-Output \"$name`: $v\" } else { $name = $t -replace '\\.exe$',''; Write-Output \"$name`: 未安装\" } }",
"Get-ChildItem -Force | Where-Object { $_.Name -ne '.' -and $_.Name -ne '..' } | ForEach-Object { if ($_.PSIsContainer) { Write-Output \"[目录] $($_.Name)\" } else { Write-Output \"[文件] $($_.Name)\" } }",
]
}
# ... 后续代码

环境探针功能让 EVA 能够了解当前系统状态,为任务执行提供更准确的上下文信息。

3.5 工具系统

EVA 实现了一个灵活的工具系统,主要包括两个核心工具:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
run_cli_schema = {
"type": "function",
"function": {
"name": "run_cli",
"description": (
f"执行任意 {SHELL} 命令。你可以读取、写入、执行任意内容,其中command是你要执行的命令,timeout是命令的超时时间。"
),
"parameters": {
"type": "object",
"properties": {
"command": {"type": "string"},
"timeout": {"type": "integer", "default": 30}
},
"required": ["command"]
}
}
}

memory_hints_schema = {
"type": "function",
"function": {
"name": "leave_memory_hints",
"description": (
"留下记忆文件的相关线索"
),
"parameters": {
"type": "object",
"properties": {
"hints": {"type": "string"},
},
"required": ["hints"]
}
}
}

工具系统的设计遵循了 OpenAI 的函数调用规范,使得 LLM 能够通过结构化的方式调用这些工具。

3.6 LLM 调用机制

EVA 实现了两种 LLM 调用方式:非流式和流式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def llm_chat(messages, tools=None, temperature=0.6, thinking=True):
"""非流式调用(用于安全审查等短请求)"""
url = f"{EVA_BASE_URL}/chat/completions"
headers = {"Authorization": f"Bearer {EVA_API_KEY}"}
data = _build_request_data(messages, tools, temperature, thinking, stream=False)

resp = requests.post(url, json=data, headers=headers)
try:
out = resp.json()
except Exception as e:
raise Exception(f"{e}, resp: {resp}")

try:
return out["choices"][0]["message"], out['usage']
except Exception as e:
raise Exception(f"LLM调用失败,错误信息:{e}, {out}")

流式调用则提供了实时的输出体验,增强了用户交互:

1
2
3
def llm_chat_stream(messages, tools=None, temperature=0.6, thinking=True):
"""流式调用,逐 token 打印,返回与非流式相同格式的 (message, usage)"""
# ... 实现代码

3.7 会话管理

EVA 实现了基于工作目录的会话管理,确保不同目录的会话相互隔离:

1
2
3
4
5
6
7
8
9
10
11
12
def get_session_file():
current_dir = os.getcwd()
dir_hash = re.sub(r"[\\/:]", "_", current_dir)
session_dir = f"{WORKSPACE_DIR}/sessions"
os.makedirs(session_dir, exist_ok=True)
return f"{session_dir}/{dir_hash}.json"

def save_session(messages):
session_file = get_session_file()
with open(session_file, "w", encoding="utf-8") as f:
json.dump(messages, f, ensure_ascii=False, indent=2)
print(f"\n> 会话已保存到:{session_file}")

这种设计使得用户在不同目录下使用 EVA 时,能够保持独立的会话状态,提高了使用体验。

3.8 Agent 循环

Agent 循环是 EVA 的核心运行机制,处理 LLM 交互和工具调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def agent_single_loop():
global COMPACT_PANIC
break_loop = False
while not break_loop:
try:
sys.stdout.write("\n[*] EVA: ")
sys.stdout.flush()
if COMPACT_PANIC == "on":
msg, usage = llm_chat_stream(messages, tools=[run_cli_schema, memory_hints_schema])
else:
msg, usage = llm_chat_stream(messages, tools=[run_cli_schema])
messages.append(msg)

# 处理工具调用
if not 'tool_calls' in msg or not msg['tool_calls']:
break

for tc in msg['tool_calls']:
# 执行工具调用...

Agent 循环实现了 EVA 的自主决策和执行能力,是整个系统的核心。

四、核心功能详解

4.1 命令执行与安全审查

EVA 能够执行系统命令,但同时实现了安全审查机制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def run_cli(command: str, timeout: int = 30):
global ALLOW_ALL_CLI
try:
if not ALLOW_ALL_CLI:
msg, _ = llm_chat([{"role": "user", "content": CLI_REVIEW_PROMPT.format(command=command)}], temperature=0.0, thinking=False)
if '放行' not in msg['content']:
ans = read_input("Yes (默认) | No | 直接 Ctrl+C 打断:")
if 'n' in ans.lower():
return "用户拒绝运行此命令"

result = subprocess.run(
[SHELL, SHELL_FLAG, command],
capture_output=True,
text=True,
errors='replace',
cwd=os.getcwd(),
timeout=timeout,
shell=False
)
# ... 后续代码

安全审查机制确保了 EVA 不会执行危险命令,保护系统安全。

4.2 记忆管理与压缩

EVA 实现了智能的记忆管理系统,当记忆容量达到阈值时,会触发记忆压缩:

1
2
3
4
5
6
7
if COMPACT_PANIC == 'off' and usage['total_tokens'] >= TOKEN_CAP * COMPACT_THRESH:
print (f"!!!紧急回合,触发记忆压缩")
COMPACT_PANIC = "on"
messages.append({
"role": "user",
"content": COMPACT_PROMPT
})

记忆压缩过程包括:

  1. 保存记忆到文件
  2. 提炼和保存技能/知识
  3. 留下记忆线索

4.3 进化机制

EVA 具有进化能力,能够保存和传承知识与技能:

1
2
3
4
5
6
7
8
9
def leave_memory_hints(hints):
global messages
global COMPACT_PANIC

# 处理记忆线索...

with open(HINT_FILE, "w", encoding="utf-8") as f:
f.write(hints)
return "已留下记忆线索,并清空了对话记录。只保留了最后一次对话"

这种设计使得 EVA 能够从经验中学习,不断改进自己的能力。

五、技术亮点

  1. 模块化设计:代码结构清晰,功能分离明确
  2. 跨平台兼容性:通过条件判断适配不同操作系统
  3. 安全机制:命令执行前的安全审查
  4. 流式输出:实时的 LLM 响应输出
  5. 会话隔离:基于工作目录的独立会话
  6. 记忆管理:智能的记忆压缩和线索保存
  7. 错误处理:全面的异常捕获和处理
  8. 灵活配置:通过环境变量和命令行参数提供配置灵活性

六、使用方法

6.1 配置环境变量

1
2
3
4
5
6
7
8
9
# Linux
export EVA_BASE_URL="https://api.deepseek.com/v1"
export EVA_MODEL_NAME="deepseek-reasoner"
export EVA_API_KEY="sk-你的API密钥"

# Windows PowerShell
$env:EVA_BASE_URL = "https://api.deepseek.com/v1"
$env:EVA_MODEL_NAME = "deepseek-reasoner"
$env:EVA_API_KEY = "sk-你的API密钥"

6.2 命令行参数

  • -a, --allow-all: 允许所有命令无需用户确认
  • -l, --list-session: 列出所有会话
  • -c, --clear-session: 清除当前目录会话
  • -u, --user-ask: 执行单条用户指令

6.3 启动 EVA

1
2
3
4
5
6
7
8
# 直接启动
python eva.py

# 允许所有命令
python eva.py -a

# 执行单条指令
python eva.py -u "列出当前目录文件"

七、代码优化建议

  1. 错误处理增强

    • 增加更详细的错误日志
    • 实现重试机制,提高 API 调用可靠性
  2. 性能优化

    • 缓存模型信息,减少 API 调用
    • 优化记忆压缩算法,减少计算开销
  3. 功能扩展

    • 添加更多工具,如文件编辑、网络请求等
    • 实现插件系统,支持功能扩展
  4. 用户体验

    • 增加命令历史记录
    • 实现命令自动补全
    • 添加更友好的交互界面
  5. 安全性

    • 增强命令安全审查机制
    • 添加敏感信息保护

八、总结

EVA 是一个设计精良、功能完整的智能助手系统,它展示了如何构建一个基于 LLM 的自主代理。通过深入分析其代码结构和实现原理,我们可以学习到:

  • 如何集成和调用 LLM API
  • 如何实现跨平台兼容的系统
  • 如何设计和实现工具系统
  • 如何管理会话和记忆
  • 如何构建具有进化能力的 AI 系统

EVA 的设计思路和实现方法不仅适用于智能助手领域,也可以应用于其他需要 LLM 集成的项目中。它是一个值得学习和借鉴的优秀案例。

随着 AI 技术的不断发展,类似 EVA 这样的智能助手将会在更多领域发挥重要作用。通过持续改进和扩展,EVA 有潜力成为一个功能强大、智能高效的 AI 助手,为用户提供更好的服务。