【AI】一. LLM大模型开发核心-LangChain框架实战&Env虚拟环境配置 小滴课堂讲师 2025年09月17日 ai大模型, aigc, python 预计阅读 28 分钟 #### LLM开发框架LangChain介绍和技术生态 ##### 背景需求 * 大模型(如ChatGPT、DeepSeek)的局限性: - 无法获取训练数据外的实时信息(如今天的天气) - 不能直接执行具体操作(发邮件/查数据库) - 处理复杂任务时缺乏步骤规划能力 * 开发者的痛点 ```java // 传统Java开发模式 vs AI应用开发 String result = service.doSomething(input); // 确定性结果 // VS String aiResponse = llm.generate(prompt); // 非确定性输出 ``` 什么是LangChain框架(类似SpringCloud) * 是一个基于大型语言模型(LLM)开发应用程序的框架,专为构建与大语言模型(LLMs)相关的应用而设计。 * 通过将多个 API、数据源和外部工具无缝集成,LangChain 能帮助开发者更高效地构建智能应用。 * 从与 OpenAI 、DeepSeek等顶级大模型供应商的集成,到复杂的对话系统、智能搜索、推荐系统等 * LangChain 提供了丰富的功能和灵活的接口,极大地方便了开发者的工作。 * **通俗点:LangChain 就是对各类大模型提供的 API 的套壳,方便开发者使用这些 API和协议,搭建起来的模块和接口组合** * 官网:https://www.langchain.com * GIthub地址:https://github.com/langchain-ai/langchain ##### LangChain生态产品介绍 LangChain * 提供模块化开发能力,支持LLM(如GPT、Claude等)与外部数据源(数据库、API)的集成 * 包含链(Chain)、代理(Agent)、记忆(Memory)等核心组件,用于构建复杂AI应用  LangServer * 部署工具,可将LangChain应用快速转换为REST API,支持并行处理、流式传输和异步调用 * 自动生成OpenAPI文档, 滚动更新支持, 内置Prometheus指标, 适用于企业级生产环境  LangSmith * 开发者调试与监控平台,支持对LLM应用的性能分析、测试和部署优化 * 提供可视化调试界面和自动化评估工具,提升开发效率与可靠性  LangGraph * 状态管理工具,用于构建多代理系统,支持流式处理和复杂任务分解 * 可视化流程设计器, 循环/条件分支支持,分布式状态持久化, 自动断点续跑  产品矩阵对比 | **产品** | **核心价值** | **Java生态对标** | **适用场景** | | :------------: | :----------------: | :------------------: | :----------------------: | | LangSmith | 全生命周期可观测性 | Prometheus + Grafana | 生产环境监控、效果评估 | | LangServe | 快速服务化 | Spring Boot | 模型API部署、快速原型 | | LangGraph | 复杂流程编排 | Activiti BPMN | 业务工作流设计、状态管理 | | LangChain Core | 基础组件库 | Spring AI | 基础AI功能开发 |  #### Python虚拟环境evn应用讲解和实战 > python版本选择:**3.12.6** > > conda环境配置:https://blog.virtualagent.cn/blog/details/id/252 ##### 什么是Python的虚拟环境 * 类似虚拟机、沙箱机制一样,隔离不同的项目依赖的环境 * 核心作用 * **隔离项目依赖**:不同项目可能依赖同一库的不同版本。 * **避免全局污染**:防止安装过多全局包导致冲突。 * **便于协作**:通过依赖清单(如`requirements.txt`)复现环境 虚拟环境 vs 全局环境 | **特性** | **虚拟环境** | **全局环境** | | :----------: | :--------------------------: | :------------------------: | | **依赖隔离** | 项目独立,互不影响 | 所有项目共享 | | **安全性** | 避免权限问题(无需sudo安装) | 需谨慎操作(可能影响系统) | | **适用场景** | 开发、测试、多版本项目 | 系统级工具或少量通用库 | ##### 镜像源配置 * 查看系统配置的镜像源操作 ```python pip config list pip config get global.index-url ``` * 配置国内镜像源 ```shell pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple ``` ##### 虚拟环境基础操作 * 创建虚拟环境 ```shell # 语法:python -m venv <环境目录名> python -m venv myenv # 创建名为myenv的虚拟环境 ``` * 激活虚拟环境 * Windows(CMD/PowerShell) ```shell myenv\Scripts\activate.bat # CMD myenv\Scripts\Activate.ps1 # PowerShell(需管理员权限解除限制) ``` * Linux/macOS: ```shell source myenv/bin/activate ``` * 激活后提示符变化 ```shell source myenv/bin/activate ``` * 退出虚拟环境 ```shell deactivate ``` ##### 依赖管理 * 安装库到虚拟环境 ```shell # 激活环境后操作 (myenv) pip install requests # 安装最新版本 (myenv) pip install django==3.2 # 安装指定版本 ``` * 导出依赖清单 ```shell (myenv) pip freeze > requirements.txt ``` * 从清单恢复依赖 ```shell # 在新环境中执行 (myenv) pip install -r requirements.txt ``` ##### 最佳实践与案例 * 典型项目流程(区分Linux、Mac和Window) ```shell # 创建项目目录并进入 mkdir myproject && cd myproject # 创建虚拟环境 python -m venv .venv # 激活环境(Windows: .venv\Scripts\activate) source .venv/bin/activate # 安装依赖 pip install django pandas # 导出依赖 pip freeze > requirements.txt # 开发完成后退出 deactivate ``` * 协作复现环境 ```shell # 克隆项目后操作 git clone https://github.com/user/project.git cd project # 创建并激活虚拟环境 python -m venv .venv source .venv/bin/activate # 安装依赖 pip install -r requirements.txt ``` ##### 常见问题与解决 * 虚拟环境激活失败 * 现象:source: command not found * 原因:在Windows使用Linux命令或在Linux未使用source。 * 解决:根据操作系统选择正确激活命令。 * 跨平台路径问题 * 问题:Windows与Linux路径格式差异导致脚本无法运行。 * 方案:使用/统一路径分隔符,或在代码中处理路径 * 依赖版本冲突 * 场景:项目A需要`numpy==1.18`,项目B需要`numpy==1.20`。 * 解决:为每个项目创建独立虚拟环境。 案例实战:LangChain框架环境搭建 #### VSCode编辑器LangChain环境安装和验证 ##### Python虚拟环境和项目创建 * 创建虚拟环境(Windows/macOS/Linux通用) ```python # 创建环境目录 python -m venv langchain_env ``` * 激活虚拟环境 * **Windows** ```python .\langchain_env\Scripts\activate ``` * **macOS/Linux** ```python source langchain_env/bin/activate ``` * 验证环境 ```python # 查看Python路径(应显示虚拟环境路径) which python # macOS/Linux where python # Windows ``` ##### LangChain环境安装 * 安装核心依赖包**requirements.txt** ```sh aiohappyeyeballs==2.4.3 aiohttp==3.10.10 aiosignal==1.3.1 annotated-types==0.7.0 anyio==4.6.0 attrs==24.2.0 beautifulsoup4==4.12.3 certifi==2024.8.30 charset-normalizer==3.4.0 dashscope==1.20.11 dataclasses-json==0.6.7 distro==1.9.0 frozenlist==1.4.1 h11==0.14.0 httpcore==1.0.6 httpx==0.27.2 idna==3.10 jiter==0.6.1 jsonpatch==1.33 jsonpointer==3.0.0 langchain==0.3.3 langchain-community==0.3.2 langchain-core==0.3.40 langchain-openai==0.3.7 langchain-text-splitters==0.3.0 langsmith==0.1.134 marshmallow==3.22.0 multidict==6.1.0 mypy-extensions==1.0.0 numexpr==2.10.1 numpy==1.26.4 openai==1.65.2 orjson==3.10.7 packaging==24.1 propcache==0.2.0 pydantic==2.7.4 pydantic-settings==2.5.2 pydantic_core==2.18.4 python-dotenv==1.0.1 PyYAML==6.0.2 regex==2024.11.6 requests==2.32.3 requests-toolbelt==1.0.0 sniffio==1.3.1 soupsieve==2.6 SQLAlchemy==2.0.35 tenacity==8.5.0 tiktoken==0.9.0 tqdm==4.66.5 typing-inspect==0.9.0 typing_extensions==4.12.2 urllib3==2.2.3 websocket-client==1.8.0 wikipedia==1.4.0 yarl==1.15.0 ``` * 执行 ```sh # 安装依赖 pip install -r requirements.txt ``` * 验证安装【很多模块后续使用会验证】 ```python # 执行简单测试 from langchain_core.prompts import ChatPromptTemplate print(ChatPromptTemplate.from_template("Hello 欢迎来到小滴课堂-AI大模型开发课程 {title}!").format(title=",干就完了")) # 应输出: Human: Hello 欢迎来到小滴课堂-AI大模型开发课程 ,干就完了! ``` #### LangChain框架模块和大模型IO交互链路讲解 大模型IO交互链路概览  LangChain模块对比大家熟知的Java Spring生态 | LangChain模块 | Spring对应技术 | 交互方式差异 | | :-----------: | :-------------: | :----------------: | | Models | Spring AI | 多模型热切换支持 | | Memory | Redis/Hazelcast | 内置对话上下文管理 | | Chains | Activity工作流 | 动态流程重组能力 | | Agents | Drools规则引擎 | 基于LLM的决策机制 | ##### LangChain架构六大模块 * **Models(模型层)** - 相当于`interface LLM`,支持多种大模型(OpenAI/Gemini等) - 示例:就像Java中的JDBC接口,可以对接不同数据库 * **Prompts(提示工程)** - 相当于模板引擎(类似Thymeleaf) ```python from langchain.prompts import PromptTemplate template = """ 你是一个Java专家,请用比喻解释{concept}: 要求: 1. 用{framework}框架做类比 2. 不超过2句话 """ prompt = PromptTemplate.from_template(template) print(prompt.format(concept="机器学习", framework="Spring")) ``` * **Chains(任务链)** - 类似Java的工作流引擎,将多个组件组合在一起,创建一个单一、连贯的任务 - 包括不同的链之间组合 ```python from langchain.chains import LLMChain # 创建任务链(类似Java的链式调用) chain = LLMChain(llm=model, prompt=prompt) result = chain.run(concept="多线程", framework="Spring Batch") ``` * **Memory(记忆)** - 类似HTTP Session的会话管理 ```python from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory() memory.save_context({"input": "你好"}, {"output": "您好!"}) ``` * **Indexes(索引)** - 类似数据库索引+JDBC连接 - 对不通的文档进行结构化的方法,包括提取、切割、向量存储等,方便 LLM 能够更好的与之交互 ```python from langchain.document_loaders import WebBaseLoader # 加载外部数据(类似JDBC读取数据库) loader = WebBaseLoader("https://docs.spring.io/spring-boot/docs/current/reference/html/") docs = loader.load() ``` * **Agents(智能体)** - 类似策略模式+工厂模式,比chain更高级,可以自己选择调用链路 - 比如下一步有多个选择, 包括不同工具、流程链路等,由程序自己选择 ```python from langchain.agents import Tool, initialize_agent tools = [ Tool(name="Calculator", func=lambda x: eval(x), description="计算数学表达式") ] agent = initialize_agent(tools, llm, agent="zero-shot-react-description") ``` * 常见分层设计和交互如下 ```markdown +----------------+ | 应用层 (Agents) | +----------------+ | 编排层 (Chains) | +----------------+ | 能力层 (Tools) | +----------------+ | 模型层 (Models) | +----------------+ | 数据层 (Memory) | +----------------+ ``` #### 大模型Model-IO链路抽象和Chat模型开发 大模型使用开发的Model IO链路核心三要素  | 组件 | 作用 | 典型类/方法 | | :---------: | :------------------------: | :-------------------------------------------: | | **Prompts** | 构建模型输入的结构化模板 | `ChatPromptTemplate`, `FewShotPromptTemplate` | | **Models** | 对接不同LLM服务的统一接口 | `ChatOpenAI` | | **Parsers** | 将模型输出转换为结构化数据 | `StrOutputParser`, `JsonOutputParser` |  LangChain支持的模型类型说明 * 文本生成模型(Text Generation Models-逐渐少用了,Chat更强大) * 功能:生成连贯文本,主要用于处理文本相关的任务,如自然语言理解、文本生成、情感分析、翻译 * 典型模型:GPT-3、Claude、PaLM * 对话模型(Chat Models,多数采用这个) * 功能:处理多轮对话,人机交互中的对话能力,能够进行自然流畅的对话交流,适用于客户服务、智能助手 * 典型模型:GPT-4、Claude-2 * 嵌入模型(Embedding Models) * 功能:生成文本向量表示,将文本转换为固定长度的向量表示,向量保留了数据的语义信息,便于后续的相似度计算、分类等任务。 * 典型模型:text-embedding-ada-002 * 多模态模型(Multimodal Models) * 功能:处理文本+图像,例如文本、图像、音频等,更全面的信息理解和处理能力。 * 典型模型:GPT-4V、Qwen-omni-turbo * 其他更多.... * LangChain开发LLM聊天模型快速编码实战 ```python from langchain_openai import ChatOpenAI # 调用Chat Completion API llm = ChatOpenAI( model_name='qwen-plus', base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-0903038424424850a88ed161845d7d4c") response = llm.invoke('你是谁?') print(response) ``` #### 类型增强模块Typing应用和案例 Python的动态类型痛点 ```python # 传统动态类型代码示例 def calculate(a, b): return a + b # 无法直观看出参数类型和返回值类型 result1 = calculate(3, 5) # ✅ 正确用法 result2 = calculate("3", 5) # ❌ 运行时才报错 ``` ##### 什么是Typing模块 * 自python3.5开始,PEP484为python引入了类型注解(type hints), 为Python带来了类型提示和类型检查的能力。 * 允许开发者在代码中添加类型注解,提高代码的可读性和可维护性。 * 尽管Python是一种动态类型语言,但类型注解能让开发者更清晰地了解函数和变量的预期类型 * 核心 * **提升代码可读性**:明确参数和返回类型 * **增强IDE支持**:智能提示与自动补全 * **静态类型检查**:开发阶段发现潜在错误 * **完善文档生成**:自动生成类型化API文档 ##### 核心语法快速入门 * 简单类型(Primitive Types) * Python内置的基本数据类型注解 * 适用场景:变量、函数参数、返回值的简单类型声明 * 类型注解不影响运行时行为 * 兼容子类型(如int注解可接受bool值) ``` age: int = 25 # 整数类型 name: str = "Alice" # 字符串类型 price: float = 9.99 # 浮点数类型 is_valid: bool = True # 布尔类型 data: bytes = b"binary" # 字节类型 ``` * 容器类型 * 有多种内置的类型别名,比如`List`、`Tuple`、`Dict`等,可用于注解变量和函数的预期类型 * 例如 * `Dict[str, int]`表示键是字符串类型,值是整数类型的字典 * `Set[int]`表示整数类型的集合 * `List`同质元素的序列容器 * 适用场景:列表类型数据,元素类型相同 ```python from typing import List scores: List[int] = [90, 85, 95] # 整型列表 matrix: List[List[float]] = [[1.1, 2.2], [3.3]] # 嵌套列表 ``` * `Dict` 键值对映射容器 * 适用场景:字典类型数据,需指定键值类型 ```python from typing import Dict person: Dict[str, str] = {"name": "Bob", "job": "dev"} # 字符串字典 config: Dict[str, Union[int, str]] = {"timeout": 30} # 混合值类型 ``` * `Tuple`固定长度、类型的不可变序列 - 适用场景:坐标、数据库记录等固定结构 - 变长声明:`Tuple[T, ...]`:元素类型相同但长度不限 , ():空元组 ```python from typing import Tuple point: Tuple[float, float] = (3.14, 2.71) # 二元坐标 rgb: Tuple[int, int, int] = (255, 0, 128) # 颜色值 flexible: Tuple[str, ...] = ("a", "b", "c") # 任意长度元组 ``` * `Set` 无序不重复元素的集合 - 适用场景:去重数据、集合运算 ```python from typing import Set unique_ids: Set[int] = {1, 2, 3} # 整型集合 tags: Set[Union[str, int]] = {"urgent", 1001} # 混合类型集合 ``` * 任意类型 `Any` - 动态类型占位符,放弃类型检查, 应尽量避免过度使用 - 适用场景:兼容无类型代码或动态行为 ```python from typing import Any def debug_log(obj: Any) -> None: print(repr(obj)) ``` * 函数类型注解 * 为函数添加typing模块的注解后,函数使用者就能清晰的了解函数的参数以及返回值类型 ```python def greet(name: str) -> str: # 参数类型 -> 返回值类型 return f"Hello, {name}" def calculate(a: int, b: int) -> int: return a * b # 无返回值使用None def show_info(info: str) -> None: print(info) ``` * `Literal` 字面量类型 * 精确值类型约束, 替代简单字符串枚举 * 适用场景:枚举值的类型安全 ```python from typing import Literal # 限定特定值 HttpMethod = Literal["GET", "POST", "PUT", "DELETE"] def send_request(method: HttpMethod, url: str) -> None: print(f"Sending {method} request to {url}") send_request("POST", "/api") # ✅ send_request("PATCH", "/api") # ❌ mypy报错 ``` * `Union`联合类型 * Union允许参数接受多种不同类型的数据。 * 例如 `Union[int, float]`表示变量可以是int类型或float类型 ```python from typing import Union def process_input(value: Union[int, str]) -> None: if isinstance(value, int): print(f"Number: {value}") else: print(f"String: {value}") process_input(42) # Number: 42 process_input("test") # String: test ``` * `Optional`可选类型 * `Optional`表示参数可以是指定类型或者`None` * 让编译器识别到该参数有一个类型提示,可以使指定类型,也可以是None,且参数是可选非必传的。 * `Optional[int]` 等价于 `Union[int, None]`,表示:既可以传指定的类型 int,也可以传 None, `Optional[ ]` 里面只能写一个数据类型 * 适用场景:可能返回空值的操作 * 在下面函数定义中,Optional[str] = None表示参数name的类型可以是str或None。 * 注意 * `= None`可省略,它表示默认参数。 * 从 Python 3.10 开始,Optional[Type] 可以直接用 `Type | None` 替代,写法更清晰 ```python from typing import Optional def greet1(name: Optional[str] = None) -> str: if name: return f"Hello, {name}!" else: return "Hello, world!" def greet2(name: Optional[str]) -> str: if name: return f"Hello, {name}!" else: return "Hello, world!" print(greet1()) # print(greet2()) # 报错,必须要有参数 print(greet1("老王")) print(greet2("冰冰")) ``` * 类型别名 * 自定义类型别名提高代码可读性。 ```python from typing import Tuple # 基本别名 UserId = int Point = Tuple[float, float] def get_user(id: UserId) -> str: return f"User{id}" def plot(points: List[Point]) -> None: for x, y in points: print(f"({x}, {y})") ``` * `NewType`新类型创建 * 创建具有类型检查的语义化新类型 * 适合 区分相同基础类型的不同用途 ```python from typing import NewType # 创建强类型 UserId = NewType('UserId', int) admin_id = UserId(1001) def print_id(user_id: UserId) -> None: print(user_id) # 正确调用 print_id(admin_id) # ✅ print_id(1001) # ❌ mypy报错 ``` * `TypeVar`(类型变量) * 创建通用类型参数 * 适用场景:泛型函数/类的类型参数化;比如创建一个函数,无论是处理整数、字符串还是自定义对象 ```python from typing import TypeVar, Sequence T = TypeVar('T') # 无约束类型 Num = TypeVar('Num', int, float) # 受限类型 def first(items: Sequence[T]) -> T: return items[0] def sum(values: Sequence[Num]) -> Num: return sum(values) ``` ```python from typing import TypeVar # 定义一个泛型变量T T = TypeVar('T') # 创建一个泛型函数 def get_first_item(items: list[T]) -> T: """获取列表的第一个元素""" if items: return items[0] raise ValueError("列表为空") # 使用示例 numbers = [1, 2, 3, 4, 5] words = ['apple', 'banana', 'cherry', 'fruit'] print(get_first_item(numbers)) # 输出: 1 print(get_first_item(words)) # 输出: apple ``` ###
评论区