LangChain 深入

作者:吴佳浩日期:2025/12/1

LangChain 深入

这里需要装什么包什么依赖 我就不再一一赘述了 大家可以先看上一篇 《Langchain 浅出》

那么如果出现缺失的依赖怎么办 ?简单 缺什么装什么

人工智能的无限可能.png

目录

  • 1、Python 依赖安装
  • 2、词工程最佳实践
  • 3、性能优化技巧
  • 4、常见问题与解决方案
  • 5、调试和错误处理
  • 6、生产环境最佳实践

想了想还是给补一份基础的依赖吧 ,至于为什么,我也不知道 但是我还是补上了

另外

本章篇幅比较密的代码示例需要个人花点时间理解和消化有问题可以在评论区交流

Python 依赖安装(全套覆盖)

核心依赖(所有 demo 都需要)

1pip install --upgrade pip setuptools wheel
2pip install python-dotenv           # 环境变量管理
3pip install langchain==1.0.*       # LangChain 1.x 核心
4pip install langchain-ollama       # Ollama LLM 支持
5pip install ollama                  # Ollama 官方客户端(模型自检/拉取)
6

向量数据库与文档检索(文档助手/检索 demo)

1pip install langchain-chroma        # Chroma 向量数据库
2pip install langchain-community     # 社区扩展功能(额外工具、插件)
3pip install chromadb                # Chroma 官方依赖
4

文档加载(PDF / Word / 通用文档)

1pip install unstructured           # 文本/结构化文档加载
2pip install pypdf                   # PDF 文档解析
3pip install python-docx             # Word 文档解析
4

Embeddings / NLP(可选替代 Ollama Embedding)

1pip install sentence-transformers   # 文本向量生成,可选
2

词工程最佳实践

1flowchart TD
2    A[开始] --> B["定义示例数据<br>examples"]
3    B --> C["创建PromptTemplate<br>example_prompt"]
4    C --> D["设置LengthBasedExampleSelector<br>selector"]
5    D --> E["构建FewShotPromptTemplate<br>few_shot"]
6    E --> F["初始化ChatOllama模型"]
7    F --> G["遍历输入情绪列表"]
8    G --> H["格式化提示词<br>few_shot.format()"]
9    H --> I["调用模型生成回复<br>llm.invoke()"]
10    I --> J["打印回复结果"]
11    J --> K{还有更多情绪?}
12    K -->|是| G
13    K -->|否| END(("END"))
14
15

创建文件 advanced_prompting.py

1"""
2高级提示词技巧(基于 LangChain 1.0 + LangGraph)
3"""
4
5from langchain_ollama import ChatOllama
6from langchain_core.prompts import (
7    ChatPromptTemplate, # 提示词模板
8    SystemMessagePromptTemplate,# 系统消息模板
9    HumanMessagePromptTemplate,# 角色消息模板
10    PromptTemplate, # 单个示例格式
11    FewShotPromptTemplate # 少样本学习示例
12)
13from langchain_core.example_selectors import LengthBasedExampleSelector
14# from dotenv import load_dotenv 还是和之前一样 因为我们本地使用的ollama基本都是默认的配置所以暂时不加载配置文件 
15
16# load_dotenv()
17
18
19def few_shot_learning():
20    """少样本学习:通过示例教模型执行任务(LangChain 1.0 风格)"""
21
22    examples = [
23        {"input": "开心", "output": "😊 今天心情真好!"},
24        {"input": "难过", "output": "😢 有些失落,不过会慢慢好起来。"},
25        {"input": "兴奋", "output": "🎉 太棒了!令人振奋的消息!"}
26    ]
27
28    # 单个示例格式
29    example_prompt = PromptTemplate(
30        template="情绪:{input}\n回复:{output}",
31        input_variables=["input", "output"],
32    )
33
34    # 示例选择器(自动选择合适数量)
35    selector = LengthBasedExampleSelector(
36        examples=examples,
37        example_prompt=example_prompt,
38        max_length=100
39    )
40
41    few_shot = FewShotPromptTemplate(
42        example_selector=selector,
43        example_prompt=example_prompt,
44        prefix="你是一个情感友好的 AI 助手,会用 emoji 回复:\n\n示例:",
45        suffix="\n情绪:{input}\n回复:",
46        input_variables=["input"]
47    )
48
49    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.7)
50
51    emotions = ["激动", "焦虑", "感动"]
52
53    print("\n=== 少样本学习示例 ===")
54    for emotion in emotions:
55        prompt = few_shot.format(input=emotion)
56        res = llm.invoke(prompt)
57        print(f"\n情绪:{emotion}")
58        print(f"AI 回复:{res.content}")
59
60
61def role_based_prompting():
62    """基于角色的提示词(新版 lc3 PromptTemplate)"""
63
64    system_template = """
65你是一名{role}。
66特点:{characteristics}
67回答风格:{style}
68"""
69
70    system_msg = SystemMessagePromptTemplate.from_template(system_template)
71    human_msg = HumanMessagePromptTemplate.from_template("{question}")
72
73    prompt = ChatPromptTemplate.from_messages([system_msg, human_msg])
74
75    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.6)
76
77    roles = [
78        {
79            "role": "资深软件架构师",
80            "characteristics": "熟悉微服务、性能优化、分布式架构",
81            "style": "严谨、专业、会给出架构图示建议",
82            "question": "如何设计一个高并发的电商系统?"
83        },
84        {
85            "role": "耐心的编程老师",
86            "characteristics": "善于用比喻解释复杂概念",
87            "style": "温和、逐步讲解、举例子",
88            "question": "什么是类和对象?"
89        }
90    ]
91
92    print("\n=== 基于角色的提示词示例 ===")
93    for config in roles:
94        msgs = prompt.format_messages(**config)
95        res = llm.invoke(msgs)
96        print(f"\n角色:{config['role']}")
97        print(f"回答:{res.content}")
98
99
100def chain_of_thought_prompting():
101    """思维链提示(手动 CoT)"""
102
103    llm = ChatOllama(model="qwen3-coder:30b", temperature=0)
104
105    normal = "商店有23个苹果,卖出17个,又进了30个,现在有多少?"
106
107    cot = """
108商店有23个苹果,卖出17个,又进30个。
109
110请按照步骤推理:
1111. 卖出后剩余多少
1122. 再加上进货数量
1133. 计算最终结果
114"""
115
116    print("\n=== 思维链对比 ===")
117
118    print("\n【普通提示】")
119    print(llm.invoke(normal).content)
120
121    print("\n【思维链 CoT】")
122    print(llm.invoke(cot).content)
123
124
125if __name__ == "__main__":
126    few_shot_learning()
127    role_based_prompting()
128    chain_of_thought_prompting()
129
130

输出结果:

太长这里就放个截图示意吧

image.png image.png image.png image.png


性能优化技巧

1flowchart TD
2    开始[开始程序] --> 功能选择
3
4    功能选择 --> 缓存示例
5    功能选择 --> 批处理示例
6    功能选择 --> 流式输出示例
7
8    %% 缓存示例
9    缓存示例 --> 创建缓存
10    创建缓存 --> 初始化LLM
11    初始化LLM --> 第一次调用
12    第一次调用 --> 模型推理
13    模型推理 --> 存入缓存
14    初始化LLM --> 第二次调用
15    第二次调用 --> 缓存命中
16    缓存命中 --> 缓存完成
17
18    %% 批处理示例
19    批处理示例 --> 准备问题列表
20    准备问题列表 --> 循环调用
21    循环调用 --> 记录耗时1
22    准备问题列表 --> 批量调用
23    批量调用 --> 记录耗时2
24    记录耗时2 --> 批处理完成
25
26    %% 流式输出示例
27    流式输出示例 --> 初始化LLM流
28    初始化LLM流 --> 调用流方法
29    调用流方法 --> 接收分块
30    接收分块 --> 流处理完成
31
32    缓存完成 --> 结束
33    批处理完成 --> 结束
34    流处理完成 --> 结束
35
36

创建文件 optimization_tips.py

1"""
2LangChain 1.x 性能优化技巧示例 —— 最新写法(2025)
3"""
4
5import time
6from dotenv import load_dotenv
7load_dotenv()
8
9# LangChain 1.x 最新模块
10from langchain_core.caches import InMemoryCache
11
12
13# Ollama LLM
14from langchain_ollama import ChatOllama
15
16
17def caching_example():
18    """使用缓存减少重复调用"""
19
20    print("=" * 50)
21    print("缓存优化示例(LangChain 1.x)")
22    print("=" * 50)
23
24    # 设置全局缓存(官方推荐方式)
25    cache = InMemoryCache()
26
27    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.7,cache=cache)
28
29    question = "什么是机器学习?"
30
31    # 第一次调用(非缓存)
32    print(f"\n问题:{question}")
33    print("第一次调用(未缓存)...")
34    start = time.time()
35    response1 = llm.invoke(question)
36    time1 = time.time() - start
37    print(f"耗时:{time1:.2f} 秒")
38    print(f"答案:{response1.content[:100]}...")
39
40    # 第二次调用(缓存命中)
41    print("\n第二次调用(已缓存)...")
42    start = time.time()
43    response2 = llm.invoke(question)
44    time2 = time.time() - start
45    print(f"耗时:{time2:.2f} 秒")
46    if time2 == 0:
47     print("🚀 速度提升:∞(缓存命中,耗时约 0 秒)")
48    else:
49        print(f"🚀 速度提升:{time1/time2:.1f} 倍")
50
51
52def batch_processing():
53    """批量处理以减少网络调用"""
54
55    print("\n" + "=" * 50)
56    print("批量处理示例(LangChain 1.x)")
57    print("=" * 50)
58
59    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.7)
60
61    questions = [
62        "Python 是什么?",
63        "Java 是什么?",
64        "JavaScript 是什么?"
65    ]
66
67    # 方式1:逐个处理
68    print("\n方式1:逐个调用 invoke()")
69    start = time.time()
70    for q in questions:
71        llm.invoke(q)
72    time1 = time.time() - start
73    print(f"总耗时:{time1:.2f} 秒")
74
75    # 方式2:批量处理(LangChain 1.x 推荐)
76    print("\n方式2:使用 llm.batch()")
77    start = time.time()
78    responses = llm.batch(questions)
79    time2 = time.time() - start
80    if time2 == 0:
81        print("🚀 速度提升:∞(缓存命中,耗时约 0 秒)")
82    else:
83        print(f"🚀 速度提升:{time1/time2:.1f} 倍")
84
85
86def streaming_output():
87    """流式输出,提升用户体验"""
88
89    print("\n" + "=" * 50)
90    print("流式输出示例(LangChain 1.x)")
91    print("=" * 50)
92
93    # 流式输出无需 streaming=True
94    llm = ChatOllama(
95        model="qwen3-coder:30b",
96        temperature=0.7,
97    )
98
99    print("\n生成中:", end="", flush=True)
100
101    # LangChain 1.x 官方写法:llm.stream()
102    for chunk in llm.stream("请用100字介绍人工智能的发展历史"):
103        print(chunk.content, end="", flush=True)
104
105    print("\n")
106
107
108if __name__ == "__main__":
109    caching_example()
110    batch_processing()
111    streaming_output()
112
113

输出结果:

1==================================================
2缓存优化示例(LangChain 1.x)
3==================================================
4
5问题:什么是机器学习?
6第一次调用(未缓存)...
7耗时:1.35 
8答案:机器学习是人工智能的一个重要分支,它让计算机能够在不被明确编程的情况下,通过分析大量数据来自动学习和改进。
9
10## 核心概念
11机器学习让计算机从经验中学习规律,并利用这些规律对新的、未见过的数据进行预...
12
13第二次调用(已缓存)...
14耗时:0.00 
15🚀 速度提升:∞(缓存命中,耗时约 0 秒)
16
17==================================================
18批量处理示例(LangChain 1.x)
19==================================================
20
21方式1:逐个调用 invoke()
22总耗时:4.56 
23
24方式2:使用 llm.batch()
25🚀 速度提升:1.0 
26
27==================================================
28流式输出示例(LangChain 1.x)
29==================================================
30
31生成中:人工智能发展可追溯至1950年代。1956年达特茅斯会议正式确立AI概念。经历了多次起伏:1970年代专家系统兴起,1980年代遭遇"AI寒冬",1990年代机器学习兴起。21世纪后,大数据、深度学习技术突破,AI迎来快速发展期,在图像识
32别、自然语言处理等领域取得重大进展,正深刻改变着人类生活。
33
34(venv) PS D:\softwares\langchin_learning> 
35

常见问题与解决方案(1.0 版本)

1. 模型初始化与 API Key

问题:模型无法调用或报错

解决方案

  • OpenAI:检查 API Key 是否正确,确保环境变量已加载
1import os  
2from dotenv import load_dotenv  
3load_dotenv()  
4api_key = os.getenv("OPENAI_API_KEY")  
  • ChatOllama / 本地 Ollama 模型:无需网络 API,只要 Ollama Server 已启动即可
1ollama list  # 检查模型是否可用  
  • 确保 虚拟环境正确激活,并安装最新依赖:
1pip install -U langchain langchain-ollama python-dotenv  

2. 依赖包版本冲突

问题ImportError 或模块版本不兼容

解决方案

  • 使用虚拟环境隔离项目依赖(venv / conda / poetry)
  • 升级至最新版本:
1pip install --upgrade langchain langchain-ollama python-dotenv  
  • 确保 Python 版本 3.9 以上

3. 网络与本地服务连接问题

问题:模型无法访问

解决方案

  • OpenAI:确保网络可用,必要时配置代理
  • ChatOllama(本地模型)
    • Ollama Server 必须启动
    • 使用命令检查模型列表:
    1ollama list  
    • 测试本地端口:
    1curl http://localhost:11434  

4. Token 限制或显存问题

问题:模型响应超时或显存不足

解决方案

  • OpenAI:注意速率限制(RateLimit),可降低请求频率或批量调用
  • 本地 Ollama
    • 没有调用次数限制,但受显卡显存影响
    • 可选择小模型,如:
    1Qwen2.5:3B < Qwen2.5:7B < Qwen3-coder:30B  
  • 对于超长 Prompt:建议分段或使用 llm.batch() 批量调用

5. 流式输出与回调问题

问题:流式输出不生效或回调不触发

解决方案

  • 流式输出
    • 最新 LangChain 1.x 不再使用 streaming=True 参数
    • 正确方法:
    1for chunk in llm.stream("你的 Prompt"):  
    2    print(chunk.content, end="")  
  • 回调
    • 使用 langchain_core.callbacks.BaseCallbackHandler 编写自定义回调
    • 确保在 LLM 或 Runnable 初始化时传入:
    1from langchain_core.callbacks import CallbackManager, BaseCallbackHandler  
    2class MyHandler(BaseCallbackHandler):  
    3    def on_llm_new_token(self, token):  
    4        print(token, end="")  
    5callback_manager = CallbackManager([MyHandler()])  
    6llm = ChatOllama(model="Qwen2.5:7b", callback_manager=callback_manager)  

6. 其他常见问题

  • 缓存未生效:确保使用最新 InMemoryCachePersistentCache,并传入 LLM:
1from langchain_core.caches import InMemoryCache  
2llm = ChatOllama(model="Qwen2.5:7b", cache=InMemoryCache())  
  • 批量调用报错:检查输入是 list[str],使用 .batch() 方法
  • 超长输出截断:可使用 max_tokens 参数或分段请求

调试和错误处理

创建文件 debugging_guide.py

1"""
2LangChain 1.x 调试与错误处理示例 —— 最新写法(2025)
3"""
4
5import logging
6from dotenv import load_dotenv
7load_dotenv()
8
9# 最新 LangChain 1.x 模块
10from langchain_ollama import ChatOllama
11from langchain_core.callbacks import StdOutCallbackHandler
12
13# 配置日志
14logging.basicConfig(level=logging.INFO)
15logger = logging.getLogger(__name__)
16
17
18def verbose_mode_example():
19    """使用回调追踪详细执行过程(替代旧的 LLMChain + verbose)"""
20    
21    print("=" * 50)
22    print("Verbose 模式示例")
23    print("=" * 50)
24    
25    # 初始化 Ollama LLM
26    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.7)
27    
28    # 回调处理器打印详细信息
29    handler = StdOutCallbackHandler()
30    
31    # 直接调用 LLM 并传入回调
32    response = llm.invoke(
33        "请用一句话介绍量子计算",
34        config={"callbacks": [handler]}
35    )
36    
37    print(f"\n最终结果:{response.content}")
38
39
40def callback_example():
41    """使用回调处理器追踪 LLM 调用"""
42    
43    print("\n" + "=" * 50)
44    print("回调处理器示例")
45    print("=" * 50)
46    
47    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.7)
48    
49    handler = StdOutCallbackHandler()
50    
51    response = llm.invoke(
52        "什么是区块链?",
53        config={"callbacks": [handler]}
54    )
55    
56    print(f"\n答案:{response.content}")
57
58
59def error_handling_example():
60    """错误处理最佳实践"""
61    
62    print("\n" + "=" * 50)
63    print("错误处理示例")
64    print("=" * 50)
65    
66    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.7)
67    
68    try:
69        response = llm.invoke("测试问题")
70        print(f"成功:{response.content}")
71        
72    except Exception as e:
73        logger.error(f"调用 LLM 出错: {type(e).__name__}")
74        logger.error(f"错误详情: {str(e)}")
75        
76        err_msg = str(e).lower()
77        if "rate_limit" in err_msg:
78            print("触发速率限制,请稍后重试")
79        elif "authentication" in err_msg:
80            print("API 密钥错误,请检查配置")
81        elif "timeout" in err_msg:
82            print("请求超时,请检查网络")
83        else:
84            print(f"未知错误:{e}")
85
86
87def token_counting():
88    """Token 计数示例(仅适用于 OpenAI API)"""
89    
90    print("\n" + "=" * 50)
91    print("Token 计数示例")
92    print("=" * 50)
93    
94    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.7)
95    
96    # Ollama 本地模型无法使用 get_openai_callback
97    print("⚠ Ollama 本地模型不支持 OpenAI Token 计数,此示例仅供 OpenAI API 使用")
98    
99    # OpenAI 可用写法(保留示例)
100    """
101    from langchain_core.callbacks import get_openai_callback
102    with get_openai_callback() as cb:
103        response = llm.invoke("请详细介绍 Python 编程语言的特点和应用场景")
104        print(f"答案:{response.content}")
105        print(f"总 Token:{cb.total_tokens}, 提示词 Token:{cb.prompt_tokens}, 响应 Token:{cb.completion_tokens}")
106        print(f"总成本:${cb.total_cost:.4f}")
107    """
108
109
110if __name__ == "__main__":
111    verbose_mode_example()
112    callback_example()
113    error_handling_example()
114    token_counting()
115
116

输出结果:

1==================================================
2Verbose 模式示例
3==================================================
4INFO:httpx:HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
5
6最终结果:量子计算是一种利用量子比特的叠加和纠缠特性进行并行计算的新型计算方式,能够在某些特定问题上实现指数级的计算速度提升。
7
8==================================================
9回调处理器示例
10==================================================
11INFO:httpx:HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
12
13答案:区块链是一种**分布式数据库技术**,它将数据存储在按时间顺序链接的区块中,每个区块都包含前一个区块的加密哈希值,形成一个不可篡改的链式结构。
14
15## 核心特征
16
17**1. 去中心化**
18- 没有单一控制者
19- 多个节点共同维护网络
20
21**2. 不可篡改**
22- 一旦数据写入就很难修改
23- 修改需要网络中大多数节点同意
24
25**3. 透明可追溯**
26- 所有交易记录公开可见
27- 可以追踪数据的完整历史
28
29## 工作原理
30
311. **区块创建**:新数据被打包成区块
322. **加密验证**:通过密码学算法验证区块
333. **网络共识**:多个节点确认区块有效性
344. **链式连接**:新区块链接到现有链上
35
36## 主要应用
37- **加密货币**:比特币、以太坊等
38- **智能合约**:自动执行的合约协议
39- **供应链管理**:商品溯源追踪
40- **数字身份**:身份认证和管理
41- **医疗记录**:安全存储和共享
42
43区块链技术正在多个领域发挥重要作用,为数据安全和信任建立提供了新的解决方案。
44
45==================================================
46错误处理示例
47==================================================
48INFO:httpx:HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
49成功:您好!我注意到您提到了"测试问题",但我没有看到具体需要测试的内容。为了更好地帮助您,能否请您:
50
511. **说明具体需要测试什么?**
52   - 是技术问题、逻辑问题、还是其他类型的测试?
53   - 请提供详细的问题描述
54
552. **告知测试的背景**
56   - 这是关于什么领域的测试?
57   - 有什么特殊要求吗?
58
593. **提供相关材料**
60   - 如果有代码、数据或其他资料,请一并提供
61
62请补充这些信息,我就能为您提供更准确和有用的测试帮助了。期待您的详细说明!
63
64==================================================
65Token 计数示例
66==================================================
67 Ollama 本地模型不支持 OpenAI Token 计数,此示例仅供 OpenAI API 使用
68

生产环境最佳实践

1sequenceDiagram
2    participant 用户
3    participant 日志系统
4    participant 限流器
5    participant LLM客户端
6    participant Ollama模型
7
8    用户->>日志系统: 发送请求 "问题 X"
9    日志系统->>日志系统: 记录收到的请求
10    日志系统->>限流器: 检查请求是否允许
11    alt 请求被允许
12        限流器-->>日志系统: 允许
13        日志系统->>LLM客户端: 调用 safe_generate()
14        LLM客户端->>LLM客户端: validate_input()
15        alt 输入有效
16            LLM客户端->>LLM客户端: retry_on_failure
17            LLM客户端->>Ollama模型: invoke(prompt)
18            Ollama模型-->>LLM客户端: 返回生成内容
19            LLM客户端-->>日志系统: 响应生成成功
20            日志系统-->>用户: 返回响应内容
21        else 输入无效
22            LLM客户端-->>日志系统: 输入验证失败
23            日志系统-->>用户: 返回错误信息
24        end
25    else 请求被限制
26        限流器-->>日志系统: 超过速率限制
27        日志系统-->>用户: 返回限制提示
28    end
29
30

创建文件 production_best_practices.py

1"""
2生产环境部署最佳实践(LangChain 1.0 + Ollama)
3"""
4
5from langchain_ollama import ChatOllama
6from dotenv import load_dotenv
7import os
8import time
9from functools import wraps
10from collections import deque
11import logging
12
13load_dotenv()
14
15# =========================
16# 重试装饰器
17# =========================
18def retry_on_failure(max_retries=3, delay=1):
19    """自动重试失败的请求"""
20    def decorator(func):
21        @wraps(func)
22        def wrapper(*args, **kwargs):
23            for attempt in range(max_retries):
24                try:
25                    return func(*args, **kwargs)
26                except Exception as e:
27                    if attempt < max_retries - 1:
28                        print(f"尝试 {attempt + 1} 失败: {e}")
29                        print(f"等待 {delay} 秒后重试...")
30                        time.sleep(delay * (attempt + 1))
31                    else:
32                        print(f"所有 {max_retries} 次尝试均失败")
33                        raise
34        return wrapper
35    return decorator
36
37# =========================
38# 生产环境 LLM 客户端
39# =========================
40class ProductionLLMClient:
41    """生产环境 LLM 客户端封装(Ollama)"""
42    def __init__(self):
43        # 从环境变量读取配置
44        self.model = os.getenv("LLM_MODEL", "Qwen2.5:7b")
45        self.temperature = float(os.getenv("LLM_TEMPERATURE", "0.7"))
46        self.max_tokens = int(os.getenv("LLM_MAX_TOKENS", "500"))
47
48        # 初始化 Ollama LLM
49        self.llm = ChatOllama(
50            model=self.model,
51            temperature=self.temperature,
52            max_tokens=self.max_tokens,
53            streaming=False
54        )
55
56        print(f"✓ LLM 客户端初始化完成")
57        print(f"  模型: {self.model}")
58        print(f"  温度: {self.temperature}")
59        print(f"  最大 Token: {self.max_tokens}")
60
61    @retry_on_failure(max_retries=3, delay=2)
62    def generate(self, prompt):
63        """生成响应(带重试机制)"""
64        try:
65            response = self.llm.invoke(prompt)
66            return response.content
67        except Exception as e:
68            print(f"生成失败: {e}")
69            raise
70
71    def validate_input(self, text, max_length=1000):
72        """验证输入合法性"""
73        if not text or not isinstance(text, str):
74            return False
75        if len(text) > max_length:
76            return False
77        return True
78
79    def safe_generate(self, user_input):
80        """安全生成响应"""
81        if not self.validate_input(user_input):
82            return {"success": False, "error": "输入无效或过长"}
83        try:
84            response = self.generate(user_input)
85            return {"success": True, "response": response}
86        except Exception as e:
87            return {"success": False, "error": str(e)}
88
89# =========================
90# 日志示例
91# =========================
92def logging_example():
93    logging.basicConfig(
94        level=logging.INFO,
95        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
96        handlers=[logging.FileHandler('langchain_app.log'), logging.StreamHandler()]
97    )
98    logger = logging.getLogger(__name__)
99
100    print("=" * 50)
101    print("日志记录示例")
102    print("=" * 50)
103
104    client = ProductionLLMClient()
105    user_input = "什么是机器学习?"
106    logger.info(f"收到用户请求: {user_input}")
107
108    result = client.safe_generate(user_input)
109    if result["success"]:
110        logger.info("响应生成成功")
111        print(f"\n响应: {result['response']}")
112    else:
113        logger.error(f"响应生成失败: {result['error']}")
114        print(f"\n错误: {result['error']}")
115
116# =========================
117# 速率限制示例
118# =========================
119def rate_limiting_example():
120    class RateLimiter:
121        """简单速率限制器"""
122        def __init__(self, max_calls, time_window):
123            self.max_calls = max_calls
124            self.time_window = time_window
125            self.calls = deque()
126
127        def allow_request(self):
128            now = time.time()
129            while self.calls and self.calls[0] < now - self.time_window:
130                self.calls.popleft()
131            if len(self.calls) < self.max_calls:
132                self.calls.append(now)
133                return True
134            return False
135
136    print("\n" + "=" * 50)
137    print("速率限制示例")
138    print("=" * 50)
139
140    limiter = RateLimiter(max_calls=5, time_window=60)
141    client = ProductionLLMClient()
142
143    for i in range(7):
144        if limiter.allow_request():
145            print(f"\n请求 {i+1}: 允许")
146            result = client.safe_generate(f"问题 {i+1}")
147            print(f"响应: {result.get('response', result.get('error'))[:50]}...")
148        else:
149            print(f"\n请求 {i+1}: 被限制(超过速率限制)")
150
151# =========================
152# 主函数
153# =========================
154if __name__ == "__main__":
155    logging_example()
156    rate_limiting_example()
157
158

输出结果:

1==================================================
2日志记录示例
3==================================================
4 LLM 客户端初始化完成
5  模型: qwen3-coder:30b
6  温度: 0.7
7  最大 Token: 500
82025-12-02 01:20:12,445 - __main__ - INFO - 收到用户请求: 什么是机器学习?
92025-12-02 01:20:12,649 - httpx - INFO - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
102025-12-02 01:20:14,011 - __main__ - INFO - 响应生成成功
11
12响应: 机器学习是人工智能的一个重要分支,它让计算机能够在不被明确编程的情况下,通过分析大量数据来自动学习和改进。
13
14## 核心概念
15机器学习让计算机从数据中"学习"规律和模式,然后利用这些知识对新的、未见过的数据进行预测或决策。
16
17## 工作原理
181. **输入数据** - 提供大量带有标签或无标签的数据
192. **算法学习** - 机器学习算法分析数据中的模式
203. **建立模型** - 构建能够识别模式的数学模型
214. **预测应用** - 对新数据进行预测或分类
22
23## 主要类型
24- **监督学习** - 使用带标签的数据训练
25- **无监督学习** - 从未标记数据中发现隐藏模式
26- **强化学习** - 通过与环境交互来学习最优行为
27
28## 常见应用
29- 图像识别和人脸识别
30- 语音助手(如Siri、Alexa)
31- 推荐系统(如抖音、淘宝推荐)
32- 自动驾驶汽车
33- 医疗诊断辅助
34- 金融风险评估
35
36机器学习正在深刻改变我们的生活,让许多以前需要人类智能才能完成的任务变得自动化。
37
38==================================================
39速率限制示例
40==================================================
41 LLM 客户端初始化完成
42  模型: qwen3-coder:30b
43  温度: 0.7
44  最大 Token: 500
45
46请求 1: 允许
472025-12-02 01:20:14,109 - httpx - INFO - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
48响应: 您好!我注意到您提到了"问题 1",但我没有看到具体的问题内容。请您提供需要解决的问题,我会很乐意帮...
49
50请求 2: 允许
512025-12-02 01:20:14,529 - httpx - INFO - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
52响应: 我注意到您提到了"问题 2",但我没有看到具体的问题内容。请您提供需要解答的具体问题,我会很乐意帮助...
53
54请求 3: 允许
552025-12-02 01:20:14,948 - httpx - INFO - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
56响应: 我需要更多信息来帮助您解决"问题 3"。您能提供以下信息吗:
57
581. **具体问题内容** - 您想...
59
60请求 4: 允许
612025-12-02 01:20:15,564 - httpx - INFO - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
62响应: 我需要更多信息来帮助您解决"问题4"。您能提供:
63
641. **具体的问题内容** - 您想解决什么问...
65
66请求 5: 允许
672025-12-02 01:20:16,073 - httpx - INFO - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
68响应: 我需要更多信息来帮助您解决"问题 5"。您能提供:
69
701. **具体的问题内容** - 您想解决什么...
71
72请求 6: 被限制(超过速率限制)
73
74请求 7: 被限制(超过速率限制)
75

常见应用场景

场景 1:智能客服机器人

🔹 流程说明

  1. 用户输入 → 机器人接收
  2. 机器人拼接系统提示 + 最近 N 轮对话 → 形成完整 prompt
  3. 窗口记忆 → 保留最近几轮对话,避免 prompt 过长
  4. 调用 Ollama LLM → 生成回答
  5. 更新历史 → 将用户消息和模型回答都记录进窗口记忆
  6. 返回给用户 → 输出响应
1sequenceDiagram  
2    participant 用户  
3    participant 客服机器人  
4    participant LLM模型  
5    用户->>客服机器人: 输入消息 "问题 X"  
6    客服机器人->>客服机器人: 拼接系统提示和历史对话  
7    客服机器人->>客服机器人: 保留最近 N 轮对话(窗口记忆)  
8    客服机器人->>LLM模型: invoke(prompt)  
9    LLM模型-->>客服机器人: 返回生成内容  
10    客服机器人->>客服机器人: 更新窗口记忆 (user + assistant)  
11    客服机器人-->>用户: 返回响应内容  
1"""
2智能客服机器人示例(LangChain 1.x + Ollama)
3"""
4
5from langchain_ollama import ChatOllama
6from langchain_core.caches import InMemoryCache
7from dotenv import load_dotenv
8load_dotenv()
9
10class CustomerServiceBot:
11    """客服机器人类(新写法)"""
12
13    def __init__(self, window_size: int = 5):
14        # 窗口记忆:只保留最近 window_size 轮对话
15        self.window_size = window_size
16        self.history = []  # [(role, content)],role: "user"  "assistant"
17
18        # 系统提示词
19        self.system_prompt = """你是一名专业的客服代表,具有以下特点:
20            1. 友好、耐心、专业
21            2. 能够快速理解客户问题
22            3. 提供清晰、准确的答案
23            4. 对于不确定的问题,会坦诚告知并提供进一步帮助的途径
24
25            客户服务原则:
26            - 始终保持礼貌和专业
27            - 快速响应客户问题
28            - 提供具体的解决方案
29            - 必要时询问更多细节
30            """
31
32        # 初始化 Ollama LLM
33        self.llm = ChatOllama(
34            model="qwen3-coder:30b",
35            temperature=0.7,
36            streaming=False,
37            cache=InMemoryCache()  # 可选缓存
38        )
39
40    def _build_prompt(self, user_message: str) -> str:
41        """根据系统提示和窗口记忆生成完整 prompt"""
42        prompt_parts = [self.system_prompt]
43        # 添加最近的对话历史
44        for role, content in self.history[-self.window_size:]:
45            prefix = "客户:" if role == "user" else "客服:"
46            prompt_parts.append(f"{prefix} {content}")
47        # 添加当前用户问题
48        prompt_parts.append(f"客户:{user_message}\n客服:")
49        return "\n".join(prompt_parts)
50
51    def respond(self, user_message: str) -> str:
52        """生成响应并更新窗口记忆"""
53        prompt = self._build_prompt(user_message)
54        response = self.llm.invoke(prompt).content.strip()
55        # 更新窗口记忆
56        self.history.append(("user", user_message))
57        self.history.append(("assistant", response))
58        return response
59
60    def reset(self):
61        """清空对话历史"""
62        self.history.clear()
63
64
65# =========================
66# 使用示例
67# =========================
68if __name__ == "__main__":
69    bot = CustomerServiceBot()
70    print("客服机器人已启动(输入 'quit' 退出)\n")
71
72    while True:
73        user_input = input("客户: ")
74        if user_input.lower() == "quit":
75            print("已退出对话。")
76            break
77        response = bot.respond(user_input)
78        print(f"客服: {response}\n")
79
80

输出结果:(输出结果中的客户是我自己输入的内容模拟客户和客服对话的过程)

1客服机器人已启动(输入 'quit' 退出)
2
3客户: 我的东西什么时候发货
4客服: 您好!很抱歉为您查询订单发货信息。为了更好地帮助您,我需要一些详细信息:
5
61. 您能提供订单号码吗?(通常在订单确认邮件或您的账户订单历史中)
72. 您购买的是什么商品?
83. 大概是什么时候下的订单?
9
10有了这些信息,我就能为您准确查询发货状态了。
11
12另外,一般来说:
13- 普通订单通常在1-3个工作日内发货
14- 特殊商品可能需要更长时间
15- 促销活动期间可能会有延迟
16
17请提供您的订单信息,我会立即为您查询具体的发货时间!
18
19客户: 这样啊  那好吧
20客服: 您好!感谢您的耐心等待。
21
22为了能准确告诉您具体的发货时间,我需要您提供以下信息:
23
241. **订单号码**(在订单确认邮件或账户订单历史中可以找到)
252. **商品名称**(您购买了什么产品)
263. **下单时间**(大概什么时候买的)
27
28有了这些信息,我就能立即为您查询准确的发货状态了。
29
30如果您暂时找不到订单信息,也可以告诉我您的手机号或邮箱,我可以帮您查找相关订单。
31
32请问您现在方便提供这些信息吗?我会尽快为您查询!
33
34客户: 没了谢谢
35客服: 您好!感谢您的回复。
36
37如果您暂时无法提供订单信息,我完全理解。不过为了能帮您查询具体的发货时间,还是需要一些基本信息才能继续为您服务。
38
39如果您后续找到了订单号码或其他相关信息,欢迎随时联系我们,我会第一时间为您查询。
40
41另外,如果您是通过我们的官方渠道下单的,也可以:
42- 查看手机短信中的订单确认信息
43- 登录账户查看订单历史记录
44- 检查邮箱中的订单确认邮件
45
46如果您有任何其他问题或需要进一步帮助,请随时告诉我。祝您生活愉快!😊
47
48---
49*此回复符合客服专业标准:保持友好、提供帮助、不强求、给予选择、礼貌结束对话*
50

场景 2:代码生成助手

流程说明

  1. 用户输入编程语言和任务描述
  2. CodeGenerator 使用 PromptTemplate 将输入格式化为完整 Prompt
  3. 调用 ChatOllama 生成代码
    • 可以同步 invoke()
    • 或流式 stream()
  4. 对返回内容进行异常处理
  5. 返回最终代码或错误信息给用户
1sequenceDiagram  
2    autonumber  
3    participant 用户  
4    participant CodeGenerator  
5    participant PromptTemplate  
6    participant ChatOllama  
7    participant 响应处理  
8    用户->>CodeGenerator: 输入语言和任务  
9    CodeGenerator->>PromptTemplate: 根据输入生成完整 Prompt  
10    PromptTemplate-->>CodeGenerator: 返回格式化 Prompt  
11    CodeGenerator->>ChatOllama: 调用 invoke()  stream() 生成代码  
12    ChatOllama-->>CodeGenerator: 返回生成内容(流式或完整)  
13    CodeGenerator->>响应处理: 异常检查与处理  
14    响应处理-->>用户: 输出最终代码或错误信息  
1"""
2代码生成助手(LangChain 1.0 + Ollama)
3零警告、带异常处理、支持流式
4"""
5from __future__ import annotations
6import sys
7from typing import Optional
8
9from langchain_ollama import ChatOllama
10from langchain.prompts import PromptTemplate
11from langchain_core.output_parsers import StrOutputParser
12from ollama import Client as OllamaClient  # 轻量检查模型是否存在
13
14OLLAMA_HOST = "http://localhost:11434"  # 按需修改
15
16
17class CodeGenerator:
18    """代码生成器(兼容 LangChain 1.0)"""
19
20    def __init__(
21        self,
22        model: str = "qwen2.5:7b",
23        temperature: float = 0.3,
24        streaming: bool = False,
25    ) -> None:
26        self.model = model
27        self._validate_model()  # 启动前自检
28
29        self.llm = ChatOllama(
30            base_url=OLLAMA_HOST,
31            model=model,
32            temperature=temperature,
33            streaming=streaming,
34        )
35        self.prompt = PromptTemplate(
36            input_variables=["language", "task"],
37            template="""你是一名经验丰富的 {language} 开发者。
38
39任务:{task}
40
41要求:
421. 代码清晰、简洁
432. 添加必要注释
443. 遵循最佳实践
454. 包含错误处理
46
47请生成完整可运行代码:""",
48        )
49        # 1.0 管道语法:prompt | llm | parser
50        self.chain = self.prompt | self.llm | StrOutputParser()
51        self.streaming = streaming
52
53    # ---------- 工具 ----------
54    def _validate_model(self) -> None:
55        """本地不存在则自动拉取,失败抛 RuntimeError"""
56        try:
57            client = OllamaClient(host=OLLAMA_HOST)
58            models = {m["model"] for m in client.list()["models"]}
59            if self.model not in models:
60                print(f"[Info] 本地未检测到 {self.model},正在拉取...")
61                client.pull(self.model)
62        except Exception as e:
63            raise RuntimeError(f"Ollama 连接/拉取失败:{e}") from e
64
65    # ---------- 主要 API ----------
66    def generate(self, language: str, task: str) -> str:
67        """同步生成,返回字符串"""
68        try:
69            return self.chain.invoke({"language": language, "task": task})
70        except Exception as e:
71            return f"[Error] 生成失败:{e}"
72
73    def generate_stream(self, language: str, task: str):
74        """流式生成,生成器逐段 yield"""
75        if not self.streaming:
76            yield "[Warn] streaming=False,已强制返回完整文本\n"
77            yield self.generate(language, task)
78            return
79
80        try:
81            for chunk in self.chain.stream({"language": language, "task": task}):
82                yield chunk
83        except Exception as e:
84            yield f"[Error] 流式生成失败:{e}"
85
86
87# =========================
88# CLI 体验入口
89# =========================
90if __name__ == "__main__":
91    tasks = [
92        ("Python", "创建一个函数,计算列表中所有数字的平均值,包含异常处理"),
93        ("JavaScript", "写一个函数,实现防抖(debounce)功能,含注释"),
94    ]
95
96    gen = CodeGenerator(streaming=True)  # False 则一次性输出
97
98    for lang, task in tasks:
99        print("\n" + "=" * 70)
100        print(f"语言:{lang}  |  任务:{task}")
101        print("=" * 70 + "\n")
102
103        # 流式打印
104        for piece in gen.generate_stream(lang, task):
105            print(piece, end="", flush=True)
106        print()
107

输出结果:

1======================================================================
2语言:Python  |  任务:创建一个函数,计算列表中所有数字的平均值,包含异常处理
3======================================================================       
4
5```python
6def calculate_average(numbers):
7    """
8    计算列表中所有数字的平均值
9         
10    参数:
11        numbers (list): 包含数字的列表
12         
13    返回:
14        float: 数字的平均值
15      
16    异常:
17        TypeError: 当输入不是列表或列表中包含非数字元素时抛出
18        ValueError: 当列表为空时抛出
19    """
20     
21    # 检查输入是否为列表
22    if not isinstance(numbers, list):
23        raise TypeError("输入必须是一个列表")
24     
25    # 检查列表是否为空
26    if len(numbers) == 0:
27        raise ValueError("列表不能为空")
28     
29    # 检查列表中的每个元素是否为数字
30    for i, item in enumerate(numbers):
31        if not isinstance(item, (int, float)):
32            raise TypeError(f"列表中第 {i+1} 个元素 '{item}' 不是数字")
33
34    # 计算平均值
35    total = sum(numbers)
36    average = total / len(numbers)
37
38    return average
39
40
41def main():
42    """
43    主函数,用于测试 calculate_average 函数
44    """
45
46    # 测试用例
47    test_cases = [
48        [1, 2, 3, 4, 5],           # 正常情况
49        [10.5, 20.3, 30.2],        # 浮点数
50        [100],                     # 单个元素
51        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],  # 多个元素
52    ]
53
54    print("=== 正常测试用例 ===")
55    for i, test_list in enumerate(test_cases, 1):
56        try:
57            result = calculate_average(test_list)
58            print(f"测试 {i}: {test_list} -> 平均值: {result}")
59        except (TypeError, ValueError) as e:
60            print(f"测试 {i} 出错: {e}")
61
62    print("\n=== 异常处理测试 ===")
63
64    # 异常测试用例
65    error_test_cases = [
66        [],                        # 空列表
67        [1, 2, "3", 4],           # 包含字符串
68        [1, 2, None, 4],          # 包含 None
69        "not a list",             # 非列表输入
70        [1, 2, 3.5, "hello", 4],  # 混合类型
71    ]
72
73    for i, test_case in enumerate(error_test_cases, 1):
74        try:
75            result = calculate_average(test_case)
76            print(f"异常测试 {i}: {test_case} -> 平均值: {result}")
77        except (TypeError, ValueError) as e:
78            print(f"异常测试 {i}: {test_case} -> 错误: {e}")
79
80
81# 额外提供一个更简洁的版本(如果需要)
82def calculate_average_simple(numbers):
83    """
84    计算列表中所有数字的平均值(简化版本)
85
86    参数:
87        numbers (list): 包含数字的列表
88
89    返回:
90        float: 数字的平均值
91
92    异常:
93        TypeError: 当输入不是列表或列表中包含非数字元素时抛出
94        ValueError: 当列表为空时抛出
95    """
96
97    if not isinstance(numbers, list):
98        raise TypeError("输入必须是一个列表")
99
100    if not numbers:
101        raise ValueError("列表不能为空")
102
103    # 使用列表推导式检查所有元素是否为数字
104    if not all(isinstance(x, (int, float)) for x in numbers):
105        raise TypeError("列表中必须全部是数字")
106
107    return sum(numbers) / len(numbers)
108
109
110if __name__ == "__main__":
111    main()
112
113    print("\n=== 简化版本测试 ===")
114    try:
115        result = calculate_average_simple([1, 2, 3, 4, 5])
116        print(f"简化版本结果: {result}")
117    except (TypeError, ValueError) as e:
118        print(f"简化版本错误: {e}")

这个代码包含了以下特性:

主要功能:

  1. calculate_average() - 主要函数,计算平均值并包含完整的异常处理
  2. main() - 测试函数,演示正常和异常情况
  3. calculate_average_simple() - 简化版本,代码更简洁

异常处理:

  • 检查输入是否为列表
  • 检查列表是否为空
  • 检查列表中每个元素是否为数字(int 或 float)
  • 提供详细的错误信息

最佳实践:

  • 清晰的文档字符串
  • 详细的注释
  • 完整的测试用例
  • 遵循 Python 编码规范
  • 包含正常和异常情况的测试

运行结果示例:

=== 正常测试用例 ===
测试 1: [1, 2, 3, 4, 5] -> 平均值: 3.0
测试 2: [10.5, 20.3, 30.2] -> 平均值: 20.333333333333332
测试 3: [100] -> 平均值: 100.0
测试 4: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -> 平均值: 5.5

=== 异常处理测试 ===
异常测试 1: [] -> 错误: 列表不能为空
异常测试 2: [1, 2, '3', 4] -> 错误: 列表中第 3 个元素 '3' 不是数字
异常测试 3: [1, 2, None, 4] -> 错误: 列表中第 3 个元素 'None' 不是数字
异常测试 4: not a list -> 错误: 输入必须是一个列表
异常测试 5: [1, 2, 3.5, 'hello', 4] -> 错误: 列表中第 4 个元素 'hello' 不是数字

====================================================================== 语言:JavaScript | 任务:写一个函数,实现防抖(debounce)功能,含注释

1/**
2 * 防抖函数 - 防止函数在短时间内被频繁调用
3 * @param {Function} func - 需要防抖的函数
4 * @param {number} delay - 延迟时间(毫秒)
5 * @param {boolean} immediate - 是否立即执行(可选,默认false)
6 * @returns {Function} 返回防抖后的函数
7 * @throws {Error} 当参数类型不正确时抛出错误
8 */
9function debounce(func, delay, immediate = false) {
10  // 参数类型检查
11  if (typeof func !== 'function') {
12    throw new Error('第一个参数必须是函数');
13  }
14
15  if (typeof delay !== 'number' || delay < 0) {
16    throw new Error('延迟时间必须是大于等于0的数字');
17  }
18
19  let timeoutId = null; // 存储定时器ID
20
21  /**
22   * 防抖后的函数
23   * @param {...any} args - 原函数的参数
24   * @returns {any} 原函数的返回值
25   */
26  return function (...args) {
27    // 获取当前函数的上下文
28    const context = this;
29
30    // 清除之前的定时器
31    if (timeoutId) {
32      clearTimeout(timeoutId);
33    }
34
35    // 如果设置为立即执行
36    if (immediate) {
37      // 如果定时器不存在,说明是第一次执行,立即执行函数
38      const callNow = !timeoutId;
39
40      // 设置新的定时器,用于下次触发时的延迟执行
41      timeoutId = setTimeout(() => {
42        timeoutId = null; // 清空定时器ID,允许下次立即执行
43      }, delay);
44
45      // 如果是第一次执行,立即调用函数
46      if (callNow) {
47        return func.apply(context, args);
48      }
49    } else {
50      // 普通防抖:延迟执行
51      timeoutId = setTimeout(() => {
52        func.apply(context, args);
53      }, delay);
54    }
55  };
56}
57
58// 使用示例
59console.log('=== 防抖函数使用示例 ===');
60
61// 示例1:普通防抖
62const debouncedSearch = debounce(function (query) {
63  console.log('搜索:', query);
64  // 模拟搜索请求
65  return `搜索结果: ${query}`;
66}, 500);
67
68// 模拟频繁调用
69debouncedSearch('a');
70debouncedSearch('ab');
71debouncedSearch('abc');
72// 只有最后一次会执行,延迟500ms
73
74// 示例2:立即执行防抖
75const debouncedClick = debounce(function (event) {
76  console.log('点击事件:', event.target.id);
77  return '点击处理完成';
78}, 300, true);
79
80// 模拟点击事件
81debouncedClick({ target: { id: 'btn1' } });
82debouncedClick({ target: { id: 'btn2' } });
83// 第一次会立即执行,后续调用会被防抖
84
85// 示例3:错误处理演示
86try {
87  // 错误的参数类型
88  debounce('not a function', 100);
89} catch (error) {
90  console.log('捕获错误:', error.message);
91}
92
93try {
94  debounce(function() {}, -100);
95} catch (error) {
96  console.log('捕获错误:', error.message);
97}
98
99// 高级用法:取消防抖
100function createDebouncedFunction(func, delay) {
101  const debounced = debounce(func, delay);
102
103  // 添加取消方法
104  debounced.cancel = function () {
105    if (timeoutId) {
106      clearTimeout(timeoutId);
107      timeoutId = null;
108    }
109  };
110
111  return debounced;
112}
113
114// 使用取消功能
115const cancellableDebounce = createDebouncedFunction(function (data) {
116  console.log('处理数据:', data);
117}, 1000);
118
119cancellableDebounce('test1');
120cancellableDebounce.cancel(); // 取消执行
121cancellableDebounce('test2'); // 会正常执行
122
123console.log('防抖函数演示完成');

这个防抖函数实现包含以下特性:

主要功能:

  1. 普通防抖 - 在最后一次调用后延迟执行
  2. 立即执行防抖 - 第一次立即执行,后续调用防抖
  3. 完整的参数验证 - 类型检查和错误处理
  4. 上下文保持 - 保持原函数的this指向
  5. 参数传递 - 支持传递任意参数给原函数

特色功能:

  • 错误处理 - 对参数类型进行严格检查
  • 可取消 - 提供取消执行的功能
  • 详细注释 - 每个部分都有清晰的注释说明
  • 使用示例 - 包含多种使用场景的演示

使用场景:

  • 搜索框输入监听
  • 窗口大小调整事件
  • 按钮点击防抖
  • 滚动事件处理
  • 表单验证等需要防抖的场景

---

### 总结

Langchain的部分我们差不多就讲到这里接下来我们

下一篇我们讲LangGraph

学 LangChain 打造智能链式推理,

学 LangGraph 则是在此基础上构建复杂多节点知识与逻辑的可视化智能图,使系统架构更直观、高效且易于管理。

### 进阶学习资源

#### 官方资源

* **LangChain 官方文档**:[python.langchain.com/](https://link.juejin.cn?target=https%3A%2F%2Fpython.langchain.com%2F "https://python.langchain.com/")
* **LangChain GitHub**:[github.com/langchain-a…](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flangchain-ai%2Flangchain "https://github.com/langchain-ai/langchain")
* **LangChain 教程**:[python.langchain.com/docs/tutori…](https://link.juejin.cn?target=https%3A%2F%2Fpython.langchain.com%2Fdocs%2Ftutorials%2F "https://python.langchain.com/docs/tutorials/")

---

> 《[LangChain 深入](https://www.xyzblog.publicvm.com/5120f961698aab1119e232985cdd5d8d0dc3b9521d3b5f8adc2ee748273d4f88)》 是转载文章,[点击查看原文](https://juejin.cn/post/7578699975414366208)。

相关推荐


编程界 语言神 : 赶紧起来学 Rust 了!
Pomelo_刘金2025/12/10

大家对 Rust 的印象 没接触过的: 编程界语言神 整天重构这重构那 还要 要干掉 c++ ?! 稍微了解过的: 学习曲线: 但实际上是: 第一个高峰是 借用检查器,第二个是异步,第三个是unsafe,第四个是宏怎么玩? 开始接触之后 编译器不让我写代码,怎么写都报错 写 rust 代码像是在跟 rust 编译器谈对象 , 我只是传个参数,你跟我讲所有权、借用、生命周期?” 写的代码上线之后,还不错哦 “别的语言项目上线流程” 内容: 编译 ✔ 测试(偶尔挂一两条)✔ 上线后:半


ZooKeeper+Kafka
吉良吉影1232025/12/18

目录 一、Zookeeper 1.1 Zookeeper 概述 1.2 Zookeeper 工作机制 1.3 ZooKeeper 特点 1.4 Zookeeper 数据结构 1.5 ZooKeeper 应用场景 1.6 Zookeeper 选举机制 1.6.1 第一次启动选举机制 1.6.2 非第一次启动选举机制 Leader 的作用 1. 处理所有写请求(核心职责) 2. 主导 Leader 选举 3. 管理集群数据同步 4. 维护集群状态 Follower


算法竞赛中的数据结构:图
喜欢吃燃面2025/12/27

目录 一.图的基本概念1.图的定义2.图、树、线性表的联系与区别2.1 核心联系2.2 核心区别 二.图的分类1.按边的方向分类2.按边的权重分类3 .按顶点和边的数量分类4 .按连通性分类(针对无向图)5 .按强连通性分类(针对有向图)6 .其他特殊类型7.顶点的度(补充)8.路径及相关长度概念(补充)8.1 路径8.2 路径长度(无权图)8.3 带权路径长度(带权图)8.4 核心区别对比 三.邻接矩阵1.邻接矩阵【注意】 四.邻接表五.链式前向星


Linux系统安全及应用(账号权限管理、登录控制、弱口令、端口扫描)
晚风吹人醒.2026/1/5

目录 1. 账号管理与权限控制         1.1 基本安全措施:                 1.1.1 账号管理和文件权限                 1.1.2 密码安全控制                 1.1.3历史命令和自动注销         1.2 用户切换与提权: 2. 系统引导与登录控制         2.1 开关机安全控制:                 2.1.1 GRUB                 2.1.2 限制更改GRUB


绘制K线第二章:背景网格绘制
佛系打工仔2026/1/13

绘制K线第二章:背景网格绘制 在第一章的基础上,我们简单修饰一下,补充一个背景九宫格的绘制功能。这个功能可以让K线图更加清晰易读,帮助用户快速定位价格和时间。 二、网格配置 确定网格的行数和列数 在绘制网格之前,我们需要确定: 几行:将高度分成几等份(对应价格轴) 几列:将宽度分成几等份(对应时间轴) 例如:4列5行,表示宽度分成4等份,高度分成5等份。 在Config中配置 为了灵活配置网格,我们在 KLineConfig 中添加了两个字段: data class KLineConfig(


Python 线程局部存储:threading.local() 完全指南
哈里谢顿2026/1/21

一句话总结: threading.local() 是 Python 标准库提供的「线程局部存储(Thread Local Storage, TLS)」方案,让同一段代码在不同线程里拥有各自独立的变量空间,从而避免加锁,也避免了层层传参的狼狈。 1. 为什么需要线程局部存储? 在多线程环境下,如果多个线程共享同一个全局变量,就必须: 加锁 → 代码变复杂、性能下降; 或者层层传参 → 代码臃肿、可维护性差。 有些场景只想让线程各自持有一份副本,互不干扰: Web 服务:每个请求线程绑定自

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客