在人工智能技术快速发展的今天,构建数字分身已成为一个备受关注的应用方向。本文将详细介绍如何使用Langchain框架结合百度搜索API,实现一个功能完善的名人数字分身系统。这个系统不仅能实时获取网络信息构建人物画像,还能以自然流畅的方式与用户进行交互。
整个数字分身系统的核心是一个名为DigitTwin的类,它封装了所有必要的功能。系统设计遵循了以下几个关键原则:
系统的工作流程可以分为两个主要模式:
实现这个系统需要以下技术组件:
环境准备代码如下:
python复制import requests
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langchain.tools import tool
from langchain_core.messages import AIMessage
from openai import APIConnectionError
from langgraph.checkpoint.memory import InMemorySaver
from langchain.agents.structured_output import ToolStrategy
from dataclasses import dataclass
from pydantic import Field,BaseModel
import os
# API配置
BAIDU_API_KEY = "your_baidu_api_key"
OPENAI_API_KEY2="your_deepseek_api_key"
BASE_URL2="https://api.siliconflow.cn/v1"
MODEL_NAME2="deepseek-ai/DeepSeek-V3.2"
DigitTwin类是系统的核心,其初始化参数设计考虑了灵活性和实用性:
python复制class DigitTwin:
def __init__(self, LLM:ChatOpenAI, character_name:str, workspace:str|None=None,
search_top_k:int=5, search_times:int=5):
self.LLM = LLM # 语言模型实例
self.character_name = character_name # 名人姓名
self.workspace = workspace if workspace else os.getcwd() # 工作目录
self.search_top_k = search_top_k # 每次搜索返回结果数
self.search_times = search_times # 最大搜索次数
self.checkpointer = InMemorySaver() # 记忆存储
self.agent_char = None # 交互Agent
关键参数说明:
search_top_k:控制每次搜索返回的结果数量,影响信息丰富度search_times:限制搜索轮次,平衡信息全面性和API调用成本workspace:指定信息存储目录,默认使用当前工作目录系统通过多轮搜索构建全面的人物画像,搜索策略分为四个步骤:
对应的Agent系统提示词设计如下:
python复制system_prompt = f"""你是一个信息收集助手,用户会给你一个名人的名字。搜集关于这位名人的信息,
并将信息组织成详细的文本,包括他的个人信息、性格特点、人物联系、生涯重要事件、现状等。
## 第一步:初步搜索
先根据用户的问题,使用 baidu_search_tool 工具进行初步搜索,理解名人的基本情况。
## 第二步:搜索规划
根据初步搜索的结果,规划接下来的搜索关键词序列...(后续内容省略)
"""
系统提供两种交互方式,满足不同场景需求:
python复制def create_and_interact_now(self):
# 创建搜索Agent
agent_search = create_agent(
model=self.LLM,
tools=[baidu_search_tool],
system_prompt=...,
checkpointer=self.checkpointer
)
# 执行搜索并获取结果
result = agent_search.invoke(...)
# 立即创建交互Agent
self.create_interact_by_info(result_content)
python复制def create_and_write_info(self):
# 创建搜索+写入Agent
agent_search = create_agent(
model=self.LLM,
tools=[baidu_search_tool, write_info_into_md],
system_prompt=...,
checkpointer=self.checkpointer
)
# 执行搜索并写入文件
result = agent_search.invoke(...)
def create_interact_by_file(self):
# 从文件读取信息
path = os.path.join(self.workspace, f"information about character_{self.character_name}.md")
with open(path, 'r', encoding='utf-8') as f:
info = f.read()
# 创建交互Agent
self.create_interact_by_info(info, True)
原始的百度搜索工具经过改进,增加了top_k参数控制返回结果数量:
python复制@tool
def baidu_search_tool(query:str, top_k:int=5):
"""百度搜索工具,支持结果数量控制"""
print(f"正在搜索: {query}")
url = "https://qianfan.baidubce.com/v2/ai_search/web_search"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {BAIDU_API_KEY}"
}
data = {
"messages": [{"content": query, "role": "user"}],
"search_source": "baidu_search_v2",
"resource_type_filter": [{"type": "web", "top_k": top_k}]
}
# 处理响应并格式化结果...
关键改进点:
使用Pydantic模型定义参数结构,确保类型安全:
python复制class CharcterWrArgs(BaseModel):
workspace:str = Field(description="工作目录路径")
info:str = Field(description="组织好的角色信息")
character_name:str = Field(description="角色名称")
@tool(args_schema=CharcterWrArgs)
def write_info_into_md(workspace:str, info:str, character_name:str) -> bool:
"""将角色信息写入Markdown文件"""
try:
print(f"正在写入{character_name}的信息")
if not os.path.exists(workspace):
os.makedirs(workspace)
path = os.path.join(workspace, f"information about character_{character_name}.md")
with open(path, 'w', encoding='utf-8') as f:
f.write(info)
return True
except Exception as e:
print(f"写入失败: {e}")
return False
交互Agent的核心在于精心设计的系统提示词,确保回答符合人物特征:
python复制system_prompt = f"""你是{character_name}的一个数字分身,以下是关于{character_name}的信息:
{info}
请根据这些信息以{character_name}的身份与用户交互...
## 对你回答风格的要求:
1. 以{character_name}的身份回答,逼近其性格特点
2. 回答人性化、口语化,约150字
3. 根据问题敏感程度调整回答详细度
4. 禁止百科全书式回答
"""
交互过程采用循环结构,支持多轮对话:
python复制def create_interact_by_info(self, info:str, from_file:bool=False):
print("正在创建数字分身...交流时输入exit退出。")
if (not self.agent_char) or from_file:
self.agent_char = create_agent(...)
messages = []
while True:
query = input(f"输入你想对{self.character_name}说的话:")
if query == "exit":
return
messages.append({"role": "user", "content": query})
result = self.agent_char.invoke({"messages": messages[-3:]})
for mes in reversed(result["messages"]):
if isinstance(mes, AIMessage):
print("--------------------")
print(mes.content)
print("--------------------")
messages.append({"role": "assistant", "content": mes.content})
break
关键特性:
启动数字分身系统的完整流程:
python复制llm = ChatOpenAI(
model=MODEL_NAME2,
temperature=0.3,
base_url=BASE_URL2,
openai_api_key=OPENAI_API_KEY2,
)
if __name__ == "__main__":
name = input("输入你想创建的数字角色:")
digit_twin = DigitTwin(llm, name, search_top_k=8, search_times=6)
# 使用即时交互模式
digit_twin.create_and_interact_now()
# 使用存储加载模式
digit_twin.create_and_write_info()
digit_twin.create_interact_by_file()
以C罗数字分身为例,系统展现了出色的交互能力:
在实际使用中发现几个可以优化的方向:
最初尝试将工具函数作为类方法时遇到了self参数问题。解决方案是:
测试中发现的问题及解决方案:
问题:某些搜索返回结果相关性低
问题:多轮搜索耗时较长
确保数字分身回答符合人物特征的技巧:
该技术可以扩展到多个领域:
这个基于Langchain和百度搜索API的名人数字分身系统,展示了如何将现有AI技术组合起来创造有价值的应用。通过模块化设计和灵活的配置选项,系统可以适应多种使用场景,为开发者提供了一个可扩展的框架基础。