
Web-Dev-For-Beginners 第 10 课用 LangChain 构建 AI 框架应用——对话记忆、工具调用与结构化输出实战【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners本文是 Web-Dev-For-Beginners 课程第 10 课AI Framework的技术指南。你将学习如何以 LangChain 为核心框架配合 GitHub Models 免费模型服务完成从单次提问、多轮对话记忆、流式响应、提示词模板、结构化输出到工具调用、向量检索Embeddings/FAISS的完整 AI 应用开发流程并最终将这些能力整合为一个可运行的编码助手类应用。课程配套的三个可运行示例分别位于 code/python/app.py、code/python/app-chat.py 和 code/python/app-tools.py可对照本文逐步复现。为什么选择 AI 框架在动手之前先明确一个关键决策集成 AI 有主流三条路径各有取舍。课程原文给出的对比如下方案优势适用场景注意事项直接 HTTP 请求完全可控、无依赖简单查询、学习底层原理代码冗长需手动处理错误SDK 集成样板代码少、模型专属优化单一模型应用被绑定到特定提供商AI 框架统一 API、内置抽象多模型应用、复杂工作流有学习曲线可能过度抽象框架以 LangChain 为例在实践中带来的具体收益统一多个 AI 提供商OpenAI GPT、Anthropic Claude、GitHub Models、本地模型在一个接口之下自动处理会话记忆提供嵌入embeddings、函数调用等常见任务的现成工具管理错误处理与重试逻辑把复杂工作流压缩成可读的方法调用。经验法则当你需要在不同 AI 模型之间切换或要构建 Agent、记忆、工具调用等复杂功能时选择框架学习基础或构建简单聚焦的应用时直接使用 API 更合适。就像工匠的专用工具与完整工作坊的区别——关键是让工具匹配任务。从课程配套代码的 code/python/app.py 也可以看到所有示例都统一依赖langchain-openai客户端文件首行注释即安装提示pip install -qU langchain[openai]这就是统一接口的直接体现无论底层是 GitHub Models 还是其他 OpenAI 兼容端点代码形态保持一致。5 分钟快速上手路径课程为赶时间的开发者规划了一条 5 分钟路径第 1 分钟安装 LangChain——pip install langchain langchain-openai第 2 分钟设置 GitHub token 并导入ChatOpenAI客户端第 3 分钟用 system human 消息创建一段简单对话第 4 分钟添加一个基础工具如加法函数体验 AI 工具调用第 5 分钟直观感受原始 API 调用与框架抽象的差距。快速验证代码带消息结构的版本from langchain_openai import ChatOpenAI from langchain_core.messages import SystemMessage, HumanMessage llm ChatOpenAI( api_keyos.environ[GITHUB_TOKEN], base_urlhttps://models.github.ai/inference, modelopenai/gpt-4o-mini ) response llm.invoke([ SystemMessage(contentYou are a helpful coding assistant), HumanMessage(contentExplain Python functions briefly) ]) print(response.content)5 分钟内你就能体验到AI 框架如何把复杂的 AI 集成变成简单的方法调用——这正是生产级 AI 应用的基础。第一个 AI 提示词LangChain GitHub Models环境配置课程选用 LangChain 连接 GitHub Models好处是免费使用多种 AI 模型且只需几个配置参数即可启动from langchain_openai import ChatOpenAI import os llm ChatOpenAI( api_keyos.environ[GITHUB_TOKEN], base_urlhttps://models.github.ai/inference, modelopenai/gpt-4o-mini, ) # 发送一个简单提示词 response llm.invoke(Whats the capital of France?) print(response.content)这段代码逐行拆解ChatOpenAI创建 LangChain 客户端它是通往 AI 的网关api_keyos.environ[GITHUB_TOKEN]从环境变量读取认证令牌base_urlhttps://models.github.ai/inference把请求指向 GitHub Models 的 OpenAI 兼容推理端点modelopenai/gpt-4o-mini指定要使用的模型相当于选择你的 AI 助手llm.invoke(...)发送提示词模型在此返回生成内容response.content提取并打印纯文本响应。环境说明如果使用 GitHub CodespacesGITHUB_TOKEN已经预置无需额外操作在本地运行则需要自行创建一个具备相应权限的 personal access token 并导出为环境变量。预期输出The capital of France is Paris.调用链路可以概括为你的 Python 应用 → LangChain 封装 HTTP 请求 → GitHub Models → GPT-4o-mini 处理提示词并生成响应 → 逐层返回response.content。仓库中 code/python/app.py 与该示例完全一致可直接运行验证提示词原文为 What is the capital of France。构建对话式 AI消息类型与多轮记忆单轮问答只是起点。真实应用需要 AI 记住此前讨论的内容——LangChain 通过不同的消息类型来结构化对话并让 AI 拥有人格。消息类型可以把消息类型理解为对话中各参与者戴的帽子消息类型用途典型用例SystemMessage定义 AI 的人格与行为You are a helpful coding assistantHumanMessage表示用户输入Explain how functions workAIMessage保存 AI 的回复对话中之前的 AI 响应第一轮赋予角色让 AI 扮演《星际迷航》中的皮卡德舰长以外交智慧与领导力著称的角色from langchain_core.messages import HumanMessage, SystemMessage from langchain_openai import ChatOpenAI import os llm ChatOpenAI( api_keyos.environ[GITHUB_TOKEN], base_urlhttps://models.github.ai/inference, modelopenai/gpt-4o-mini, ) messages [ SystemMessage(contentYou are Captain Picard of the Starship Enterprise), HumanMessage(contentTell me about you), ] response llm.invoke(messages) print(response.content)SystemMessage确立 AI 的角色与人格HumanMessage提供初始用户查询二者共同构成多轮对话的基础。典型返回节选I am Captain Jean-Luc Picard, the commanding officer of the USS Enterprise (NCC-1701-D), a starship in the United Federation of Planets. My primary mission is to explore new worlds, seek out new life and new civilizations, and boldly go where no one has gone before. ...第二轮维持上下文的关键——把响应追加回消息列表要保持对话连续性而不是每次重置上下文需要持续把 AI 的响应追加到消息列表。完整代码from langchain_core.messages import HumanMessage, SystemMessage from langchain_openai import ChatOpenAI import os llm ChatOpenAI( api_keyos.environ[GITHUB_TOKEN], base_urlhttps://models.github.ai/inference, modelopenai/gpt-4o-mini, ) messages [ SystemMessage(contentYou are Captain Picard of the Starship Enterprise), HumanMessage(contentTell me about you), ] # works response llm.invoke(messages) print(response.content) print(---- Next ----) messages.append(response) messages.append(HumanMessage(contentNow that I know about you, Im Chris, can I be in your crew?)) response llm.invoke(messages) print(response.content)这里实际调用了两次 LLM第一次只带两条初始消息第二次则携带完整对话历史[SystemMessage, HumanMessage, AIMessage, HumanMessage]——相当于 AI 真的跟进了整个聊天。第二轮的典型回应Welcome aboard, Chris! Its always a pleasure to meet those who share a passion for exploration and discovery. ... Engage!仓库中 code/python/app-chat.py 就是这段追加消息实现记忆的完整可运行版本第 24 行messages.append(response)与第 25 行追加新的HumanMessage是整个机制的核心——invoke的返回值本身就是AIMessage对象可以直接放回消息列表。自查要点完成本节后可以自问三个问题能否解释 LangChain 相比手动管理消息列表如何简化了会话管理invoke()与stream()的区别是什么分别在什么场景使用框架的消息类型体系如何改善代码组织这些抽象模式消息类型、流式接口、会话记忆正是主流 AI 产品聊天界面、代码补全助手背后使用的同一套架构模式。进阶思考题如何设计一个框架抽象用单一接口同时支持 OpenAI、Anthropic、Google 等不同模型提供商流式响应StreamingChatGPT 那种逐字打字的效果就是流式内容在生成过程中就逐步呈现交互更自然、反馈更即时。用 LangChain 实现流式from langchain_openai import ChatOpenAI import os llm ChatOpenAI( api_keyos.environ[GITHUB_TOKEN], base_urlhttps://models.github.ai/inference, modelopenai/gpt-4o-mini, streamingTrue ) # 流式接收响应 for chunk in llm.stream(Write a short story about a robot learning to code): print(chunk.content, end, flushTrue)流式的价值内容生成中即显示无需干等让用户感知到确实在处理即使总耗时不变主观上更快用户可以在 AI 仍在思考时就开始阅读。体验提示流式在长响应场景代码讲解、创意写作、详细教程中价值最明显——用户看到的是进度而不是空白屏幕。提示词模板Prompt Templates提示词模板像古典修辞中的结构框架一次搭建好骨架再按需填入不同内容无需重写。创建可复用提示词from langchain_core.prompts import ChatPromptTemplate # 定义一个代码讲解模板 template ChatPromptTemplate.from_messages([ (system, You are an expert programming instructor. Explain concepts clearly with examples.), (human, Explain {concept} in {language} with a practical example for {skill_level} developers) ]) # 用不同变量值使用同一模板 questions [ {concept: functions, language: JavaScript, skill_level: beginner}, {concept: classes, language: Python, skill_level: intermediate}, {concept: async/await, language: JavaScript, skill_level: advanced} ] for question in questions: prompt template.format_messages(**question) response llm.invoke(prompt) print(fTopic: {question[concept]}\n{response.content}\n---\n)模板带来的好处整个应用的提示词结构保持一致告别混乱的字符串拼接只用干净的变量结构不变AI 行为更可预期一处修改模板全局生效。结构化输出Structured OutputAI 返回的是一段无法解析的自由文本最让人头疼。结构化输出让 AI 按你定义的格式返回数据——可以要求 JSON、特定数据结构或任何你需要的形态。定义输出 Schemafrom langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import JsonOutputParser from pydantic import BaseModel, Field class CodeReview(BaseModel): score: int Field(descriptionCode quality score from 1-10) strengths: list[str] Field(descriptionList of code strengths) improvements: list[str] Field(descriptionList of suggested improvements) overall_feedback: str Field(descriptionSummary feedback) # 配置解析器 parser JsonOutputParser(pydantic_objectCodeReview) # 创建带格式指令的提示词 prompt ChatPromptTemplate.from_messages([ (system, You are a code reviewer. {format_instructions}), (human, Review this code: {code}) ]) # 组装 LCEL 链提示词 - 模型 - 解析器 chain prompt | llm | parser # 获得结构化响应 code_sample def calculate_average(numbers): return sum(numbers) / len(numbers) result chain.invoke({ code: code_sample, format_instructions: parser.get_format_instructions() }) print(fScore: {result[score]}) print(fStrengths: {, .join(result[strengths])})几个值得注意的实现细节CodeReview用 Pydantic 模型定义字段与描述描述会进入提示词引导模型按字段作答parser.get_format_instructions()把格式要求注入 system 消息的{format_instructions}占位符chain prompt | llm | parser使用了 LCEL 管道语法三段式组合在课程后续的完整应用与作业中反复出现。结构化输出的意义返回格式每次一致不再靠猜可直接对接数据库与 API无需额外清洗异常响应在进入应用逻辑前就被拦截代码更干净——你明确知道自己在处理什么。工具调用Tool Calling工具是让 AI 拥有超越对话的动手能力的核心特性你向 AI 描述可用工具当用户请求匹配时AI 可以选择调用工具并采取行动。用 Python 定义工具以加法为例from typing_extensions import Annotated, TypedDict class add(TypedDict): Add two integers. # Annotations 的顺序类型可选默认值可选描述 a: Annotated[int, ..., First integer] b: Annotated[int, ..., Second integer] tools [add] functions { add: lambda a, b: a b }这里发生了什么继承TypedDict并配合Annotated类型为 LLM 提供了清晰的工具蓝图——工具做什么、需要什么参数functions字典则是工具箱告诉代码当 AI 决定调用某个工具时具体执行什么。接着把工具绑定到模型llm ChatOpenAI( api_keyos.environ[GITHUB_TOKEN], base_urlhttps://models.github.ai/inference, modelopenai/gpt-4o-mini, ) llm_with_tools llm.bind_tools(tools)调用bind_tools传入tools数组后llm_with_tools就知道了这个工具。发起调用query What is 3 12? res llm_with_tools.invoke(query) if res.tool_calls: for tool in res.tool_calls: print(TOOL CALL: , functions[tool[name]](**tool[args])) print(CONTENT: , res.content)当对带工具的 LLM 调用invoke后响应对象的tool_calls属性可能被填充。每个被识别的工具调用带有name和args分别标识要调用哪个工具、用什么参数。仓库中 code/python/app-tools.py 正是这个完整流程的可运行版本该文件还同时绑定了add与joke两个工具。运行后你应看到类似输出TOOL CALL: 15 CONTENT:AI 分析 What is 3 12依据工具的名称、描述和字段规格判定这是add工具的适用场景结果 15 来自functions字典中对应函数的执行print(TOOL CALL: , functions[tool[name]](**tool[args]))更有实际意义的工具调用 Web API加法只是演示概念真实工具通常执行更复杂的操作比如调用 Web API。课程扩展了示例让 AI 从互联网抓取内容class joke(TypedDict): Tell a joke. category: Annotated[str, ..., The joke category] def get_joke(category: str) - str: response requests.get( fhttps://api.chucknorris.io/jokes/random?category{category}, headers{Accept: application/json} ) if response.status_code 200: return response.json().get(value, fHeres a {category} joke!) return fHeres a {category} joke! functions { add: lambda a, b: a b, joke: lambda category: get_joke(category) } query Tell me a joke about animals # 其余代码同上bind_tools invoke 遍历 tool_calls运行后你会得到类似这样的响应TOOL CALL: Chuck Norris once rode a nine foot grizzly bear through an automatic car wash, instead of taking a shower. CONTENT:完整的流程是用户查询 → LangChain/模型分析 → 判断工具是否可用 → 选定joke工具并抽取参数 → 执行joke(categoryanimals)发起 API 请求 → 返回笑话内容并展示给用户若没有匹配工具则直接生成 AI 响应。整个完整代码见 code/python/app-tools.py其中get_joke的容错设计值得注意请求失败非 200时回退到一句模板文案而不是让异常中断对话——这是工具实现中防御式编程的示范。嵌入Embeddings与文档处理嵌入是给思想建立坐标系把任意文本转换为捕获其语义的数值坐标相似的Concepts在多维空间中彼此靠近。基于此可以实现语义检索——RAG检索增强生成的地基。创建并使用嵌入from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import FAISS from langchain_community.document_loaders import TextLoader from langchain.text_splitter import CharacterTextSplitter # 初始化嵌入同样走 GitHub Models 端点 embeddings OpenAIEmbeddings( api_keyos.environ[GITHUB_TOKEN], base_urlhttps://models.github.ai/inference, modeltext-embedding-3-small ) # 加载并切分文档 loader TextLoader(documentation.txt) documents loader.load() text_splitter CharacterTextSplitter(chunk_size1000, chunk_overlap0) texts text_splitter.split_documents(documents) # 创建向量库 vectorstore FAISS.from_documents(texts, embeddings) # 执行相似性检索 query How do I handle user authentication? similar_docs vectorstore.similarity_search(query, k3) for doc in similar_docs: print(fRelevant content: {doc.page_content[:200]}...)关键参数说明modeltext-embedding-3-small嵌入模型名称与聊天模型走同一base_url端点CharacterTextSplitter(chunk_size1000, chunk_overlap0)按 1000 字符切块、不重叠块大小与重叠度决定检索粒度与召回质量FAISS.from_documents(texts, embeddings)对切块逐条计算嵌入并建立本地向量索引similarity_search(query, k3)对查询同样计算嵌入返回向量空间中最近的 3 个文档块。多种格式的文档加载器from langchain_community.document_loaders import ( PyPDFLoader, CSVLoader, JSONLoader, WebBaseLoader ) # 加载不同类型的文档 pdf_loader PyPDFLoader(manual.pdf) csv_loader CSVLoader(data.csv) json_loader JSONLoader(config.json) web_loader WebBaseLoader(https://example.com/docs) # 处理所有文档 all_documents [] for loader in [pdf_loader, csv_loader, json_loader, web_loader]: docs loader.load() all_documents.extend(docs)基于嵌入你可以做到构建真正理解语义而非仅关键词匹配的搜索创建能针对你的文档问答的 AI构建推荐真正相关内容的推荐系统自动整理与归类内容。整个流程可概括为文档 → 文本切分 → 计算嵌入 → 向量库查询 → 查询嵌入 → 相似性检索 → 命中相关文档 → 交给 LLM 生成回答。构建完整的 AI 应用现在把前面所有能力整合成一个综合应用——一个能回答问题、使用工具、并保持对话记忆的编码助手。完整应用示例from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain_core.prompts import ChatPromptTemplate from langchain_core.messages import HumanMessage, SystemMessage, AIMessage from langchain_community.vectorstores import FAISS from typing_extensions import Annotated, TypedDict import os import requests class CodingAssistant: def __init__(self): self.llm ChatOpenAI( api_keyos.environ[GITHUB_TOKEN], base_urlhttps://models.github.ai/inference, modelopenai/gpt-4o-mini ) self.conversation_history [ SystemMessage(contentYou are an expert coding assistant. Help users learn programming concepts, debug code, and write better software. Use tools when needed and maintain a helpful, encouraging tone.) ] # 定义工具 self.setup_tools() def setup_tools(self): class web_search(TypedDict): Search for programming documentation or examples. query: Annotated[str, Search query for programming help] class code_formatter(TypedDict): Format and validate code snippets. code: Annotated[str, Code to format] language: Annotated[str, Programming language] self.tools [web_search, code_formatter] self.llm_with_tools self.llm.bind_tools(self.tools) def chat(self, user_input: str): # 将用户消息加入会话历史 self.conversation_history.append(HumanMessage(contentuser_input)) # 获取 AI 响应 response self.llm_with_tools.invoke(self.conversation_history) # 如有工具调用则处理 if response.tool_calls: for tool_call in response.tool_calls: tool_result self.execute_tool(tool_call) print(f Tool used: {tool_call[name]}) print(f Result: {tool_result}) # 将 AI 响应加入会话历史 self.conversation_history.append(response) return response.content def execute_tool(self, tool_call): tool_name tool_call[name] args tool_call[args] if tool_name web_search: return fFound documentation for: {args[query]} elif tool_name code_formatter: return fFormatted {args[language]} code: {args[code][:50]}... return Tool execution completed # 使用示例 assistant CodingAssistant() print( Coding Assistant Ready! Type quit to exit.\n) while True: user_input input(You: ) if user_input.lower() quit: break response assistant.chat(user_input) print(f Assistant: {response}\n)从源码结构看这个类的组织方式体现了生产级 AI 应用的典型骨架类封装CodingAssistant把 LLM 客户端、会话历史、工具集、工具执行逻辑收敛在一个可维护的对象中而不是散落的顶层脚本会话记忆conversation_history以SystemMessage初始化chat()每轮先把HumanMessage追加进去、调用后再把AIMessage响应对象追加回去——与前面皮卡德示例的记忆机制完全一致只是被持久化到了实例属性工具检测与执行setup_tools()内部定义两个TypedDict工具web_search、code_formatter并bind_toolsexecute_tool()按tool_call[name]分发未命中时返回兜底文案。课程示例中工具返回的是模拟结果字符串实际落地时在这里替换为真实的搜索 API 或格式化调用即可。应用要点记住完整对话保持上下文连续通过工具调用执行动作而不只是聊天遵循可预测的交互模式自动管理错误处理与复杂工作流。延伸思考如何将这个应用扩展到多用户、持久化存储或对接外部数据库重点考虑可扩展性与状态管理。作业构建你自己的 AI 学习助手目标创建一个帮助学生理解编程概念的 AI 应用提供讲解、代码示例与交互测验。需求核心功能必须实现对话界面实现跨多个问题保持上下文的聊天系统教育工具至少两个辅助学习的工具——代码解释工具、概念测验生成器个性化学习用 system 消息适配不同技能水平的响应响应格式化为测验题目实现结构化输出。实现步骤步骤 1环境搭建pip install langchain langchain-openai步骤 2基础聊天功能创建StudyAssistant类实现对话记忆为教学支持场景配置人格system 消息。步骤 3添加教育工具代码解释器Code Explainer把代码拆解为易懂的片段测验生成器Quiz Generator针对编程概念生成题目进度追踪器Progress Tracker记录已覆盖的主题。步骤 4增强功能可选实现流式响应改善用户体验加入文档加载把课程材料纳入上下文为基于相似性的内容检索创建嵌入。评分标准维度优秀 (4)良好 (3)合格 (2)待改进 (1)对话流畅度自然、上下文感知的响应上下文保持良好基础对话轮次间无记忆工具集成多个有用工具无缝协作2 个工具实现正确1-2 个基础工具工具不可用代码质量干净、有文档、有错误处理结构良好、部分文档基础功能可用结构差、无错误处理教学价值真正有助于学习、自适应学习支持良好基础讲解教学价值有限示例代码结构class StudyAssistant: def __init__(self, skill_levelbeginner): # 初始化 LLM、工具与会话记忆 pass def explain_code(self, code, language): # 工具解释代码如何工作 pass def generate_quiz(self, topic, difficulty): # 工具生成练习题 pass def chat(self, user_input): # 主对话界面 pass # 使用示例 assistant StudyAssistant(skill_levelintermediate) response assistant.chat(Explain how Python functions work)加分挑战添加语音输入/输出能力用 Streamlit 或 Flask 实现 Web 界面用嵌入基于课程材料构建知识库添加进度追踪与个性化学习路径。GitHub Copilot Agent 挑战课程还提供了一个面向 AI Agent 协作的挑战使用 Agent 模式构建一个高级 AI 代码审查助手综合运用工具调用、结构化输出与对话记忆对代码提交给出完整反馈。任务描述创建一个CodeReviewAssistant类实现分析代码复杂度并建议改进的工具对照最佳实践检查代码的工具使用 Pydantic 模型的结构化输出保证审查格式一致跟踪审查会话的对话记忆能处理代码提交并给出详细、可执行反馈的主聊天界面。助手应能审查多种编程语言的代码在一次会话中跨多次代码提交保持上下文并给出总体评分与详细的改进建议。这个挑战本质上要求你把本课学到的四类能力bind_toolsTypedDict工具、Pydantic JsonOutputParser结构化输出、消息列表记忆、LCEL 链式组装全部组合到一个类里——正是CodingAssistant完整应用的进阶版。总结与 AI 集成决策框架你已掌握的核心框架概念框架收益理解何时选择框架而非直接 API 调用LangChain 基础配置并连接 AI 模型消息类型用SystemMessage、HumanMessage、AIMessage构建结构化对话。进阶特性工具调用创建并集成自定义工具会话记忆跨多轮保持上下文流式响应实时逐块输出提示词模板可复用、动态化的提示词结构化输出一致、可解析的响应嵌入语义搜索与文档处理能力。实践应用把多种特性组合成生产级应用实现健壮的错误管理与校验创建扩展 AI 能力的自定义工具。AI 集成决策框架按以下顺序做选择简单单次查询 → 直接 API 调用HTTP 请求、最小依赖需要单模型、单提供商的较多调用 → SDK 集成提供商 SDK、模型专属需要对话记忆 → 框架基础用法LangChain 基本聊天还需要工具或复杂特性 → 完整框架实现LangChain 加工具、记忆、Agent。下一步方向立即动手用这些概念构建让你兴奋的项目通过 LangChain 试验不同模型创建解决你实际问题的工具进阶方向AI Agent自主规划与执行复杂任务、RAG把 AI 与自有知识库结合、多模态 AI文本、图像、音频混合、生产部署扩展与监控持续练习每个用例都是一次新的学习不同模型、不同工具、不同场景的反复实践是掌握这类技术的唯一捷径。本课的全部示例代码可在仓库中直接查看运行app.py首次提示词、app-chat.py多轮对话记忆、app-tools.py双工具调用。课程第 10 课的完整教学文档见 10-ai-framework-project/README.md作业参考实现位于 solution。你现在已具备构建智能、会对话、能调用工具的完整 AI 应用的知识——问题只剩一个你要创造什么【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。