之前的文章提到通義千問API無法通過with_structured_output/json schema的方式支持結構化輸出,如果就是想使用通義千問大模型做結構化輸出,應該怎么辦呢?有兩種辦法
使用Ollama來運行通義千問大模型
從Ollama博客文章 Structured output 中了解到,Ollama已經支持結構化輸出了,這個功能是在Ollama 0.5.0版本 引入的。通過Ollama把qwen3大模型在本地運行起來,使用下面的代碼就能看到效果。
from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field llm = init_chat_model( model_provider="openai", model="qwen3:8b", base_url="http://localhost:11434/v1", api_key="123456"
) tagging_prompt = ChatPromptTemplate.from_template( """ Extract the desired information from the following passage. Only extract the properties mentioned in the 'Classification' function. Passage: {input} """) class Classification(BaseModel): sentiment: str = Field(description="The sentiment of the text") aggressiveness: int = Field(description="How aggressive the text is on a scale from 1 to 10") language: str = Field(description="The language the text is written in") structured_llm = llm.with_structured_output(Classification) inp = "Estoy increiblemente contento de haberte conocido! Creo que seremos muy buenos amigos!"
prompt = tagging_prompt.invoke({"input": inp})
response = structured_llm.invoke(prompt)
print(response)
程序能夠正常運行并打印出Classification這個結構化的類對象內容(如下)
sentiment='positive' aggressiveness=0 language='Spanish'
如果把代碼中llm對象構造時的參數換回通義千問API的值,也即是改為
llm = init_chat_model( model_provider="openai", model="qwen-plus-latest", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key=os.environ["QWEN_API_KEY"]
)
會發現之前提到的錯誤再次出現了,這證明不是通義千問大模型不支持結構化輸出,而是通義千問API服務不支持。
如果不想使用Ollama本地運行大模型,而是想使用通義千問API服務支持結構化輸出,該怎么辦呢?
使用 PydanticOutputParser 自動生成提示詞
要使用結構化輸出,通義千問文檔里提到
您可以在提示詞中明確描述所需 JSON 的鍵值結構和數據類型,并提供標準數據樣例,這會幫助大模型達到類似效果。
借助 LangChain 的 PydanticOutputParser 可以幫我們自動生成數據結構的提示詞。參考下面的代碼
import os
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model llm = init_chat_model( model_provider="openai", model="qwen-plus-latest", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key=os.environ["QWEN_API_KEY"]
) class Classification(BaseModel): sentiment: str = Field(description="The sentiment of the text") aggressiveness: int = Field(description="How aggressive the text is on a scale from 1 to 10") language: str = Field(description="The language the text is written in") parser = PydanticOutputParser(pydantic_object=Classification) tagging_prompt = ChatPromptTemplate.from_messages([ ("system", "Extract the desired information into JSON format from the following passage." "{format_instructions}" ), ("human", "{input}")
]).partial(format_instructions=parser.get_format_instructions()) inp = "Estoy increiblemente contento de haberte conocido! Creo que seremos muy buenos amigos!"
print(tagging_prompt.invoke({"input": inp})) chain = tagging_prompt | llm | parser
response = chain.invoke({"input": inp})
print(response)
第30行代碼會打印出格式化后的提示詞,第一行后面的內容都是API根據提供的類結構生成的提示詞。
Extract the desired information into JSON format from the following passage.The output should be formatted as a JSON instance that conforms to the JSON schema below.As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.Here is the output schema:{"properties": {"sentiment": {"description": "The sentiment of the text","title": "Sentiment","type": "string"},"aggressiveness": {"description": "How aggressive the text is on a scale from 1 to 10","title": "Aggressiveness","type": "integer"},"language": {"description": "The language the text is written in","title": "Language","type": "string"}},"required": ["sentiment","aggressiveness","language"]}
真是太方便了,這下可以高效的從文檔里提取結構化數據啦。
思考
從 Ollama 0.5.0的代碼修改記錄 來看,Ollama只用了很少的代碼修改就支持了結構化輸出。那么通義千問API服務什么時候能支持起來呢?