新闻详情

新闻详情

首页 / 资讯中心 / 详情

前端转AI实战:用Python打造命令行AI助手v1的完整指南

发布时间:2026/10/2 16:00:52来源:尧图网络
前端转AI实战:用Python打造命令行AI助手v1的完整指南
前端转 AI 的进度条走到第 13 天我给自己布置了一个稍微硬核的任务把前 12 天学到的所有零散技能整合成一个真正能用的命令行 AI 助手 v1。你可能会觉得奇怪前端转 AI 不是应该先学 PyTorch、学 Transformer 吗怎么跑到命令行工具上来了我有我的理由。前 12 天我学了 Python 基础语法、HTTP 请求、JSON 处理、环境变量管理、函数封装、异常处理甚至还有一点正则表达式……单独拿出来每一项都不难但课程式学习有个致命的错觉你会调 API 不等于你能做出一个产品。中间缺的恰恰是一个把所有知识点串成一条完整链路的综合项目。命令行 AI 助手就是这个项目。为什么选它因为它足够小小到一天能做出来又足够完整完整到能覆盖一个产品级工具该有的所有环节——配置管理、上下文组装、外部 API 调用、流式解析、数据持久化、异常处理。做完它你写的代码就不再是练习作业而是一个你自己每天都在用的工具。这篇文章送给正在从前端转 AI 的朋友或者任何想搞懂一个命令行 AI 工具到底是怎么从零长出来的人。我会把 Day 13 的完整思路、代码、踩坑全部摊开来讲尤其是那些前端思维在 Python 世界里撞墙的瞬间我会单独开一章细说。1. 为什么我把第 13 天押在命令行助手上1.1 前 12 天到底学了什么让我先列一下前 12 天的学习清单不是为了凑篇幅而是为了让你看清楚综合项目到底在整合什么Day 1-3Python 基础语法。变量、类型、循环、函数、列表和字典。前端同学上手 Python 其实很快因为很多概念和 JavaScript 是相通的但也有一些地方会拧巴比如缩进代替花括号、没有 var/let 的声明体系。Day 4-5文件读写与 JSON。json.loads / json.dumps 来回折腾一开始我总觉得 Python 的 JSON 处理和 JSON.stringify 不太一样其实只是换了个名字。Day 6-7HTTP 请求与 API 调用。用 requests 库打各种公开接口GET、POST、Header 拼接、参数传递。Day 8-9环境变量与配置管理。用 python-dotenv 加载 .env 文件理解为什么要用环境变量而不是把密钥硬编码进代码。Day 10-11异常处理与日志。try/except、traceback 打印、把错误信息合理地呈现给用户。Day 12OpenAI 兼容接口的请求格式。搞懂了 messages 数组的结构system、user、assistant 三种角色以及 temperature、max_tokens 这些参数的含义。列完这份清单我自己都吓了一跳这些东西单独看每一个都像一个API 拼图碎片但拼起来就是一个完整的可运行程序。Day 13 的任务就是把碎片拼成机器。我见过太多前端转 AI 的朋友学着学着就停在会用 requests 调接口这一步。他们会写一个 demo打印出模型返回的 JSON然后觉得自己已经入门了。但实际上一个真实产品要处理的问题远比 demo 多密钥放哪里上下文怎么管理如果返回很长用户怎么等昨天聊到一半今天怎么继续聊这些事只有做一个完整项目才会逼你去想。1.2 命令行助手为什么是最合适的第一个综合项目选择命令行而不是做一个 Web 页面其实是一个刻意的决定。前端同学的第一反应往往是做一个聊天网页比较亲切——毕竟我们有 React、有组件、有 CSS。但恰恰因为前端是我们的舒适区才应该反向操作把精力全部砸在AI 工具本身的核心逻辑上而不是 UI 上。命令行有四个优势交互模型最简单。终端里只有一个循环读输入、调 API、打输出。没有路由、没有状态管理、没有组件生命周期。AI 的天然载体。ChatGPT 这类产品的原生形态就是对话而终端天然适合这种密集的文本交互。CLI 工具甚至比 Web 页面更接近工具的本质。便于扩展成 Agent。后续想加工具调用、文件读取、自动执行命令在终端环境下都顺理成章。很多真实的 AI 编程助手最早都是从 CLI 长出来的。逻辑大于样式。这个项目的难点全在数据流和边界条件上正是在这些地方前端思维和 Python 工程思维才会发生碰撞才有最大的学习价值。1.3 Day 13 的项目边界做减法比做加法更难一个综合项目最容易犯的错就是想一口气把所有东西都塞进去。我第一天动工时列了一个很长的待办清单多模型切换、函数调用、RAG 知识库、语音输入……然后我一件一件把它们划掉了。v1 只做四件事支持通过 OpenAI 兼容接口调用任意大模型换模型只改配置多轮对话能在聊天过程中记住历史流式输出让回复逐字打印出来而不是一次性砸到屏幕上本地持久化退出后下次还能接着聊这四件事分别对应当前技术栈里最核心的四块能力HTTP 请求与 API 格式、上下文组装、数据流解析、文件读写。至于多模型切换、命令系统/clear 之类的、工具调用我全部留到 v2。原因很简单v1 的设计目标是把前 12 天串起来不是做一个惊艳的产品。项目越克制完成度才越高。2. 开工前先画图纸模块划分、数据流与选型2.1 一条流水线数据是怎么流动的我虽然是个前端出身的人但设计这个项目时没有一上来就写代码而是先画了数据流图在纸上画的没上工具。整个项目本质上是一条单向流水线用户在终端输入一段文本 - 程序把这段文本和自己的配置合并成 messages 数组 - 带着 API Key 请求模型接口 - 接口以 SSE 流式返回文本片段 - 程序逐段接收并渲染到终端 - 渲染完毕把整段回复追加进历史 JSON 文件 - 回到等待输入状态这条流水线最妙的地方在于每一步对应一个独立模块模块之间只通过函数参数和返回值传数据不共享任何全局状态。这样的话哪怕某天你想把终端界面换成 Web UI只需要替换入口和渲染两部分API 调用和上下文管理完全不用动。2.2 为什么用 Python 而不是继续用 Node.js我知道你肯定想问你都是前端了为什么不用 Node.js 写这个工具用 TypeScript 不香吗用 Node 当然可以实现同样的功能甚至在前端手里可能写得更顺手。但我做这个项目的意图不是写一个只给自己用的脚本而是以这个项目为跳板彻底熟悉 AI 工程方向的 Python 生态。原因有三个AI 生态的主要接口和示例代码都优先 Python。不管是 HuggingFace、LangChain、LlamaIndex还是各种推理框架的官方示例Python 含量远高于 Node.js。想深入 AI 行业Python 是绕不开的。Python 的文本处理和文件操作非常直接写这种工具类项目心智负担小。前端转 AI 的典型路径是前端 - Python - 机器学习命令行助手作为 Python 的实战练手正好完成第一步的跨越。不过如果你想用 Node.js 复刻这个项目也没问题——requests 对应 fetch/axiosdotenv 对应 dotenv 包JSON 文件操作用 fs 模块SSE 解析用 fetch 的 ReadableStream。技术上完全等价只是语言环境的差异。2.3 目录结构与配置体系项目我放在 ~/ai-assistant也可以叫 aicli随你喜欢最终目录长这样ai-assistant/ ├── main.py # 入口交互循环 ├── config.py # 配置加载 ├── api_client.py # API 请求与流式解析 ├── history.py # 对话历史读写与截断 ├── requirements.txt └── .env # 密钥与模型参数不进 git只有四个源文件每个文件不超过 150 行。为什么这么小因为我刻意控制每个模块的职责单一config.py 只干配置的事api_client.py 只干网络的事history.py 只干持久化的事main.py 只干交互的事。这样即使代码量不大结构也是清晰的、可扩展的。requirements.txt 里只有三个依赖openai1.0.0 python-dotenv1.0.0 rich13.0.0等一下为什么用 openai 库而不是直接 requests这个问题我后面会在流式输出那一节细说先记住结论openai 官方 SDK 已经封装好了 SSE 解析和重试逻辑比手写 requests 流式解析要省事得多。rich 库是用来在终端里做彩色输出的属于锦上添花不用也行但用了之后体验会好很多。.env 配置文件长这样OPENAI_API_KEYsk-xxxx BASE_URLhttps://your-api-endpoint MODEL_NAMEgpt-4o-mini TEMPERATURE0.7 MAX_TOKENS2048 HISTORY_FILE.ai_history.json注意 BASE_URL 这一项。现在很多模型服务都提供 OpenAI 兼容接口只要你把 BASE_URL 换成对应的地址、把 MODEL_NAME 换成对应的模型名代码完全不用改。这也是我把 API 调用封装在 api_client.py 里的原因——换模型不换逻辑。3. 第一块拼图配置管理与上下文组装3.1 用 python-dotenv 把密钥从代码里剥离前端开发里我们会用环境变量存 API Key原理大家都知道但很多人到了 Python 里反而疏忽了——直接把 Key 写在代码里然后到处 git push。第 8 天的内容正好解决这个问题。config.py 的完整实现import os from dotenv import load_dotenv load_dotenv() OPENAI_API_KEY os.getenv(OPENAI_API_KEY) BASE_URL os.getenv(BASE_URL, https://api.openai.com/v1) MODEL_NAME os.getenv(MODEL_NAME, gpt-4o-mini) TEMPERATURE float(os.getenv(TEMPERATURE, 0.7)) MAX_TOKENS int(os.getenv(MAX_TOKENS, 2048)) HISTORY_FILE os.getenv(HISTORY_FILE, .ai_history.json)load_dotenv() 会自动读取项目根目录下的 .env 文件把里面的键值对塞进 os.environ。之后用 os.getenv(key, default) 取值第二个参数是默认值这样即使某个人 clone 后忘了配置 .env程序也不会直接崩掉只是部分参数会用默认值。这里有一个我在前端里特别熟悉的默认值习惯的对标JS 里是 const key process.env.KEY ?? defaultPython 里是 os.getenv(KEY, default)本质一样只是写法不同。但 Python 的 float() 和 int() 转换要特别注意如果 .env 里 TEMPERATURE 写成了非数字程序会在启动时立刻抛 ValueError这个行为其实是好事它把错误暴露在启动阶段而不是运行到一半省得用户聊了十分钟才突然崩掉。3.2 对话历史存哪里JSON 文件方案的取舍v1 的对话历史方案非常简单把 messages 数组直接序列化成 JSON写入本地文件。history.py 的核心逻辑就三个函数import json from pathlib import Path def load_history(file_path): path Path(file_path) if not path.exists(): return [] with open(path, r, encodingutf-8) as f: return json.load(f) def save_history(file_path, history): with open(file_path, w, encodingutf-8) as f: json.dump(history, f, ensure_asciiFalse, indent2) def append_message(file_path, role, content): history load_history(file_path) history.append({role: role, content: content}) save_history(file_path, history)前端同学看到这里应该很亲切这不就是 localStorage 的 JSON 版本吗区别在于localStorage 是浏览器替你管理文件这里你需要自己处理文件存在与否、编码、缩进等问题。json.dump 里的 ensure_asciiFalse 参数必须写否则下次存入的中文会被转成 \uXXXX 的转义序列虽然也能读回来但直接打开文件时你会怀疑人生。为什么 v1 不用 SQLite 或者向量数据库因为还没到那个复杂度。一天的项目JSON 文件完全可以支撑几百轮对话。等到对话数量级变大、需要按时间检索的时候再迁移到 SQLite 不迟。做综合项目最忌讳引入一个当前问题用不到的技术那叫炫技不叫工程。3.3 token 上限与截断策略前端数组思维在这里不成立这是 Day 13 里让我最受震撼的地方值得单独拿出来讲。前端处理最多显示 10 条记录你大概率会写const recent list.slice(-10);这没毛病因为每条记录的大小差不多按条数截断是合理的。但对话上下文不一样每条消息的 token 数量可能差异巨大用户抛进来一篇 5000 字的文章和用户发一句你好占的 token 完全不是一个量级。如果按条数截断很容易出现最近 10 条消息加起来超过模型上下文窗口的情况API 直接报错。正确的截断姿势是按 token 估算来截。v1 里我引入了一个非常简单的估算规则中文大约 1 个 token 对应 0.6 到 1 个汉字各家模型略有差异英文大约 4 个字符对应 1 个 token。我用了一个保守系数来估算每条消息的 token 数然后从最旧到最新依次丢弃消息直到总 token 数小于一个安全阈值MAX_CONTEXT_TOKENS 6000 def estimate_tokens(text): # 粗略估算中文按 1 字符 0.7 token英文按 4 字符 1 token chinese_chars sum(1 for c in text if \u4e00 c \u9fff) other_chars len(text) - chinese_chars return int(chinese_chars * 0.7 other_chars * 0.25) 10 def trim_history(history, max_tokensMAX_CONTEXT_TOKENS): if not history: return history system_msg None if history[0][role] system: system_msg history[0] history history[1:] while history and sum(estimate_tokens(m[content]) for m in history) max_tokens: history.pop(0) # 丢掉最早的一条 if system_msg: history.insert(0, system_msg) return history这里的核心思想是越早的消息越可能被丢弃最新的对话内容永远完整保留。为什么因为聊天场景里模型回答所依赖的通常是最近的几轮而不是三天前的寒暄。这也是一种工程取舍和前端做虚拟列表只渲染可视区域是同一个道理——资源有限优化关键部分而不是平均用力。4. 第二块拼图流式输出与终端交互体验4.1 为什么必须做流式没有打字机效果的 CLI 是残废的如果模型生成 500 个 token 需要 10 秒而你的程序在这 10 秒里什么都不显示用户会怎么想大概率会觉得程序卡死了直接 CtrlC 走人。前端开发里我们太熟悉这种体验了一个按钮点击后如果没有任何 loading 状态用户会反复点击。终端里虽然没有按钮但等待焦虑是一样的。流式输出Streaming解决的就是这个问题。模型一边生成程序一边把生成的内容打印到终端形成类似打字机的效果。用户能实时看到回复在长出来就知道程序活着而且能看到它正在往哪个方向生成。从技术上讲流式的原理也很简单模型接口支持 SSEServer-Sent Events协议返回的数据不是一口气给完的而是切分成很多小块按顺序推送。客户端每收到一块就渲染一块。这个机制比 WebSocket 还简单——单向的服务器只管推客户端只管收。4.2 用 openai SDK 还是手写 requests我的选择我在 2.3 节埋了个问题为什么用 openai 库而不是直接 requests现在来回答。手写 requests 做 SSE 解析是可行的核心代码如下import requests import json def stream_chat_with_requests(messages): resp requests.post( f{BASE_URL}/chat/completions, headers{ Authorization: fBearer {OPENAI_API_KEY}, Content-Type: application/json }, json{ model: MODEL_NAME, messages: messages, stream: True }, streamTrue, timeout(10, 300) ) for line in resp.iter_lines(): if not line: continue line line.decode(utf-8) if line.startswith(data: ): data line[6:] if data [DONE]: break chunk json.loads(data) delta chunk[choices][0][delta].get(content) if delta: yield delta这段代码不长但有几个细节要小心iter_lines 需要 streamTrue空行要跳过SSE 的 data: 前缀要剥掉[DONE] 标记要单独处理每一行可能是一个完整的 JSON。对于 v1 项目手写完全可行而且能让你把 SSE 机制彻底吃透。但如果你只想快速把工具做出来更省事的方案是直接用 openai 库from openai import OpenAI client OpenAI(api_keyOPENAI_API_KEY, base_urlBASE_URL) def stream_chat(messages): stream client.chat.completions.create( modelMODEL_NAME, messagesmessages, streamTrue, temperatureTEMPERATURE, max_tokensMAX_TOKENS ) for chunk in stream: if chunk.choices[0].delta.content: yield chunk.choices[0].delta.content我最后选择了 openai 库不是因为它比手写更高端而是因为它帮我处理了网络重试、超时、连接复用这些底层问题让我能把精力集中在业务逻辑上。但请注意我建议你先手写一遍 requests 版本再换成 SDK。这个过程的价值在于你会真正理解流式返回的本质是 SSE将来即使换一个没有官方 SDK 的模型服务你也能自己造轮子。4.3 终端渲染的细节flush、换行与 CtrlC流式输出写起来容易但终端渲染有几个细节不处理就会显得很业余。第一个坑是缓冲。如果你用 print(delta, end) 而不带 flushTrue你会发现文本并不是逐字出现的而是等缓冲区满了或者程序结束才一次性刷出来。原因在于 Python 的 print 默认走缓冲。解决方案很简单for delta in stream_chat(messages): print(delta, end, flushTrue)flushTrue 强制每次 print 立即写入终端打字机效果就出来了。第二个坑是换行。模型输出的内容可能是很长的段落也可能包含代码块。如果所有内容都原样打印长段落会在终端里自动折行这是终端自己的行为不需要你处理。但如果你要自定义缩进比如每行前面加个前缀就要小心stream 出来的内容是按 token 切分的一个你好\n世界可能被切成你好和\n世界两段你如果在每一段前面都手动加前缀就会加乱掉。稳妥的做法是把流式文本累积到行缓冲区遇到 \n 再整行渲染或者干脆不做复杂装饰原样打印。第三个坑是 CtrlC。前端常用的 AbortController 在 Python 命令行里没有对应的内置机制当用户按 CtrlC 中断流式输出时程序会抛 KeyboardInterrupt。v1 的做法是捕获这个异常优雅地结束当前回合把已经生成的内容保存进历史然后回到输入状态try: for delta in stream_chat(messages): print(delta, end, flushTrue) except KeyboardInterrupt: print(\n[interrupted] 当前回答已停止。, flushTrue)这比直接让程序退出要合理得多符合命令行工具的使用预期。前端同学可以把它想成是 fetch 请求被用户取消后你在 catch 里做清理工作的 Python 版本。5. 前端思维转换实录五个坑每个都值得单独说这一节是 Day 13 最值钱的部分。作为一名前端开发我在写这个项目的过程中踩了至少五个坑每一个都是前端经验和Python 工程习惯正面冲突的结果。写下来给同样在转型路上的朋友一个预演。5.1 异步认知冲突Node 的 async/await 和 Python 的同步阻塞前端这两年被 async/await 洗脑洗得非常彻底看到网络请求就条件反射地想要 await。到了 Python 里如果你用 requests 库它是同步阻塞的你发一个请求程序就停在那里等响应不会有任何事件循环让你切出去干别的事。我一开始非常不习惯总觉得同步阻塞是一种落后的设计。但写完这个项目我才意识到对于命令行工具来说同步反而是最合理的模型——程序本来就在等用户输入等待网络响应和等待用户输入没什么本质区别一个线程从头跑到尾状态管理变得极其简单。如果你想在 Python 里用异步那是另一个世界aiohttp、asyncio、await 关键字都有但代码复杂度会上一个台阶。v1 完全没有必要。这个认知转变对我很重要不是所有更现代的方案都适合当前场景工具的核心是匹配需求不是追逐时髦。5.2 print 不刷新你在终端里卡住的真相这个坑我在 4.3 提过但值得再展开一次。第一次跑通流式输出时我以为成功了——代码看着没问题逻辑也对但屏幕上就是什么东西都不显示一直等到整个回复结束才一口气全部打出来。我当时以为模型接口有问题各种排查最后才发现问题出在 print 的缓冲机制上。Python 的 print 默认输出到 stdoutstdout 在非交互环境比如管道、重定向到文件下是全缓冲的只有在终端环境下才是行缓冲。我一开始测试的时候用了管道把输出重定向到文件自然触发全缓冲导致流式变成了攒一波打一波。flushTrue 是解决方案但理解为什么会有这个坑比记住 flush 参数更重要。同样的场景在前端也有对应浏览器里 console.log 的表现、以及 React 的批量更新本质上也是缓冲思想。只是 Python 把这种缓冲暴露得更直接逼着你去理解底层。5.3 OpenAI 兼容接口的返回结构和前端接口约定完全不同第一次看到 OpenAI 兼容接口的返回结构时我是有点懵的。每个 chunk 长这样{ choices: [ { delta: { content: 你 } } ] }content 嵌套在 choices[0].delta.content 里中间隔了两层。这和前端常见的接口约定data.content 扁平结构相比显得很重。但理解了就明白这样设计是有原因的choices 数组是为了支持一次返回多条候选结果n 参数delta 是为了兼容非流式和流式两种模式——非流式返回 choices[0].message.content流式返回 choices[0].delta.content结构保持一致只是字段不同。前端同学看到这种为了兼容而多加一层的设计应该很有共鸣——这不就是后端版的适配层嘛。你不需要记住整个对象树只需要记住流式取内容看 choices[0].delta非流式看 choices[0].message这个手感跟操作受控组件的数据路径有点类似。5.4 Windows 终端编码GBK 与 UTF-8 的战争如果你在 Windows 上跑这个项目很有可能会遇到我踩过的第四个坑程序打印中文时终端直接报 UnicodeEncodeError或者显示成乱码。原因很简单Windows 终端的默认编码通常是 GBKcode page 936而模型的输出、你的代码都是 UTF-8 编码。解决方案有三个按优先级排列设置环境变量 PYTHONIOENCODINGutf-8这会影响 Python 的 stdout/stderr 编码。在代码开头调用 sys.stdout.reconfigure(encodingutf-8)一劳永逸。升级到 Windows Terminal而不是老的 conhost它对 UTF-8 的支持更好。我个人建议第 2 种因为它写进代码里跟着项目走其他人 clone 下来也能直接跑import sys if hasattr(sys.stdout, reconfigure): sys.stdout.reconfigure(encodingutf-8) if hasattr(sys.stderr, reconfigure): sys.stderr.reconfigure(encodingutf-8)这个小细节前端同学在做 Node 脚本的时候可能从没注意过因为 Node 内部统一用 UTF-8但 Python 的编码行为更依赖运行时环境。遇到问题别慌先查是不是编码的锅。5.5 字典取值用 .get() 而不是怕 KeyError最后一个坑属于代码习惯层面的。前端从对象里取值经常直接 user.name如果是 undefined 出了错我们习惯了直接访问属性这种宽松的方式虽然也有可选链 user?.name。到了 Python 里如果你直接 dict[name]键不存在会抛 KeyError整个程序就中断了。一开始我非常不适应写了几行代码就崩一次resp[choices][0][delta][content]只要返回结构稍有变化比如 API 报错返回的是 error 字段而不是 choices程序直接炸。后来养成习惯凡是取外部数据API 返回、用户输入、配置文件都用 .get()choices data.get(choices, []) if not choices: error_msg data.get(error, {}).get(message, 未知错误) raise RuntimeError(fAPI error: {error_msg}) delta choices[0].get(delta, {}) content delta.get(content)这看起来只是一个小习惯但背后是两种编程哲学的差异JavaScript 的哲学是宽松能跑就行Python 的哲学是显式错误要尽早暴露。做 AI 项目时外部接口返回结构往往会变防御式编程的收益极大。这个习惯是我 Day 13 最大的收获之一。6. 实测效果与 v2 规划6.1 真实对话测试三种场景下的表现跑通之后我做了三类测试分别验证工具的基本能力、上下文记忆能力和抗干扰能力。第一类测试是基础问答。输入用三句话解释什么是递归它能正常流式输出终端里逐字打出答案响应速度取决于模型服务本身的出字速度体感上和网页版的中等速度差不多。第二类测试是多轮对话。我先说我叫小明我喜欢吃火锅然后隔几轮再问我叫什么名字、我喜欢吃什么它能从历史中正确回答出来。这说明 JSON 历史方案和上下文组装逻辑是通的。第三类测试是错误场景。我把 API Key 改错、网络断掉程序能打印出明确的错误信息而不是丑陋的 traceback。这个要归功于第 10-11 天学的异常处理我在 api_client.py 里把所有可能的异常都兜住了并用 rich 库打印红色的错误提示。6.2 性能感受与 v1 的局限性实测下来我最直观的感受是流式输出的体验远远好于等半天一次性输出哪怕底层模型出字速度一样用户体感上更快了因为它把等待时间转化成了阅读时间。但也暴露了几个 v1 的局限性对话历史的截断策略比较粗糙如果某条消息特别长比如粘贴了一整篇文章即便只有两轮对话也可能触发截断把早期消息扔掉。没有并发控制用户输入过程中如果按下多个回车输入循环会混乱。v1 我只做了最简单的逐行读取没有屏蔽连击。模型的知识截止时间和上下文窗口完全取决于配置如果配置一个很小的上下文窗口模型却把 MAX_CONTEXT_TOKENS 设很大接口会直接报错。这些限制不影响 v1 的可用性但让我对从 demo 到产品的距离有了非常清醒的认知。6.3 v2 规划从能用到好用Day 13 做完之后我列了一个 v2 清单不是空想每个功能都是从 v1 使用痛点里冒出来的命令系统支持 /clear、/save、/load 这类以斜杠开头的内置指令让工具具备基础的管理能力。多会话管理每次对话保存为独立文件用 /list 查看历史会话列表用 /switch 切换。这个功能是前端路由思维的产物放在 CLI 里就是一个简单的文件索引。函数调用Function Calling让模型可以请求调用预定函数比如查询时间、读取文件内容。这是通往 Agent 的关键一步。集成 rich 的 Markdown 渲染让代码块、加粗、列表在终端里以更漂亮的形式展示出来。支持本地模型Ollama 等通过统一的 OpenAI 兼容接口把 BASE_URL 指到 localhost就能从云端模型切换到本地模型。这些功能我大概率会在 Day 20 之前陆续做掉。但 v1 的价值不在功能的丰富程度而在于一个前端开发者在第 13 天第一次完完整整地拥有了一条从零到一的 AI 工具开发闭环。这条链路上的每一个环节我都亲手推过接下来的学习就不再是理解概念而是在这个框架上做增量。对我个人来说Day 13 最大的收获不是代码本身而是终于明白了一个朴素的道理学 AI 和学前端一样真正让你成长的永远是那个你逼着自己做完的完整项目。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

SLAM工程实战:从VINS原理到RK3588部署的五大核心战场 2026/10/2 18:33:52

SLAM工程实战:从VINS原理到RK3588部署的五大核心战场

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
毕业论文查重率居高不下,实测靠谱的降AIGC平台推荐与TaoToken统一Key接入指南 2026/10/2 18:33:51

毕业论文查重率居高不下,实测靠谱的降AIGC平台推荐与TaoToken统一Key接入指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Unity FPS显示原理与工程级性能监控实战 2026/10/2 18:33:51

Unity FPS显示原理与工程级性能监控实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
无经验怎么积累测试项目?两周搭建一份能写进简历的实战经历 2026/10/2 18:33:26

无经验怎么积累测试项目?两周搭建一份能写进简历的实战经历

大概每个准备入行软件测试的人,都经历过这种卡壳时刻:测试基础看完了、用例设计方法背熟了、面试八股文也过了一轮,打开简历模板,光标停在“项目经验”那一栏,半天敲不出一个字。我在帮人改简历的时候,几乎…

阅读更多 →
Hudi + Hive 增量数据处理全攻略:从同步机制到小文件优化 2026/10/2 18:33:26

Hudi + Hive 增量数据处理全攻略:从同步机制到小文件优化

做网约车大数据项目那段时间,每天几十亿条订单、轨迹、支付流水往数据平台涌。团队最头疼的并不是数据量大,而是“变化”本身:订单状态不停更新、司机位置持续漂移、部分记录还要回滚删除。如果还是按离线思路每天全量重跑,计算资…

阅读更多 →
端到端数字产品交付:从概念到上线的链路设计与实践 2026/10/2 18:33:26

端到端数字产品交付:从概念到上线的链路设计与实践

前段时间有个做产品的朋友问我:现在到处都在说“端到端”,是不是以后一个人把所有事干了就行?这个问题把我问笑了。“端到端”这三个字确实被说烂了,尤其是智驾圈,隔三差五一个端到端大模型。但在数字产品交付的语境里…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉