官方的文档如下
https://docs.crewai.com/concepts/knowledge
但是不知道为什么,可能是版本的问题(我用的是0.86.0),参考官方文档的配置我会报错,并且也导入不了数据库,也可能用的不是官方API。本文以常用的csv
,json
,pdf
作为知识库进行举例
重点:下面的代码是基于0.83.0版本的!!!最新版本(0.108.0)框架的配置可以移步文章底部补充
使用csv文件作为数据源
def csv_knowledge_source():
# 指定向量数据库持久化文件夹(如需要可取消注释)
os.environ["CREWAI_STORAGE_DIR"] = "vector_store_csv"
current_dir = Path(__file__).parent
csv_path = current_dir / "files/high_school_scores.csv"
if not csv_path.exists():
raise FileNotFoundError(f"CSV file not found at {csv_path}")
csv_source = CSVKnowledgeSource(
file_path=csv_path,
metadata={"preference": "score"}
)
openai_api_base = os.getenv("OPENAI_API_BASE")
openai_api_key = os.getenv("OPENAI_API_KEY")
if not openai_api_base or not openai_api_key:
raise ValueError("OPENAI_API_BASE or OPENAI_API_KEY not set.")
agent = Agent(
role="高中老师",
goal="你了解学生的所有成绩",
backstory="你经常关注学生的成绩",
verbose=True,
)
task = Task(
description="使用知识库中的信息回答有关学生成绩的问题: {question}",
expected_output="基于知识库数据的解答:",
agent=agent,
)
crew = Crew(
agents=[agent],
tasks=[task],
verbose=True,
process=Process.sequential,
knowledge={
"sources": [csv_source],
# "embedder": {
# "provider": "openai",
# "api_base": openai_api_base, # 移除了config层级
# "api_key": openai_api_key,
# "model": "text-embedding-3-small"
# }
}
)
try:
result = crew.kickoff(inputs={"question": "孙七的语文成绩是多少"})
print(result)
except Exception as e:
print(f"An error occurred: {e}")
high_school_scores.csv
文件
学生姓名,语文成绩,数学成绩,英语成绩
张三,63,137,66
李四,82,98,83
王五,66,50,96
赵六,57,109,145
孙七,136,121,147
使用json
文件作为数据源
def json_knowledge_source():
# 指定向量数据库持久化文件夹
os.environ["CREWAI_STORAGE_DIR"] = "vector_store_json"
# 获取当前位置路径
current_dir = Path(__file__).parent
# 指定到文件路径
json_path = current_dir / "files/high_school_scores.json"
json_source = JSONKnowledgeSource(
file_path=json_path, metadata={"preference": "personal"}
)
agent = Agent(
role="高中老师",
goal="你了解学生的所有成绩",
backstory="""你经常关注学生的成绩""",
verbose=True,
)
task = Task(
description="使用知识库中的信息回答有关学生成绩的问题: {question}",
expected_output="基于知识库数据的解答:",
agent=agent,
)
crew = Crew(
agents=[agent],
tasks=[task],
verbose=True,
process=Process.sequential,
knowledge={
"sources": [json_source],
"metadata": {"preference": "personal"},
# "embedder_config": {
# "provider": "openai",
# "config": {"model": "text-embedding-3-small"}
# }
}
)
crew.kickoff(inputs={"question": "孙七的语文成绩是多少"})
high_school_scores.json
[
{
"姓名": "张三",
"语文": 63,
"数学": 137,
"英语": 66
},
{
"姓名": "李四",
"语文": 82,
"数学": 98,
"英语": 83
},
{
"姓名": "王五",
"语文": 66,
"数学": 50,
"英语": 96
},
{
"姓名": "赵六",
"语文": 57,
"数学": 109,
"英语": 145
},
{
"姓名": "孙七",
"语文": 136,
"数学": 121,
"英语": 147
}
]
使用pdf文件作为数据源
def pdf_knowledge_source():
# 指定向量数据库持久化文件夹
os.environ["CREWAI_STORAGE_DIR"] = "vector_store_pdf"
# 获取当前位置路径
current_dir = Path(__file__).parent
# 指定到文件路径
pdf_path = current_dir / "files/人物介绍.pdf"
pdf_source = PDFKnowledgeSource(
file_path=pdf_path, metadata={"preference": "personal"}
)
agent = Agent(
role="About User",
goal="你了解文档的一切。",
backstory="""你是一个回答文档内容的高手。""",
verbose=True
)
task = Task(
description="回答有关用户的问题: {question}",
expected_output="解答问题。",
agent=agent,
)
crew = Crew(
agents=[agent],
tasks=[task],
verbose=True,
process=Process.sequential,
knowledge={
"sources": [pdf_source],
"metadata": {"preference": "personal"},
}
)
crew.kickoff(inputs={"question": "张三的基本信息?"})
人物介绍.pdf
张三,35 岁,是一位在科技领域崭露头角的软件工程师。他毕业于国内顶尖学府的计算机科学专业,凭借扎实的专业知识和对技术的热爱,在行业内积累了丰富的经验。
张三性格沉稳且富有创造力,面对复杂的技术难题,总能冷静分析,找到创新的解决方案。工作之余,他还是个户外运动爱好者,经常参与登山、骑行活动,这不仅锻炼了他的体魄,也培养了他坚韧不拔的毅力。在团队合作中,张三善于倾听他人意见,凭借出色的沟通能力,总能高效地协调团队成员,推动项目顺利进行。无论是工作还是生活,他都以积极的态度影响着身边的人,是大家眼中的榜样。
参考资料:
https://www.bilibili.com/video/BV1jPBfYfE8C
2.20 补充
向量数据库的本地存储位置,Win系统的在这里
C:\Users\用户名\AppData\Local\CrewAI
快速浏览:
Win+R,然后粘贴
explorer.exe C:\Users\%USERNAME%\AppData\Local\CrewAI
如果使用的版本是0.86.0的,将会出现如下错误,暂时还不知道是什么原因。并且目前还不可以使用自定义的embedding
层。借此博文,也希望抛砖引玉一下,求助怎么解决上述问题~
3.20 补充
更新到了最新的crewai 0.108.0版本
使用如下的配置可以正常使用知识库和自定义embedder
划重点!!!!!!!正确的写法是knowledge_sources
而不是knowledge_source
,否则不会进行数据向量化,而且还不报错,智能体还调用不了这个知识库,这个卡了我一天!!!
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.knowledge.source.json_knowledge_source import JSONKnowledgeSource
from dotenv import load_dotenv
import os
load_dotenv()
@CrewBase
class SimpleKnowledgeExample:
"""SimpleKnowledgeExample crew"""
agents_config = "config/agents.yaml"
tasks_config = "config/tasks.yaml"
json_knowledge_source = JSONKnowledgeSource(
file_paths=["lorenze.json", "random.json"]
)
@agent
def researcher(self) -> Agent:
return Agent(config=self.agents_config["researcher"], verbose=True)
@task
def research_task(self) -> Task:
return Task(
config=self.tasks_config["research_task"],
)
@crew
def crew(self) -> Crew:
"""Creates the SimpleKnowledgeExample crew"""
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=True,
knowledge_sources=[self.json_knowledge_source],
embedder={
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
# "api_key": GEMINI_API_KEY,
"api_base": "http://localhost:11434",
}
}
# embedder={
# "provider": "openai",
# "config": {
# "model": "text-embedding-3-small",
# "api_key": os.getenv("OPENAI_API_KEY"),
# "api_base": os.getenv("OPENAI_API_BASE"),
# }
# }
)
文件目录如下:
效果如下:
后台日志也显示用到了自己的embedder
但是还有bug,不能使用命令清除knowledge,需要从本地自己删除(目录见上文)
此外,传入的路径也可以使用相对路径,knowledge也不用局限于图中的位置
# 获取当前位置路径
current_dir = Path(__file__).parent
# 获取当前位置的上一级路径
parent_dir = current_dir.parent.parent
# 标准知识库文件
random_path = parent_dir / "my_knowledge/random.json"
lorenze_path = parent_dir / "my_knowledge/random.json"
print(random_path, lorenze_path)
json_knowledge_source = JSONKnowledgeSource(
file_paths=[random_path, lorenze_path]
)
可以把knowledge放在项目根目录,文件夹也不限于knowledge
这个名称(比如改成my_knowledge)
3.24 补充
数据集不支持中文
看GitHub的ISSUE #2454里应该是一个Bug,数据集的名称目前不支持中文,会生成knowledge但是不会查询到里面的信息
数据集里有中文内容不会影响
Agent里面的Role内容也不能为中文
而goal和backstory可以为中文,不会影响程序正常运行
附部分源码:
def set_knowledge(self, crew_embedder: Optional[Dict[str, Any]] = None):
try:
if self.embedder is None and crew_embedder:
self.embedder = crew_embedder
if self.knowledge_sources:
full_pattern = re.compile(r"[^a-zA-Z0-9\-_\r\n]|(\.\.)")
knowledge_agent_name = f"{re.sub(full_pattern, '_', self.role)}"
if isinstance(self.knowledge_sources, list) and all(
isinstance(k, BaseKnowledgeSource) for k in self.knowledge_sources
):
self.knowledge = Knowledge(
sources=self.knowledge_sources,
embedder=self.embedder,
collection_name=knowledge_agent_name,
storage=self.knowledge_storage or None,
)
except (TypeError, ValueError) as e:
raise ValueError(f"Invalid Knowledge Configuration: {str(e)}")