从零开始学LangChain(二):Models 模型详解
本系列教程将带你从零开始学习LangChain框架,构建强大的AI应用程序。
什么是Models? 在LangChain中,Models是指与大语言模型(LLMs)交互的接口。LangChain提供了统一的API,让你可以轻松切换不同的模型提供商,而无需修改代码。
LangChain支持两种主要的模型类型。LLM是大语言模型,接收文本字符串并返回文本字符串,适用于文本补全、翻译、摘要等场景。Chat Model是聊天模型,接收消息列表并返回消息,专为对话系统和聊天机器人设计。
核心区别在于输入输出的格式。LLM输入字符串输出字符串,而Chat Model输入消息列表输出消息对象。
LLM 使用指南 LangChain提供了多种LLM的集成,包括OpenAI、Anthropic、Hugging Face等。
使用OpenAI LLM 1 2 3 4 5 6 7 8 9 10 11 12 from langchain_openai import OpenAIllm = OpenAI( model="gpt-3.5-turbo-instruct" , temperature=0.7 , max_tokens=256 ) response = llm.invoke("解释什么是机器学习" ) print (response)
使用Anthropic Claude 1 2 3 4 5 6 7 8 9 from langchain_anthropic import AnthropicLLMllm = AnthropicLLM( model="claude-3-opus-20240229" , temperature=0.5 , max_tokens=1024 ) response = llm.invoke("用简单的比喻解释量子计算" )
控制生成参数 理解并正确使用这些参数,能显著提升输出质量。temperature控制随机性,范围0-2,创意任务用0.7,精确任务用0。max_tokens限制最大生成token数,通常设置为256-2048。top_p是核采样参数,范围0-1,通常设为0.9,与temperature二选一。frequency_penalty是频率惩罚,范围-2到2,用于减少重复,推荐0-0.5。presence_penalty是存在惩罚,同样范围-2到2,用于鼓励新话题,推荐0-0.5。
让我们看看温度参数的实际效果。
1 2 3 4 5 6 7 8 9 10 11 from langchain_openai import OpenAIllm_cold = OpenAI(temperature=0 ) print ("低温输出:" )print (llm_cold.invoke("讲一个关于程序员的故事" ))llm_hot = OpenAI(temperature=1.2 ) print ("\n高温输出:" )print (llm_hot.invoke("讲一个关于程序员的故事" ))
Chat Model 使用指南 Chat Model专为对话场景设计,支持系统消息、多轮对话等高级功能。
基础用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from langchain_openai import ChatOpenAIfrom langchain.schema import HumanMessage, SystemMessage, AIMessagechat = ChatOpenAI(model="gpt-4" , temperature=0.7 ) messages = [ SystemMessage(content="你是一个友好的Python导师,擅长用比喻解释复杂概念。" ), HumanMessage(content="什么是装饰器?" ) ] response = chat.invoke(messages) print (response.content)
多轮对话 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from langchain_openai import ChatOpenAIfrom langchain.schema import HumanMessage, AIMessagechat = ChatOpenAI(model="gpt-3.5-turbo" ) conversation = [ HumanMessage(content="我叫张三" ), AIMessage(content="你好张三,很高兴认识你!" ), HumanMessage(content="我还叫什么名字?" ) ] response = chat.invoke(conversation) print (response.content)
使用提示词模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from langchain_openai import ChatOpenAIfrom langchain.prompts import ChatPromptTemplatechat = ChatOpenAI(model="gpt-3.5-turbo" ) prompt = ChatPromptTemplate.from_messages([ ("system" , "你是一位专业的{role}。" ), ("human" , "请回答:{question}" ) ]) chain = prompt | chat response = chain.invoke({ "role" : "Python工程师" , "question" : "Python中的GIL是什么?" }) print (response.content)
流式输出 流式输出让用户实时看到生成过程,大幅提升体验。
基础流式输出 1 2 3 4 5 6 7 8 9 from langchain_openai import ChatOpenAIchat = ChatOpenAI(model="gpt-3.5-turbo" ) for chunk in chat.stream("请用3个要点介绍LangChain" ): print (chunk.content, end="" , flush=True ) print ()
异步流式输出 1 2 3 4 5 6 7 8 9 10 11 12 13 import asynciofrom langchain_openai import ChatOpenAIasync def stream_chat (): chat = ChatOpenAI(model="gpt-3.5-turbo" ) async for chunk in chat.astream("写一首关于编程的诗" ): print (chunk.content, end="" , flush=True ) print () asyncio.run(stream_chat())
流式输出到UI 1 2 3 4 5 6 7 8 9 10 11 12 13 from langchain_openai import ChatOpenAIfrom typing import Iteratordef create_streaming_ui (prompt: str ) -> Iterator[str ]: """模拟UI中显示流式输出""" chat = ChatOpenAI(model="gpt-3.5-turbo" ) for chunk in chat.stream(prompt): yield chunk.content for text in create_streaming_ui("介绍Python" ): print (text, end="" , flush=True )
结构化输出 让LLM按照指定格式输出,便于程序处理。
使用OutputFixerParser 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from langchain_openai import ChatOpenAIfrom langchain.output_parsers import OutputFixingParserfrom langchain.output_parsers import PydanticOutputParserfrom pydantic import BaseModel, Fieldclass Recipe (BaseModel ): name: str = Field(description="菜名" ) ingredients: list [str ] = Field(description="食材列表" ) steps: list [str ] = Field(description="制作步骤" ) parser = PydanticOutputParser(pydantic_object=Recipe) fixing_parser = OutputFixingParser.from_llm( parser=parser, llm=ChatOpenAI(model="gpt-3.5-turbo" ) ) chat = ChatOpenAI(model="gpt-3.5-turbo" ) prompt = "教我做番茄炒蛋" response = chat.invoke(prompt + "\n\n" + parser.get_format_instructions()) recipe = fixing_parser.parse(response.content) print (f"菜名: {recipe.name} " )print (f"食材: {recipe.ingredients} " )print (f"步骤: {recipe.steps} " )
JSON模式输出 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from langchain_openai import ChatOpenAIchat = ChatOpenAI(model="gpt-3.5-turbo" ) prompt = """ 请以JSON格式返回以下信息: - 书名 - 作者 - 出版年份 书籍:《Python编程从入门到实践》 """ response = chat.invoke(prompt) print (response.content)
输出会是JSON格式的书名、作者和出版年份信息。
模型切换最佳实践 使用环境变量配置 1 2 3 4 5 6 7 8 9 10 11 12 13 import osfrom langchain_openai import ChatOpenAIfrom langchain_anthropic import ChatAnthropicmodel_provider = os.getenv("MODEL_PROVIDER" , "openai" ) if model_provider == "openai" : model = ChatOpenAI(model="gpt-4" ) elif model_provider == "anthropic" : model = ChatAnthropic(model="claude-3-opus-20240229" ) else : raise ValueError(f"Unknown provider: {model_provider} " )
创建模型工厂 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from langchain_openai import ChatOpenAIfrom langchain_anthropic import ChatAnthropicdef create_llm (provider: str = "openai" , **kwargs ): """模型工厂函数""" providers = { "openai" : ChatOpenAI, "anthropic" : ChatAnthropic, } if provider not in providers: raise ValueError(f"Unknown provider: {provider} " ) return providers[provider](**kwargs) model = create_llm( provider="openai" , model="gpt-4" , temperature=0.7 )
实战示例:智能摘要生成器 让我们创建一个实用的摘要生成工具。
完整代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 from langchain_openai import ChatOpenAIfrom langchain.prompts import ChatPromptTemplatefrom enum import Enumclass SummaryStyle (str , Enum): BRIEF = "brief" DETAILED = "detailed" BULLET_POINTS = "bullet_points" TLDR = "tldr" class ArticleSummarizer : def __init__ (self ): self .chat = ChatOpenAI(model="gpt-3.5-turbo" , temperature=0.5 ) self .prompt = ChatPromptTemplate.from_messages([ ("system" , "你是一位专业的文章摘要专家。" ), ("human" , """请为以下文章生成{style}摘要: 文章标题:{title} 文章内容:{content} 要求: 1. 保留核心信息 2. 语言简洁明了 3. 字数控制在{max_words}字以内""" ) ]) def summarize ( self, title: str , content: str , style: SummaryStyle = SummaryStyle.BRIEF, max_words: int = 100 ) -> str : """生成文章摘要""" chain = self .prompt | self .chat style_map = { SummaryStyle.BRIEF: "简要的" , SummaryStyle.DETAILED: "详细的" , SummaryStyle.BULLET_POINTS: "要点式" , SummaryStyle.TLDR: "一句话" } response = chain.invoke({ "title" : title, "content" : content, "style" : style_map[style], "max_words" : max_words }) return response.content summarizer = ArticleSummarizer() article = """ LangChain是一个用于开发由大型语言模型(LLMs)驱动的应用程序的框架。 它提供了标准化的接口来调用不同的LLM,支持链式调用、工具集成、记忆管理等功能。 使用LangChain,开发者可以快速构建聊天机器人、文档问答、代码生成等AI应用。 """ print ("=== 简要摘要 ===" )print (summarizer.summarize( title="LangChain入门" , content=article, style=SummaryStyle.BRIEF )) print ("\n=== 要点式摘要 ===" )print (summarizer.summarize( title="LangChain入门" , content=article, style=SummaryStyle.BULLET_POINTS )) print ("\n=== 一句话摘要 ===" )print (summarizer.summarize( title="LangChain入门" , content=article, style=SummaryStyle.TLDR, max_words=30 ))
常见错误与解决方案 API密钥未设置 症状是出现ValueError: Please set OPENAI_API_KEY environment variable错误。解决方案是加载环境变量并验证密钥是否设置。
1 2 3 4 5 6 7 8 9 import osfrom dotenv import load_dotenvload_dotenv() if not os.getenv("OPENAI_API_KEY" ): raise ValueError("请设置OPENAI_API_KEY环境变量" )
模型不支持流式输出 症状是出现NotImplementedError: stream() is not supported错误。解决方案是检查是否支持流式输出,如果不支持则回退到普通调用。
1 2 3 4 5 6 7 8 9 10 chat = ChatOpenAI(model="gpt-3.5-turbo" ) if hasattr (chat, 'stream' ): for chunk in chat.stream("Hello" ): print (chunk.content) else : response = chat.invoke("Hello" ) print (response.content)
输出token超限 症状是出现openai.error.InvalidRequestError: This model's maximum context length is 4097 tokens错误。解决方案是限制输出长度或使用更长的上下文模型。
1 2 3 4 5 6 7 8 chat = ChatOpenAI( model="gpt-3.5-turbo" , max_tokens=1000 ) chat_long = ChatOpenAI(model="gpt-3.5-turbo-16k" )
系列导航