哪些是大型網(wǎng)站友情鏈接樣式
前序
之前了解了Models,Prompt,但有些資料又把這塊與輸出合稱為模型輸入輸出(Model I/O)?:這是與各種大語言模型進行交互的基本組件。它允許開發(fā)者管理提示(prompt),通過通用接口調(diào)用語言模型,并從模型輸出中提取信息。簡單來說,這個組件負責與大語言模型“對話”,將請求傳遞給模型,并接收回復(fù)?。
這篇文章就補充一下這個O(output)的內(nèi)容。
輸出解釋器
Output Parsers(輸出解析器),是langchain中提供給我們對模型響應(yīng)內(nèi)容進行格式化輸出的。LLM的輸出為文本,但在程序中除了顯示文本,如果希望獲得更多不同的結(jié)構(gòu)化數(shù)據(jù)時,就可以使用langchain提供的輸出解析器(Output Parsers)來完成了。輸出解析器(Output Parsers)實際上就是結(jié)構(gòu)化語言模型提供的響應(yīng)處理工具類,其提供了如下兩個方法給開發(fā)者使用,也是這些響應(yīng)類必須實現(xiàn)的兩個方法:
get_format_instructions() -> str :返回一個包含語言模型如何格式化輸出的指令字符串。
invoke()-> Any:接受一個結(jié)構(gòu)化言模型的響應(yīng)對象,并將其解析為指定格式
Str輸出解析器
import os
from langchain_deepseek import ChatDeepSeek
from langchain.prompts import PromptTemplate# 初始化模型
os.environ['DEEPSEEK_API_KEY'] = "sk-e2xxx"
chat_model = ChatDeepSeek(model="deepseek-chat",temperature=0.4,max_tokens=None,timeout=None,max_retries=2,)# 創(chuàng)建提示模板
prompt_template = PromptTemplate(input_variables=["context"],template="基于給定的文案,以幽默詼諧的風格生成一段回答文本:{context}",
)# 使用模型生成文本
context = "成都今天出太陽了,天氣真好,我們翹班出去玩吧。"
prompt = prompt_template.format(context=context)
result = chat_model.invoke(prompt)
print(result)
回答內(nèi)容很長,但是我們需要的只有content那串。引入StrOutputParser
,把返回的結(jié)果,經(jīng)過解析,就只有文本結(jié)果內(nèi)容了
...
from langchain_core.output_parsers import StrOutputParser
res = StrOutputParser().invoke(input=result)
print(res)
List輸出解析器
import os
from langchain_deepseek import ChatDeepSeek# 初始化模型
os.environ['DEEPSEEK_API_KEY'] = "sk-e24324xxx"
chat_model = ChatDeepSeek(model="deepseek-chat",temperature=0.4,max_tokens=None,timeout=None,max_retries=2,)
from langchain_core.output_parsers import CommaSeparatedListOutputParser
from langchain_core.prompts import PromptTemplateparser = CommaSeparatedListOutputParser()prompt = PromptTemplate.from_template(template="請列出5個{item}的不同叫法.\n{format_instructions}\n",partial_variables={"format_instructions": parser.get_format_instructions()},
)messages = prompt.invoke({'item': '土豆'})
print(messages)result = chat_model.invoke(messages)
res = parser.invoke(result)
print(res)"""
text='請列出5個土豆的不同叫法.\nYour response should be a list of comma separated values, eg: `foo, bar, baz` or `foo,bar,baz`\n'
['馬鈴薯', '洋芋', '土豆', '薯仔', '地蛋']
"""
Json輸出解釋器
其他內(nèi)容大差不差,把 CommaSeparatedListOutputParser
換成JsonOutputParser
就行
from pydantic import BaseModel, Field
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplateclass JsonParser(BaseModel):question: str = Field(description='問題')answer: str = Field(description='答案')parser = JsonOutputParser(pydantic_object=JsonParser)prompt = PromptTemplate(template="回答問題.\n{format_instructions}\n{query}\n",input_variables=["query"],partial_variables={"format_instructions": parser.get_format_instructions()},
)# print(parser.get_format_instructions())messages = prompt.invoke({'query': '講一個腦筋急轉(zhuǎn)彎的問題和答案。'})
response = chat_model.invoke(messages)
content = parser.invoke(response)
print(content) """
{'question': '什么東西越洗越臟?', 'answer': '水'}
"""
stream輸出解析器
如果輸出內(nèi)容很長,一直等處理完才返回結(jié)果也不大好,比如我們正常使用在線大模型,它都是幾個字幾個字往外吐的,不是最后直接給答案。
這里就需要用到stream輸出解析器
import os
from langchain_deepseek import ChatDeepSeek# 初始化模型
os.environ['DEEPSEEK_API_KEY'] = "sk-e24xxx"
chat_model = ChatDeepSeek(model="deepseek-chat",temperature=0.4,max_tokens=None,timeout=None,max_retries=2,)from langchain_ollama.llms import OllamaLLM
from langchain_core.prompts import PromptTemplateprompt_template = PromptTemplate.from_template("你是一名名經(jīng)驗豐富的{role},{ability},{prompt}")
messages = prompt_template.invoke({"role": "修仙小說作家", "ability": "熟悉各種神話傳說和修仙小說","prompt": "請你寫一部與牧神記類似的小說,要求:全書至少600章,每一章字數(shù)在8000字以上,劇情緊湊,各個角色的個性分明"})
print(messages)for chunk in chat_model.stream(messages):print(chunk, end="", flush=True)
或者這樣不好看,也可以用上面的字符串輸出解釋器來處理一下輸出內(nèi)容
from langchain_core.output_parsers import StrOutputParser# 修改一下輸出這里
for chunk in chat_model.stream(messages):print(StrOutputParser().invoke(chunk), end="", flush=True)
到這里,就就開始慢慢幫我們寫小說了。
Cache
如果每次問同樣的,都調(diào)用大模型推理,那么會比較耗💰,可以把問題和答案記錄下來,以后遇到同樣的問題,則不必再使用大模型推理。
基于langchain提供的輸出緩存,讓LLM在遇到同一prompt時,直接調(diào)用緩存中的結(jié)果,也可以達到加速的效果。
# -*- coding: utf-8 -*-
# @Author : John
# @Time : 2025/02/27
# @File : langchain_cache.pyimport time
import redis
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
# from langchain_community.cache import InMemoryCache # 把輸出緩存到內(nèi)存中
from langchain_community.cache import RedisCache # 把輸出緩存到Redis數(shù)據(jù)庫中
from langchain.globals import set_llm_cacheimport os
from langchain_deepseek import ChatDeepSeek# 初始化模型
os.environ['DEEPSEEK_API_KEY'] = "sk-e243xxxf"
chat_model = ChatDeepSeek(model="deepseek-chat",temperature=0.4, # temperature 溫度值,數(shù)值越趨向0,回答越謹慎,數(shù)值越趨向1,回答則越腦洞大開,主要控制大模型輸出的創(chuàng)造力max_tokens=None,timeout=None,max_retries=2,)prompt_template = PromptTemplate.from_template("你是一個產(chǎn)品顧問。請給公司剛生產(chǎn)出來的 {production},取一個好聽的名字和廣告語。")
messages = prompt_template.invoke({"production": "充電寶"})# 開啟緩存
redis = redis.Redis("localhost", port=6379, password="qwe123", db=2)
set_llm_cache(RedisCache(redis))timers = []
for _ in range(5):t1 = time.time()response = chat_model.invoke(messages)t2 = time.time()print(t2 - t1, response)timers.append(t2 - t1)print(timers)
可以看到輸出結(jié)果都是一致的。只有第一次真正請求了deepseek,花了65s獲得了結(jié)果,后面都是第一次結(jié)果保存到redis,從redis獲取的。