Chandra代码实例:通过curl/API调用Chandra后端服务的Python示例
1. 什么是Chandra:一个私有化AI聊天助手
Chandra不是另一个云端API服务,而是一个真正属于你自己的AI聊天助手。它的名字源自梵语中的“月神”,象征着智慧、静谧与内在洞察力——这恰恰契合了它作为本地AI服务的本质:不喧哗、不外泄、不依赖网络,只在你需要时安静而可靠地回应。
当你启动Chandra镜像,它会在容器内自动完成三件关键事:安装Ollama运行时、拉取并加载Google的gemma:2b轻量模型、启动前端Web界面。整个过程无需手动配置,也不需要你打开终端敲命令。它像一台即插即用的智能收音机——通电即响,静音即止。
但Chandra的价值远不止于点开网页聊天。它的后端完全基于标准HTTP API设计,这意味着你可以绕过前端界面,直接用Python脚本、curl命令,甚至自动化工作流与它对话。这种能力,让Chandra从“玩具级聊天框”跃升为可集成、可编排、可嵌入业务流程的私有AI引擎。
如果你正在寻找一种方式,把大模型能力安全地嵌入内部系统——比如客服工单自动摘要、研发文档实时问答、或HR面试问题生成——那么理解如何调用Chandra的API,就是迈出的第一步,也是最关键的一步。
2. Chandra的API结构与通信原理
2.1 后端服务是如何暴露的
Chandra镜像启动后,会同时运行两个核心服务:
- Ollama服务:默认监听
http://localhost:11434(容器内),提供标准的Ollama REST API(如/api/chat,/api/generate) - Chandra Web服务:作为代理层和前端服务器,监听
http://localhost:8080(容器外映射端口),它将用户请求转发给Ollama,并处理会话状态、流式响应封装等逻辑
关键事实:Chandra前端本身并不处理模型推理,它只是一个轻量级网关。所有真正的AI计算都发生在Ollama层。因此,直接调用Ollama API更底层、更灵活;而调用Chandra API则更贴近实际使用体验(如支持多轮上下文、消息历史管理)。
本教程聚焦于Chandra提供的标准聊天API,因为它完整复现了你在网页界面上的操作逻辑:发送消息 → 接收流式回复 → 保持会话连贯性。
2.2 核心API端点与请求格式
Chandra对外暴露的聊天接口是:
POST http://<your-server-ip>:8080/api/chat它接受一个标准JSON payload,结构如下:
{ "model": "gemma:2b", "messages": [ { "role": "user", "content": "你好,介绍一下你自己。" } ], "stream": true }model:指定使用的模型名称(必须与Ollama中已加载的模型名一致)messages:消息数组,每条包含role(user或assistant)和content(文本内容)stream:设为true可获得逐字流式响应(与网页“打字机效果”一致);设为false则等待完整回复后一次性返回
响应体是Server-Sent Events(SSE)格式,每行以data:开头,内容为JSON字符串。这是实现流畅对话体验的关键机制。
2.3 为什么不用直接调Ollama?——Chandra API的独特价值
你当然可以直接向http://localhost:11434/api/chat发送请求。但Chandra API做了几项重要增强:
- 自动会话管理:无需手动拼接历史消息,Chandra内部维护上下文窗口
- 统一错误处理:模型未加载、服务不可用等异常被标准化为HTTP状态码+清晰提示
- 跨域就绪:已预配置CORS,方便前端JS直连(对Python调用无影响,但体现设计完整性)
- 轻量认证预留:路径设计支持未来扩展Bearer Token验证(当前未启用,但结构已就位)
换句话说:Ollama是引擎,Chandra是方向盘+仪表盘+安全气囊——它让你开得更稳、更省心。
3. Python调用实战:从零开始构建一个命令行聊天器
3.1 环境准备与依赖安装
我们不需要复杂框架。仅需Python 3.8+ 和两个轻量库:
pip install requests sseclient-pyrequests:发起HTTP请求sseclient-py:优雅解析Server-Sent Events流(比手动按行解析更健壮)
注意:不要使用
sseclient(旧版,不维护),务必安装sseclient-py(活跃维护,兼容Python 3.9+)
3.2 完整可运行代码:支持多轮对话的CLI聊天器
以下代码实现了与Chandra Web UI完全一致的交互体验:输入问题 → 实时显示AI逐字回复 → 自动将本次对话加入历史 → 支持连续提问。
# chandra_cli.py import requests from sseclient import SSEClient import sys # 配置:请根据你的部署情况修改 CHANDRA_URL = "http://localhost:8080" # 若部署在远程服务器,请替换为公网IP或域名 MODEL_NAME = "gemma:2b" def chat_with_chandra(): print(" Chandra CLI 聊天器已启动(输入 'quit' 或 'exit' 退出)") print(" 提示:支持中文,可随时追问上一个问题\n") # 维护会话历史(模拟Web UI的上下文记忆) messages = [] while True: try: # 1. 获取用户输入 user_input = input("🧑 你: ").strip() if user_input.lower() in ["quit", "exit", "q"]: print("👋 再见!Chandra随时待命。") break if not user_input: continue # 2. 构建请求数据 payload = { "model": MODEL_NAME, "messages": [{"role": "user", "content": user_input}], "stream": True } # 3. 发送POST请求,启用流式响应 response = requests.post( f"{CHANDRA_URL}/api/chat", json=payload, stream=True, timeout=120 # 防止长思考卡死 ) # 4. 检查HTTP状态 if response.status_code != 200: print(f"❌ 请求失败: {response.status_code} - {response.text[:100]}") continue # 5. 解析SSE流,逐块打印AI回复 print("🌙 Chandra: ", end="", flush=True) client = SSEClient(response) assistant_reply = "" for event in client.events(): if event.data == "[DONE]": break try: data = event.data.strip() if not data: continue chunk = eval(data) # 简单解析JSON字符串(生产环境建议用json.loads) if "message" in chunk and "content" in chunk["message"]: content = chunk["message"]["content"] if content: print(content, end="", flush=True) assistant_reply += content except Exception as e: print(f"\n 解析响应时出错: {e}") break print() # 换行 # 6. 将本轮对话加入历史(为下一轮提问提供上下文) messages.append({"role": "user", "content": user_input}) messages.append({"role": "assistant", "content": assistant_reply}) except KeyboardInterrupt: print("\n\n👋 手动中断,再见!") break except requests.exceptions.RequestException as e: print(f"\n❌ 网络错误: {e}") print(" 请确认Chandra服务正在运行,且地址正确。") except Exception as e: print(f"\n❌ 未知错误: {e}") if __name__ == "__main__": chat_with_chandra()3.3 代码关键点详解
stream=True+SSEClient:这是实现“打字机效果”的核心。requests的stream=True开启流式读取,SSEClient负责按data:分隔符解析事件流,避免手动处理换行和边界。eval(data)的说明:此处为简化演示(gemma:2b返回的content不含恶意代码)。生产环境应严格使用json.loads(data)并捕获JSONDecodeError。timeout=120:gemma:2b通常在1–3秒内响应,但复杂问题可能稍长。设超时防止程序假死。messages历史管理:虽然Chandra API当前版本不强制要求传入历史消息(它内部会缓存),但显式维护messages数组是良好实践,确保逻辑清晰、便于未来迁移到需要显式上下文的模型(如llama3)。
3.4 运行效果实录
启动脚本后,你会看到类似这样的交互:
Chandra CLI 聊天器已启动(输入 'quit' 或 'exit' 退出) 提示:支持中文,可随时追问上一个问题 🧑 你: 你好,介绍一下你自己。 🌙 Chandra: 你好!我是Chandra,一个由本地Ollama驱动的AI聊天助手。我基于Google的gemma:2b模型,所有计算都在你的设备上完成,不上传任何数据,保障你的隐私安全。我可以帮你解答问题、创作文字、编写代码,或者只是陪你聊聊天。有什么我可以帮你的吗? 🧑 你: 你能写一首关于月亮的五言绝句吗? 🌙 Chandra: 当然可以: 银汉无声转玉盘, 清辉漫洒夜阑干。 桂影婆娑风自远, 冰轮皎洁照人寒。 ——希望你喜欢这首小诗! 🧑 你: quit 👋 再见!Chandra随时待命。每一行AI回复都是实时逐字打印,毫无延迟感——这正是流式API的价值所在。
4. curl命令速查:快速验证与调试
当Python环境不可用,或你需要快速测试API连通性时,curl是最直接的工具。
4.1 最简curl调用(非流式,适合调试)
curl -X POST http://localhost:8080/api/chat \ -H "Content-Type: application/json" \ -d '{ "model": "gemma:2b", "messages": [{"role": "user", "content": "你好"}], "stream": false }'此命令将返回完整JSON响应,包含message.content字段。适用于检查服务是否存活、模型是否加载成功。
4.2 流式curl调用(模拟真实体验)
curl -X POST http://localhost:8080/api/chat \ -H "Content-Type: application/json" \ -d '{ "model": "gemma:2b", "messages": [{"role": "user", "content": "讲个冷笑话"}], "stream": true }' \ | grep "content" | sed 's/.*"content":"\([^"]*\)".*/\1/' | tr -d '\n'grep "content":过滤出含content的data行sed:提取双引号内的文本tr -d '\n':删除换行,实现“打字”效果
注意:此命令在macOS上需安装GNU sed(
brew install gnu-sed),并改用gsed。Linux用户可直接使用。
4.3 常见HTTP错误码速查表
| 状态码 | 含义 | 典型原因 | 解决方案 |
|---|---|---|---|
404 Not Found | /api/chat路径不存在 | Chandra服务未启动,或端口映射错误 | 检查容器日志,确认8080端口已正确暴露 |
503 Service Unavailable | Ollama服务未就绪 | 镜像刚启动,Ollama仍在加载模型(约需60–90秒) | 等待1–2分钟后再试,或查看容器日志中Ollama is ready提示 |
400 Bad Request | JSON格式错误或model名不存在 | model字段拼写错误(如写成gemma2b) | 使用curl http://localhost:11434/api/tags查看已加载模型列表 |
408 Request Timeout | 请求超时 | 网络延迟高,或模型响应慢(罕见于gemma:2b) | 增加curl的--max-time 120参数,或检查服务器资源 |
5. 进阶应用:将Chandra集成到你的工作流中
5.1 场景一:自动化文档问答机器人
假设你有一份PDF技术手册,想让它“活”起来:
- 用
pymupdf提取PDF文本 - 用
sentence-transformers做向量切分 - 将每个段落作为独立
user消息,批量调用Chandra API - 返回结果按相关性排序,生成精准答案
# 伪代码示意 for chunk in document_chunks[:5]: # 取前5个最相关的段落 response = requests.post( f"{CHANDRA_URL}/api/chat", json={ "model": "gemma:2b", "messages": [ {"role": "user", "content": f"根据以下文档片段回答问题:{chunk}"}, {"role": "user", "content": "Chandra,Kubernetes中Service的ClusterIP类型作用是什么?"} ] } ) # 解析response.json()["message"]["content"]5.2 场景二:邮件智能摘要服务
每天收上百封邮件?用Chandra自动生成摘要:
# 从邮箱API拉取最新5封未读邮件 emails = get_unread_emails(limit=5) for email in emails: summary = requests.post( f"{CHANDRA_URL}/api/chat", json={ "model": "gemma:2b", "messages": [{ "role": "user", "content": f"请用不超过50字,概括以下邮件的核心内容和行动项:\n{email.body}" }] } ).json()["message"]["content"] print(f"📧 {email.subject} → {summary}")5.3 场景三:代码审查辅助(需微调提示词)
虽然gemma:2b不是专为代码设计,但通过强提示词可胜任基础任务:
prompt = """你是一名资深Python工程师。请严格按以下步骤审查代码: 1. 指出所有潜在的空指针风险(None检查缺失) 2. 标注任何违反PEP8的命名规范 3. 用中文给出1条最关键的改进建议 代码如下: ```python def process_data(items): result = [] for item in items: result.append(item.upper()) return result ```""" response = requests.post( f"{CHANDRA_URL}/api/chat", json={"model": "gemma:2b", "messages": [{"role": "user", "content": prompt}]} ).json()["message"]["content"]提示:将上述场景中的
requests.post替换为你在3.2节写的流式函数,即可获得实时审查反馈。
6. 总结:掌握API,就是掌握Chandra的全部潜力
Chandra的价值,从来不在那个简洁的网页界面上。它真正的力量,藏在/api/chat这个短短的路径之后——那里是一扇门,通往一个完全可控、绝对私有、随时待命的AI大脑。
通过本文的Python示例,你已经掌握了:
- 如何用标准HTTP协议与Chandra通信
- 如何解析流式响应,实现“所问即所得”的实时体验
- 如何维护对话历史,让AI记住上下文
- 如何用curl快速诊断服务状态
- 如何将Chandra无缝嵌入文档处理、邮件管理、代码审查等真实工作流
你不再是一个被动的聊天用户,而是一个能调度AI能力的架构师。下一步,你可以:
- 把CLI脚本打包成桌面App(用
pyinstaller) - 将API接入企业微信/钉钉机器人
- 用FastAPI封装一层业务逻辑,提供
/summarize、/translate等语义化接口 - 甚至为不同部门部署多个Chandra实例,各自加载专属模型(如
phi3:3.8b用于代码,tinyllama用于会议纪要)
技术的终极自由,是选择权。而Chandra,正把这份自由,交还到你手中。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。