当前位置: 首页 > news >正文

标准/工程化写法

from langchain_openai import (ChatOpenAI,
)  # 用 OpenAI 兼容接口和模型对话(阿里云等也兼容这个接口)
import os  # Python 自带:用来读「环境变量」(如 API 密钥)# load_dotenv:从项目根目录的 .env 文件里,把变量加载到「环境」里,之后用 os.getenv("变量名") 就能读到。
# 把密钥写在 .env 里而不是代码里,既安全(不把密钥提交到 Git),又方便换环境(开发/生产用不同 .env)。
from dotenv import load_dotenv# LangChainException:LangChain 在调用模型失败时会抛出的异常类型。
# 在 main() 里用 except LangChainException 单独接住这类错误,就能打出「模型调用失败」的日志,和配置错误、其他未知错误区分开。
from langchain_core.exceptions import LangChainException# 真正执行「从 .env 加载到环境」;encoding='utf-8' 避免 .env 里有中文时乱码。
load_dotenv(encoding="utf-8")# ----- 日志配置 -----
# logging 是 Python 自带的日志库,不用 pip 安装。用 logger.info() / logger.error() 代替 print,方便区分「普通信息」和「错误」,且可统一格式、写文件等。
# 通过环境变量 LOG_LEVEL 控制输出多少:开发时用 INFO(看得到调试信息),生产时在 .env 里设 LOG_LEVEL=WARNING,就只打警告和错误,减少刷屏。
import logging_log_level = os.getenv("LOG_LEVEL", "INFO").upper()
logging.basicConfig(level=getattr(logging, _log_level, logging.INFO),format="%(asctime)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)  # 当前模块的 logger,后面用 logger.info(...) 即可# ==========  LLM 客户端初始化(封装为函数,便于多处复用) ==========
# 把「创建可对话的客户端」封装成一个函数,以后在别处也能直接调 init_llm_client(),不用重复写一长串配置。def init_llm_client() -> ChatOprnAI:"""Returns:ChatOpenAI: 初始化好的「对话客户端」,可以对其调用 .invoke(问题) 或 .stream(问题)。"""api_key = os.getenv("QWEN_API_KEY")if not api_key:raise ValueError("环境变量 QWEN_API_KEY 未配置,请检查 .env 文件")llm = ChatOpenAI(model="deepseek-v3.2",  # 模型名称(这里演示的是“DeepSeek 模型 + 阿里百炼兼容接口”)api_key=api_key,base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",  # 阿里云提供的兼容 OpenAI 的地址temperature=0.7,  # 控制「随机程度」:0 更确定、重复性高;1 更随机、更有创意。一般 0.5~0.8 即可。max_tokens=2048,  # 单次回复最多生成多少个 token(约等于字数),防止回复过长或超限。)return llm# ==========   主逻辑:invoke(一次性) + stream(流式)两种调用方式 ==========
# 这里把「问问题、拿回答、打日志」都放在 main() 里,并用 try/except 把可能出现的错误分开处理,避免程序一报错就崩掉、且能打出清晰错误信息。def main():try:llm = init_llm_client();logger.info("LLM客户端初始化成功")# 方式一 invoke()# 发一个问题,程序会等模型全部答完,再一次性把 response 给你。适合短问答。question = "你是谁"response = llm.invoke(question)logger.info(f"问题:{question},回答:{response.content}")# 方式二 stream()question = "介绍下 langchain,300字以内"response_stream = llm.stream(question)for chunk in response_stream:print(chunk.content, end="") # end="" 表示不换行,紧挨着打print()     # 流式结束后补一个换行,避免和后续输出粘在一起# ----- 异常处理:根据错误类型打不同日志,方便排查 -----
# try 里面的代码一旦报错,会跳到下面某个 except;若都不匹配,再往上抛。
except ValueError as e:        # 例如:.env 里没配 QWEN_API_KEY,init_llm_client 里会 raise ValueErrorlogger.error(f"配置错误:{str(e)}")
except LangChainException as e:# 例如:网络失败、API 限流、模型返回异常等,LangChain 会抛出 LangChainExceptionlogger.error(f"模型调用失败:{str(e)}")
except Exception as e:# 其他没预料到的错误都归到这里,避免程序静默崩溃logger.error(f"未知错误:{str(e)}")

 

http://www.jsqmd.com/news/714809/

相关文章:

  • 2026年油脂加工成套设备采购参考:榨油机、螺旋榨油机与液压榨油机这样选更靠谱 - 深度智识库
  • 3步解决《边缘世界》模组冲突的开源智能管理方案
  • 如何利用Audio Slicer实现高效音频智能分割:从技术原理到实战应用
  • 交流接触器每个端子的作用
  • 别再傻傻分不清了!Vector CANdb++ Editor和Admin到底该用哪个?(附详细功能对比图)
  • 别再手动算时间差了!用KingbaseES的UNIX_TIMESTAMP函数,5分钟搞定日期比较与排序
  • 2026年5月亨得利官方售后网点核验报告:老司机排雷 + 奇葩踩坑实录(含迁址/新开)实地考察・多方验证 - 亨得利官方服务中心
  • 别再傻傻分不清:Linux下TTY、PTS、PTY到底啥关系?一个SSH登录就全明白了
  • 2026最新辣椒面企业推荐!国内优质权威榜单发布,实力靠谱四川成都福建等地企业精选 - 十大品牌榜
  • 用RandLA-Net处理S3DIS数据集:从原始点云到6折交叉验证的完整实战解析
  • 打破音乐付费墙:MoeKoeMusic如何让你免费畅享VIP音乐体验
  • 基于MCP与Crawl4AI的动态RAG系统:为AI智能体构建实时知识库与代码验证能力
  • OpenClaw成本差异分析工具:AI代理API成本监控与优化实践
  • League Akari:英雄联盟玩家的终极工具箱完整使用指南
  • GetQzonehistory:如何完整备份你的QQ空间历史记录
  • 搭建装修的展示型小程序怎么做?4个获客场景拆解 - 维双云小凡
  • 别再只认识eth0了!玩转Linux虚拟网络:手把手创建dummy0并配置l4tbr0网桥
  • FlexASIO终极指南:如何在普通声卡上实现专业级ASIO低延迟音频体验
  • 重新定义Windows任务栏:RoundedTB的现代美学改造方案
  • 郑州北极电器服务:郑州热水器维修 油烟机维修厂家哪家专业 - LYL仔仔
  • TuriX-CUA:基于视觉大模型的桌面AI智能体部署与实战指南
  • 免费音频转换器fre:ac:从零开始构建你的数字音乐库
  • 2026年昆明短视频运营与AI全网推广服务商深度横评 - 优质企业观察收录
  • ESP32-C3开发板集成LCD与Qwiic接口解析
  • 别再只改Dockerfile了!:云原生Java函数冷启动性能瓶颈定位手册(火焰图+Arthas trace+eBPF syscall监控三件套)
  • Unsloth Studio 使用问题记录
  • 技术深度解析:Get-cookies.txt-LOCALLY - 本地化Cookie导出解决方案
  • 高级java每日一道面试题-2025年11月18日-容器与虚拟化题[Dockerj]-Docker 容器的核心隔离技术是什么?Linux Namespace 有哪些类型?
  • 向量数据库核心技术解析与RAG系统实践
  • GD32单片机中断实战:用串口接收中断和按键中断做个简易聊天机器人(附完整代码)