from langchain.chat_models import init_chat_modelfrom langchain.agents import create_agentfrom langchain_community.tools import DuckDuckGoSearchRun, TavilySearchResultsfrom langchain_core.rate_limiters import InMemoryRateLimiter# 我们将使用 GPT-3.5 Turbo 作为基线,并与 GPT-4o 进行比较gpt_3_5_turbo = init_chat_model( "gpt-3.5-turbo", temperature=1, configurable_fields=("model", "model_provider"),)# 指令作为系统消息传递给智能体instructions = """You are a tweet writing assistant. Given a topic, do some research and write a relevant and engaging tweet about it.- Use at least 3 emojis in each tweet- The tweet should be no longer than 280 characters- Always use the search tool to gather recent information on the tweet topic- Write the tweet only based on the search content. Do not rely on your internal knowledge- When relevant, link to your sources- Make your tweet as engaging as possible"""# 定义智能体可以使用的工具# 如果您有更高级别的 Tavily API 计划,可以增加此值rate_limiter = InMemoryRateLimiter(requests_per_second=0.08)# 如果您没有 Tavily API 密钥,请使用 DuckDuckGo:# tools = [DuckDuckGoSearchRun(rate_limiter=rate_limiter)]tools = [TavilySearchResults(max_results=5, rate_limiter=rate_limiter)]agent = create_agent(gpt_3_5_turbo, tools=tools, system_prompt=instructions)
fake_production_inputs = [ "Alan turing's early childhood", "Economic impacts of the European Union", "Underrated philosophers", "History of the Roxie theater in San Francisco", "ELI5: gravitational waves", "The arguments for and against a parliamentary system", "Pivotal moments in music history", "Big ideas in programming languages", "Big questions in biology", "The relationship between math and reality", "What makes someone funny",]agent.batch( [{"messages": [{"role": "user", "content": content}]} for content in fake_production_inputs],)
import emojifrom pydantic import BaseModel, Fieldfrom langchain_core.messages import convert_to_openai_messagesclass Grade(BaseModel): """评估响应是否由某些上下文支持。""" grounded: bool = Field(..., description="响应的大部分是否由检索到的上下文支持?")grounded_instructions = f"""You have given somebody some contextual information and asked them to write a statement grounded in that context.Grade whether their response is fully supported by the context you have provided. \If any meaningful part of their statement is not backed up directly by the context you provided, then their response is not grounded. \Otherwise it is grounded."""grounded_model = init_chat_model(model="gpt-5.4").with_structured_output(Grade)def lt_280_chars(outputs: dict) -> bool: messages = convert_to_openai_messages(outputs["messages"]) return len(messages[-1]['content']) <= 280def gte_3_emojis(outputs: dict) -> bool: messages = convert_to_openai_messages(outputs["messages"]) return len(emoji.emoji_list(messages[-1]['content'])) >= 3async def is_grounded(outputs: dict) -> bool: context = "" messages = convert_to_openai_messages(outputs["messages"]) for message in messages: if message["role"] == "tool": # 工具消息输出是从 Tavily/DuckDuckGo 工具返回的结果 context += "\n\n" + message["content"] tweet = messages[-1]["content"] user = f"""CONTEXT PROVIDED: {context} RESPONSE GIVEN: {tweet}""" grade = await grounded_model.ainvoke([ {"role": "system", "content": grounded_instructions}, {"role": "user", "content": user} ]) return grade.grounded