用 Python 调用大模型 API:写一个命令行 AI 助手

站长 2026-09-29 0 约 2 分钟 514 字
#Python#DeepSeek#AI#命令行工具#项目实战

我们要做什么

把前面几篇笔记学到的知识串起来,做一个真正能用的东西:

$ python ai_chat.py
🤖 AI 助手已启动(输入 /quit 退出,/clear 清空记忆)

你 > 用一句话介绍 Python
AI > Python 是一种简洁易读、生态丰富的通用编程语言。

你 > 它适合做什么
AI > (记得上文)Python 特别适合数据分析、AI 开发、自动化脚本……

功能清单:

  • 流式输出(打字机效果)
  • 多轮对话记忆
  • /quit、/clear、/save 斜杠命令
  • 配置文件管理 API Key
  • 打包成 exe 双击即用

第 1 步:基础对话循环

# ai_chat.py
import os
import sys

from openai import OpenAI

# 从环境变量读 key,不要硬编码
client = OpenAI(
    api_key=os.environ.get("DEEPSEEK_API_KEY", "sk-在这里填你的key"),
    base_url="https://api.deepseek.com",
)
MODEL = "deepseek-chat"

# 对话历史:system 人设 + 历轮问答
history = [
    {"role": "system", "content": "你是简洁专业的 AI 助手,回答控制在 300 字以内"}
]

def chat(user_input: str) -> None:
    """发送消息并流式打印回复"""
    history.append({"role": "user", "content": user_input})
    stream = client.chat.completions.create(
        model=MODEL, messages=history, stream=True
    )
    print("AI > ", end="", flush=True)
    full_reply = ""
    for chunk in stream:
        delta = chunk.choices[0].delta.content
        if delta:
            print(delta, end="", flush=True)  # 逐块打印 = 打字机效果
            full_reply += delta
    print()
    # 关键:把 AI 的回复存回历史,实现记忆
    history.append({"role": "assistant", "content": full_reply})

def main() -> None:
    print("🤖 AI 助手已启动(/quit 退出,/clear 清空记忆)\n")
    while True:
        try:
            user_input = input("你 > ").strip()
        except (KeyboardInterrupt, EOFError):  # Ctrl+C / Ctrl+D 优雅退出
            print("\n再见!")
            break
        if not user_input:
            continue
        if user_input == "/quit":
            print("再见!")
            break
        if user_input == "/clear":
            history[:] = history[:1]  # 只保留 system 人设
            print("(记忆已清空)\n")
            continue
        try:
            chat(user_input)
        except Exception as e:
            print(f"出错了:{e}\n")  # 网络错误不退出,下次还能用
        print()

if __name__ == "__main__":
    main()

到这里已经是一个能用的 AI 助手了:流式输出、有记忆、能清空、出错不崩。

第 2 步:控制记忆长度

对话历史无限增长会撞上两个天花板:模型的上下文窗口、以及你的余额(历史每轮都重新计费)。加一个滑动窗口:

MAX_HISTORY = 20  # 最多保留最近 20 条消息

def trim_history() -> None:
    """保留 system + 最近的对话,超出的最旧记录删掉"""
    if len(history) > MAX_HISTORY + 1:
        del history[1 : len(history) - MAX_HISTORY]

在 chat() 开头调用一次 trim_history() 即可。更精细的方案是按 token 数裁剪,但按条数对日常使用已足够。

第 3 步:保存对话记录

/save 命令把当前会话存成 Markdown 文件:

from datetime import datetime

def save_history() -> str:
    """导出对话到 Markdown 文件,返回文件名"""
    lines = [f"# AI 对话记录 {datetime.now():%Y-%m-%d %H:%M}\n"]
    for msg in history[1:]:  # 跳过 system
        role = "**你**" if msg["role"] == "user" else "**AI**"
        lines.append(f"{role}:{msg['content']}\n")
    filename = f"chat_{datetime.now():%Y%m%d_%H%M%S}.md"
    with open(filename, "w", encoding="utf-8") as f:
        f.write("\n".join(lines))
    return filename

在主循环里加分支:

        if user_input == "/save":
            print(f"(已保存到 {save_history()})\n")
            continue

第 4 步:配置文件管理 Key

Key 写死在代码里既危险又不方便分享,改用配置文件:

# config.py
import json
from pathlib import Path

CONFIG_PATH = Path.home() / ".ai_chat_config.json"

def load_config() -> dict:
    """读取配置,没有则引导用户创建"""
    if not CONFIG_PATH.exists():
        key = input("首次使用,请输入你的 API Key:").strip()
        CONFIG_PATH.write_text(
            json.dumps({"api_key": key, "model": "deepseek-chat"}, ensure_ascii=False, indent=2),
            encoding="utf-8",
        )
        print(f"配置已保存到 {CONFIG_PATH}\n")
    return json.loads(CONFIG_PATH.read_text(encoding="utf-8"))

主程序里:

config = load_config()
client = OpenAI(api_key=config["api_key"], base_url="https://api.deepseek.com")
MODEL = config["model"]

配置文件放在用户主目录,既不用每次输入,也不会误提交进 Git。

第 5 步:打包成 exe

让没有 Python 环境的朋友也能用:

pip install pyinstaller
pyinstaller --onefile --name ai-chat ai_chat.py

产物在 dist/ai-chat.exe,双击即用,体积约 15MB(含 Python 运行时)。

几个实用参数:

pyinstaller --onefile --name ai-chat --clean ai_chat.py
# --onefile  打成单个 exe
# --clean    清掉上次构建缓存,改代码后重新打包建议加上

完整效果与扩展方向

最终成品是一个 100 行左右的单文件工具。跑通之后,可以按需扩展:

加「温度」调节:/temp 0.3 命令动态调整创造性参数。

加预设角色:/role 翻译 切换 system 人设,一个工具当多个助手用。

统计用量:从响应里取 usage 字段,显示本次消耗了多少 token、约合多少钱:

# 非流式响应可直接读 usage;流式需设置 stream_options={"include_usage": True}
stream = client.chat.completions.create(
    model=MODEL, messages=history, stream=True,
    stream_options={"include_usage": True},
)
# 最后一个 chunk 里有 usage 信息

接入本地模型:把 base_url 换成 http://localhost:11434/v1(Ollama),这个工具就变成了离线版 AI 助手——代码一行都不用改,这就是 OpenAI 兼容接口的妙处。

回顾:这个项目用到了什么

知识点 出处
虚拟环境管理依赖 笔记 1
第三方库调用网络 API 笔记 2
异常处理与优雅退出 笔记 6
配置文件与文件读写 笔记 6/7
字符串处理 笔记 9

这就是我们 Python 专题的初衷:学语法的最好方式是做东西。这个命令行助手可能就是你以后每天用 AI 的方式之一——自己动手做的工具,用起来总是格外顺手。

评论 (0)

我的头像

还没有评论,快来抢沙发吧~