Agent-camel框架练习(4)


原作者链接🔗:https://fmhw1n4zpn.feishu.cn/docx/AF4XdOZpIo6TOaxzDK8cxInNnCe

Task1

通过调用API或本地部署reranker模型来快速将rerank模块集成到RAG应用中

https://github.com/camel-ai/camel/blob/master/camel/retrievers/cohere_rerank_retriever.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
"""
精简版Reranker系统:在CAMEL框架下集成模拟的外部Reranker模型

该脚本旨在清晰地展示如何将一个独立的Reranker模块(通过模拟外部API或本地部署模型)
集成到RAG应用中,以实现文档重排。
"""

import os
import re
import requests
from typing import List, Dict, Any

# 导入CAMEL框架核心模块
from camel.models import ModelFactory
from camel.types import ModelPlatformType
from camel.agents import ChatAgent
from camel.embeddings import SentenceTransformerEncoder
from camel.retrievers import VectorRetriever
from camel.storages.vectordb_storages import QdrantStorage

# 导入环境变量模块
from dotenv import load_dotenv

class MinimalRerankerSystem:
"""
精简版Reranker系统类
包含知识库设置、模拟的外部Reranker和答案生成的核心功能
"""

def __init__(self, api_key: str):
"""
初始化精简版Reranker系统

Args:
api_key: ModelScope API密钥
"""
self.api_key = api_key

# 初始化嵌入模型 (用于向量检索,Reranker本身不直接使用)
self.embedding_model = SentenceTransformerEncoder(
model_name='intfloat/e5-large-v2'
)

# 初始化向量存储 (用于演示文档检索,以便Reranker有文档可重排)
self.vector_storage = QdrantStorage(
vector_dim=self.embedding_model.get_output_dim(),
collection="minimal_reranker_collection",
path="storage_minimal_reranker",
collection_name="精简重排知识库"
)

# 初始化向量检索器
self.vector_retriever = VectorRetriever(
embedding_model=self.embedding_model,
storage=self.vector_storage
)

# 初始化LLM模型 (仅用于答案生成)
self.model = ModelFactory.create(
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
model_type="Qwen/Qwen2.5-72B-Instruct",
url='https://api-inference.modelscope.cn/v1/',
api_key=self.api_key
)

# 初始化RAG答案生成代理
self._init_agents()
self.knowledge_base_ready = False

def _init_agents(self):
"""初始化RAG答案生成代理"""

# RAG回答生成代理
rag_sys_msg = """
你是一个帮助回答问题的助手。
我会给你原始查询和检索到的上下文信息。
请根据检索到的上下文回答原始查询。
如果上下文信息不足以回答问题,请说"根据提供的信息,我无法完全回答这个问题"。
请确保回答准确、完整且有条理。
"""
self.rag_agent = ChatAgent(
system_message=rag_sys_msg,
model=self.model
)

def setup_knowledge_base(self, pdf_url: str = None, pdf_path: str = None):
"""
设置知识库,用于提供待重排的文档

Args:
pdf_url: PDF文件的URL
pdf_path: 本地PDF文件路径
"""
os.makedirs('local_data', exist_ok=True)

if pdf_url:
print("正在下载PDF文件...")
try:
response = requests.get(pdf_url, timeout=30)
response.raise_for_status()
pdf_path = 'local_data/knowledge_base.pdf'
with open(pdf_path, 'wb') as file:
file.write(response.content)
print(f"✓ PDF文件已下载到: {pdf_path}")
except Exception as e:
print(f"PDF下载失败: {e}")
raise

if pdf_path:
if not os.path.exists(pdf_path):
raise FileNotFoundError(f"PDF文件不存在: {pdf_path}")

print("正在处理PDF文件并建立向量数据库...")
try:
self.vector_retriever.process(content=pdf_path)
self.knowledge_base_ready = True
print("知识库设置完成!")
except Exception as e:
print(f"知识库设置失败: {e}")
raise
else:
raise ValueError("必须提供 pdf_url 或 pdf_path 参数")

def retrieve_documents(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]:
"""
从知识库中检索初步文档

Args:
query: 用户查询
top_k: 返回的文档数量

Returns:
初步检索到的文档列表
"""
if not self.knowledge_base_ready:
print("知识库未准备好,无法检索文档。")
return []

print(f"正在初步检索文档 (Top-{top_k})...")
retrieved_docs = self.vector_retriever.query(query=query, top_k=top_k)
print(f"✓ 初步检索到 {len(retrieved_docs)} 个文档。")
return retrieved_docs

def perform_external_rerank(self, query: str, documents: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""
模拟外部Reranker模型对文档进行重排。
此函数模拟了调用外部API或本地部署的Reranker模型。
这里使用简单的关键词匹配作为模拟的重排逻辑。

Args:
query: 用户查询
documents: 待重排的文档列表,每个文档字典包含 'text' 键

Returns:
根据模拟的外部Reranker重排后的文档列表,每个文档会添加 'relevance_score' 字段。
"""
if not documents:
print("没有文档可供重排,跳过外部Reranker。")
return []

print("正在使用模拟的外部Reranker进行文档重排...")

# 将查询分割成关键词(这里简单地按空格分割,实际Reranker会进行更复杂的处理)
query_keywords = set(query.lower().split())

scored_documents = []
for doc in documents:
doc_text_lower = doc['text'].lower()
# 模拟计算相关性分数:文档中包含的查询关键词越多,分数越高
relevance_score = sum(1 for keyword in query_keywords if keyword in doc_text_lower)

# 也可以添加一些随机性来模拟真实模型的复杂性
# import random
# relevance_score += random.uniform(0, 0.1)

# 将分数添加到文档字典中
doc_with_score = doc.copy()
doc_with_score['relevance_score'] = relevance_score
scored_documents.append(doc_with_score)

# 根据相关性分数降序排序
reranked_documents = sorted(scored_documents, key=lambda x: x.get('relevance_score', 0), reverse=True)

print(f"✓ 模拟外部Reranker重排完成。")
return reranked_documents

def generate_answer(self, query: str, retrieved_docs: List[Dict[str, Any]]) -> str:
"""
基于检索到的文档生成答案

Args:
query: 用户查询
retrieved_docs: 检索到的文档列表

Returns:
生成的答案
"""
if not retrieved_docs:
return "根据提供的信息,我无法完全回答这个问题。"

# 构建上下文
context = "\n\n".join([doc['text'] for doc in retrieved_docs])

# 构建提示
prompt = f"""
原始查询: {query}

检索到的上下文信息:
{context}

请根据上述上下文信息回答原始查询。
"""

print("\n正在生成答案...")
response = self.rag_agent.step(prompt)
answer = response.msgs[0].content.strip()
print("✓ 答案生成完成。")

return answer

def run_reranker_pipeline(self, query: str, top_k_initial: int = 5) -> Dict[str, Any]:
"""
运行重排器管道:初步检索 -> 外部Reranker重排 -> 答案生成

Args:
query: 用户查询
top_k_initial: 初步检索的文档数量

Returns:
包含初步文档、重排文档和最终答案的字典
"""
print("\n" + "=" * 60)
print(f"开始运行Reranker管道,查询: {query}")
print("=" * 60)

# 步骤1: 初步检索文档
initial_retrieved_docs = self.retrieve_documents(query, top_k_initial)

# 步骤2: 外部Reranker重排文档
reranked_docs = self.perform_external_rerank(query, initial_retrieved_docs)

# 步骤3: 基于重排后的文档生成答案
final_answer = self.generate_answer(query, reranked_docs)

print("\n" + "=" * 60)
print("Reranker管道执行完成!")
print("=" * 60)

return {
"query": query,
"initial_retrieved_docs": initial_retrieved_docs,
"reranked_docs": reranked_docs,
"final_answer": final_answer
}

def main():
"""主函数:演示精简版Reranker系统的使用"""

# 加载环境变量
load_dotenv()
api_key = os.getenv('MODELSCOPE_SDK_TOKEN')

if not api_key:
print("错误:请设置MODELSCOPE_SDK_TOKEN环境变量")
print("请在.env文件中添加 MODELSCOPE_SDK_TOKEN=你的API密钥")
return

# 初始化Reranker系统
print("正在初始化Reranker系统...")
reranker_system = MinimalRerankerSystem(api_key)
print("系统初始化完成!")

# 设置知识库 (使用CAMEL论文作为示例)
pdf_url = "https://arxiv.org/pdf/2303.17760.pdf"
print(f"\n正在设置知识库(使用默认CAMEL论文: {pdf_url})...")
try:
reranker_system.setup_knowledge_base(pdf_url=pdf_url)
except Exception as e:
print(f"知识库设置失败: {e}")
return

# 运行交互式会话
while True:
query = input("\n请输入您的查询(输入'quit'退出): ").strip()

if query.lower() in ['quit', 'exit', '退出']:
print("感谢使用!再见!")
break

if not query:
print("查询不能为空,请重新输入。")
continue

try:
results = reranker_system.run_reranker_pipeline(query, top_k_initial=5)

print("\n--- 原始检索结果 (Top 5) ---")
if results['initial_retrieved_docs']:
for i, doc in enumerate(results['initial_retrieved_docs']):
print(f"文档 {i+1}: {doc['text'][:150]}...")
else:
print("无原始检索文档。")

print("\n--- 外部Reranker重排后的结果 ---")
if results['reranked_docs']:
for i, doc in enumerate(results['reranked_docs']):
# 显示模拟的相关性分数
score_info = f" (相关性分数: {doc.get('relevance_score', 'N/A'):.2f})"
print(f"文档 {i+1}{score_info}: {doc['text'][:150]}...")
else:
print("无重排文档。")

print("\n--- 最终答案 ---")
print(results['final_answer'])

except Exception as e:
print(f"\n发生错误: {e}")
import traceback
traceback.print_exc() # 打印详细错误信息
continue_choice = input("是否继续?(y/n): ").strip().lower()
if continue_choice != 'y':
break

if __name__ == "__main__":
main()

我们可以运行看一下重排效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
PS D:\Camel_Test_Project> & D:/Download/Python/py-3.11.9/python.exe d:/Camel_Test_Project/Reranker_lite.py  
正在初始化Reranker系统...
W0724 23:07:45.865000 37864 site-packages\torch\distributed\elastic\multiprocessing\redirects.py:29] NOTE: Redirects are currently not supported in Windows or MacOs.
系统初始化完成!

正在设置知识库(使用默认CAMEL论文: https://arxiv.org/pdf/2303.17760.pdf)...
正在下载PDF文件...
✓ PDF文件已下载到: local_data/knowledge_base.pdf
正在处理PDF文件并建立向量数据库...
知识库设置完成!

请输入您的查询(输入'quit'退出): camel是什么?

============================================================
开始运行Reranker管道,查询: camel是什么?
============================================================
正在初步检索文档 (Top-5)...
✓ 初步检索到 5 个文档。
正在使用模拟的外部Reranker进行文档重排...
✓ 模拟外部Reranker重排完成。

正在生成答案...
✓ 答案生成完成。

============================================================
Reranker管道执行完成!
============================================================

--- 原始检索结果 (Top 5) ---
文档 1: 3 2 0 2

v o N 2

] I

A . s c [

2 v 0 6 7 7 1 . 3 0 3 2 : v i X r a

CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Soci...
文档 2: 3 2 0 2

v o N 2

] I

A . s c [

2 v 0 6 7 7 1 . 3 0 3 2 : v i X r a

CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Soci...
文档 3: me instructions and necessary inputs until you think the task is completed. When the task is completed, you must only reply with a single word <CAMEL_...
文档 4: me instructions and necessary inputs until you think the task is completed. When the task is completed, you must only reply with a single word <CAMEL_...
文档 5: Human Evaluation Guideline

Thank you for participating in our task evaluation! We are comparing the performance of ChatGPT and a method called CAMEL ...

--- 外部Reranker重排后的结果 ---
文档 1 (相关性分数: 0.00): 3 2 0 2

v o N 2

] I

A . s c [

2 v 0 6 7 7 1 . 3 0 3 2 : v i X r a

CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Soci...
文档 2 (相关性分数: 0.00): 3 2 0 2

v o N 2

] I

A . s c [

2 v 0 6 7 7 1 . 3 0 3 2 : v i X r a

CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Soci...
文档 3 (相关性分数: 0.00): me instructions and necessary inputs until you think the task is completed. When the task is completed, you must only reply with a single word <CAMEL_...
文档 4 (相关性分数: 0.00): me instructions and necessary inputs until you think the task is completed. When the task is completed, you must only reply with a single word <CAMEL_...
文档 5 (相关性分数: 0.00): Human Evaluation Guideline

Thank you for participating in our task evaluation! We are comparing the performance of ChatGPT and a method called CAMEL ...

--- 最终答案 ---
根据提供的信息,CAMEL(Communicative Agents for “Mind” Exploration of Large Language Model Society)是一种用于探索大型语言模型社会“心智”的交流代理系统。这个项目由沙特阿拉伯国王科技大学(KAUST)的研究人员开发,旨在通过交流代理来研究和理解大型语言模型之 间的互动和社会动态。更多详情可以参考该项目的官方网站:https://www.camel-ai.org。

请输入您的查询(输入'quit'退出): quit
感谢使用!再见!

Task2

使用大语言模型和简单的提示词工程在CAMEL框架下实现一个ReRanker,达成重排的效果(灵感来自CAMEL Shanghai Hackathon韬子哥QAQ)

https://github.com/fengju0213/NavigatorAI/blob/main/2Travel_information_generation.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
"""
LLM ReRanker:在CAMEL框架下实现基于大语言模型的文档重排

该脚本旨在清晰地展示如何使用CAMEL框架和简单的提示词工程实现文档重排。
"""

import os
import re
import requests
from typing import List, Dict, Any

# 导入CAMEL框架核心模块
from camel.models import ModelFactory
from camel.types import ModelPlatformType
from camel.agents import ChatAgent
from camel.embeddings import SentenceTransformerEncoder
from camel.retrievers import VectorRetriever
from camel.storages.vectordb_storages import QdrantStorage

# 导入环境变量模块
from dotenv import load_dotenv

class MinimalLLMReranker:
"""
LLM ReRanker系统类
仅包含知识库设置、LLM ReRanker和答案生成的核心功能
"""

def __init__(self, api_key: str):
"""
初始化LLM ReRanker系统

Args:
api_key: ModelScope API密钥
"""
self.api_key = api_key

# 初始化嵌入模型 (用于向量检索,ReRanker本身不直接使用)
self.embedding_model = SentenceTransformerEncoder(
model_name='intfloat/e5-large-v2'
)

# 初始化向量存储 (用于演示文档检索,以便ReRanker有文档可重排)
self.vector_storage = QdrantStorage(
vector_dim=self.embedding_model.get_output_dim(),
collection="minimal_reranker_collection",
path="storage_minimal_reranker",
collection_name="精简重排知识库"
)

# 初始化向量检索器
self.vector_retriever = VectorRetriever(
embedding_model=self.embedding_model,
storage=self.vector_storage
)

# 初始化LLM模型 (用于ReRanker和答案生成)
self.model = ModelFactory.create(
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
model_type="Qwen/Qwen2.5-72B-Instruct",
url='https://api-inference.modelscope.cn/v1/',
api_key=self.api_key
)

# 初始化LLM ReRanker代理和RAG答案生成代理
self._init_agents()
self.knowledge_base_ready = False

def _init_agents(self):
"""初始化LLM ReRanker代理和RAG答案生成代理"""

# LLM ReRanker 代理
# 提示词工程:明确要求输出格式为逗号分隔的数字序列,不含额外文字
reranker_sys_msg = """
你是一个文档重排助手。你的任务是根据用户查询,对提供的文档列表进行相关性排序。
你会接收一个用户查询和多个文档,每个文档都有一个编号。
请你根据文档与查询的深层相关性,从最相关到最不相关,输出文档的编号序列。
输出格式必须是逗号分隔的数字,例如:1, 3, 2, 4。
不要包含任何其他文字或解释。
"""
self.reranker_agent = ChatAgent(
system_message=reranker_sys_msg,
model=self.model
)

# RAG回答生成代理
rag_sys_msg = """
你是一个帮助回答问题的助手。
我会给你原始查询和检索到的上下文信息。
请根据检索到的上下文回答原始查询。
如果上下文信息不足以回答问题,请说"根据提供的信息,我无法完全回答这个问题"。
请确保回答准确、完整且有条理。
"""
self.rag_agent = ChatAgent(
system_message=rag_sys_msg,
model=self.model
)

def setup_knowledge_base(self, pdf_url: str = None, pdf_path: str = None):
"""
设置知识库,用于提供待重排的文档

Args:
pdf_url: PDF文件的URL
pdf_path: 本地PDF文件路径
"""
os.makedirs('local_data', exist_ok=True)

if pdf_url:
print("正在下载PDF文件...")
try:
response = requests.get(pdf_url, timeout=30)
response.raise_for_status()
pdf_path = 'local_data/knowledge_base.pdf'
with open(pdf_path, 'wb') as file:
file.write(response.content)
print(f"✓ PDF文件已下载到: {pdf_path}")
except Exception as e:
print(f"PDF下载失败: {e}")
raise

if pdf_path:
if not os.path.exists(pdf_path):
raise FileNotFoundError(f"PDF文件不存在: {pdf_path}")

print("正在处理PDF文件并建立向量数据库...")
try:
self.vector_retriever.process(content=pdf_path)
self.knowledge_base_ready = True
print("知识库设置完成!")
except Exception as e:
print(f"知识库设置失败: {e}")
raise
else:
raise ValueError("必须提供 pdf_url 或 pdf_path 参数")

def retrieve_documents(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]:
"""
从知识库中检索初步文档

Args:
query: 用户查询
top_k: 返回的文档数量

Returns:
初步检索到的文档列表
"""
if not self.knowledge_base_ready:
print("知识库未准备好,无法检索文档。")
return []

print(f"正在初步检索文档 (Top-{top_k})...")
retrieved_docs = self.vector_retriever.query(query=query, top_k=top_k)
print(f"✓ 初步检索到 {len(retrieved_docs)} 个文档。")
return retrieved_docs

def rerank_documents(self, query: str, documents: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""
使用LLM对文档进行重排

Args:
query: 用户查询
documents: 待重排的文档列表,每个文档字典包含 'text' 键

Returns:
根据LLM重排后的文档列表
"""
if not documents:
print("没有文档可供重排,跳过LLM重排。")
return []

print("正在使用LLM进行文档重排...")

# 构建发送给LLM的提示
prompt_parts = [f"用户查询: {query}\n\n以下是需要重排的文档列表:"]
for i, doc in enumerate(documents):
# 限制文档内容长度,避免超出LLM上下文窗口
truncated_text = doc['text'][:500] + "..." if len(doc['text']) > 500 else doc['text']
prompt_parts.append(f"文档 {i+1}:\n{truncated_text}\n")

prompt_parts.append("\n请根据文档与查询的相关性,从最相关到最不相关,输出文档的编号序列。输出格式必须是逗号分隔的数字,例如:1, 3, 2, 4。不要包含任何其他文字或解释。")
rerank_prompt = "\n".join(prompt_parts)

try:
response = self.reranker_agent.step(rerank_prompt)
reranked_order_str = response.msgs[0].content.strip()

# 解析LLM的输出,获取排序后的文档索引
# 使用正则表达式匹配数字和逗号,确保只提取数字序列
match = re.search(r'^\s*(\d+(?:\s*,\s*\d+)*)\s*$', reranked_order_str)
if match:
ordered_indices = [int(idx.strip()) - 1 for idx in match.group(1).split(',')]

# 过滤掉无效的索引(超出文档列表范围的)
valid_ordered_indices = [idx for idx in ordered_indices if 0 <= idx < len(documents)]

# 根据LLM返回的顺序重排文档
reranked_documents = [documents[i] for i in valid_ordered_indices]

# 如果LLM返回的文档数量少于原始文档数量,将未被LLM排序的文档按原顺序追加到末尾
original_indices = set(range(len(documents)))
llm_sorted_indices = set(valid_ordered_indices)
remaining_indices = sorted(list(original_indices - llm_sorted_indices))

for idx in remaining_indices:
reranked_documents.append(documents[idx])

print(f"✓ LLM重排完成。新顺序: {[idx + 1 for idx in valid_ordered_indices]}")
return reranked_documents
else:
print(f"LLM重排输出格式不正确,无法解析。原始输出: '{reranked_order_str}'。将返回原始文档顺序。")
return documents # 返回原始文档顺序
except Exception as e:
print(f"LLM重排失败: {e}。将返回原始文档顺序。")
return documents # 发生错误时返回原始文档顺序

def generate_answer(self, query: str, retrieved_docs: List[Dict[str, Any]]) -> str:
"""
基于检索到的文档生成答案

Args:
query: 用户查询
retrieved_docs: 检索到的文档列表

Returns:
生成的答案
"""
if not retrieved_docs:
return "根据提供的信息,我无法完全回答这个问题。"

# 构建上下文
context = "\n\n".join([doc['text'] for doc in retrieved_docs])

# 构建提示
prompt = f"""
原始查询: {query}

检索到的上下文信息:
{context}

请根据上述上下文信息回答原始查询。
"""

print("\n正在生成答案...")
response = self.rag_agent.step(prompt)
answer = response.msgs[0].content.strip()
print("✓ 答案生成完成。")

return answer

def run_reranker_pipeline(self, query: str, top_k_initial: int = 5) -> Dict[str, Any]:
"""
运行重排器管道:初步检索 -> LLM重排 -> 答案生成

Args:
query: 用户查询
top_k_initial: 初步检索的文档数量

Returns:
包含初步文档、重排文档和最终答案的字典
"""
print("\n" + "=" * 60)
print(f"开始运行LLM重排管道,查询: {query}")
print("=" * 60)

# 步骤1: 初步检索文档
initial_retrieved_docs = self.retrieve_documents(query, top_k_initial)

# 步骤2: LLM重排文档
reranked_docs = self.rerank_documents(query, initial_retrieved_docs)

# 步骤3: 基于重排后的文档生成答案
final_answer = self.generate_answer(query, reranked_docs)

print("\n" + "=" * 60)
print("LLM重排管道执行完成!")
print("=" * 60)

return {
"query": query,
"initial_retrieved_docs": initial_retrieved_docs,
"reranked_docs": reranked_docs,
"final_answer": final_answer
}

def main():
"""主函数:演示精简版LLM ReRanker系统的使用"""

# 加载环境变量
load_dotenv()
api_key = os.getenv('MODELSCOPE_SDK_TOKEN')

if not api_key:
print("错误:请设置MODELSCOPE_SDK_TOKEN环境变量")
print("请在.env文件中添加 MODELSCOPE_SDK_TOKEN=你的API密钥")
return

# 初始化LLM ReRanker系统
print("正在初始化LLM ReRanker系统...")
reranker_system = MinimalLLMReranker(api_key)
print("系统初始化完成!")

# 设置知识库 (使用CAMEL论文作为示例)
pdf_url = "https://arxiv.org/pdf/2303.17760.pdf"
print(f"\n正在设置知识库(使用默认CAMEL论文: {pdf_url})...")
try:
reranker_system.setup_knowledge_base(pdf_url=pdf_url)
except Exception as e:
print(f"知识库设置失败: {e}")
return

# 运行交互式会话
while True:
query = input("\n请输入您的查询(输入'quit'退出): ").strip()

if query.lower() in ['quit', 'exit', '退出']:
print("感谢使用!再见!")
break

if not query:
print("查询不能为空,请重新输入。")
continue

try:
results = reranker_system.run_reranker_pipeline(query, top_k_initial=5)

print("\n--- 原始检索结果 (Top 5) ---")
if results['initial_retrieved_docs']:
for i, doc in enumerate(results['initial_retrieved_docs']):
print(f"文档 {i+1}: {doc['text'][:150]}...")
else:
print("无原始检索文档。")

print("\n--- LLM重排后的结果 ---")
if results['reranked_docs']:
for i, doc in enumerate(results['reranked_docs']):
# 尝试获取RRF分数或相似度,如果存在的话
score_info = f" (RRF分数: {doc['rrf_score']:.4f})" if 'rrf_score' in doc else ""
score_info = f" (相似度: {doc['similarity']:.4f})" if 'similarity' in doc else score_info
print(f"文档 {i+1}{score_info}: {doc['text'][:150]}...")
else:
print("无重排文档。")

print("\n--- 最终答案 ---")
print(results['final_answer'])

except Exception as e:
print(f"\n发生错误: {e}")
import traceback
traceback.print_exc() # 打印详细错误信息
continue_choice = input("是否继续?(y/n): ").strip().lower()
if continue_choice != 'y':
break

if __name__ == "__main__":
main()

运行效果:

1
2
3
4
5
6
7
8
9
10
11
12
PS D:\Camel_Test_Project> python Reranker_simple.py
正在初始化LLM ReRanker系统...
W0724 21:56:33.691000 38432 site-packages\torch\distributed\elastic\multiprocessing\redirects.py:29] NOTE: Redirects are currently not supported in Windows or MacOs.
系统初始化完成!

正在设置知识库(使用默认CAMEL论文: https://arxiv.org/pdf/2303.17760.pdf)...
正在下载PDF文件...
✓ PDF文件已下载到: local_data/knowledge_base.pdf
正在处理PDF文件并建立向量数据库...
知识库设置完成!

请输入您的查询(输入'quit'退出):

此时我们可以输入我们想要检索的内容,因为测试的PDF文件仍为CAMEL论文官方线上文件,所以我们直接问与CAMEL相关的:“camel是什么?对于我AI学习有什么帮助?”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
请输入您的查询(输入'quit'退出):camel是什么?对于我AI学习有什么帮助?

============================================================
开始运行LLM重排管道,查询: camel是什么?对于我AI学习有什么帮助?
============================================================
正在初步检索文档 (Top-5)...
✓ 初步检索到 5 个文档。
正在使用LLM进行文档重排...
✓ LLM重排完成。新顺序: [5, 3, 4, 2, 1]

正在生成答案...
✓ 答案生成完成。

============================================================
LLM重排管道执行完成!
============================================================

--- 原始检索结果 (Top 5) ---
文档 1: Human Evaluation Guideline

Thank you for participating in our task evaluation! We are comparing the performance of ChatGPT and a method called CAMEL ...
文档 2: Objective: Your task is to compare two messages, one generated by CAMEL and the other by ChatGPT. These messages will be displayed anonymously on your...
文档 3: 3 2 0 2

v o N 2

] I

A . s c [

2 v 0 6 7 7 1 . 3 0 3 2 : v i X r a

CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Soci...
文档 4: Feedback: We highly value your feedback. If you have any suggestions, concerns, or encounter any technical issues during the evaluation, please feel f...
文档 5: agent is asked to draw all the Camelidae species. It first reasons about what animals are included in the Camelidae family and then generates and save...

--- LLM重排后的结果 ---
文档 1: agent is asked to draw all the Camelidae species. It first reasons about what animals are included in the Camelidae family and then generates and save...
文档 2: 3 2 0 2

v o N 2

] I

A . s c [

2 v 0 6 7 7 1 . 3 0 3 2 : v i X r a

CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Soci...
文档 3: Feedback: We highly value your feedback. If you have any suggestions, concerns, or encounter any technical issues during the evaluation, please feel f...
文档 4: Objective: Your task is to compare two messages, one generated by CAMEL and the other by ChatGPT. These messages will be displayed anonymously on your...
文档 5: Human Evaluation Guideline

Thank you for participating in our task evaluation! We are comparing the performance of ChatGPT and a method called CAMEL ...

--- 最终答案 ---
根据提供的信息,"camel"在这里有两个不同的含义:

1. **生物学上的驼科(Camelidae)**:这是指一类哺乳动物,包括骆驼、羊驼等。然而,这个定义与您的AI学习没有直接关系。

2. **CAMEL项目**:这是一个名为“Communicative Agents for ‘Mind’ Exploration of Large Language Model Society”的研究项目,由沙特阿拉伯阿卜杜拉国王科技大学(KAUST)的研究人员开发。CAMEL项目的目的是通过创建交互式代理来探索大型语言模型的社会“心智”。这些代理 可以生成图像、进行任务比较和评估,并通过用户反馈不断改进。

### 对于AI学习的帮助:
- **理解大型语言模型**:CAMEL项目可以帮助你更好地理解大型语言模型的工作原理和能力。
- **实践应用**:通过参与CAMEL项目,你可以实际操作和评估不同AI系统的性能,从而提升你 的实践技能。
- **研究贡献**:你的反馈和参与可以为AI研究提供有价值的数据,推动AI技术的发展。

如果你对生物学上的驼科更感兴趣,建议查阅相关的生物学资料。如果你对AI学习更感兴趣,可以进一步了解CAMEL项目并参与其中。

请输入您的查询(输入'quit'退出):

此时第一轮检索生成已经完成,代理自动进入第二个问题查询。我们继续输入我们的问题:“camel具备哪些特性?”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
请输入您的查询(输入'quit'退出):camel具备哪些特性?            

============================================================
开始运行LLM重排管道,查询: camel具备哪些特性?
============================================================
正在初步检索文档 (Top-5)...
✓ 初步检索到 5 个文档。
正在使用LLM进行文档重排...
✓ LLM重排完成。新顺序: [1, 2, 3, 4, 5]

正在生成答案...
✓ 答案生成完成。

============================================================
LLM重排管道执行完成!
============================================================

--- 原始检索结果 (Top 5) ---
文档 1: 3 2 0 2

v o N 2

] I

A . s c [

2 v 0 6 7 7 1 . 3 0 3 2 : v i X r a

CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Soci...
文档 2: me instructions and necessary inputs until you think the task is completed. When the task is completed, you must only reply with a single word <CAMEL_...
文档 3: Human Evaluation Guideline

Thank you for participating in our task evaluation! We are comparing the performance of ChatGPT and a method called CAMEL ...
文档 4: Objective: Your task is to compare two messages, one generated by CAMEL and the other by ChatGPT. These messages will be displayed anonymously on your...
文档 5: Feedback: We highly value your feedback. If you have any suggestions, concerns, or encounter any technical issues during the evaluation, please feel f...

--- LLM重排后的结果 ---
文档 1: 3 2 0 2

v o N 2

] I

A . s c [

2 v 0 6 7 7 1 . 3 0 3 2 : v i X r a

CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Soci...
文档 2: me instructions and necessary inputs until you think the task is completed. When the task is completed, you must only reply with a single word <CAMEL_...
文档 3: Human Evaluation Guideline

Thank you for participating in our task evaluation! We are comparing the performance of ChatGPT and a method called CAMEL ...
文档 4: Objective: Your task is to compare two messages, one generated by CAMEL and the other by ChatGPT. These messages will be displayed anonymously on your...
文档 5: Feedback: We highly value your feedback. If you have any suggestions, concerns, or encounter any technical issues during the evaluation, please feel f...

--- 最终答案 ---
根据提供的上下文信息,CAMEL(Communicative Agents for “Mind” Exploration of Large Language Model Society)具备以下特性:

1. **交互式代理**:CAMEL项目使用交互式代理来生成和处理任务,这些代理可以模拟人类的对话和思维过程。
2. **任务完成**:CAMEL代理能够接收任务指令,并在任务完成后回复特定的确认词 `<CAMEL_TASK_DONE>`。
3. **性能评估**:CAMEL项目包括对不同AI系统(如ChatGPT和CAMEL自身)的性能评估,通过用户反馈和投票来比较它们的表现。
4. **用户参与**:CAMEL项目鼓励用户参与任务评估,提供反馈和建议,以帮助改进AI系统的性能。
5. **生成内容**:CAMEL框架可以生成各种内容,包括文本、图像等,用于任务完成和评估。
6. **社会“心智”探索**:CAMEL项目旨在通过代理之间的互动来探索大型语言模型的社会“心智”,即这些模型如何理解和处理社会互动和复杂任务。

这些特性使得CAMEL项目在AI研究和应用中具有重要的意义,特别是在理解和发展更高级的交互 式AI系统方面。

请输入您的查询(输入'quit'退出): quit
感谢使用!再见!

此时我们可以看到两轮问答输出的排序效果:

第一次查询:“camel是什么?对于我AI学习有什么帮助?”

正在初步检索文档 (Top-5)…
✓ 初步检索到 5 个文档。
正在使用LLM进行文档重排…
✓ LLM重排完成。新顺序: [5, 3, 4, 2, 1]

  • 原始检索结果: 文档3(“CAMEL: Communicative Agents for ‘Mind’ Exploration of Large Language Model Soci…”)是关于CAMEL项目的核心文档,但是代理将其排在第三位。而文档5(“agent is asked to draw all the Camelidae species…”)是关于生物学上的“驼科”的,与AI学习的相关性较低,故排在第五位。
  • LLM重排后的结果: LLM将文档5(驼科)重排到了第一位,而将文档3(CAMEL项目)重排到了第二位。这表明LLM在这次重排中将生物学含义的“camel”置于了更高的优先级,尽管我们查询的后半部分明确指向了AI学习。
  • 最终答案: 尽管重排结果将次相关文档排在了前面,但最终答案依然能够正确识别“camel”的两种含义(生物学和CAMEL项目),并详细解释了CAMEL项目对AI学习的帮助,这说明RAG的生成部分能够有效地利用所有检索到的上下文,即使文档顺序不完全理想。

第二次查询:“camel具备哪些特性?”

  • 原始检索结果: 文档1(“CAMEL: Communicative Agents for ‘Mind’ Exploration of Large Language Model Soci…”)是关于CAMEL项目核心的文档,排在第一位。
  • LLM重排后的结果: LLM的重排顺序是[1, 2, 3, 4, 5],与原始检索结果的顺序完全一致。这表明LLM认为原始检索器提供的文档顺序已经足够优化,或者它没有找到更优的重排方式。
  • 最终答案: 最终答案详细列举了CAMEL项目的各项特性,这得益于原始检索结果中相关性高的文档(文档1)已经位于靠前的位置。

因此可见**LLM ReRanker能够根据查询对文档进行重新排序。**在第一个查询中,它改变了文档顺序,但并非总是将最相关的文档(从人类角度看)排在首位,可能受到文档内容中“camel”多义性的影响。在第二个查询中,它维持了原始顺序。这表明LLM重排器在某些情况下可以优化文档顺序,但在处理多义性查询时可能需要更精细的提示词工程或结合其他信号来确保最高相关性的文档始终排在最前面。然而,即使重排结果并非完美,RAG的生成能力依然能够从提供的上下文中提取信息并给出较为全面的答案。

关于Task1和Task2的区别思考:这两个任务都涉及在RAG应用中集成重排(ReRanker)模块,但它们在实现方式和所依赖的技术栈上存在显著区别:

Task 1:基于API调用或本地部署的预训练Reranker模型集成

  • 实现方式: 这个任务侧重于利用外部的、专门训练过的重排模型或服务
    • API 调用: 像Cohere ReRank这样的服务,提供了一个API接口,您可以将查询和文档列表发送给它,它会返回重排后的文档。这种方式通常开箱即用,性能经过优化。
    • 本地部署Reranker模型: 指的是下载并运行一个已经预训练好的重排模型(例如基于BERT、RoBERTa等架构的跨编码器模型),在本地环境中进行文档重排。
  • 特点:
    • 效率高、性能优越: 这些模型通常是专门为重排任务训练的,能够捕捉文档和查询之间的细微相关性,性能通常比通用大模型在重排上的表现更稳定和高效。
    • 开箱即用: 集成过程通常是调用SDK或API,相对简单快捷。
    • 资源消耗: 如果是本地部署,需要一定的计算资源;如果调用API,则涉及外部服务费用。
  • 参考链接分析: https://github.com/camel-ai/camel/blob/master/camel/retrievers/cohere_rerank_retriever.py 指向CAMEL框架中一个与Cohere ReRank服务集成的检索器。这明确表示Task 1是关于使用外部的、专业的重排服务

Task 2:基于大语言模型和提示词工程实现Reranker

  • 实现方式: 这个任务的核心是利用通用大语言模型的零样本或少样本能力,通过精巧的提示词(Prompt Engineering)来“引导”LLM执行重排任务
    • 您需要设计一个提示词,告诉LLM它是一个“重排助手”,提供查询和待重排的文档列表,并要求LLM输出重排后的文档顺序或评分。
    • 重排的逻辑完全由LLM的推理能力和您的提示词设计决定。
  • 特点:
    • 灵活性高: 可以根据具体需求,通过修改提示词来调整重排逻辑,适用于各种自定义场景。
    • 不依赖特定Reranker模型: 只要有通用大语言模型(如Qwen、ChatGPT等)即可实现,无需额外部署专门的重排模型。
    • 性能波动: 重排效果高度依赖于LLM的理解能力和提示词的质量,可能不如专门训练的Reranker模型稳定和极致。
    • 资源消耗: 调用LLM的API通常会有成本,且LLM的推理速度可能比专门的Reranker慢。
  • 参考链接分析: https://github.com/fengju0213/NavigatorAI/blob/main/2Travel_information_generation.py 以及您之前让我优化过的代码,都是通过在CAMEL框架中使用 ChatAgent(即一个LLM代理)并结合自定义的系统消息和用户消息来模拟重排过程的。这明确表示Task 2是关于通过提示词工程将LLM作为重排器使用

核心区别总结:

特征 Task 1:API/本地部署Reranker模型 Task 2:LLM + 提示词工程实现Reranker
重排核心 专门训练的重排模型/服务 通用大语言模型 (LLM) 的推理能力
实现方式 调用成熟的API或SDK,或部署现有模型 设计提示词,引导LLM进行重排
性能 通常更稳定、高效,针对重排任务优化 依赖LLM能力和提示词质量,可能波动较大
灵活性 较低,重排逻辑固定在模型中 较高,可通过调整提示词灵活定制重排逻辑
资源 可能需要GPU(本地)或API费用(云服务) 调用LLM的API费用,LLM本身运行资源
开发难度 相对较低,多为配置和集成 需要精通提示词工程,调试LLM行为

Task3

导出本教程文档作为一个PDF文件,尝试搭建一个具有多模态检索能力的RAG应用来帮助其他学习者回答问题。

由于我没有找到很好的将本教程文档转化为一个线上可直接数据向量化的方法,但经过运行确认确实可以将线上的PDF文档本地下载初始化数据库。
因此我们演示时暂时采用本地下载好的本教程PDF文档作为演示案例。

我们先来说明一下整个系统的具体实现:

交互式多模态RAG系统

项目简介

这是一个基于CAMEL框架的交互式多模态RAG(检索增强生成)系统,集成了PDF文档处理、网页爬取、知识图谱构建和多种检索模式。系统支持文本、图像、表格等多模态内容的智能检索和分析。

核心特性
多模态内容处理
  • PDF文档解析:支持在线PDF和本地PDF文件加载
  • 多模态元素提取:自动识别和处理文本、图像、表格内容
  • 智能内容分类:按内容类型进行分类存储和检索
多种检索模式
  1. 快速检索:基础向量检索,快速获取相关文档
  2. 深度检索:查询重写 + HyDE + RRF融合的高级检索
  3. 主题检索:PDF文档 + 网页爬取的综合检索
AI智能分析
  • CAMEL框架集成:使用CAMEL ModelFactory进行模型管理
  • 查询重写:智能优化用户查询以提高检索效果
  • HyDE增强:假设文档生成技术提升检索精度
  • RRF融合:多路检索结果的智能融合排序
网页研究系统
  • 智能网页爬取:基于主题的网页内容抓取
  • 知识图谱构建:自动构建主题相关的知识图谱
  • 多源信息融合:PDF文档与网页信息的智能整合
交互式体验
  • 实时对话界面:支持连续问答和上下文理解
  • 结果可视化:详细的检索结果展示和分析
  • 报告生成:自动生成研究报告和结果保存
系统架构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
交互式多模态RAG系统
├── 核心组件
│ ├── SimpleLLMInterface (CAMEL模型接口)
│ ├── SimpleEmbeddingModel (嵌入模型)
│ ├── SimpleVectorRetriever (向量检索器)
│ └── SimpleRAGSystem (RAG核心系统)
├── 检索模式
│ ├── 快速检索 (基础向量检索)
│ ├── 深度检索 (重写+HyDE+RRF)
│ └── 主题检索 (PDF+网页爬取)
├── 网页研究系统
│ ├── UniversalResearchSystem (通用研究系统)
│ ├── InteractiveResearchSystem (交互式研究)
│ └── EnhancedInteractiveResearchSystem (增强版)
└── 交互界面
├── 知识库管理
├── 查询处理
└── 结果展示
核心框架
  • CAMEL: AI智能体框架,提供模型管理和工具集成
  • LangChain: 大语言模型应用开发框架
  • Sentence Transformers: 文本嵌入和语义检索
文档处理
  • PyPDF: PDF文档解析和文本提取
  • Unstructured: 多模态文档元素识别和处理
  • BeautifulSoup: HTML内容解析和清理
检索和存储
  • Scikit-learn: 向量相似度计算和机器学习
  • NumPy: 数值计算和向量操作
  • Neo4j: 知识图谱存储和查询(可选)
网页爬取
  • Requests: HTTP请求和网页内容获取
  • Firecrawl: 智能网页内容抓取
  • SearchToolkit: 网页搜索和信息检索

基本使用流程

  1. 选择PDF来源

    • 在线PDF(输入URL)
    • 本地PDF(输入文件路径)
    • 默认示例PDF(CAMEL论文)
  2. 选择检索模式

    • 快速检索:适合简单问答
    • 深度检索:适合复杂分析
    • 主题检索:适合综合研究
  3. 输入查询问题

    • 支持中英文查询
    • 支持复杂的多步骤问题
    • 支持上下文相关的连续对话
  4. 查看结果

    • 检索到的相关文档
    • AI生成的详细答案
    • 可选的结果保存功能
高级功能
网页研究模式
1
2
# 启动增强版研究系统
python RAG_WEB_TOPIC_Enhanced.py
自定义检索参数
1
2
3
4
5
6
7
8
9
# 在代码中调整检索参数
results = rag_system.enhanced_query(
original_query=query,
use_rewriting=True, # 启用查询重写
use_hyde=True, # 启用HyDE增强
use_rrf=True, # 启用RRF融合
top_k=5, # 返回文档数量
multimodal_preference=['text', 'image', 'table'] # 多模态偏好
)
检索模式
快速检索
  • 用途:基础问答和快速信息查找
  • 特点:速度快,资源消耗低
  • 适用场景:简单事实查询,概念解释
深度检索
  • 用途:复杂分析和深度研究
  • 特点:多步骤处理,结果精确
  • 适用场景:学术研究,技术分析
主题检索
  • 用途:综合信息收集和跨源研究
  • 特点:结合PDF和网页信息
  • 适用场景:市场调研,趋势分析

接下来我们来看看具体的实现代码:

实现代码:

实现代码主要分为3个部分:

主代码:【Interactive_Multimodal_RAG.py】集成“快速检索”+“深度检索”的多模态RAG应用
分支代码:【RAG_WEB_TOPIC_Enhanced.py + RAG_WEB_TOPIC.py】集成“主题”检索的Web 抓取 + 知识图谱构建的综合RAG应用

说明:RAG_WEB_TOPIC_Enhanced.py 系统基于 RAG_WEB_TOPIC.py 改进开发,在使用运行RAG_WEB_TOPIC_Enhanced.py 的时候会同时运行 RAG_WEB_TOPIC.py 中的一些基础依赖和配置。

主代码:【Interactive_Multimodal_RAG.py】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
"""
交互式多模态RAG系统
支持PDF上传、多种检索模式和网页爬取功能
"""

import os
import sys
import json
import requests
import io
import numpy as np
from typing import List, Dict, Any, Optional
from dotenv import load_dotenv
from sklearn.metrics.pairwise import cosine_similarity

# 在文件顶部添加CAMEL相关导入
from camel.models import ModelFactory
from camel.types import ModelPlatformType

# PDF处理
try:
from pypdf import PdfReader
except ImportError:
print("缺少pypdf库,请运行: pip install pypdf")
sys.exit(1)

try:
from unstructured.partition.auto import partition
from unstructured.documents.elements import Text, Image, Table
except ImportError:
print("缺少unstructured库,请运行: pip install unstructured")
sys.exit(1)

# 嵌入模型
try:
from sentence_transformers import SentenceTransformer
EMBEDDING_AVAILABLE = True
except ImportError:
print("缺少sentence-transformers库")
EMBEDDING_AVAILABLE = False

# 导入网页研究系统
try:
from RAG_WEB_TOPIC_Enhanced import EnhancedInteractiveResearchSystem
WEB_RESEARCH_AVAILABLE = True
print("Web research system available")
except ImportError:
print("Web research system not available")
WEB_RESEARCH_AVAILABLE = False

class SimpleLLMInterface:
"""LLM接口 - 使用CAMEL ModelFactory"""

def __init__(self, api_key: str, model_name: str = "Qwen/Qwen2.5-72B-Instruct", use_camel: bool = True):
if not api_key:
raise ValueError("API key is required")

self.api_key = api_key
self.model_name = model_name
self.use_camel = use_camel
self.model = None

if use_camel:
try:
# 使用CAMEL ModelFactory初始化模型
self.model = ModelFactory.create(
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
model_type=model_name,
url='https://api-inference.modelscope.cn/v1/',
api_key=api_key
)
print(f"CAMEL LLM initialized: {model_name}")
print(f"API key: {api_key[:10]}...{api_key[-4:]}")
except Exception as e:
print(f"CAMEL initialization failed, using fallback: {e}")
self.model = None
else:
print(f"Direct API LLM initialized: {model_name}")
print(f"API key: {api_key[:10]}...{api_key[-4:]}")

def generate(self, prompt: str, max_tokens: int = 500) -> str:
"""生成文本回答 - 使用CAMEL模型或直接API调用"""
# 如果CAMEL模型可用,尝试使用
if self.model is not None:
try:
print(f"Generating response with CAMEL model...")
# 使用CAMEL模型生成回答
from camel.messages import BaseMessage

# 创建用户消息
user_message = BaseMessage.make_user_message(
role_name="user",
content=prompt
)

# 调用模型生成回答
response = self.model.run([user_message])

# 修复:正确处理CAMEL模型的响应
if response:
# 如果响应是BaseMessage对象
if hasattr(response, 'content'):
return response.content
# 如果响应是列表,取第一个元素
elif isinstance(response, list) and len(response) > 0:
first_response = response[0]
if hasattr(first_response, 'content'):
return first_response.content
else:
return str(first_response)
# 如果响应是字符串
elif isinstance(response, str):
return response
# 其他情况转换为字符串
else:
return str(response)
else:
raise Exception("No response generated from CAMEL model")

except Exception as e:
print(f"CAMEL generation failed, using fallback: {str(e)[:100]}...")
# 降级到直接API调用
return self._fallback_generate(prompt, max_tokens)
else:
# 直接使用API调用
print(f"Generating response with direct API call...")
return self._fallback_generate(prompt, max_tokens)

def _fallback_generate(self, prompt: str, max_tokens: int = 500) -> str:
"""降级方案:直接API调用 - 增加重试机制和超时处理"""
max_retries = 3
timeout_seconds = 60 # 增加超时时间

for attempt in range(max_retries):
try:
import requests

headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}

data = {
"model": self.model_name,
"messages": [{"role": "user", "content": prompt}],
"max_tokens": max_tokens,
"temperature": 0.7
}

print(f"API调用 {attempt + 1}/{max_retries}...")

response = requests.post(
"https://api-inference.modelscope.cn/v1/chat/completions",
headers=headers,
json=data,
timeout=timeout_seconds
)

if response.status_code == 200:
result = response.json()
if 'choices' in result and len(result['choices']) > 0:
content = result['choices'][0]['message']['content']
print(f"√ API调用成功")
return content
else:
raise Exception(f"API响应格式错误: {result}")
else:
raise Exception(f"API调用失败 (状态码: {response.status_code}): {response.text}")

except requests.exceptions.Timeout:
print(f"API调用超时 (尝试 {attempt + 1}/{max_retries})")
if attempt == max_retries - 1:
return f"抱歉,由于网络超时,无法生成回答。请稍后重试。"
continue

except requests.exceptions.ConnectionError:
print(f"网络连接错误 (尝试 {attempt + 1}/{max_retries})")
if attempt == max_retries - 1:
return f"抱歉,网络连接失败,无法生成回答。请检查网络连接。"
continue

except Exception as e:
print(f"API调用失败 (尝试 {attempt + 1}/{max_retries}): {str(e)[:100]}...")
if attempt == max_retries - 1:
return f"生成答案时出现错误: {str(e)}"
continue

return "抱歉,多次尝试后仍无法生成回答,请稍后重试。"

class SimpleEmbeddingModel:
"""简化的嵌入模型"""

def __init__(self, model_name: str = 'intfloat/e5-large-v2'):
if not EMBEDDING_AVAILABLE:
raise ImportError("sentence-transformers not available")

try:
self.model = SentenceTransformer(model_name)
print(f"√ Embedding model loaded: {model_name}")
except Exception as e:
print(f"Failed to load embedding model: {e}")
raise

def encode(self, texts: List[str]) -> np.ndarray:
"""文本编码"""
try:
return self.model.encode(texts, convert_to_numpy=True)
except Exception as e:
print(f"Encoding failed: {e}")
return np.array([])

class SimpleVectorRetriever:
"""简化的向量检索器"""

def __init__(self, embedding_model: SimpleEmbeddingModel):
self.embedding_model = embedding_model
self.documents = []
self.doc_metadata = []
self.document_ids = []
self.doc_embeddings = None
print("√ Simple vector retriever initialized")

def add_documents(self, texts: List[str], metadata: List[Dict[str, Any]]):
"""添加文档"""
if not texts:
return

try:
# 生成文档ID
new_ids = [f"doc_{len(self.documents) + i}" for i in range(len(texts))]

# 存储文档
self.documents.extend(texts)
self.doc_metadata.extend(metadata)
self.document_ids.extend(new_ids)

# 计算嵌入
print(f"Computing embeddings for {len(texts)} documents...")
new_embeddings = self.embedding_model.encode(texts)

if self.doc_embeddings is None:
self.doc_embeddings = new_embeddings
else:
self.doc_embeddings = np.vstack([self.doc_embeddings, new_embeddings])

print(f"Added {len(texts)} documents to retriever")

except Exception as e:
print(f"Error adding documents: {e}")
raise

def query(self, query_text: str, top_k: int = 5, filter_type: Optional[str] = None) -> List[Dict[str, Any]]:
"""检索相关文档"""
if not self.documents or self.doc_embeddings is None:
print("No documents in retriever")
return []

try:
# 计算查询嵌入
query_embedding = self.embedding_model.encode([query_text])

# 计算相似度
similarities = cosine_similarity(query_embedding, self.doc_embeddings)[0]

# 获取top_k结果
top_indices = np.argsort(similarities)[::-1][:top_k * 2]

results = []
for idx in top_indices:
if idx >= len(self.documents):
continue

doc_type = self.doc_metadata[idx].get('type', 'unknown')
if filter_type and doc_type != filter_type:
continue

results.append({
'text': self.documents[idx],
'similarity': float(similarities[idx]),
'metadata': self.doc_metadata[idx],
'id': self.document_ids[idx]
})

if len(results) >= top_k:
break

print(f"Retrieved {len(results)} documents")
return results

except Exception as e:
print(f"Query failed: {e}")
return []

class SimpleRAGSystem:
"""简化的RAG系统 - 集成CAMEL ModelFactory"""

def __init__(self, api_key: str, model_name: str = "Qwen/Qwen2.5-72B-Instruct", use_camel: bool = True):
if not api_key:
raise ValueError("错误:API key required")

try:
if use_camel:
print("Initializing Simple RAG System with CAMEL...")
else:
print("Initializing Simple RAG System with direct API...")

# 使用LLM接口(CAMEL或直接API)
self.llm = SimpleLLMInterface(api_key=api_key, model_name=model_name, use_camel=use_camel)
# 保持原有的嵌入模型和检索器
self.embedding_model = SimpleEmbeddingModel()
self.vector_retriever = SimpleVectorRetriever(self.embedding_model)

self.knowledge_base_initialized = False
self.multimodal_content_store = {}

print("√ Simple RAG System initialized successfully!")

except Exception as e:
print(f"错误:Initialization failed: {e}")
raise

def setup_knowledge_base(self, pdf_url: Optional[str] = None, pdf_path: Optional[str] = None):
"""设置知识库"""
try:
if pdf_url:
print(f"↓ Loading PDF from URL: {pdf_url}")
response = requests.get(pdf_url, timeout=30)
response.raise_for_status()
pdf_bytes = response.content
print(f"√ PDF downloaded ({len(pdf_bytes)} bytes)")
pdf_file = io.BytesIO(pdf_bytes)
elements = partition(file=pdf_file)
elif pdf_path:
print(f"Loading PDF from: {pdf_path}")
if not os.path.exists(pdf_path):
raise FileNotFoundError(f"错误:PDF not found: {pdf_path}")
elements = partition(filename=pdf_path)
print(f"√ PDF loaded successfully")
else:
raise ValueError("错误:Either pdf_url or pdf_path required")

except Exception as e:
print(f"错误:PDF loading error: {e}")
raise

# 处理文档元素
texts_to_embed = []
metadata_to_embed = []
multimodal_id_counter = 0

for element in elements:
element_text = str(element).strip()
if not element_text or len(element_text) < 10:
continue

multimodal_id = f"multimodal_{multimodal_id_counter}"
multimodal_id_counter += 1

if isinstance(element, Text):
texts_to_embed.append(element_text)
metadata_to_embed.append({
'type': 'text',
'source': 'pdf',
'multimodal_id': multimodal_id
})
elif isinstance(element, Image):
# 图像处理
image_description = f"图像内容: {element_text}"
texts_to_embed.append(image_description)
metadata_to_embed.append({
'type': 'image',
'source': 'pdf',
'multimodal_id': multimodal_id
})
self.multimodal_content_store[multimodal_id] = {
'type': 'image',
'data': element_text
}
elif isinstance(element, Table):
# 表格处理
table_description = f"表格内容: {element_text}"
texts_to_embed.append(table_description)
metadata_to_embed.append({
'type': 'table',
'source': 'pdf',
'multimodal_id': multimodal_id
})
self.multimodal_content_store[multimodal_id] = {
'type': 'table',
'data': element_text
}
else:
# 其他类型作为文本处理
texts_to_embed.append(element_text)
metadata_to_embed.append({
'type': 'text',
'source': 'pdf',
'multimodal_id': multimodal_id
})

if texts_to_embed:
self.vector_retriever.add_documents(texts_to_embed, metadata_to_embed)
self.knowledge_base_initialized = True

text_count = sum(1 for meta in metadata_to_embed if meta.get('type') == 'text')
image_count = sum(1 for meta in metadata_to_embed if meta.get('type') == 'image')
table_count = sum(1 for meta in metadata_to_embed if meta.get('type') == 'table')

print(f"√ Knowledge base setup complete: {len(texts_to_embed)} elements")
print(f" Content: {text_count} text, {image_count} images, {table_count} tables")
else:
raise ValueError("No content extracted from PDF")

def get_available_retrieval_methods(self) -> List[str]:
"""获取可用的检索方法"""
return ["Vector", "Enhanced"]

def _query_rewriting(self, original_query: str) -> str:
"""查询重写 - 使用CAMEL模型"""
try:
prompt = f"""请重写以下查询,使其更适合文档检索和信息提取:

原始查询:{original_query}

重写要求:
1. 保持查询的核心意图
2. 使用更具体和明确的词汇
3. 适合向量检索和语义匹配
4. 只返回重写后的查询,不要其他解释

重写后的查询:"""

rewritten_query = self.llm.generate(prompt, max_tokens=100)

# 清理返回结果,只保留重写的查询
if rewritten_query and not rewritten_query.startswith("抱歉") and not rewritten_query.startswith("生成答案时出现错误"):
# 提取实际的重写查询
lines = rewritten_query.strip().split('\n')
for line in lines:
line = line.strip()
if line and not line.startswith('重写后的查询') and not line.startswith('原始查询'):
rewritten_query = line
break

print(f"Query rewritten: {original_query} -> {rewritten_query[:50]}...")
return rewritten_query.strip()
else:
print(f"警告:Query rewriting failed, using original query")
return original_query

except Exception as e:
print(f"警告:Query rewriting failed: {e}")
return original_query

def _hyde_generation(self, query: str) -> str:
"""HyDE假设文档生成 - 使用CAMEL模型"""
try:
prompt = f"""基于以下查询,生成一个假设性的文档片段,该片段可能包含查询的答案:

查询:{query}

要求:
1. 生成一个200-300字的文档片段
2. 内容应该直接回答查询问题
3. 使用专业和准确的语言
4. 包含相关的技术细节和概念

假设文档:"""

hyde_doc = self.llm.generate(prompt, max_tokens=300)

if hyde_doc and not hyde_doc.startswith("抱歉") and not hyde_doc.startswith("生成答案时出现错误"):
print(f"📝 HyDE document generated: {len(hyde_doc)} characters")
return hyde_doc.strip()
else:
print(f"警告:HyDE generation failed, using original query")
return query

except Exception as e:
print(f"警告:HyDE generation failed: {e}")
return query

def _rrf_fusion(self, all_results: List[List[Dict]], k: int = 60) -> List[Dict[str, Any]]:
"""RRF融合多个检索结果"""
try:
doc_scores = {}

for results in all_results:
for rank, doc in enumerate(results):
doc_id = doc.get('id', '')
if doc_id:
rrf_score = 1.0 / (k + rank + 1)
if doc_id in doc_scores:
doc_scores[doc_id]['score'] += rrf_score
else:
doc_scores[doc_id] = {
'doc': doc,
'score': rrf_score
}

# 按分数排序
sorted_docs = sorted(doc_scores.values(), key=lambda x: x['score'], reverse=True)

# 为文档添加RRF分数
final_docs = []
for item in sorted_docs:
doc = item['doc'].copy()
doc['rrf_score'] = item['score']
final_docs.append(doc)

return final_docs

except Exception as e:
print(f"警告:RRF fusion failed: {e}")
return all_results[0] if all_results else []

def enhanced_query(self, original_query: str, use_rewriting: bool = True, use_hyde: bool = True,
use_rrf: bool = True, top_k: int = 5, rrf_k: int = 60,
multimodal_preference: Optional[List[str]] = None) -> Dict[str, Any]:
"""执行增强型RAG查询"""
if not self.knowledge_base_initialized:
raise RuntimeError("Knowledge base not initialized")

# 根据参数确定检索类型
if use_rewriting and use_hyde and use_rrf:
print("\n执行深度检索...")
print("="*60)
print("开始执行深度RAG查询")
print("="*60)
else:
print("\n执行检索...")
print("="*40)

query_for_retrieval = original_query
rewritten_query = None
hyde_doc = None
retrieval_method = "Vector"
all_retrieved_results = []

# 步骤1: 查询重写
if use_rewriting:
print("\n步骤1: 查询重写")
print("-" * 30)
print(f"原始查询: {original_query}")
rewritten_query = self._query_rewriting(original_query)
query_for_retrieval = rewritten_query
print(f"重写查询: {rewritten_query}")
retrieval_method += "+Rewriting"

# 步骤2: 文档检索
print("\n步骤2: 文档检索")
print("-" * 30)
if use_hyde and use_rrf:
print("使用HyDE+RRF组合方法进行检索...")
print("使用RRF算法进行混合检索(HyDE增强向量检索)...")
else:
print("使用基础向量检索...")

# HyDE生成
if use_hyde:
print("执行HyDE增强向量检索...")
hyde_doc = self._hyde_generation(query_for_retrieval)
print("生成的假设文档:")
print(hyde_doc)
retrieval_method += "+HyDE"

# 多模态检索
text_results = self.vector_retriever.query(query_for_retrieval, top_k=top_k, filter_type='text')
all_retrieved_results.append(text_results)
print(f"✓ HyDE向量检索完成,获得 {len(text_results)} 个结果")

if multimodal_preference:
if 'image' in multimodal_preference:
image_results = self.vector_retriever.query(query_for_retrieval, top_k=top_k, filter_type='image')
all_retrieved_results.append(image_results)
print(f"✓ 图像检索完成,获得 {len(image_results)} 个结果")
retrieval_method += "+Image"
if 'table' in multimodal_preference:
table_results = self.vector_retriever.query(query_for_retrieval, top_k=top_k, filter_type='table')
all_retrieved_results.append(table_results)
print(f"✓ 表格检索完成,获得 {len(table_results)} 个结果")
retrieval_method += "+Table"

if hyde_doc:
print("执行BM25检索(使用原始查询)...")
hyde_results = self.vector_retriever.query(hyde_doc, top_k=top_k)
all_retrieved_results.append(hyde_results)
print(f"✓ BM25检索成功,获得 {len(hyde_results)} 个结果")

# RRF融合
if use_rrf and len(all_retrieved_results) > 1:
print("使用RRF算法融合检索结果...")
final_retrieved_docs = self._rrf_fusion(all_retrieved_results, k=rrf_k)
retrieval_method += "+RRF"

# 统计唯一文档数量
unique_doc_ids = set()
for res_list in all_retrieved_results:
for doc in res_list:
unique_doc_ids.add(doc.get('id', ''))
print(f"RRF融合完成,共处理 {len(unique_doc_ids)} 个唯一文档,返回前 {top_k} 个结果")
print(f"HyDE+RRF检索完成,返回 {len(final_retrieved_docs)} 个文档")
else:
unique_docs = {}
for res_list in all_retrieved_results:
for doc in res_list:
if doc.get('id') not in unique_docs:
unique_docs[doc.get('id')] = doc
final_retrieved_docs = list(unique_docs.values())
print(f"文档合并完成,返回 {len(final_retrieved_docs)} 个文档")

# 限制最终文档数量
final_retrieved_docs = final_retrieved_docs[:top_k]

# 显示检索到的文档预览
for i, doc in enumerate(final_retrieved_docs, 1):
similarity = doc.get('similarity', 0)
rrf_score = getattr(doc, 'rrf_score', similarity) # 如果有RRF分数则使用,否则使用相似度
text_preview = doc.get('text', '')[:200] + "..." if len(doc.get('text', '')) > 200 else doc.get('text', '')
print(f"文档 {i} (RRF分数: {rrf_score:.4f}):")
print(f"{text_preview}")
print()

# 步骤3: 答案生成
print("步骤3: 答案生成")
print("-" * 30)
print()

# 构建上下文
context_texts = []
for doc in final_retrieved_docs:
context_texts.append(doc['text'])

# 生成最终答案
separator = '\n---\n'
context_str = separator.join(context_texts)

prompt_for_llm = f"""你是一个专业的文档分析助手。请基于以下PDF文档内容回答用户问题。

文档内容:
{context_str}

用户问题:{original_query}

回答要求:
1. 仔细阅读并理解文档内容
2. 基于文档内容提供准确、详细的答案
3. 如果文档中没有相关信息,请明确说明
4. 使用清晰的结构组织答案
5. 引用具体的文档内容支持你的回答

请提供详细的答案:"""

print("正在生成最终答案...")
final_answer = self.llm.generate(prompt_for_llm, max_tokens=800)

if final_answer and not final_answer.startswith("抱歉") and not final_answer.startswith("生成答案时出现错误"):
print("√ 答案生成成功")
print("最终答案:")
print(final_answer)
else:
print("警告:答案生成失败,提供基于检索文档的简化回答")
# 提供基于检索文档的简化回答
simple_answer = f"基于检索到的文档内容,关于'{original_query}'的相关信息如下:\n\n"
for i, doc in enumerate(final_retrieved_docs[:3], 1):
simple_answer += f"{i}. {doc['text'][:200]}...\n\n"
final_answer = simple_answer
print("最终答案:")
print(final_answer)

return {
'original_query': original_query,
'rewritten_query': rewritten_query,
'hyde_doc': hyde_doc,
'retrieved_docs': final_retrieved_docs,
'final_answer': final_answer,
'retrieval_method': retrieval_method
}

class InteractiveMultimodalRAG:
"""交互式多模态RAG系统 - 集成CAMEL ModelFactory"""

def __init__(self):
self.api_key = None
self.rag_system = None
self.web_research_system = None
self.knowledge_base_loaded = False
self.current_pdf_source = None

def initialize_system(self):
"""初始化系统 - 使用CAMEL ModelFactory"""
print("初始化交互式多模态RAG系统...")

# 加载环境变量
load_dotenv()

# 获取API密钥
self.api_key = os.getenv('MODELSCOPE_SDK_TOKEN')
if not self.api_key:
print("错误:错误:请设置MODELSCOPE_SDK_TOKEN环境变量")
print("提示:在.env文件中添加 MODELSCOPE_SDK_TOKEN=your_api_key")
return False

try:
# 使用集成CAMEL的简化RAG系统
self.rag_system = SimpleRAGSystem(api_key=self.api_key, model_name="Qwen/Qwen2.5-72B-Instruct")
print("√ 集成CAMEL的RAG系统初始化成功")

# 初始化网页研究系统
if WEB_RESEARCH_AVAILABLE:
try:
self.web_research_system = EnhancedInteractiveResearchSystem()
print("√ 网页研究系统初始化成功")
except Exception as e:
print(f"!警告: 网页研究系统初始化失败: {e}")
self.web_research_system = None

return True

except Exception as e:
print(f"!错误:系统初始化失败: {e}")
return False

def load_pdf_knowledge_base(self):
"""加载PDF知识库"""
print("\nPDF知识库设置")
print("="*50)
print("1. 在线PDF (输入URL)")
print("2. 本地PDF (输入文件路径)")
print("3. 使用默认示例PDF")

choice = input("\n请选择PDF来源 (1-3): ").strip()

try:
if choice == "1":
pdf_url = input("请输入PDF的URL: ").strip()
if not pdf_url:
print("错误:URL不能为空")
return False

print(f"↓ 正在加载在线PDF: {pdf_url}")
self.rag_system.setup_knowledge_base(pdf_url=pdf_url)
self.current_pdf_source = f"在线PDF: {pdf_url}"

elif choice == "2":
pdf_path = input("请输入PDF文件路径: ").strip()
if not pdf_path:
print("错误:文件路径不能为空")
return False

if not os.path.exists(pdf_path):
print(f"错误:文件不存在: {pdf_path}")
return False

print(f"状态查询: 正在加载本地PDF: {pdf_path}")
self.rag_system.setup_knowledge_base(pdf_path=pdf_path)
self.current_pdf_source = f"本地PDF: {pdf_path}"

elif choice == "3":
pdf_url = "https://arxiv.org/pdf/2303.17760.pdf"
print(f"↓ 正在加载默认示例PDF: {pdf_url}")
self.rag_system.setup_knowledge_base(pdf_url=pdf_url)
self.current_pdf_source = f"示例PDF: CAMEL论文"

else:
print("错误:无效选择")
return False

self.knowledge_base_loaded = True
print("√ PDF知识库加载成功!")
return True

except Exception as e:
print(f"错误:PDF加载失败: {e}")
return False

def execute_query(self, query: str, retrieval_mode: str) -> Dict[str, Any]:
"""执行查询"""
if not self.knowledge_base_loaded:
return {"error": "知识库未加载,请先加载PDF"}

print(f"\n执行查询: {query}")
print(f"检索模式: {retrieval_mode}")

try:
if retrieval_mode == "快速检索":
# 基础向量检索 - 直接检索生成答案
return self.quick_retrieval(query)

elif retrieval_mode == "深度检索":
# 完整增强检索
results = self.rag_system.enhanced_query(
original_query=query,
use_rewriting=True,
use_hyde=True,
use_rrf=True,
top_k=5,
multimodal_preference=['text', 'image', 'table']
)

elif retrieval_mode == "主题检索":
# 网页爬取检索 - 使用真实的网页研究系统
return self.topic_retrieval(query)

else:
return {"error": f"未知检索模式: {retrieval_mode}"}

return results

except Exception as e:
return {"error": f"查询执行失败: {e}"}

def quick_retrieval(self, query: str) -> Dict[str, Any]:
"""快速检索 - 基础向量检索直接生成答案"""
print("\n执行快速检索...")
print("="*40)

try:
# 直接进行向量检索
print("正在进行向量检索...")
retrieved_docs = self.rag_system.vector_retriever.query(query, top_k=3, filter_type='text')

if not retrieved_docs:
return {"error": "未找到相关文档"}

print(f"√ 检索到 {len(retrieved_docs)} 个相关文档")

# 显示检索到的文档
for i, doc in enumerate(retrieved_docs, 1):
similarity = doc.get('similarity', 0)
text_preview = doc.get('text', '')[:150] + "..." if len(doc.get('text', '')) > 150 else doc.get('text', '')
print(f"文档 {i} (相似度: {similarity:.3f}):")
print(f" {text_preview}")
print()

# 构建简单的上下文
context_texts = [doc['text'] for doc in retrieved_docs]
context_str = '\n---\n'.join(context_texts)

# 生成答案
print("正在生成答案...")
prompt = f"""基于以下文档内容回答问题:

文档内容:
{context_str}

问题:{query}

请提供简洁明确的答案:"""

final_answer = self.rag_system.llm.generate(prompt, max_tokens=400)

print("√ 快速检索完成")

return {
'original_query': query,
'retrieved_docs': retrieved_docs,
'final_answer': final_answer,
'retrieval_method': 'Quick Vector Retrieval'
}

except Exception as e:
return {"error": f"快速检索失败: {e}"}

def topic_retrieval(self, query: str) -> Dict[str, Any]:
"""主题检索 - 集成网页研究系统"""
print("\n执行网页检索...")
print("="*40)

try:
if not self.web_research_system:
print("警告:网页研究系统不可用,使用备用方案")
return self.perform_fallback_topic_search(query)

# 使用网页研究系统进行搜索
print("正在进行网页研究...")
web_content = ""
web_sources = []

try:
# 检查可用的方法并调用正确的方法
if hasattr(self.web_research_system, 'research_and_analyze'):
# 使用正确的方法名
research_result = self.web_research_system.research_and_analyze(query)
if isinstance(research_result, dict):
web_content = research_result.get('content', '')
web_sources = research_result.get('sources', [])
else:
web_content = str(research_result)
web_sources = ["网页研究结果"]
print("√ 网页研究完成")

elif hasattr(self.web_research_system, 'toolkit') and hasattr(self.web_research_system.toolkit, 'search_web_for_topic'):
# 使用工具包搜索
search_result = self.web_research_system.toolkit.search_web_for_topic(query, "")
web_content = search_result
web_sources = ["网页搜索结果"]
print("√ 网页搜索完成")

elif hasattr(self.web_research_system, 'run_interactive_session'):
# 尝试使用交互式会话方法
print("警告:使用交互式研究系统,但无法直接调用")
web_content = f"关于'{query}'的网页研究信息需要交互式操作"
web_sources = ["交互式研究系统"]

else:
print("警告:网页研究系统方法不可用")
web_content = f"关于'{query}'的网页搜索信息暂时不可用"
web_sources = []

except Exception as e:
print(f"警告:网页搜索失败: {e}")
web_content = f"网页搜索遇到错误: {str(e)}"
web_sources = []

# 同时进行PDF检索
print("正在检索PDF文档...")
pdf_docs = self.rag_system.vector_retriever.query(query, top_k=3, filter_type='text')

# 合并结果
combined_context = ""

# 添加PDF内容
if pdf_docs:
pdf_context = "\n".join([doc['text'] for doc in pdf_docs])
combined_context += f"PDF文档内容:\n{pdf_context}\n\n"
print(f"√ 检索到 {len(pdf_docs)} 个PDF文档")

# 添加网页内容
if web_content and web_content.strip() and not web_content.startswith("关于") and not web_content.startswith("网页搜索遇到错误"):
combined_context += f"网页搜索内容:\n{web_content}\n\n"

if not combined_context.strip():
print("警告:未找到相关信息,使用备用方案")
return self.perform_fallback_topic_search(query)

# 生成综合答案
print("正在生成综合答案...")
prompt = f"""基于以下PDF文档和网页搜索的信息,回答问题:

{combined_context}

问题:{query}

请提供综合性的详细答案:"""

final_answer = self.rag_system.llm.generate(prompt, max_tokens=800)

print("主题检索完成")

return {
'original_query': query,
'pdf_docs': pdf_docs,
'web_sources': web_sources,
'final_answer': final_answer,
'retrieval_method': 'PDF+Web Topic Retrieval'
}

except Exception as e:
print(f"警告:主题检索失败,使用备用方案: {e}")
return self.perform_fallback_topic_search(query)

def perform_web_research(self, query: str) -> Dict[str, Any]:
"""执行网页研究"""
print("正在进行网页研究...")

try:
# 模拟网页研究结果
web_content = f"基于网页搜索的{query}相关信息:\n"
web_content += "- 网页来源1的相关内容\n"
web_content += "- 网页来源2的相关内容\n"
web_content += "- 网页来源3的相关内容"

return {
"web_content": web_content,
"sources": ["网页来源1", "网页来源2", "网页来源3"],
"method": "web_research"
}

except Exception as e:
print(f"网页研究失败: {e}")
return {"error": f"网页研究失败: {e}"}

def perform_fallback_topic_search(self, query: str) -> Dict[str, Any]:
"""备用主题搜索 - 仅使用PDF检索"""
print("执行备用主题搜索(仅PDF检索)...")

try:
# 进行PDF检索
print("正在检索PDF文档...")
pdf_docs = self.rag_system.vector_retriever.query(query, top_k=5, filter_type='text')

if not pdf_docs:
return {"error": "未找到相关PDF文档"}

print(f"检索到 {len(pdf_docs)} 个PDF文档")

# 显示检索到的文档
for i, doc in enumerate(pdf_docs, 1):
similarity = doc.get('similarity', 0)
text_preview = doc.get('text', '')[:150] + "..." if len(doc.get('text', '')) > 150 else doc.get('text', '')
print(f"文档 {i} (相似度: {similarity:.3f}):")
print(f" {text_preview}")
print()

# 构建上下文
pdf_context = "\n".join([doc['text'] for doc in pdf_docs])

# 生成答案
print("正在生成答案...")
prompt = f"""基于以下PDF文档内容回答问题:

PDF文档内容:
{pdf_context}

问题:{query}

请提供详细的答案,特别关注CAMEL框架的特性和工具:"""

final_answer = self.rag_system.llm.generate(prompt, max_tokens=800)

print("√ 备用主题搜索完成")

return {
'original_query': query,
'retrieved_docs': pdf_docs,
'final_answer': final_answer,
'retrieval_method': 'Fallback PDF Topic Retrieval'
}

except Exception as e:
print(f"备用主题搜索失败: {e}")
return {"error": f"备用主题搜索失败: {e}"}

def merge_web_and_pdf_results(self, web_results: Dict, pdf_results: Dict, query: str) -> Dict[str, Any]:
"""合并网页和PDF检索结果"""
try:
# 合并上下文
combined_context = ""

# 添加PDF内容
if 'retrieved_docs' in pdf_results:
pdf_context = "\n".join([doc['text'] for doc in pdf_results['retrieved_docs']])
combined_context += f"PDF文档内容:\n{pdf_context}\n\n"

# 添加网页内容
if 'web_content' in web_results:
combined_context += f"网页搜索内容:\n{web_results['web_content']}\n\n"

# 生成综合答案
prompt = f"基于以下PDF文档和网页搜索的信息,回答问题:\n\n{combined_context}\n\n问题:{query}\n\n请提供综合性的详细答案。"

final_answer = self.rag_system.llm.generate(prompt, max_tokens=800)

return {
'original_query': query,
'pdf_docs': pdf_results.get('retrieved_docs', []),
'web_sources': web_results.get('sources', []),
'final_answer': final_answer,
'retrieval_method': 'PDF+Web主题检索'
}

except Exception as e:
return {"error": f"结果合并失败: {e}"}

def display_results(self, results: Dict[str, Any]):
"""显示查询结果"""
if 'error' in results:
print(f"错误: {results['error']}")
return

print("\n" + "="*20 + " 深度检索结果 " + "="*20)
print(f"原结始查询: {results.get('original_query', 'N/A')}")

if results.get('rewritten_query'):
print(f"重写查询: {results['rewritten_query']}")

print(f"检索方法: {results.get('retrieval_method', 'N/A')}")

# 显示检索到的文档
retrieved_docs = results.get('retrieved_docs', [])
if retrieved_docs:
print(f"\n检索到的文档 (共{len(retrieved_docs)}个):")
print()
for i, doc in enumerate(retrieved_docs, 1):
rrf_score = doc.get('rrf_score', doc.get('similarity', 0))
text_preview = doc.get('text', '')[:200] + "..." if len(doc.get('text', '')) > 200 else doc.get('text', '')
print(f"文档 {i}:")
print(f"相关度分数: {rrf_score}")
print(f"内容预览: {text_preview}")
print()

# 显示最终答案
final_answer = results.get('final_answer', 'N/A')
print("💡 生成答案:")
print(final_answer)
print("="*60)

# 询问是否保存结果
save_choice = input("\n询问:是否保存结果到文件?(y/n): ").strip().lower()
if save_choice == 'y':
self._save_results_to_file(results)

def _save_results_to_file(self, results: Dict[str, Any]):
"""保存结果到文件"""
try:
from datetime import datetime
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f"rag_query_result_{timestamp}.txt"

with open(filename, 'w', encoding='utf-8') as f:
f.write("="*60 + "\n")
f.write("RAG查询结果报告\n")
f.write("="*60 + "\n\n")
f.write(f"查询时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"原始查询: {results.get('original_query', 'N/A')}\n")
if results.get('rewritten_query'):
f.write(f"重写查询: {results['rewritten_query']}\n")
f.write(f"检索方法: {results.get('retrieval_method', 'N/A')}\n\n")

# 保存检索文档
retrieved_docs = results.get('retrieved_docs', [])
if retrieved_docs:
f.write(f"检索到的文档 (共{len(retrieved_docs)}个):\n")
f.write("-" * 40 + "\n")
for i, doc in enumerate(retrieved_docs, 1):
rrf_score = doc.get('rrf_score', doc.get('similarity', 0))
f.write(f"\n文档 {i}:\n")
f.write(f"相关度分数: {rrf_score}\n")
f.write(f"内容: {doc.get('text', '')}\n")
f.write("-" * 40 + "\n")

# 保存最终答案
f.write(f"\n生成答案:\n")
f.write(results.get('final_answer', 'N/A'))
f.write("\n\n" + "="*60)

print(f"√ 结果已保存到: {filename}")
except Exception as e:
print(f"错误:保存失败: {e}")

def run_interactive_session(self):
"""运行交互式会话"""
if not self.initialize_system():
return

print("\n交互式多模态RAG系统")
print("="*60)
print("功能特性:")
print("- 支持在线/本地PDF加载")
print("- 三种检索模式")
print("- 网页爬取集成")
print("- 多模态内容处理")
print("="*60)

# 加载知识库
if not self.load_pdf_knowledge_base():
print("知识库加载失败,退出系统")
return

print(f"\n当前知识库: {self.current_pdf_source}")
print(f"🔧 可用检索方法: {', '.join(self.rag_system.get_available_retrieval_methods())}")

while True:
try:
print("\n" + "="*60)
print("查询选项")
print("="*60)

# 获取用户查询
query = input("请输入您的问题 (输入 'quit' 退出, 'reload' 重新加载PDF): ").strip()

if query.lower() == 'quit':
break
elif query.lower() == 'reload':
if self.load_pdf_knowledge_base():
print(f"√ 知识库已重新加载: {self.current_pdf_source}")
continue
elif not query:
print("问题不能为空")
continue

# 选择检索模式
print("\n选择检索模式:")
print("1. 快速检索 (基础向量检索)")
print("2. 深度检索 (重写+HyDE+RRF)")
print("3. 主题检索 (PDF+网页爬取)")

mode_choice = input("请选择模式 (1-3): ").strip()

mode_map = {
"1": "快速检索",
"2": "深度检索",
"3": "主题检索"
}

retrieval_mode = mode_map.get(mode_choice)
if not retrieval_mode:
print("无效选择,使用默认快速检索")
retrieval_mode = "快速检索"

# 执行查询
results = self.execute_query(query, retrieval_mode)

# 显示结果
self.display_results(results)

# 询问是否继续
continue_choice = input("\n是否继续查询?(y/n): ").strip().lower()
if continue_choice != 'y':
break

except KeyboardInterrupt:
print("\n\n用户中断,退出系统")
break
except Exception as e:
print(f"系统错误: {e}")
continue

print("\n感谢使用交互式多模态RAG系统!")

def main():
"""主函数"""
try:
interactive_rag = InteractiveMultimodalRAG()
interactive_rag.run_interactive_session()
except Exception as e:
print(f"系统启动失败: {e}")
sys.exit(1)

if __name__ == "__main__":
main()

分支代码1:【RAG_WEB_TOPIC_Enhanced.py】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
import os
import time
import json
import logging
from typing import List, Dict, Optional, Any
from dataclasses import dataclass
from pathlib import Path
from datetime import datetime
import agentops
import requests
from colorama import Fore, init
from bs4 import BeautifulSoup
from camel.loaders import Firecrawl, UnstructuredIO
from camel.retrievers import AutoRetriever
from camel.toolkits import FunctionTool, SearchToolkit
from camel.types import ModelPlatformType, StorageType
from camel.embeddings import SentenceTransformerEncoder
from camel.models import ModelFactory
from camel.societies import RolePlaying
from camel.utils import print_text_animated
from camel.storages import Neo4jGraph
from camel.agents import KnowledgeGraphAgent, ChatAgent
from camel.messages import BaseMessage
from dotenv import load_dotenv

# 导入原始系统的所有类和配置
from RAG_WEB_TOPIC import (
ResearchConfig, ConfigManager, UniversalResearchSystem,
InteractiveResearchSystem
)

# 初始化 colorama
init(autoreset=True)

# 全局会话数据记录
research_session_data = {
'start_time': None,
'end_time': None,
'topic': '',
'research_question': '',
'search_results': [],
'retrieval_results': [],
'knowledge_graphs': [],
'conversation_history': [],
'generated_files': [],
'system_stats': {}
}

class EnhancedInteractiveResearchSystem(InteractiveResearchSystem):
"""增强版交互式研究系统 - 支持最终报告生成"""

def __init__(self):
super().__init__()
self.session_data = research_session_data

def log_search_result(self, query: str, results: Any):
"""记录搜索结果"""
self.session_data['search_results'].append({
'query': query,
'results': str(results)[:1000], # 限制长度
'timestamp': datetime.now().isoformat()
})

def log_retrieval_result(self, urls: List[str], query: str, results: Any):
"""记录检索结果"""
self.session_data['retrieval_results'].append({
'urls': urls,
'query': query,
'results': str(results)[:1000], # 限制长度
'timestamp': datetime.now().isoformat()
})

def log_knowledge_graph(self, text_input: str, topic: str, result: str):
"""记录知识图谱构建"""
self.session_data['knowledge_graphs'].append({
'input_text': text_input[:500] + "..." if len(text_input) > 500 else text_input,
'topic': topic,
'result': result[:500] + "..." if len(result) > 500 else result,
'timestamp': datetime.now().isoformat()
})

def log_conversation(self, role: str, content: str):
"""记录对话历史"""
self.session_data['conversation_history'].append({
'role': role,
'content': content[:800] + "..." if len(content) > 800 else content,
'timestamp': datetime.now().isoformat()
})

def create_enhanced_research_tools(self, topic: str) -> List[FunctionTool]:
"""创建增强版研究工具(带日志记录)"""

def enhanced_retrieve_urls(urls: List[str], query: str) -> str:
result = self.toolkit.retrieve_information_from_urls(urls, query)
self.log_retrieval_result(urls, query, result)
return result

def enhanced_search_topic(query: str) -> str:
result = self.toolkit.search_web_for_topic(query, topic)
self.log_search_result(query, result)
return result

def enhanced_build_kg(text_input: str) -> str:
result = self.toolkit.build_knowledge_graph(text_input, topic)
self.log_knowledge_graph(text_input, topic, result)
return result

return [
FunctionTool(enhanced_retrieve_urls),
FunctionTool(enhanced_search_topic),
FunctionTool(enhanced_build_kg),
]

def generate_final_research_report(self) -> str:
"""生成最终研究报告"""

if not self.model:
return "❌ AI模型未初始化,无法生成最终报告"

print(Fore.BLUE + "📊 正在生成最终研究报告...")

# 计算统计数据
duration = "未知"
if self.session_data['start_time'] and self.session_data['end_time']:
start = datetime.fromisoformat(self.session_data['start_time'])
end = datetime.fromisoformat(self.session_data['end_time'])
duration = str(end - start)

total_searches = len(self.session_data['search_results'])
total_retrievals = len(self.session_data['retrieval_results'])
total_kg = len(self.session_data['knowledge_graphs'])
total_conversations = len(self.session_data['conversation_history'])

# 收集关键信息
search_summary = "\n".join([f"- {item['query']}: {item['results'][:200]}..."
for item in self.session_data['search_results'][:5]])

retrieval_summary = "\n".join([f"- {item['query']}: {item['results'][:200]}..."
for item in self.session_data['retrieval_results'][:5]])

conversation_summary = "\n".join([f"**{item['role']}**: {item['content'][:300]}..."
for item in self.session_data['conversation_history'][:10]])

report_prompt = f"""
基于以下研究系统的完整运行数据,生成一份详细的最终研究报告:

## 研究基本信息:
- 研究主题: {self.session_data['topic']}
- 研究问题: {self.session_data['research_question']}
- 研究时长: {duration}
- 开始时间: {self.session_data['start_time']}
- 结束时间: {self.session_data['end_time']}

## 系统运行统计:
- 执行搜索次数: {total_searches}
- 执行检索次数: {total_retrievals}
- 生成知识图谱数量: {total_kg}
- 对话轮次: {total_conversations}
- 生成文件数量: {len(self.session_data['generated_files'])}

## 搜索结果摘要:
{search_summary}

## 检索结果摘要:
{retrieval_summary}

## 对话历史摘要:
{conversation_summary}

## 生成的文件:
{', '.join(self.session_data['generated_files'])}

请按以下结构生成最终研究报告:

# {self.session_data['topic']} - 研究最终报告

## 1. 执行摘要
- 研究目标和范围
- 主要发现概述
- 系统运行效果评估

## 2. 研究方法和过程
- 数据收集方法
- 检索和分析流程
- 知识图谱构建过程
- 技术工具使用情况

## 3. 详细研究结果
- 核心发现和数据
- 关键信息分析
- 重要观点整理

## 4. 系统性能分析
- RAG检索效果评估
- 知识图谱构建质量
- 对话系统表现
- 数据处理效率

## 5. 结论和建议
- 研究结论总结
- 发现的问题和局限
- 改进建议
- 后续研究方向

## 6. 技术附录
- 系统配置参数
- 生成的文件清单
- 数据来源统计
- 运行日志摘要

请确保报告内容详实、分析深入、结论客观,重点回答研究问题。
"""

try:
# 创建报告生成智能体
report_agent = ChatAgent(
system_message=BaseMessage.make_assistant_message(
role_name="研究报告专家",
content="你是一个专业的研究分析师和技术系统评估专家,擅长生成详细的研究报告和系统评估报告。"
),
model=self.model
)

user_msg = BaseMessage.make_user_message(
role_name="报告请求者",
content=report_prompt
)

response = report_agent.step(user_msg)

# 保存最终报告
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
topic_safe = "".join(c for c in self.session_data['topic'] if c.isalnum() or c in (' ', '-', '_')).rstrip()
topic_safe = topic_safe.replace(' ', '_')[:50] # 限制文件名长度

report_filename = f"final_research_report_{topic_safe}_{timestamp}.md"

with open(report_filename, 'w', encoding='utf-8') as f:
f.write(response.msg.content)

self.session_data['generated_files'].append(report_filename)

print(Fore.GREEN + f"✅ 最终报告已保存: {report_filename}")
return response.msg.content

except Exception as e:
error_msg = f"❌ 最终报告生成失败: {e}"
print(Fore.RED + error_msg)
return error_msg

def run_enhanced_interactive_research(self):
"""运行增强版交互式研究(含最终报告)"""
if not self.model or not self.research_system:
print(Fore.RED + "❌ 系统未正确初始化,无法运行")
return

print(Fore.CYAN + "🚀 增强版通用AI研究系统(含最终报告)")
print("="*70)

while True:
try:
# 重置会话数据
self.session_data.update({
'start_time': datetime.now().isoformat(),
'end_time': None,
'topic': '',
'research_question': '',
'search_results': [],
'retrieval_results': [],
'knowledge_graphs': [],
'conversation_history': [],
'generated_files': [],
'system_stats': {}
})

# 获取用户输入
print(Fore.YELLOW + "\n请输入研究信息:")
topic = input(Fore.CYAN + "研究主题: ").strip()
if not topic:
break

research_question = input(Fore.CYAN + "具体问题: ").strip()
if not research_question:
research_question = f"关于{topic}的综合信息"

# 记录研究信息
self.session_data['topic'] = topic
self.session_data['research_question'] = research_question

print(Fore.BLUE + f"\n📋 开始研究:")
print(Fore.BLUE + f" 主题: {topic}")
print(Fore.BLUE + f" 问题: {research_question}")
print("="*70)

# 创建增强版研究工具和任务
tools = self.create_enhanced_research_tools(topic)
task_prompt = self.create_research_task(topic, research_question)

# 创建角色扮演系统
role_play_session = RolePlaying(
assistant_role_name="AI研究助理",
user_role_name="研究用户",
assistant_agent_kwargs=dict(
model=self.model,
tools=tools,
),
user_agent_kwargs=dict(model=self.model),
task_prompt=task_prompt,
with_task_specify=False,
)

# 记录初始对话
self.log_conversation("系统", f"开始研究: {topic} - {research_question}")

# 执行研究
print(Fore.GREEN + f"🤖 AI助理已准备就绪")
print(Fore.BLUE + f"👤 开始研究对话...")

input_msg = role_play_session.init_chat()
chat_turn_limit = 8

for i in range(chat_turn_limit):
print(Fore.MAGENTA + f"\n--- 研究轮次 {i+1} ---")

try:
assistant_response, user_response = role_play_session.step(input_msg)

# 记录对话
self.log_conversation("助理", assistant_response.msg.content)
self.log_conversation("用户", user_response.msg.content)

if assistant_response.terminated or user_response.terminated:
print(Fore.GREEN + "✅ 研究任务完成")
break

# 显示进度
print(Fore.CYAN + f"🔄 助理: {assistant_response.msg.content[:200]}...")
print(Fore.BLUE + f"🔄 用户: {user_response.msg.content[:200]}...")

input_msg = assistant_response.msg
time.sleep(1) # 避免请求过快

except Exception as e:
print(Fore.RED + f"研究过程出错: {e}")
break

# 记录结束时间
self.session_data['end_time'] = datetime.now().isoformat()

print(Fore.GREEN + "\n" + "="*80)
print(Fore.GREEN + "✅ 角色扮演研究阶段完成")
print(Fore.GREEN + "="*80)

# 生成最终报告
print(Fore.CYAN + "\n🎯 开始生成最终研究报告...")
print("="*70)

final_report = self.generate_final_research_report()

print(Fore.MAGENTA + "\n" + "="*100)
print(Fore.MAGENTA + "📊 最终研究报告预览")
print(Fore.MAGENTA + "="*100)
print(final_report[:1000] + "..." if len(final_report) > 1000 else final_report)
print(Fore.MAGENTA + "="*100)

# 显示生成的文件统计
print(Fore.GREEN + f"\n📁 本次研究共生成 {len(self.session_data['generated_files'])} 个文件:")
for file in self.session_data['generated_files']:
print(Fore.GREEN + f" 📄 {file}")

# 询问是否继续
print(Fore.YELLOW + "\n" + "="*70)
continue_research = input(Fore.CYAN + "是否继续新的研究? (y/n): ").strip().lower()
if continue_research != 'y':
break

except KeyboardInterrupt:
print(Fore.YELLOW + "\n用户中断研究")
break
except Exception as e:
print(Fore.RED + f"系统错误: {e}")
continue

print(Fore.GREEN + "\n👋 感谢使用增强版通用AI研究系统!")

def main():
"""主函数"""
print(Fore.CYAN + "🎯 增强版通用AI研究系统启动(含最终报告)")
print("="*60)

try:
enhanced_system = EnhancedInteractiveResearchSystem()
enhanced_system.run_enhanced_interactive_research()
except Exception as e:
print(Fore.RED + f"❌ 系统启动失败: {e}")
print(Fore.YELLOW + "💡 请检查配置和依赖项")

if __name__ == "__main__":
main()

分支代码2:【RAG_WEB_TOPIC.py】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
import os
import time
import json
import logging
from typing import List, Dict, Optional
from dataclasses import dataclass
from pathlib import Path
import agentops
import requests
from colorama import Fore, init
from bs4 import BeautifulSoup
from camel.loaders import Firecrawl, UnstructuredIO
from camel.retrievers import AutoRetriever
from camel.toolkits import FunctionTool, SearchToolkit
from camel.types import ModelPlatformType, StorageType
from camel.embeddings import SentenceTransformerEncoder
from camel.models import ModelFactory
from camel.societies import RolePlaying
from camel.utils import print_text_animated
from camel.storages import Neo4jGraph
from camel.agents import KnowledgeGraphAgent
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# 初始化 colorama
init(autoreset=True)

@dataclass
class ResearchConfig:
"""研究系统配置类"""
# API配置 - 直接配置所有必要密钥
agentops_api_key: str = "3e6edf79-2c28-400f-8433-cf4fa764444d"
firecrawl_api_key: str = "fc-58764a3cc0184450b220d2dd1ca687c2"
modelscope_api_key: str = "64af0689-2660-4285-99ff-270e4c7416a3"

# Neo4j配置
neo4j_url: str = "bolt://localhost:7687"
neo4j_username: str = "neo4j"
neo4j_password: str = "tyy20060315"

# 模型配置
model_platform: str = "openai_compatible"
model_name: str = "Qwen/Qwen2.5-72B-Instruct"
model_url: str = "https://api-inference.modelscope.cn/v1/"

# 存储配置
vector_storage_path: str = "research_data"
storage_type: str = "qdrant"

# 搜索配置
max_search_results: int = 10
max_urls_to_process: int = 5
similarity_threshold: float = 0.3

class ConfigManager:
"""配置管理器 - 安全地处理敏感信息"""

def __init__(self, config_file: str = "config.json"):
self.config_file = Path(config_file)
self.config = ResearchConfig()
self._load_config()

def _load_config(self):
"""从配置文件和环境变量加载配置"""
# 直接使用配置的API密钥,如果环境变量存在则优先使用环境变量
self.config.agentops_api_key = os.getenv("AGENTOPS_API_KEY", self.config.agentops_api_key)
self.config.firecrawl_api_key = os.getenv("FIRECRAWL_API_KEY", self.config.firecrawl_api_key)
self.config.modelscope_api_key = os.getenv("MODELSCOPE_SDK_TOKEN", self.config.modelscope_api_key)
self.config.neo4j_password = os.getenv("NEO4J_PASSWORD", self.config.neo4j_password)

# 设置环境变量以供其他组件使用
os.environ["AGENTOPS_API_KEY"] = self.config.agentops_api_key
os.environ["FIRECRAWL_API_KEY"] = self.config.firecrawl_api_key
os.environ["MODELSCOPE_SDK_TOKEN"] = self.config.modelscope_api_key

# 从配置文件加载非敏感配置
if self.config_file.exists():
try:
with open(self.config_file, 'r', encoding='utf-8') as f:
file_config = json.load(f)

# 更新非敏感配置
for key, value in file_config.items():
if not key.endswith('_key') and not key.endswith('_password'):
if hasattr(self.config, key):
setattr(self.config, key, value)

except Exception as e:
logging.warning(f"配置文件加载失败: {e}")

def create_sample_config(self):
"""创建示例配置文件"""
sample_config = {
"neo4j_url": "bolt://localhost:7687",
"neo4j_username": "neo4j",
"model_name": "Qwen/Qwen2.5-72B-Instruct",
"model_url": "https://api-inference.modelscope.cn/v1/",
"vector_storage_path": "research_data",
"max_search_results": 10,
"max_urls_to_process": 5,
"similarity_threshold": 0.3
}

with open(self.config_file, 'w', encoding='utf-8') as f:
json.dump(sample_config, f, indent=2, ensure_ascii=False)

print(Fore.YELLOW + f"已创建示例配置文件: {self.config_file}")

def display_config_status(self):
"""显示配置状态"""
print(Fore.CYAN + "\n🔧 系统配置状态:")
print("="*50)

# API密钥状态
print(Fore.BLUE + "📋 API密钥配置:")
api_keys = [
("AgentOps", self.config.agentops_api_key),
("Firecrawl", self.config.firecrawl_api_key),
("ModelScope", self.config.modelscope_api_key),
]

for name, key in api_keys:
if key:
masked_key = key[:8] + "..." + key[-4:] if len(key) > 12 else "***"
print(Fore.GREEN + f" ✅ {name}: {masked_key}")
else:
print(Fore.RED + f" ❌ {name}: 未配置")

# Neo4j配置状态
print(Fore.BLUE + "\n🗄️ Neo4j配置:")
print(Fore.BLUE + f" URL: {self.config.neo4j_url}")
print(Fore.BLUE + f" 用户名: {self.config.neo4j_username}")
if self.config.neo4j_password:
print(Fore.GREEN + f" ✅ 密码: {'*' * len(self.config.neo4j_password)}")
else:
print(Fore.RED + f" ❌ 密码: 未配置")

print("="*50)

def test_api_connections(self):
"""测试API连接"""
print(Fore.CYAN + "\n🔗 测试API连接:")
print("="*40)

# 测试Firecrawl API
if self.config.firecrawl_api_key:
try:
from camel.loaders import Firecrawl
firecrawl = Firecrawl()
print(Fore.GREEN + "✅ Firecrawl API: 连接正常")
except Exception as e:
print(Fore.RED + f"❌ Firecrawl API: {str(e)[:50]}...")

# 测试ModelScope API
if self.config.modelscope_api_key:
try:
model = ModelFactory.create(
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
model_type=self.config.model_name,
url=self.config.model_url,
api_key=self.config.modelscope_api_key
)
print(Fore.GREEN + "✅ ModelScope API: 连接正常")
except Exception as e:
print(Fore.RED + f"❌ ModelScope API: {str(e)[:50]}...")

print("="*40)

class SearchEngine:
"""统一的搜索引擎类"""

def __init__(self, config: ResearchConfig):
self.config = config
self.search_toolkit = SearchToolkit()

def duckduckgo_lite_search(self, query: str, max_results: int = None) -> List[Dict]:
"""使用DuckDuckGo Lite API进行搜索"""
if max_results is None:
max_results = self.config.max_search_results

url = f"https://lite.duckduckgo.com/lite/?q={query.replace(' ', '+')}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}

try:
resp = requests.get(url, headers=headers, timeout=10)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")

results = []
for link in soup.select("a[href*='http']")[:max_results]:
href = link.get("href", "")
text = link.get_text(strip=True)

if href and text and len(text) > 10:
results.append({
"title": text[:100],
"url": href,
"snippet": text[:200]
})

return results
except Exception as e:
logging.error(f"DuckDuckGo Lite搜索失败: {e}")
return []

def search_web(self, query: str, topic: str = "") -> str:
"""通用网络搜索功能"""
search_query = f"{query} {topic}".strip()
print(Fore.BLUE + f"🔍 网络搜索: {search_query}")

try:
# 首先尝试DuckDuckGo Lite搜索
print(Fore.CYAN + "🔄 使用 DuckDuckGo Lite 搜索...")
search_results = self.duckduckgo_lite_search(search_query)

if search_results:
formatted_results = f"🔍 搜索查询: {search_query}\n\n"
formatted_results += "🌐 搜索结果:\n"
formatted_results += "="*50 + "\n"

urls_found = []
for i, result in enumerate(search_results, 1):
title = result.get('title', '无标题')
url = result.get('url', '无链接')
snippet = result.get('snippet', '无描述')

formatted_results += f"{i}. 📰 {title}\n"
formatted_results += f" 📝 {snippet}\n"
formatted_results += f" 🔗 {url}\n\n"

if url != '无链接':
urls_found.append(url)

if urls_found:
formatted_results += "\n📎 发现的相关URL:\n"
for url in urls_found[:self.config.max_urls_to_process]:
formatted_results += f"- {url}\n"

print(Fore.GREEN + f"✅ 搜索完成,找到 {len(search_results)} 个结果")
return formatted_results
else:
raise Exception("DuckDuckGo Lite 未返回结果")

except Exception as e:
print(Fore.YELLOW + f"⚠️ 主搜索方法失败: {str(e)[:50]}...")

# 备用搜索方法
try:
print(Fore.BLUE + "🔄 尝试备用搜索方法...")
search_results = self.search_toolkit.search_duckduckgo(search_query)

formatted_results = f"🔍 搜索查询: {search_query}\n\n"
formatted_results += "🌐 搜索结果 (备用方法):\n"
formatted_results += "="*50 + "\n"

if isinstance(search_results, list):
for i, result in enumerate(search_results[:self.config.max_search_results], 1):
if isinstance(result, dict):
title = result.get('title', '无标题')
snippet = result.get('snippet', '无描述')
link = result.get('link', '无链接')
formatted_results += f"{i}. {title}\n {snippet}\n 链接: {link}\n\n"
else:
formatted_results += f"{i}. {str(result)[:200]}...\n\n"

return formatted_results

except Exception as backup_e:
error_msg = f"所有搜索方法都失败了: {str(backup_e)[:100]}..."
print(Fore.RED + error_msg)
return f"搜索查询: {search_query}\n\n搜索服务暂时不可用,请稍后重试。"

class UniversalResearchSystem:
"""通用研究系统"""

def __init__(self, config_manager: ConfigManager):
self.config = config_manager.config
self._init_components()

def _init_components(self):
"""初始化系统组件"""
# 基础组件
self.firecrawl = Firecrawl()
self.auto_retriever = AutoRetriever(
vector_storage_local_path=self.config.vector_storage_path,
storage_type=StorageType.QDRANT,
embedding_model=SentenceTransformerEncoder(),
)
self.search_engine = SearchEngine(self.config)
self.uio = UnstructuredIO()

# 知识图谱组件
self.neo4j_graph = None
self.kg_agent = None
self._init_knowledge_graph()

def _init_knowledge_graph(self):
"""初始化知识图谱组件"""
if not self.config.neo4j_password:
print(Fore.YELLOW + "⚠️ Neo4j密码未配置,将使用文本格式知识图谱")
return

try:
print(Fore.BLUE + "🔗 尝试连接Neo4j数据库...")

import neo4j
driver = neo4j.GraphDatabase.driver(
self.config.neo4j_url,
auth=(self.config.neo4j_username, self.config.neo4j_password)
)

# 验证连接
with driver.session() as session:
result = session.run("RETURN 1 as test")
test_value = result.single()["test"]
if test_value == 1:
print(Fore.GREEN + "✅ Neo4j连接测试成功")

driver.close()

# 初始化CAMEL的Neo4j组件
self.neo4j_graph = Neo4jGraph(
url=self.config.neo4j_url,
username=self.config.neo4j_username,
password=self.config.neo4j_password,
)

# 需要模型才能初始化KG Agent
if hasattr(self, 'model') and self.model:
self.kg_agent = KnowledgeGraphAgent(model=self.model)
print(Fore.GREEN + "✅ 知识图谱组件初始化成功")

except ImportError:
print(Fore.RED + "❌ neo4j驱动未安装,请运行: pip install neo4j")
except Exception as e:
print(Fore.RED + f"❌ Neo4j连接失败: {e}")
print(Fore.YELLOW + "💡 将使用文本格式知识图谱")

class ResearchToolkit:
"""研究工具包"""

def __init__(self, research_system: UniversalResearchSystem):
self.system = research_system

def retrieve_information_from_urls(self, urls: List[str], query: str) -> str:
"""从URL列表中检索相关信息"""
print(Fore.BLUE + f"开始检索: {query}")
print(Fore.BLUE + f"数据源: {len(urls)} 个URL")

aggregated_content = ''

# 限制处理的URL数量
urls_to_process = urls[:self.system.config.max_urls_to_process]

for i, url in enumerate(urls_to_process, 1):
try:
print(Fore.CYAN + f"抓取 {i}/{len(urls_to_process)}: {url}")
scraped_content = self.system.firecrawl.scrape(url)
aggregated_content += scraped_content["markdown"] + "\n\n"
print(Fore.GREEN + f"成功抓取 {len(scraped_content['markdown'])} 字符")
except Exception as e:
print(Fore.RED + f"抓取失败: {str(e)[:100]}...")
continue

if not aggregated_content.strip():
return "所有 URL 都抓取失败,无法继续处理"

try:
retrieved_info = self.system.auto_retriever.run_vector_retriever(
query=query,
contents=aggregated_content,
top_k=5,
similarity_threshold=self.system.config.similarity_threshold,
)

result = f"检索查询: {retrieved_info['Original Query']}\n\n"
result += "相关信息:\n"
for i, context in enumerate(retrieved_info['Retrieved Context'], 1):
result += f"{i}. {context[:300]}...\n\n"

return result

except Exception as e:
return f"检索失败: {e}"

def search_web_for_topic(self, query: str, topic: str = "") -> str:
"""根据主题搜索网络信息"""
return self.system.search_engine.search_web(query, topic)

def build_knowledge_graph(self, text_input: str, topic: str = "") -> str:
"""构建知识图谱"""
if not self.system.neo4j_graph or not self.system.kg_agent:
print(Fore.YELLOW + "Neo4j未配置,创建文本格式知识图谱...")

kg_result = f"知识图谱(文本格式) - 主题: {topic}\n"
kg_result += "="*50 + "\n\n"

# 简单的实体提取逻辑
lines = text_input.split('\n')
entities = []
relationships = []

for line in lines:
if len(line.strip()) > 10: # 过滤短行
words = line.split()
if len(words) > 3: # 寻找可能的实体
for word in words:
if len(word) > 4 and word.isalpha():
entities.append(word)

# 去重并限制数量
entities = list(set(entities))[:10]

kg_result += "主要实体:\n"
for entity in entities:
kg_result += f"- {entity}\n"

kg_result += f"\n关系网络:\n"
kg_result += f"- 主题: {topic}\n"
kg_result += f"- 相关实体数量: {len(entities)}\n"
kg_result += f"- 文本长度: {len(text_input)} 字符\n"

return kg_result

print(Fore.BLUE + f"开始构建知识图谱 - 主题: {topic}")

try:
element_example = self.system.uio.create_element_from_text(
text=text_input,
element_id=f"research_{topic}_{int(time.time())}"
)

graph_elements = self.system.kg_agent.run(element_example, parse_graph_elements=True)
self.system.neo4j_graph.add_graph_elements(graph_elements=[graph_elements])

print(Fore.GREEN + "知识图谱构建完成")
return f"知识图谱构建成功 - 主题: {topic}\n提取了图形元素: {str(graph_elements)[:200]}..."

except Exception as e:
error_msg = f"知识图谱构建失败: {e}"
print(Fore.RED + error_msg)
return error_msg

class InteractiveResearchSystem:
"""交互式研究系统"""

def __init__(self):
self.config_manager = ConfigManager()
self.model = None
self.research_system = None
self.toolkit = None
self._init_system()

def _init_system(self):
"""初始化系统"""
# 显示配置状态
self.config_manager.display_config_status()

# 测试API连接
self.config_manager.test_api_connections()

# 检查配置
if not self._check_config():
return

# 初始化模型
if not self._init_model():
return

# 初始化研究系统
self.research_system = UniversalResearchSystem(self.config_manager)
self.research_system.model = self.model # 为知识图谱组件提供模型

# 重新初始化知识图谱(现在有模型了)
if self.research_system.neo4j_graph and not self.research_system.kg_agent:
try:
self.research_system.kg_agent = KnowledgeGraphAgent(model=self.model)
print(Fore.GREEN + "✅ 知识图谱代理初始化成功")
except Exception as e:
print(Fore.YELLOW + f"知识图谱代理初始化失败: {e}")

self.toolkit = ResearchToolkit(self.research_system)

# 初始化AgentOps
if self.config_manager.config.agentops_api_key:
try:
agentops.init(
api_key=self.config_manager.config.agentops_api_key,
default_tags=["Universal Research", "Interactive"]
)
print(Fore.GREEN + "✅ AgentOps初始化成功")
except Exception as e:
print(Fore.YELLOW + f"AgentOps初始化失败: {e}")

def _check_config(self) -> bool:
"""检查配置完整性"""
missing_configs = []

if not self.config_manager.config.modelscope_api_key:
missing_configs.append("MODELSCOPE_SDK_TOKEN")

if missing_configs:
print(Fore.RED + "❌ 缺少必要的环境变量配置:")
for config in missing_configs:
print(Fore.RED + f" {config}")

if not self.config_manager.config_file.exists():
print(Fore.BLUE + "\n📝 创建示例配置文件...")
self.config_manager.create_sample_config()

return False

return True

def _init_model(self) -> bool:
"""初始化模型"""
try:
self.model = ModelFactory.create(
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
model_type=self.config_manager.config.model_name,
url=self.config_manager.config.model_url,
api_key=self.config_manager.config.modelscope_api_key
)
print(Fore.GREEN + f"✅ 模型初始化成功: {self.config_manager.config.model_name}")
return True
except Exception as e:
print(Fore.RED + f"❌ 模型初始化失败: {e}")
return False

def create_research_tools(self, topic: str) -> List[FunctionTool]:
"""为特定主题创建研究工具"""

def retrieve_urls_for_topic(urls: List[str], query: str) -> str:
return self.toolkit.retrieve_information_from_urls(urls, query)

def search_topic_info(query: str) -> str:
return self.toolkit.search_web_for_topic(query, topic)

def build_topic_knowledge_graph(text_input: str) -> str:
return self.toolkit.build_knowledge_graph(text_input, topic)

return [
FunctionTool(retrieve_urls_for_topic),
FunctionTool(search_topic_info),
FunctionTool(build_topic_knowledge_graph),
]

def create_research_task(self, topic: str, research_question: str) -> str:
"""创建研究任务提示"""
return f"""
对"{topic}"进行全面研究,专门回答以下问题:"{research_question}"

请按照以下步骤进行系统性研究:

1. **信息搜索阶段**
- 使用搜索工具获取与"{topic}"和"{research_question}"相关的URL和基础信息
- 识别最相关和权威的信息源

2. **深度检索阶段**
- 使用检索工具从找到的URL中获取详细内容
- 重点关注能够回答研究问题的信息

3. **分析整理阶段**
- 系统分析所有收集到的信息
- 识别关键事实、数据和观点
- 评估信息的可靠性和相关性

4. **报告撰写阶段**
- 撰写一份全面的研究报告
- 确保报告直接回答了研究问题
- 提供具体的事实支撑和数据引用

5. **知识图谱构建阶段**
- 使用知识图谱工具为报告内容构建结构化的知识图谱
- 展示关键概念之间的关系

研究重点:
- 主题: {topic}
- 核心问题: {research_question}
- 确保信息的准确性和时效性
- 提供多角度的分析视角
- 包含具体的案例和数据支撑

请系统性地完成上述研究任务,提供高质量的研究成果。
"""

def run_interactive_research(self):
"""运行交互式研究"""
if not self.model or not self.research_system:
print(Fore.RED + "❌ 系统未正确初始化,无法运行")
return

print(Fore.CYAN + "🚀 通用AI研究系统")
print("="*60)

while True:
try:
# 获取用户输入
print(Fore.YELLOW + "\n请输入研究信息:")
topic = input(Fore.CYAN + "研究主题: ").strip()
if not topic:
break

research_question = input(Fore.CYAN + "具体问题: ").strip()
if not research_question:
research_question = f"关于{topic}的综合信息"

print(Fore.BLUE + f"\n📋 开始研究:")
print(Fore.BLUE + f" 主题: {topic}")
print(Fore.BLUE + f" 问题: {research_question}")
print("="*60)

# 创建研究工具和任务
tools = self.create_research_tools(topic)
task_prompt = self.create_research_task(topic, research_question)

# 创建角色扮演系统
role_play_session = RolePlaying(
assistant_role_name="AI研究助理",
user_role_name="研究用户",
assistant_agent_kwargs=dict(
model=self.model,
tools=tools,
),
user_agent_kwargs=dict(model=self.model),
task_prompt=task_prompt,
with_task_specify=False,
)

# 执行研究
print(Fore.GREEN + f"🤖 AI助理: {role_play_session.assistant_sys_msg.content[:100]}...")
print(Fore.BLUE + f"👤 用户: {role_play_session.user_sys_msg.content[:100]}...")

input_msg = role_play_session.init_chat()
chat_turn_limit = 8

for i in range(chat_turn_limit):
print(Fore.MAGENTA + f"\n--- 研究轮次 {i+1} ---")

try:
assistant_response, user_response = role_play_session.step(input_msg)

if assistant_response.terminated or user_response.terminated:
print(Fore.GREEN + "✅ 研究任务完成")
break

# 显示进度
print(Fore.CYAN + f"🔄 助理: {assistant_response.msg.content[:200]}...")
print(Fore.BLUE + f"🔄 用户: {user_response.msg.content[:200]}...")

input_msg = assistant_response.msg
time.sleep(1) # 避免请求过快

except Exception as e:
print(Fore.RED + f"研究过程出错: {e}")
break

# 询问是否继续
print(Fore.YELLOW + "\n" + "="*60)
continue_research = input(Fore.CYAN + "是否继续新的研究? (y/n): ").strip().lower()
if continue_research != 'y':
break

except KeyboardInterrupt:
print(Fore.YELLOW + "\n用户中断研究")
break
except Exception as e:
print(Fore.RED + f"系统错误: {e}")
continue

print(Fore.GREEN + "\n👋 感谢使用通用AI研究系统!")

def main():
"""主函数"""
print(Fore.CYAN + "🎯 通用AI研究系统启动")
print("="*50)

try:
research_system = InteractiveResearchSystem()
research_system.run_interactive_research()
except Exception as e:
print(Fore.RED + f"❌ 系统启动失败: {e}")
print(Fore.YELLOW + "💡 请检查配置和依赖项")

if __name__ == "__main__":
main()
我们运行一下整个系统,分别测试一下各个检索功能的差异:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
PS G:\Python-Camel-project> & D:/Download/Python/py-3.11.9/python.exe g:/Python-Camel-project/Multimodal_RAG/Interactive_Multimodal_RAG.py
W0725 14:45:52.142000 34656 site-packages\torch\distributed\elastic\multiprocessing\redirects.py:29] NOTE: Redirects are currently not supported in Windows or MacOs.
Web research system available
初始化交互式多模态RAG系统...
Initializing Simple RAG System with CAMEL...
CAMEL LLM initialized: Qwen/Qwen2.5-72B-Instruct
API key: 64af0689-2...16a3
√ Embedding model loaded: intfloat/e5-large-v2
√ Simple vector retriever initialized
√ Simple RAG System initialized successfully!
√ 集成CAMEL的RAG系统初始化成功

🔧 系统配置状态:
==================================================
📋 API密钥配置:
✅ AgentOps: 3e6edf79...444d
✅ Firecrawl: fc-58764...87c2
✅ ModelScope: 64af0689...16a3

🗄️ Neo4j配置:
URL: bolt://localhost:7687
用户名: neo4j
✅ 密码: ***********
==================================================

🔗 测试API连接:
========================================
✅ Firecrawl API: 连接正常
✅ ModelScope API: 连接正常
========================================
✅ 模型初始化成功: Qwen/Qwen2.5-72B-Instruct
D:\Download\Python\py-3.11.9\Lib\site-packages\camel\toolkits\function_tool.py:533: UserWarning: Parameter description is missing for the function 'search_linkup'. The parameter definition is {'enum': ['searchResults', 'sourcedAnswer', 'structured'], 'type': ['string', 'null']}. This may affect the quality of tool calling.
warnings.warn(
D:\Download\Python\py-3.11.9\Lib\site-packages\camel\toolkits\function_tool.py:533: UserWarning: Parameter description is missing for the function 'search_alibaba_tongxiao'. The parameter definition is {'enum': ['OneDay', 'OneWeek', 'OneMonth', 'OneYear', 'NoLimit'], 'type': ['string', 'null']}. This may affect the quality of tool calling.
warnings.warn(
D:\Download\Python\py-3.11.9\Lib\site-packages\camel\toolkits\function_tool.py:533: UserWarning: Parameter description is missing for the function 'search_alibaba_tongxiao'. The parameter definition is {'anyOf': [{'enum': ['finance', 'law', 'medical', 'internet', 'tax', 'news_province', 'news_center'], 'type': 'string'}, {'type': 'null'}], 'type': ['null']}. This may affect the quality of tool calling.
warnings.warn(
🔗 尝试连接Neo4j数据库...
✅ Neo4j连接测试成功
✅ 知识图谱代理初始化成功
🖇 AgentOps: WARNING: agentops is out of date. Please update with the command: 'pip install --upgrade agentops'
🖇 AgentOps: Session Replay: https://app.agentops.ai/drilldown?session_id=1daa3df4-89ba-4a7a-a1f9-991c342edb8b
✅ AgentOps初始化成功
√ 网页研究系统初始化成功

交互式多模态RAG系统
============================================================
功能特性:
- 支持在线/本地PDF加载
- 三种检索模式
- 网页爬取集成
- 多模态内容处理
============================================================

PDF知识库设置
==================================================
1. 在线PDF (输入URL)
2. 本地PDF (输入文件路径)
3. 使用默认示例PDF

请选择PDF来源 (1-3): 2
请输入PDF文件路径: G:\Program for work\Other\CamelAgent.pdf
状态查询: 正在加载本地PDF: G:\Program for work\Other\CamelAgent.pdf
Loading PDF from: G:\Program for work\Other\CamelAgent.pdf
√ PDF loaded successfully
Computing embeddings for 1839 documents...
Added 1839 documents to retriever
√ Knowledge base setup complete: 1839 elements
Content: 1839 text, 0 images, 0 tables
√ PDF知识库加载成功!

当前知识库: 本地PDF: G:\Program for work\Other\CamelAgent.pdf
🔧 可用检索方法: Vector, Enhanced

============================================================
查询选项
============================================================
我们可以看到系统启动成功,本地PDF文件也成功加载了,现在我们先进行快速检索的演示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
请输入您的问题 (输入 'quit' 退出, 'reload' 重新加载PDF): camel agent框架具备有什么特性?可以调用哪些工具?

选择检索模式:
1. 快速检索 (基础向量检索)
2. 深度检索 (重写+HyDE+RRF)
3. 主题检索 (PDF+网页爬取)
请选择模式 (1-3): 1

执行查询: camel agent框架具备有什么特性?可以调用哪些工具?
检索模式: 快速检索

执行快速检索...
========================================
正在进行向量检索...
Retrieved 3 documents
√ 检索到 3 个相关文档
文档 1 (相似度: 0.910):
结语 恭喜您!在阅读到这里时,您已经掌握了 CAMEL-AI 应用开发框架的基础知识,并能够利 用 Agent 实例在您的代码逻辑中执行复杂的任务。此外,您还可以尝试将 Agent 实例整合 到更复杂的工作流中,或实现 Agent 实例之间的协同工作。

文档 2 (相似度: 0.910):
为什么选择 CAMEL Multi-Agent? 选择 CAMEL Multi-Agent 框架,你将获得以下优势:

文档 3 (相似度: 0.902):
Model 是 Agent 的大脑,负责处理所有输入和输出数据。通过有效调用不同的模型,智能 体可以根据任务需求执行文本分析、图像识别和复杂推理等操作。CAMEL 提供了一系列标

正在生成答案...
Generating response with CAMEL model...
CAMEL generation failed, using fallback: 'BaseMessage' object has no attribute 'get'...
API调用 1/3...
√ API调用成功
√ 快速检索完成

==================== 快速检索结果 ====================
原结始查询: camel agent框架具备有什么特性?可以调用哪些工具?
检索方法: Quick Vector Retrieval

检索到的文档 (共3个):

文档 1:
相关度分数: 0.9104779362678528
内容预览: 结语 恭喜您!在阅读到这里时,您已经掌握了 CAMEL-AI 应用开发框架的基础知识 ,并能够利 用 Agent 实例在您的代码逻辑中执行复杂的任务。此外,您还可以尝试将 Agent 实例整合 到更复杂的工作流中,或实现 Agent 实例之间的协同工作。

文档 2:
相关度分数: 0.9104548692703247
内容预览: 为什么选择 CAMEL Multi-Agent? 选择 CAMEL Multi-Agent 框架,你将获得以下优势:

文档 3:
相关度分数: 0.9016962051391602
内容预览: Model 是 Agent 的大脑,负责处理所有输入和输出数据。通过有效调用不同的模型 ,智能 体可以根据任务需求执行文本分析、图像识别和复杂推理等操作。CAMEL 提供了一系列 标

💡 生成答案:
CAMEL Agent框架的特性包括:

1. **多智能体协作**:支持多个Agent实例之间的协同工作,以完成更复杂的任务。
2. **灵活的任务处理能力**:通过Model(智能体的大脑)处理所有输入和输出数据,能够根据任务需求执行多种操作。

可以调用的工具包括:

- **文本分析**:处理和理解文本数据。
- **图像识别**:识别和分析图像内容。
- **复杂推理**:进行复杂的逻辑推理和决策。
============================================================

询问:是否保存结果到文件?(y/n): n

是否继续查询?(y/n): y

============================================================
查询选项
============================================================
接着我们测试深度检索的效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
请输入您的问题 (输入 'quit' 退出, 'reload' 重新加载PDF): camel agent框架具备有什么特性?可以调用哪些工具?

选择检索模式:
1. 快速检索 (基础向量检索)
2. 深度检索 (重写+HyDE+RRF)
3. 主题检索 (PDF+网页爬取)
请选择模式 (1-3): 2

执行查询: camel agent框架具备有什么特性?可以调用哪些工具?
检索模式: 深度检索

执行深度检索...
============================================================
开始执行深度RAG查询
============================================================

步骤1: 查询重写
------------------------------
原始查询: camel agent框架具备有什么特性?可以调用哪些工具?
Generating response with CAMEL model...
CAMEL generation failed, using fallback: 'BaseMessage' object has no attribute 'get'...
API调用 1/3...
√ API调用成功
Query rewritten: camel agent框架具备有什么特性?可以调用哪些工具? -> Camel Agent框 架的具体特性和可调用的工具有哪些?...
重写查询: Camel Agent框架的具体特性和可调用的工具有哪些?

步骤2: 文档检索
------------------------------
使用HyDE+RRF组合方法进行检索...
使用RRF算法进行混合检索(HyDE增强向量检索)...
执行HyDE增强向量检索...
Generating response with CAMEL model...
CAMEL generation failed, using fallback: 'BaseMessage' object has no attribute 'get'...
API调用 1/3...
√ API调用成功
📝 HyDE document generated: 633 characters
生成的假设文档:
在分布式计算领域,Camel Agent框架因其灵活性和强大的扩展性而受到广泛关注。该框架设计 用于支持复杂环境下的任务调度与资源管理,尤其适用于异构系统中。Camel Agent框架的核心 特性包括但不限于:

1. **模块化架构**:Camel Agent采用高度模块化的架构设计,允许开发者根据具体需求灵活选择和组合不同的组件。这种设计不仅简化了开发流程,还极大地提高了系统的可维护性和可扩展性。

2. **丰富的插件支持**:框架内置了多种插件,涵盖了从数据处理到通信协议转换等多个方面 。例如,提供了RESTful API、AMQP (Advanced Message Queuing Protocol) 等多种消息传递机制的支持,以及对JSON、XML等数据格式的解析能力。此外,Camel Agent还支持自定义插件的开发,以满足特定应用场景的需求。

3. **强大的路由与转换功能**:利用Apache Camel的核心优势,Camel Agent能够实现复杂的消息路由和转换逻辑。通过定义EIPs (Enterprise Integration Patterns),可以轻松构建高效的数据流处理管道,支持同步/异步调用、错误处理及重试机制等高级特性。

4. **动态配置与热更新**:Camel Agent支持运行时动态调整配置参数,无需重启服务即可生效,极大提升了运维效率。同时,它也具备热部署能力,允许在不停机的情况下更新应用逻辑或添加新功能
Retrieved 5 documents
✓ HyDE向量检索完成,获得 5 个结果
Retrieved 0 documents
✓ 图像检索完成,获得 0 个结果
Retrieved 0 documents
✓ 表格检索完成,获得 0 个结果
执行BM25检索(使用原始查询)...
Retrieved 5 documents
✓ BM25检索成功,获得 5 个结果
使用RRF算法融合检索结果...
RRF融合完成,共处理 10 个唯一文档,返回前 5 个结果
HyDE+RRF检索完成,返回 10 个文档
文档 1 (RRF分数: 0.9160):
结语 恭喜您!在阅读到这里时,您已经掌握了 CAMEL-AI 应用开发框架的基础知识,并能够利 用 Agent 实例在您的代码逻辑中执行复杂的任务。此外,您还可以尝试将 Agent 实例整合 到 更复杂的工作流中,或实现 Agent 实例之间的协同工作。

文档 2 (RRF分数: 0.9094):
想象一下,如果没有统一的语言和行为规范,来自不同公司或者基于不同技术背景开发的 AI Agent 就很难顺畅地合作。这会限制 AI Agent 网络的扩展,最终也会限制它们解决更复杂 现实 问题的能力。这种情况有点像互联网早期,各个计算机系统互不兼容,连接非常受限, 导致整 个网络发展缓慢。 一个统一的通信协议不仅仅能解决眼前的互操作问题,更有可能 催生出一个由无数智能体连接而成的巨大网络。在这个网络...

文档 3 (RRF分数: 0.9136):
评审者 Agent 的 评审标准。如果

文档 4 (RRF分数: 0.9050):
除了能把工具包转换成 MCP 服务器外,CAMEL 框架还支持一个更强大的功能:把整个 CAMEL 代理(Agent)本身也作为 MCP 服务器发布出去。这意味着,一个你精心配置好的 CAMEL 代理—— 它可能拥有特定的 AI 模型、独特的系统指令(system message),甚至内 置了一些其他的工 具——现在可以作为一个独立的服务运行。然后,任何支持 MCP 协议的 客户端(比如像 Anth...

文档 5 (RRF分数: 0.9120):
Model 是 Agent 的大脑,负责处理所有输入和输出数据。通过有效调用不同的模型,智能 体可以根据任务需求执行文本分析、图像识别和复杂推理等操作。CAMEL 提供了一系列标

步骤3: 答案生成
------------------------------

正在生成最终答案...
Generating response with CAMEL model...
CAMEL generation failed, using fallback: 'BaseMessage' object has no attribute 'get'...
API调用 1/3...
√ API调用成功
√ 答案生成成功
最终答案:
### CAMEL Agent框架的特性及可调用工具

#### 特性

1. **标准化协议支持**:
- CAMEL Agent框架支持多种标准化协议,特别是模型上下文协议(MCP)、Agent间协议(A2A)和Agent网络协议(ANP)。这些协议确保了不同AI Agent之间的互操作性和高效协作(文档 内容:“这些协议为解决 AI Agent 在理解上下文、使用工具和相互协作方面的难题提供了有效 的思路。”)。

2. **高度可扩展性**:
- CAMEL框架允许开发者将自定义的工具和服务转换成MCP服务,使得这些工具和服务可以被 其他支持MCP协议的客户端识别和使用(文档内容:“除了能把工具包转换成 MCP 服务器外,CAMEL 框架还支持一个更强大的功能:把整个 CAMEL 代理(Agent)本身也作为 MCP 服务器发布出去。”)。

3. **复杂的多代理交互**:
- CAMEL框架内置了多代理角色扮演(RolePlaying)模块和“工作组”(Workforce)模块,这些模块可以实现多个代理之间的协同工作,形成复杂的交互场景(文档内容:“其内部一些更复 杂的模块,比如用于实现多代理角色扮演(RolePlaying)的模块,或者用于组织多个代理协同 工作的‘工作组’(Workforce)模块,也计划或者正在被实现为 MCP 服务器。”)。

4. **代码即提示(Code-as-Prompt)**:
- CAMEL框架强调编写既清晰易懂又可被AI代理准确理解的代码,这一设计理念有助于提高集成的质量和稳定性(文档内容:“CAMEL 框架中有一个核心的设计哲学叫做‘代码即提示’(Code-as-Prompt)。它强调编写既清晰易懂(对人类开发者而言)又能被 AI 代理准确理解的代码。”)。

#### 可调用的工具

1. **文本分析工具**:
- CAMEL Agent框架支持调用文本分析工具,这些工具可以帮助Agent执行文本分类、情感分 析、关键词提取等任务(文档内容:“通过有效调用不同的模型,智能体可以根据任务需求执行 文本分析、图像识别和复杂推理等操作。”)。

2. **图像识别工具**:
- 框架内的Agent可以调用图像识别工具,用于图像分类、目标检测、图像生成等任务。

3. **复杂推理工具**:
- 支持调用复杂推理工具,这些工具可以帮助Agent解决需要多步推理的问题,例如决策树、逻辑推理等。

4. **自定义工具和服务**:
- 开发者可以将自己开发的工具和服务转换成MCP服务,这些服务可以被其他支持MCP协议的 客户端调用,从而实现更广泛的应用(文档内容:“这意味着,一个你精心配置好的 CAMEL 代理——它可能拥有特定的 AI 模型、独特的系统指令(system message),甚至内置了一些其他的工具——现在可以作为一个独立的服务运行。”)。

通过上述特性和工具的支持,CAMEL Agent框架不仅能够实现单一Agent的强大功能,还能促进不同Agent之间的协同工作,形成一个高效的AI生态系统。

==================== 深度检索结果 ====================
原结始查询: camel agent框架具备有什么特性?可以调用哪些工具?
重写查询: Camel Agent框架的具体特性和可调用的工具有哪些?
检索方法: Vector+Rewriting+HyDE+Image+Table+RRF

检索到的文档 (共5个):

文档 1:
相关度分数: 0.01639344262295082
内容预览: 结语 恭喜您!在阅读到这里时,您已经掌握了 CAMEL-AI 应用开发框架的基础知识 ,并能够利 用 Agent 实例在您的代码逻辑中执行复杂的任务。此外,您还可以尝试将 Agent 实例整合 到更复杂的工作流中,或实现 Agent 实例之间的协同工作。

文档 2:
相关度分数: 0.01639344262295082
内容预览: 想象一下,如果没有统一的语言和行为规范,来自不同公司或者基于不同技术背景开发的 AI Agent 就很难顺畅地合作。这会限制 AI Agent 网络的扩展,最终也会限制它们解决更复杂 现实问题的能力。这种情况有点像互联网早期,各个计算机系统互不兼容,连接非常受限 , 导致整个网络发展缓慢。 一个统一的通信协议不仅仅能解决眼前的互操作问题,更有可能 催生出一个由无数智能体连接而成的巨大网络。在这个网络...

文档 3:
相关度分数: 0.016129032258064516
内容预览: 评审者 Agent 的 评审标准。如果

文档 4:
相关度分数: 0.016129032258064516
内容预览: 除了能把工具包转换成 MCP 服务器外,CAMEL 框架还支持一个更强大的功能:把整 个 CAMEL 代理(Agent)本身也作为 MCP 服务器发布出去。这意味着,一个你精心配置好的 CAMEL 代理——它可能拥有特定的 AI 模型、独特的系统指令(system message),甚至内 置了一 些其他的工具——现在可以作为一个独立的服务运行。然后,任何支持 MCP 协议的 客户端(比如像 Anth...

文档 5:
相关度分数: 0.015873015873015872
内容预览: Model 是 Agent 的大脑,负责处理所有输入和输出数据。通过有效调用不同的模型 ,智能 体可以根据任务需求执行文本分析、图像识别和复杂推理等操作。CAMEL 提供了一系列 标

💡 生成答案:
### CAMEL Agent框架的特性及可调用工具

#### 特性

1. **标准化协议支持**:
- CAMEL Agent框架支持多种标准化协议,特别是模型上下文协议(MCP)、Agent间协议(A2A)和Agent网络协议(ANP)。这些协议确保了不同AI Agent之间的互操作性和高效协作(文档 内容:“这些协议为解决 AI Agent 在理解上下文、使用工具和相互协作方面的难题提供了有效 的思路。”)。

2. **高度可扩展性**:
- CAMEL框架允许开发者将自定义的工具和服务转换成MCP服务,使得这些工具和服务可以被 其他支持MCP协议的客户端识别和使用(文档内容:“除了能把工具包转换成 MCP 服务器外,CAMEL 框架还支持一个更强大的功能:把整个 CAMEL 代理(Agent)本身也作为 MCP 服务器发布出去。”)。

3. **复杂的多代理交互**:
- CAMEL框架内置了多代理角色扮演(RolePlaying)模块和“工作组”(Workforce)模块,这些模块可以实现多个代理之间的协同工作,形成复杂的交互场景(文档内容:“其内部一些更复 杂的模块,比如用于实现多代理角色扮演(RolePlaying)的模块,或者用于组织多个代理协同 工作的‘工作组’(Workforce)模块,也计划或者正在被实现为 MCP 服务器。”)。

4. **代码即提示(Code-as-Prompt)**:
- CAMEL框架强调编写既清晰易懂又可被AI代理准确理解的代码,这一设计理念有助于提高集成的质量和稳定性(文档内容:“CAMEL 框架中有一个核心的设计哲学叫做‘代码即提示’(Code-as-Prompt)。它强调编写既清晰易懂(对人类开发者而言)又能被 AI 代理准确理解的代码。”)。

#### 可调用的工具

1. **文本分析工具**:
- CAMEL Agent框架支持调用文本分析工具,这些工具可以帮助Agent执行文本分类、情感分 析、关键词提取等任务(文档内容:“通过有效调用不同的模型,智能体可以根据任务需求执行 文本分析、图像识别和复杂推理等操作。”)。

2. **图像识别工具**:
- 框架内的Agent可以调用图像识别工具,用于图像分类、目标检测、图像生成等任务。

3. **复杂推理工具**:
- 支持调用复杂推理工具,这些工具可以帮助Agent解决需要多步推理的问题,例如决策树、逻辑推理等。

4. **自定义工具和服务**:
- 开发者可以将自己开发的工具和服务转换成MCP服务,这些服务可以被其他支持MCP协议的 客户端调用,从而实现更广泛的应用(文档内容:“这意味着,一个你精心配置好的 CAMEL 代理——它可能拥有特定的 AI 模型、独特的系统指令(system message),甚至内置了一些其他的工具——现在可以作为一个独立的服务运行。”)。

通过上述特性和工具的支持,CAMEL Agent框架不仅能够实现单一Agent的强大功能,还能促进不同Agent之间的协同工作,形成一个高效的AI生态系统。
============================================================

询问:是否保存结果到文件?(y/n): n

是否继续查询?(y/n): y

============================================================
查询选项
============================================================
最后我们来测试一下主题检索:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
请输入您的问题 (输入 'quit' 退出, 'reload' 重新加载PDF): camel agent框架具备有什么特性?可以调用哪些工具?

选择检索模式:
1. 快速检索 (基础向量检索)
2. 深度检索 (重写+HyDE+RRF)
3. 主题检索 (PDF+网页爬取)
请选择模式 (1-3): 3

执行查询: camel agent框架具备有什么特性?可以调用哪些工具?
检索模式: 主题检索

执行网页检索...
========================================
正在进行网页研究...
🔍 网络搜索: camel agent框架具备有什么特性?可以调用哪些工具?
🔄 使用 DuckDuckGo Lite 搜索...
✅ 搜索完成,找到 10 个结果
√ 网页搜索完成
正在检索PDF文档...
Retrieved 3 documents
√ 检索到 3 个PDF文档
正在生成综合答案...
Generating response with CAMEL model...
CAMEL generation failed, using fallback: 'BaseMessage' object has no attribute 'get'...
API调用 1/3...
√ API调用成功
主题检索完成

==================== 深度检索结果 ====================
原结始查询: camel agent框架具备有什么特性?可以调用哪些工具?
检索方法: PDF+Web Topic Retrieval
💡 生成答案:
**CAMEL Agent框架的特性及其可调用的工具**

### 特性

1. **多智能体系统支持**:CAMEL Agent框架支持创建和管理多个智能体,这些智能体可以在同一个系统中协同工作,共同完成复杂的任务。每个智能体都可以根据其角色和任务进行配置,从而实现高度的灵活性和适应性。

2. **模块化设计**:框架采用模块化设计,使得开发者可以轻松地添加或移除功能模块,如不 同的感知模块、决策模块等,以适应不同应用场景的需求。

3. **强大的模型支持**:CAMEL Agent框架中的每个Agent都有一个“大脑”,即Model,它负责处理所有输入和输出的数据。通过调用不同的模型,智能体能够执行文本分析、图像识别、复杂推理等多种任务。

4. **高效的任务调度与管理**:该框架提供了高效的任务调度机制,确保多个Agent之间可以有效地分配和执行任务,即使在资源有限的情况下也能保持良好的性能。

5. **易于集成第三方服务**:CAMEL Agent框架设计时考虑到了与其他服务和技术栈的兼容性,允许开发者轻松集成外部API和服务,如云存储、数据库、消息队列等,进一步扩展应用的功能 。

### 可调用的工具

1. **自然语言处理(NLP)工具**:包括但不限于文本分类、情感分析、实体识别等功能,帮助智能体更好地理解和生成人类语言。

2. **计算机视觉(CV)工具**:如图像分类、目标检测、人脸识别等,使智能体能够在视觉任 务中发挥重要作用。

3. **机器学习/深度学习框架**:如TensorFlow、PyTorch等,为智能体提供了强大的算法支持 ,使其能够学习和改进自己的行为模式。

4. **数据存储与处理工具**:例如MongoDB、MySQL等数据库管理系统,以及Hadoop、Spark等大数据处理平台,用于管理和分析大量数据。

5. **通信协议与工具**:包括RESTful API、WebSocket等,确保智能体之间以及智能体与外部 世界之间的高效通信。

6. **任务调度与管理工具**:如Celery、RabbitMQ等,帮助实现任务的异步处理和分布式计算 ,提高系统的响应速度和处理能力。

综上所述,CAMEL Agent框架不仅具备强大的多智能体系统支持和模块化设计,还能够调用多种 先进的工具和技术,使其成为构建复杂智能应用的理想选择。
============================================================

询问:是否保存结果到文件?(y/n): n

是否继续查询?(y/n): y

============================================================
查询选项
============================================================
请输入您的问题 (输入 'quit' 退出, 'reload' 重新加载PDF):
基于以上运行结果,我们来总结一下功能实现效果

我们可以看到,该交互式多模态RAG系统在功能实现和交互设计上表现良好,成功支持PDF知识库加载、三种检索模式和答案生成,答案质量随模式增强而提升。然而,CAMEL框架的稳定性问题、多模态支持的未充分利用、网页研究的模拟性以及性能和界面局限影响了整体效果。通过解决CAMEL兼容性、增强多模态和网页功能、优化性能和用户体验,系统可进一步提升实用性和适应稳定性,适用于更广泛的应用场景。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
 G:\Python-Camel-project\Interactive_Multi_RAG> & D:/Download/Python/py-3.11.9/python.exe g:/Python-Camel-project/Interactive_Multi_RAG/Enhanced_Interactive_Multimodal_RAG.py
W0725 16:44:30.290000 32324 site-packages\torch\distributed\elastic\multiprocessing\redirects.py:29] NOTE: Redirects are currently not supported in Windows or MacOs.
✓ 使用Rich增强界面
╭────────────────────────────────── 🎯 系统启动 ───────────────────────────────────╮
│ │
│ │
│ 🤖 交互式多模态RAG系统 v2.0 │
│ │
│ ✨ 新功能特性: │
│ • 🔧 增强的CAMEL框架集成和稳定性改进 │
│ • 🖼️ 改进的多模态支持 (图像OCR + 表格提取)

│ • 🌐 真实网页研究和内容分析 │
│ • ⚡ 性能监控和优化 │
│ • 🎨 增强的用户界面体验 │
│ │
│ 🚀 支持的检索模式: │
│ • 快速检索: 基础向量检索 │
│ • 深度检索: 查询重写 + HyDE + RRF融合 │
│ • 主题检索: PDF + 网页内容综合分析 │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────╯
🚀 正在初始化增强RAG系统...
性能监控器初始化 (详细监控: 开启)
🚀 初始化增强RAG系统...
正在初始化CAMEL模型...
CAMEL模型测试失败: 'BaseMessage' object has no attribute 'get'...
⚠ CAMEL模型初始化成功但测试失败,将使用直接API调用
✅ 嵌入模型加载成功
✅ 增强向量检索器初始化完成
✅ 增强文档管理器初始化完成
📁 缓存目录: document_cache
📋 支持格式: ['.pdf', '.docx', '.doc', '.txt', '.md', '.csv', '.xlsx', '.xls', '.pptx', '.ppt', '.json', '.xml', '.html', '.rtf']
多模态处理器初始化:
图像OCR: ✓
表格处理: ✓
PyMuPDF: ✓
网页研究系统初始化:
BeautifulSoup4: ✓
DuckDuckGo搜索: ✓
✅ 增强RAG系统初始化完成!
✅ 增强RAG系统初始化成功!
🔧 系统状态
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 组件 ┃ 状态 ┃ 详情 ┃
┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ LLM接口 │ ✅ 正常 │ │
│ 嵌入模型 │ ✅ 正常 │ intfloat/e5-large-v2 │
│ 文档管理 │ ✅ 正常 │ │
│ 多模态处理 │ ✅ 正常 │ OCR: True, 表格: True │
│ 网页研究 │ ✅ 正常 │ │
│ 知识库 │ ✅ 正常 │ │
│ 性能监控 │ ✅ 正常 │ │
└──────────────────────┴─────────────────┴───────────────────────┘

📚 文档知识库设置
┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 选项 ┃ 描述 ┃
┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1 │ 在线文档 (输入URL) │
│ 2 │ 本地文档 (输入文件路径) │
│ 3 │ 批量本地文档 (输入目录路径) │
│ 4 │ 使用默认示例PDF │
└──────────┴─────────────────────────────┘

请选择文档来源 [1/2/3/4] (4): 2
请输入文档文件路径 (回车结束): G:\Program for work\Other\CamelAgent.pdf
请输入文档文件路径 (回车结束): G:\Program for work\Other\CamelAgent.pdf
请输入文档文件路径 (回车结束):
⏳ 正在加载 2 个文档...
⏱ 开始监控: setup_knowledge_base
📚 正在设置知识库...
文档数量: 2
来源类型: path

📄 处理文档: G:\Program for work\Other\CamelAgent.pdf
📄 处理文档: G:\Program for work\Other\CamelAgent.pdf
✅ 文档缓存已保存: 271 个块
✅ 文档处理完成: 271 个块, 耗时 13.07s
✅ 文档处理完成: 271 个块

📄 处理文档: G:\Program for work\Other\CamelAgent.pdf
📄 处理文档: G:\Program for work\Other\CamelAgent.pdf
⚡ 使用缓存数据
✅ 文档处理完成: 271 个块

⏳ 正在构建向量索引...
⏱ 开始监控: add_documents
⏳ 正在计算 542 个文档的嵌入向量...
✅ 成功添加 542 个文档到检索器
✓ 操作完成: add (耗时: 343.83s, 内存: 794.0MB)

✅ 知识库设置完成!
处理文档数: 2
总文档块数: 542
内容统计: 文本(418) 图像(116) 表格(8) 其他(0)
缓存统计: 1 个文档, 0.4MB
✓ 操作完成: setup (耗时: 356.98s, 内存: 794.0MB)
✅ 知识库设置完成!

💭 请输入您的问题 (): 介绍camel中的rag使用

🔍 选择检索模式
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 模式 ┃ 描述 ┃ 特点 ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1. 快速检索 │ 基础向量检索 │ 速度快,适合简单查询 │
│ 2. 深度检索 │ 查询重写+HyDE+RRF │ 准确度高,适合复杂查询 │
│ 3. 主题检索 │ PDF+网页综合分析 │ 信息全面,适合研究性查询 │
└──────────────┴───────────────────┴──────────────────────────┘
请选择检索模式 [1/2/3] (1): 2
⏳ 正在执行深度检索...
⏱ 开始监控: enhanced_query_深度检索

🔍 执行深度检索: 介绍camel中的rag使用
============================================================
🔬 执行深度检索...
📝 步骤1: 查询重写
API调用尝试 1/3
✓ API调用成功
🧠 步骤2: HyDE假设文档生成
API调用尝试 1/3
✓ API调用成功
🔍 步骤3: 多路检索
⏱ 开始监控: vector_query
✅ 检索到 5 个相关文档
✓ 操作完成: vector (耗时: 0.20s, 内存: 569.7MB)
⏱ 开始监控: vector_query
✅ 检索到 5 个相关文档
✓ 操作完成: vector (耗时: 0.19s, 内存: 571.0MB)
⏱ 开始监控: vector_query
✅ 检索到 5 个相关文档
✓ 操作完成: vector (耗时: 0.95s, 内存: 584.7MB)
⏱ 开始监控: vector_query
✅ 检索到 0 个相关文档
✓ 操作完成: vector (耗时: 0.12s, 内存: 581.9MB)
⏱ 开始监控: vector_query
✅ 检索到 0 个相关文档
✓ 操作完成: vector (耗时: 0.14s, 内存: 581.7MB)
🔀 步骤4: RRF结果融合
💡 步骤5: 生成最终答案
API调用尝试 1/3
✓ API调用成功
✓ 操作完成: enhanced (耗时: 41.24s, 内存: 910.7MB)

================================================================================
╭──────────────────────────────────── 查询信息 ────────────────────────────────────╮
│ 🔍 查询: 介绍camel中的rag使用 │
│ 🔧 方法: 深度检索(重写+HyDE+RRF) │
│ 📝 重写: 在Apache Camel中实现RAG(Retrieval-Augmented │
│ Generation)的具体应用和配置方法 │
╰──────────────────────────────────────────────────────────────────────────────────╯

📄 检索到的文档 (共11个):
╭───────────────────────────────────── 文档 1 ─────────────────────────────────────╮
│ 相关度分数: 0.0474 │
│ 内容预览: DataWhale 和 CAMEL │
│ 之间的关系是合作和知识共享。尽管它们生活在不同的环境中—— │
│ CAMEL 生活在沙漠,而 DataWhale 生活在海洋,但它们都发现了神秘的古代文物,分别是 │
│ 古代石板和古老羊皮纸。通过一只信使鸟的帮助,它们了解到对方的发现并决定合作解开这 │
│ 些文物的秘密。CAMEL 跨越沙漠来到海洋边缘,而 DataWhale 也游到岸边与 CAMEL 会 │
│ 合。最终,它们共同努力... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────── 文档 2 ─────────────────────────────────────╮
│ 相关度分数: 0.0320 │
│ 内容预览: DataWhale 和 CAMEL │
│ 之间的关系是合作和知识共享。尽管它们生活在不同的环境中—— │
│ CAMEL 生活在沙漠,而 DataWhale 生活在海洋,但它们都发现了神秘的古代文物,分别是 │
│ 古代石板和古老羊皮纸。通过一只信使鸟的帮助,它们了解到对方的发现并决定合作解开这 │
│ 些文物的秘密。CAMEL 跨越沙漠来到海洋边缘,而 DataWhale 也游到岸边与 CAMEL 会 │
│ 合。最终,它们共同努力... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────── 文档 3 ─────────────────────────────────────╮
│ 相关度分数: 0.0310 │
│ 内容预览: # 遍历文本检索结果 │
│ for rank, result in enumerate(text_results): │
│ text = result['text'] │
│ doc_scores = doc_scores.get(text, 0) + 1 / (rank + m) │
│ │
│ # 按融合分数排序并返回前k 个结果 │
│ ... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────── 文档 4 ─────────────────────────────────────╮
│ 相关度分数: 0.0164 │
│ 内容预览: │
│ 观察到文案风格确实更加活泼,且红圈部分正确修改成了中南海和配图也十分吻合。 │
│ 6. 搭配前端食用 │
│ 综合案例中为了尽可能让大家直观的感受到基于CAMEL 框架的Agent 产品开发的乐趣,我 │
│ 们还为大家准备了精美的前端,搭配之前的几个后端模块一起构成我们的NavigatorAI 旅游 │
│ │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────── 文档 5 ─────────────────────────────────────╮
│ 相关度分数: 0.0164 │
│ 内容预览: │
│ The CAMEL framework ( (https://github.com/camel-ai)) │
│ developed by the CAMEL-AI community is one of the earliest open-source │
│ multi-agent │
│ projects based on large languag... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────── 文档 6 ─────────────────────────────────────╮
│ 相关度分数: 0.0161 │
│ 内容预览: │
│ 观察到文案风格确实更加活泼,且红圈部分正确修改成了中南海和配图也十分吻合。 │
│ 6. 搭配前端食用 │
│ 综合案例中为了尽可能让大家直观的感受到基于CAMEL 框架的Agent 产品开发的乐趣,我 │
│ 们还为大家准备了精美的前端,搭配之前的几个后端模块一起构成我们的NavigatorAI 旅游 │
│ │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────── 文档 7 ─────────────────────────────────────╮
│ 相关度分数: 0.0161 │
│ 内容预览: │
│ The CAMEL framework ( (https://github.com/camel-ai)) │
│ developed by the CAMEL-AI community is one of the earliest open-source │
│ multi-agent │
│ projects based on large languag... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────── 文档 8 ─────────────────────────────────────╮
│ 相关度分数: 0.0159 │
│ 内容预览: # 遍历文本检索结果 │
│ for rank, result in enumerate(text_results): │
│ text = result['text'] │
│ doc_scores = doc_scores.get(text, 0) + 1 / (rank + m) │
│ │
│ # 按融合分数排序并返回前k 个结果 │
│ ... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────── 文档 9 ─────────────────────────────────────╮
│ 相关度分数: 0.0159 │
│ 内容预览: │
│ 此外,还有其他一些研究和项目也在探索如何利用LLMs 构建多智能体系统,比如通过模拟 │
│ 社会动态、协作解决问题等。这些工作都在不同程度上推动了 │
│ 该领域的进步。 │
│ │
│ 如果您有更具体的时间范围或其他标准来定义“第一个”,请提供更多信息,这样我可以尝试 │
│ 给出更加准确的答案。" │
│ 之后我们将之前设定的memory 赋值给agent: │
│ # 将memory 赋值给agent │
│ agent.memory... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭──────────────────────────────────── 文档 10 ─────────────────────────────────────╮
│ 相关度分数: 0.0156 │
│ 内容预览: │
│ 此外,还有其他一些研究和项目也在探索如何利用LLMs 构建多智能体系统,比如通过模拟 │
│ 社会动态、协作解决问题等。这些工作都在不同程度上推动了 │
│ 该领域的进步。 │
│ │
│ 如果您有更具体的时间范围或其他标准来定义“第一个”,请提供更多信息,这样我可以尝试 │
│ 给出更加准确的答案。" │
│ 之后我们将之前设定的memory 赋值给agent: │
│ # 将memory 赋值给agent │
│ agent.memory... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭──────────────────────────────────── 文档 11 ─────────────────────────────────────╮
│ 相关度分数: 0.0154 │
│ 内容预览: # 创建或初始化向量存储(例如 QdrantStorage) │
│ from camel.storages.vectordb_storages import QdrantStorage │
│ │
│ vector_storage = QdrantStorage( │
│ vector_dim=embedding_model.get_output_dim(), # 嵌入向量的维度 │
│ collecti... │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭────────────────────────────────── 💡 生成答案 ───────────────────────────────────╮
│ ### CAMEL 中的 RAG 使用介绍 │
│ │
│ #### 1. RAG 基本概念 │
│ RAG(Retrieval-Augmented │
│ Generation)是一种结合了信息检索和自然语言生成的技术。它通过先从大量文档中检索出 │
│ 与查询相关的片段,再利用这些片段生成高质量的回答,从而提高生成内容的相关性和准确 │
│ 性。在 CAMEL 框架中,RAG 技术被广泛应用于知识问答、客户服务等领域。 │
│ │
│ #### 2. CAMEL 框架中的 RAG 组件 │
│ 根据文档内容,CAMEL 框架中的 RAG 技术涉及以下几个主要组件: │
│ │
│ - **CAMEL**:一个强大的多代理框架,支持 Retrieval-Augmented Generation │
│ 和多代理角色扮演场景,允许执行复杂的 AI 驱动任务。 │
│ - │
│ **Firecrawl**:一个强大的网络抓取工具,可简化从各种网页中提取和清理内容的过程。 │
│ - **Qdrant**:一种高效的向量存储系统,与 Camel 的 AutoRetriever │
│ 一起使用,根据向量相似性存储和检索相关信息。 │
│ - **BM25Retriever**:一种基于 BM25 算法的检索器,用于从文本中检索相关信息。 │
│ - **SentenceTransformerEncoder**:用于生成文本的向量表示,以便进行向量检索。 │
│ │
│ #### 3. RAG 的具体实现步骤 │
│ 以下是使用 CAMEL 框架实现 RAG 的具体步骤: │
│ │
│ ##### 3.1 设置 API 密钥 │
│ 首先,需要设置所需的 API 密钥,例如 AgentOps 和 Firecrawl 的 API 密钥: │
│ ```python │
│ import os │
│ from getpass import getpass │
│ │
│ # 输入 AgentOps API 密钥 │
│ agentops_api_key = getpass('请输入您的 API 密钥: ') │
│ os.environ["AGENTOPS_API_KEY"] = agentops_api_key │
│ │
│ # 输入 Firecrawl API 密钥 │
│ firecrawl_api_key = getpass('Enter your API key: ') │
│ os.environ["FIRECRAWL_API_KEY"] = firecrawl_api_key │
│ ``` │
│ │
│ ##### 3.2 使用 Firecrawl 抓取网页内容 │
│ 使用 Firecrawl 从指定的 URL 抓取并清理内容: │
│ ```python │
│ from camel.loaders import Firecrawl │
│ │
│ firecrawl = Firecrawl() │
│ │
│ # 从指定的 URL 抓取并清理内容 │
│ response = firecrawl.scrape(url="https://www.camel-ai.org/") │
│ ``` │
│ │
│ ##### 3.3 初始化检索器 │
│ 初始化向量检索器和 BM25 检索器: │
│ ```python │
│ from camel.embeddings import SentenceTransformerEncoder │
│ from camel.storage import QdrantStorage │
│ from camel.retrievers import VectorRetriever, BM25Retriever │
│ │
│ # 初始化嵌入模型 │
│ embedding_model = SentenceTransformerEncoder(model_name='intfloat/e5-large-v2') │
│ │
│ # 初始化向量存储 │
│ vector_storage = QdrantStorage( │
│ vector_dim=embedding_model.get_output_dim(), │
│ collection="demo_collection", │
│ path="storage_customized_run", │
│ collection_name="paper" │
│ ) │
│ │
│ # 初始化向量检索器 │
│ vr = VectorRetriever(embedding_model=embedding_model, storage=vector_storage) │
│ │
│ # 初始化 BM25 检索器 │
│ bm25r = BM25Retriever() │
│ ``` │
│ │
│ ##### 3.4 处理文档 │
│ 处理需要检索的文档内容: │
│ ```python │
│ content_path = "local_data/camel_paper.pdf" │
│ │
│ # 处理向量检索器的文档 │
│ vr.process(content=content_path) │
│ │
│ # 处理 BM25 检索器的文档 │
│ bm25r.process(content_input_path=content_path) │
│ ``` │
│ │
│ ##### 3.5 执行查询 │
│ 执行查询并获取检索结果: │
│ ```python │
│ query = "CAMEL 是 │
╰──────────────────────────────────────────────────────────────────────────────────╯
================================================================================
💾 是否保存结果到文件? [y/n] (n): n
🔄 是否继续查询? [y/n] (y): y

💭 请输入您的问题 (): 科普camel架构的功能和特性

🔍 选择检索模式
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 模式 ┃ 描述 ┃ 特点 ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1. 快速检索 │ 基础向量检索 │ 速度快,适合简单查询 │
│ 2. 深度检索 │ 查询重写+HyDE+RRF │ 准确度高,适合复杂查询 │
│ 3. 主题检索 │ PDF+网页综合分析 │ 信息全面,适合研究性查询 │
└──────────────┴───────────────────┴──────────────────────────┘
请选择检索模式 [1/2/3] (1): 3
⏳ 正在执行主题检索...
⏱ 开始监控: enhanced_query_主题检索

🔍 执行主题检索: 科普camel架构的功能和特性
============================================================
🌐 执行主题检索...
📄 步骤1: PDF文档检索
⏱ 开始监控: vector_query
✅ 检索到 5 个相关文档
✓ 操作完成: vector (耗时: 0.19s, 内存: 1275.8MB)
🔍 步骤2: 网页研究

开始网页研究: 科普camel架构的功能和特性
==================================================
使用DuckDuckGo搜索...
⚠ DuckDuckGo搜索失败: https://duckduckgo.com/?q=%E7%A7%91%E6%99%AEcamel%E6%9E%B6%E6%9E%84%E7%9A%84%E5%8A%9F%E8%83%BD%E5%92%8C%E7%89%B9%E6%80%A7 202 Ratelimit
使用备用搜索方法...
✓ 备用搜索完成,生成 3 个模拟结果
✓ 找到 3 个搜索结果
正在获取网页内容 1/3: 关于科普camel架构的功能和特性的学术资源...
✓ 成功获取内容 (706字符)
正在获取网页内容 2/3: 科普camel架构的功能和特性 - 维基百科...
✓ 成功获取内容 (3003字符)
正在获取网页内容 3/3: 科普camel架构的功能和特性技术文档...
⚠ 网页内容获取失败 (https://docs.example.com): HTTPSConnectionPool(host='docs.example.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1006)')))
⚠ 内容获取失败
✓ 网页研究完成,分析了 2 个网页
🧩 步骤3: 综合分析
API调用尝试 1/3
✓ API调用成功
✓ 操作完成: enhanced (耗时: 38.07s, 内存: 1307.3MB)

================================================================================
╭──────────────────────────────────── 查询信息 ────────────────────────────────────╮
│ 🔍 查询: 科普camel架构的功能和特性 │
│ 🔧 方法: 主题检索(PDF+网页) │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭────────────────────────────────── 💡 生成答案 ───────────────────────────────────╮
│ ### CAMEL 架构的功能和特性 │
│ │
│ **CAMEL(Customized Applications for Mobile network Enhanced Logic)** │
│ 是一种用于移动网络中实现定制化应用的逻辑框架。它允许运营商根据不同的业务需求,灵 │
│ 活地提供增值服务,如预付费服务、智能网服务等。以下是结合PDF文档和网页信息对CAMEL │
│ 架构功能和特性的详细介绍: │
│ │
│ #### 1. **灵活性和可扩展性** │
│ - **灵活性**:CAMEL │
│ 架构设计允许运营商根据市场和客户需求快速推出新的增值服务,无需对核心网络进行大规 │
│ 模改造。 │
│ - **可扩展性**:随着技术的发展和新业务的增加,CAMEL │
│ 架构能够轻松扩展,支持更多的服务和应用。 │
│ │
│ #### 2. **智能网服务** │
│ - **预付费服务**:CAMEL │
│ 支持预付费用户的服务管理,包括账户充值、余额查询、计费等。 │
│ - **个性化服务**:运营商可以通过CAMEL 提供个性化的服务,如铃声下载、彩信等。 │
│ - **位置服务**:CAMEL 可以支持基于用户位置的增值服务,如导航、天气预报等。 │
│ │
│ #### 3. **协作与知识共享** │
│ - **跨领域合作**:CAMEL │
│ 架构鼓励不同背景和技术领域的合作。例如,在PDF文档中提到的故事中,CAMEL(代表沙漠 │
│ 中的骆驼)和DataWhale(代表海洋中的鲸鱼)通过合作解开了古老的符号之谜,找到了知 │
│ 识的宝库。 │
│ - │
│ **知识共享**:通过合作,不同实体可以共享知识和资源,推动整体发展。这不仅限于技术 │
│ 领域,还包括文化、教育等多个方面。 │
│ │
│ #### 4. **技术实现** │
│ - **Agent 技术**:CAMEL 架构利用Agent技术来实现智能化的服务。Agent │
│ 可以自主地执行任务,如搜索信息、处理请求等。 │
│ - **前端与后端集成**:CAMEL │
│ 架构不仅提供了强大的后端模块,还配备了精美的前端界面,使得用户能够直观地体验和使 │
│ 用各种服务。例如,PDF文档中提到的“NavigatorAI │
│ 旅游”应用,就是一个典型的前后端集成示例。 │
│ │
│ #### 5. **可靠性和安全性** │
│ - **可靠性**:CAMEL │
│ 架构设计注重系统的稳定性和可靠性,确保服务的连续性和高质量。 │
│ - **安全性**:通过多种安全机制,CAMEL │
│ 架构保护用户数据和交易的安全,防止未经授权的访问和攻击。 │
│ │
│ #### 6. **创新与未来展望** │
│ - **创新**:CAMEL 架构不断推动技术创新,探索新的应用场景和服务模式。 │
│ - **未来展望**:随着5G和物联网技术的发展,CAMEL │
│ 架构将进一步拓展其应用范围,支持更多智能化和个性化的服务。 │
│ │
│ ### 总结 │
│ CAMEL │
│ 架构以其灵活性、可扩展性、智能网服务、协作与知识共享、技术实现、可靠性和安全性等 │
│ 多方面的优势,成为移动网络增值服务的重要支撑。通过不断的技术创新和跨领域的合作, │
│ CAMEL 架构将继续推动移动通信行业的发展,为用户提供更加丰富和便捷的服务。 │
╰──────────────────────────────────────────────────────────────────────────────────╯
================================================================================
💾 是否保存结果到文件? [y/n] (n): n
🔄 是否继续查询? [y/n] (y): n

============================================================
📊 最终性能报告
============================================================

============================================================
性能监控报告
============================================================
总操作数: 10
整体成功率: 100.0%
总耗时: 781.91秒
平均耗时: 78.19秒
平均内存使用: 797.1MB

操作详情:
------------------------------------------------------------
add:
调用次数: 1
成功率: 100.0%
平均耗时: 343.83秒
平均内存: 794.0MB

setup:
调用次数: 1
成功率: 100.0%
平均耗时: 356.98秒
平均内存: 794.0MB

vector:
调用次数: 6
成功率: 100.0%
平均耗时: 0.30秒
平均内存: 694.1MB

enhanced:
调用次数: 2
成功率: 100.0%
平均耗时: 39.65秒
平均内存: 1109.0MB

============================================================
💾 是否保存结果到文件? [y/n] (n): n
✅ 感谢使用增强的交互式多模态RAG系统!
PS G:\Python-Camel-project\Interactive_Multi_RAG>
fwd-i-search: _
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
PS G:\Python-Camel-project\Interactive_Multi_RAG> & D:/Download/Python/py-3.11.9/python.exe g:/Python-Camel-project/Interactive_Multi_RAG/Enhanced_Interactive_Multimodal_RAG.py
W0725 20:04:54.071000 28968 site-packages\torch\distributed\elastic\multiprocessing\redirects.py:29] NOTE: Redirects are currently not supported in Windows or MacOs.
✓ 使用Rich增强界面
╭─────────────────────────────────────────── 🎯 系统启动 ───────────────────────────────────────────╮
│ │
│ │
│ 🤖 交互式多模态RAG系统 v2.0 │
│ │
│ ✨ 新功能特性: │
│ • 🔧 增强的CAMEL框架集成和稳定性改进 │
│ • 🖼️ 改进的多模态支持 (图像OCR + 表格提取) │
│ • 🌐 真实网页研究和内容分析 │

│ • ⚡ 性能监控和优化 │
│ • 🎨 增强的用户界面体验 │
│ │
│ 🚀 支持的检索模式: │
│ • 快速检索: 基础向量检索 │
│ • 深度检索: 查询重写 + HyDE + RRF融合 │
│ • 主题检索: PDF + 网页内容综合分析 │
│ │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
🚀 正在初始化增强RAG系统...
性能监控器初始化 (详细监控: 开启)
🚀 初始化增强RAG系统...
正在初始化CAMEL模型...
CAMEL模型测试失败: 'BaseMessage' object has no attribute 'get'...
⚠ CAMEL模型初始化成功但测试失败,将使用直接API调用
✅ 嵌入模型加载成功
✅ 增强向量检索器初始化完成
✅ 增强文档管理器初始化完成
📁 缓存目录: document_cache
📋 支持格式: ['.pdf', '.docx', '.doc', '.txt', '.md', '.csv', '.xlsx', '.xls', '.pptx', '.ppt', '.json', '.xml', '.html', '.rtf']
多模态处理器初始化:
图像OCR: ✓
表格处理: ✓
PyMuPDF: ✓
网页研究系统初始化:
BeautifulSoup4: ✓
DuckDuckGo搜索: ✓
✅ 增强RAG系统初始化完成!
✅ 增强RAG系统初始化成功!
🔧 系统状态
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 组件 ┃ 状态 ┃ 详情 ┃
┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ LLM接口 │ ✅ 正常 │ │
│ 嵌入模型 │ ✅ 正常 │ intfloat/e5-large-v2 │
│ 文档管理 │ ✅ 正常 │ │
│ 多模态处理 │ ✅ 正常 │ OCR: True, 表格: True │
│ 网页研究 │ ✅ 正常 │ │
│ 知识库 │ ✅ 正常 │ │
│ 性能监控 │ ✅ 正常 │ │
└──────────────────────┴─────────────────┴───────────────────────┘

📚 文档知识库设置
┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 选项 ┃ 描述 ┃
┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1 │ 在线文档 (输入URL) │
│ 2 │ 本地文档 (输入文件路径) │
│ 3 │ 批量本地文档 (输入目录路径) │
│ 4 │ 使用默认示例PDF │
└──────────┴─────────────────────────────┘

请选择文档来源 [1/2/3/4] (4): 2
请输入文档文件路径 (回车结束): G:\Program for work\Other\CamelAgent.pdf
请输入文档文件路径 (回车结束):
⏳ 正在加载 1 个文档...
⏱ 开始监控: setup_knowledge_base
📚 正在设置知识库...
文档数量: 1
来源类型: path

📄 处理文档: G:\Program for work\Other\CamelAgent.pdf
📄 处理文档: G:\Program for work\Other\CamelAgent.pdf
⚡ 使用缓存数据
✅ 文档处理完成: 271 个块

⏳ 正在构建向量索引...
⏱ 开始监控: add_documents
⏳ 正在计算 271 个文档的嵌入向量...
✅ 成功添加 271 个文档到检索器
✓ 操作完成: add (耗时: 92.37s, 内存: 2280.5MB)

✅ 知识库设置完成!
处理文档数: 1
总文档块数: 271
内容统计: 文本(209) 图像(58) 表格(4) 其他(0)
缓存统计: 1 个文档, 0.4MB
✓ 操作完成: setup (耗时: 92.39s, 内存: 2280.5MB)
✅ 知识库设置完成!

💭 请输入您的问题 (): 详细说明camel框架roleplaying的特点以及使用场景

🔍 选择检索模式
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 模式 ┃ 描述 ┃ 特点 ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1. 快速检索 │ 基础向量检索 │ 速度快,适合简单查询 │
│ 2. 深度检索 │ 查询重写+HyDE+RRF │ 准确度高,适合复杂查询 │
│ 3. 主题检索 │ PDF+网页综合分析 │ 信息全面,适合研究性查询 │
└──────────────┴───────────────────┴──────────────────────────┘
请选择检索模式 [1/2/3] (1): 2
⏳ 正在执行深度检索...
⏱ 开始监控: enhanced_query_深度检索

🔍 执行深度检索: 详细说明camel框架roleplaying的特点以及使用场景
============================================================
🔬 执行深度检索...
📝 步骤1: 查询重写
API调用尝试 1/3
✓ API调用成功
🧠 步骤2: HyDE假设文档生成
API调用尝试 1/3
✓ API调用成功
🔍 步骤3: 多路检索
⏱ 开始监控: vector_query
✅ 检索到 5 个相关文档
✓ 操作完成: vector (耗时: 0.16s, 内存: 1775.6MB)
⏱ 开始监控: vector_query
✅ 检索到 5 个相关文档
✓ 操作完成: vector (耗时: 0.08s, 内存: 1784.3MB)
⏱ 开始监控: vector_query
✅ 检索到 5 个相关文档
✓ 操作完成: vector (耗时: 0.48s, 内存: 1807.9MB)
⏱ 开始监控: vector_query
✅ 检索到 0 个相关文档
✓ 操作完成: vector (耗时: 0.06s, 内存: 1806.8MB)
⏱ 开始监控: vector_query
✅ 检索到 0 个相关文档
✓ 操作完成: vector (耗时: 0.06s, 内存: 1806.4MB)
🔀 步骤4: RRF结果融合
💡 步骤5: 生成最终答案
API调用尝试 1/3
✓ API调用成功
✓ 操作完成: enhanced (耗时: 52.06s, 内存: 1815.8MB)

================================================================================
╭──────────────────────────────────────────── 查询信息 ─────────────────────────────────────────────╮
│ 🔍 查询: 详细说明camel框架roleplaying的特点以及使用场景 │
│ 🔧 方法: 深度检索(重写+HyDE+RRF) │
│ 📝 重写: 详细描述Apache Camel框架中角色扮演功能的特性及其应用场景 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯

📄 检索到的文档 (共12个):
╭───────────────────────────────────────────── 文档 1 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0320 │
│ 内容预览: │
│ 在调用工具时,CAMEL 框架会将每一次FunctionCall 都记录下来,方便我们后续查看、验 │
│ 证。 │
│ 8. 第二章课程作业 │
│ Task1 │
│ • │
│ 现在来布置一些作业,帮助你利用 CAMEL 的 Prompt 功能进行练习: │
│ 1. 角色扮演任务Agent:使用 AISocietyPromptTemplateDict,创建一个角色扮演任务 │
│ Agent。假设你想让 AI 扮演一个“健康顾问”... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 2 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0315 │
│ 内容预览: 和结构化对话机制,实现智能体之间的有效协作。 │
│ 在CAMEL 框架中,ChatAgent 是最基础的智能体单元,负责处理对话逻辑和任务执行。而 │
│ RolePlaying 和Workforce 则是多智能体系统,用于协调多个智能体的协作。 │
│ 详见我们的开源仓库和项目主页 │
│ • │
│ 论文:https://ghli.org/camel.pdf │
│ • │
│ 项目主页:https://www.camel-ai.o... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 3 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0313 │
│ 内容预览: DataWhale 和 CAMEL 之间的关系是合作和知识共享。尽管它们生活在不同的环境中—— │
│ CAMEL 生活在沙漠,而 DataWhale 生活在海洋,但它们都发现了神秘的古代文物,分别是 │
│ 古代石板和古老羊皮纸。通过一只信使鸟的帮助,它们了解到对方的发现并决定合作解开这 │
│ 些文物的秘密。CAMEL 跨越沙漠来到海洋边缘,而 DataWhale 也游到岸边与 CAMEL 会 │
│ 合。最终,它们共同努力... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 4 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0164 │
│ 内容预览: 如果你无法回答问题就说我不知道。 │
│ """ │
│ │
│ model = ModelFactory.create( │
│ model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL, │
│ model_type="Qwen/Qwen2.5-72B-Instruct", │
│ url='https://api-infe... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 5 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0164 │
│ 内容预览: 通过一只飞翔在天空中的信使鸟,CAMEL 和DataWhale 得知彼此的发现,并决定合作解开 │
│ 这个谜团。骆驼踏上了漫长的旅程,穿越沙漠来到了海洋边缘,而鲸鱼则游到岸边,与CAMEL │
│ 会合。 │
│ │
│ 在一起研究这些古老的符号时,CAMEL 运用了它在沙漠中磨炼出的耐心和智慧,而 │
│ DataWhale 则利用它在海洋中获得的知识和洞察力。经过一番努力,它们终于解读出这些符 │
│ 号的含义。原来,这些符号描绘的... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 6 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0161 │
│ 内容预览: │
│ 2. 使用API 调用模型 │
│ 类 Unix 系统(Linux / macOS) │
│ 在终端执行: │
│ export MODELSCOPE_SDK_TOKEN="你的ModelScope 令牌" │
│ Windows 系统 │
│ 命令提示符(CMD): │
│ set MODELSCOPE_SDK_TOKEN="你的ModelScope 令牌" │
│ PowerShell: │
│ $env:MODELSCOP... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 7 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0161 │
│ 内容预览: │
│ 观察到文案风格确实更加活泼,且红圈部分正确修改成了中南海和配图也十分吻合。 │
│ 6. 搭配前端食用 │
│ 综合案例中为了尽可能让大家直观的感受到基于CAMEL 框架的Agent 产品开发的乐趣,我 │
│ 们还为大家准备了精美的前端,搭配之前的几个后端模块一起构成我们的NavigatorAI 旅游 │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 8 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0161 │
│ 内容预览: │
│ 此外,还有其他一些研究和项目也在探索如何利用LLMs 构建多智能体系统,比如通过模拟 │
│ 社会动态、协作解决问题等。这些工作都在不同程度上推动了 │
│ 该领域的进步。 │
│ │
│ 如果您有更具体的时间范围或其他标准来定义“第一个”,请提供更多信息,这样我可以尝试 │
│ 给出更加准确的答案。" │
│ 之后我们将之前设定的memory 赋值给agent: │
│ # 将memory 赋值给agent │
│ agent.memory... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 9 ──────────────────────────────────────────────╮
│ 相关度分数: 0.0159 │
│ 内容预览: 2. 信息检索:支持根据特定查询或上下文快速检索相关信息,帮助agent 在需要时做 │
│ 出准确的判断。 │
│ 3. 记忆更新:能够根据新的信息和经验动态更新存储内容,以反映环境或任务的变化。 │
│ 4. 记忆管理:包括老化机制和优先级管理,确保较重要的信息能够长期保留,而不再 │
│ 需要的信息可以被有效清除,以优化存储资源的使用。 │
│ CAMEL 中的Memory 模块提供了一个灵活的系统,用于存储、检索和管理 A... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 10 ─────────────────────────────────────────────╮
│ 相关度分数: 0.0156 │
│ 内容预览: │
│ 可以看到对于自己不了解或者不确定的内容,Agent 系统会主动去用搜索工具搜索相应的信 │
│ 息,有的小伙伴可能会有疑问啦,我们怎么确定Agent 系统是否真的是调用了搜索工具去找 │
│ 寻了对应的内容才给出的回答还是出现了幻觉呢,麻烦一点的办法就是我们去搜索一下对应 │
│ 的query,看一下是不是真的是模型输出的那样: │
│ │
│ 可以发现Google 搜索的内容显示结果正如模型输出的那样:牛津大学真的没有确切的... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 11 ─────────────────────────────────────────────╮
│ 相关度分数: 0.0154 │
│ 内容预览: from camel.utils import print_text_animated │
│ from camel.models import ModelFactory │
│ from camel.types import ModelPlatformType │
│ │
│ from dotenv import load_dotenv │
│ │
│ import os │
│ │
│ load_dotenv(dotenv_path=... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 12 ─────────────────────────────────────────────╮
│ 相关度分数: 0.0154 │
│ 内容预览: │
│ 作业二:通过系统性的学习相信你已经了解了如何去构建属于你的Agent 和多Agent 系统, │
│ 请回顾整体的内容并思考,我们可以在哪些方面进一步优化多智能体系统,将你的想法提交 │
│ 到CAMEL 仓库的issue 列表中,并参考贡献者指南提交你的代码来进行优化。 │
│ │
│ 结语 │
│ 恭喜您!在阅读到这里时,您已经掌握了 CAMEL-AI 应用开发框架的基础知识,并能够利 │
│ 用 Agent 实例在您的代码逻辑... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────────────────── 💡 生成答案 ───────────────────────────────────────────╮
│ ### CAMEL 框架 RolePlaying 特点及使用场景 │
│ │
│ #### 一、RolePlaying 特点 │
│ │
│ 1. **角色定义** │
│ - **Assistant 角色**:负责执行具体任务并提供解决方案的智能体。 │
│ - **User 角色**:负责提供指令和任务需求的智能体。 │
│ - **特定领域角色**:如程序员、交易员等专业角色,可以根据具体任务需求设定不同的角色。 │
│ │
│ 2. **交互规则** │
│ - │
│ **角色固定**:防止角色翻转,维持对话的稳定性。每个智能体都有明确的角色定位,确保不会混淆角色身份 │
│ 。 │
│ - **格式规范**:要求回复具有固定的开始和结束格式,例如: │
│ ```plaintext │
│ Solution: <YOUR_SOLUTION> │
│ Next request. │
│ ``` │
│ - │
│ **预定义的提示词**:通过预定义的提示词为不同的智能体创建唯一的初始设置,帮助智能体克服角色翻转、 │
│ 助手重复指令、模糊回复、消息无限循环以及对话终止条件等挑战。例如: │
│ ```python │
│ system_message = """ │
│ ===== RULES OF ASSISTANT ===== │
│ 1. Never forget you are a {ASSISTANT_ROLE} and I am a {USER_ROLE} │
│ 2. Never flip roles! Never instruct me! │
│ 3. You must decline my instruction honestly if you cannot perform it │
│ 4. Always start with: Solution: <YOUR_SOLUTION> │
│ 5. Always end with: Next request. │
│ """ │
│ ``` │
│ │
│ 3. **关键机制** │
│ - **角色固定**:确保每个智能体在对话过程中保持其角色身份,避免混淆。 │
│ - **格式规范**:确保回复的格式一致,便于用户理解和后续处理。 │
│ - **启发式提示**:通过预定义的提示词引导智能体完成任务,同时保持与人类意图的一致性。 │
│ │
│ #### 二、使用场景 │
│ │
│ 1. **教育与培训** │
│ - │
│ **角色扮演任务**:例如,创建一个健康顾问角色,为用户提供饮食和锻炼建议。通过思维链方式逐步提供健 │
│ 康方案。 │
│ - **代码生成任务**:利用 CodePromptTemplateDict 创建一个任务 │
│ Agent,帮助用户学习新的编程语言,逐步生成学习计划,包括基本概念、代码示例和练习题目。 │
│ │
│ 2. **客户服务** │
│ - **虚拟助手**:创建不同领域的虚拟助手,如技术支持、销售咨询等,提供专业的解答和服务。 │
│ - **客户互动**:通过角色扮演机制,模拟客户与服务人员的对话,提高服务质量。 │
│ │
│ 3. **多智能体协作** │
│ - │
│ **复杂任务处理**:在多智能体系统中,通过角色扮演机制协调多个智能体的协作,完成复杂的任务。例如, │
│ 交通管理、分布式机器人系统、经济市场模拟等。 │
│ - **团队合作**:模拟团队成员之间的互动,提高团队协作效率。 │
│ │
│ 4. **研究与开发** │
│ - │
│ **对话数据生成**:利用角色扮演生成对话数据,用于研究代理社会的行为和能力,为调查对话语言模型提供 │
│ 宝贵的资源。 │
│ - **行为分析**:通过角色扮演模拟不同情境下的对话,分析智能体的行为和决策过程。 │
│ │
│ #### 三、总结 │
│ │
│ CAMEL 框架的 RolePlaying │
│ 机制通过角色定义、交互规则和关键机制,确保智能体在对话过程中保持角色一致性,提供高质量的回复。这 │
│ 一机制广泛应用于教育、客户服务、多智能体协作和研究开发等多个领域,为实现复杂任务提供了有力支持。 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
================================================================================
💾 是否保存结果到文件? [y/n] (n): n
🔄 是否继续查询? [y/n] (y): y

💭 请输入您的问题 (): 详细说明camel框架roleplaying的特点以及使用场景

🔍 选择检索模式
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 模式 ┃ 描述 ┃ 特点 ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1. 快速检索 │ 基础向量检索 │ 速度快,适合简单查询 │
│ 2. 深度检索 │ 查询重写+HyDE+RRF │ 准确度高,适合复杂查询 │
│ 3. 主题检索 │ PDF+网页综合分析 │ 信息全面,适合研究性查询 │
└──────────────┴───────────────────┴──────────────────────────┘
请选择检索模式 [1/2/3] (1): 3
⏳ 正在执行主题检索...
⏱ 开始监控: enhanced_query_主题检索

🔍 执行主题检索: 详细说明camel框架roleplaying的特点以及使用场景
============================================================
🌐 执行主题检索...
📄 步骤1: PDF文档检索
⏱ 开始监控: vector_query
✅ 检索到 5 个相关文档
✓ 操作完成: vector (耗时: 0.08s, 内存: 1879.9MB)
🔍 步骤2: 网页研究

开始网页研究: 详细说明camel框架roleplaying的特点以及使用场景
==================================================
使用DuckDuckGo搜索...
⚠ DuckDuckGo搜索失败: https://duckduckgo.com/?q=%E8%AF%A6%E7%BB%86%E8%AF%B4%E6%98%8Ecamel%E6%A1%86%E6%9E%B6roleplaying%E7%9A%84%E7%89%B9%E7%82%B9%E4%BB%A5%E5%8F%8A%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF 202 Ratelimit
使用备用搜索方法...
✓ 备用搜索完成,生成 3 个模拟结果
✓ 找到 3 个搜索结果
正在获取网页内容 1/3: 关于详细说明camel框架roleplaying的特点以及使用场景的学术资源...
✓ 成功获取内容 (706字符)
正在获取网页内容 2/3: 详细说明camel框架roleplaying的特点以及使用场景 - 维基百科...
✓ 成功获取内容 (3003字符)
正在获取网页内容 3/3: 详细说明camel框架roleplaying的特点以及使用场景技术文档...
⚠ 网页内容获取失败 (https://docs.example.com): HTTPSConnectionPool(host='docs.example.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1006)')))
⚠ 内容获取失败
✓ 网页研究完成,分析了 2 个网页
🧩 步骤3: 综合分析
API调用尝试 1/3
✓ API调用成功
✓ 操作完成: enhanced (耗时: 34.56s, 内存: 1867.2MB)

================================================================================
╭──────────────────────────────────────────── 查询信息 ─────────────────────────────────────────────╮
│ 🔍 查询: 详细说明camel框架roleplaying的特点以及使用场景 │
│ 🔧 方法: 主题检索(PDF+网页) │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────────────────── 💡 生成答案 ───────────────────────────────────────────╮
│ **CAMEL框架中的RolePlaying机制详解及其应用场景** │
│ │
│ ### 特点 │
│ │
│ 1. **角色扮演(Role-Playing)**: │
│ - │
│ **角色定义**:CAMEL框架中的RolePlaying机制允许为不同的智能体(Agent)定义独特的角色,如“健康顾问” │
│ 、“股票交易员”等。每个角色都有明确的目标和行为准则,确保智能体在交互中保持角色一致性。 │
│ - **角色固定**:防止智能体在对话中角色翻转,确保对话的稳定性和连贯性。 │
│ │
│ 2. **交互规则**: │
│ - **系统消息**:通过预定义的系统消息(System │
│ Message),为智能体设定交互规则。例如,智能体必须始终记得自己的角色,不得指令用户,如果无法执行任 │
│ 务则应诚实地拒绝。 │
│ - **格式规范**:要求智能体的回复具有固定的开始和结束格式,如“Solution: <YOUR_SOLUTION>”和“Next │
│ request.”,确保对话的结构化和清晰度。 │
│ │
│ 3. **大语言模型(LLMs)**: │
│ - │
│ **认知增强**:每个智能体都使用大语言模型来增强其认知能力,使其能够理解和生成自然语言,从而有效地 │
│ 解释指令、生成响应并参与复杂对话。 │
│ │
│ 4. **记忆(Memory)**: │
│ - **上下文记忆**:智能体能够记住对话的历史,以便在对话中做出更合理的回应。 │
│ - **外部记忆**:智能体还可以访问外部知识库,以获取更多背景信息和支持。 │
│ │
│ 5. **工具(Tools)**: │
│ - │
│ **具身化能力**:智能体可以使用一系列工具与外部世界交互,如调用API、查询数据库等,这些工具增强了智 │
│ 能体的实用性和灵活性。 │
│ │
│ 6. **通信(Communication)**: │
│ - │
│ **灵活通信**:CAMEL框架支持智能体之间的灵活通信,允许它们在多智能体系统中进行协作或竞争,以实现更 │
│ 复杂的行为和决策。 │
│ │
│ 7. **推理(Reasoning)**: │
│ - **规划与学习**:智能体具备规划能力和奖励学习机制,能够优化任务完成的过程,提高效率和效果。 │
│ │
│ ### 应用场景 │
│ │
│ 1. **教育与培训**: │
│ - │
│ **个性化教学**:通过角色扮演,智能体可以根据学生的需求提供个性化的教学内容,如逐步生成编程学习计 │
│ 划,包括基本概念、代码示例和练习题目。 │
│ - **模拟训练**:在医疗、军事等领域,智能体可以模拟专家或对手,为学员提供真实的训练环境。 │
│ │
│ 2. **客户服务**: │
│ - **虚拟助手**:智能体可以扮演客服代表,为用户提供产品咨询、技术支持等服务,提升客户体验。 │
│ - **情感支持**:智能体可以扮演心理顾问,为用户提供情感支持和心理健康建议。 │
│ │
│ 3. **金融与交易**: │
│ - **交易机器人**:智能体可以开发为交易机器人,协助用户进行股票市场分析和交易决策。 │
│ - **风险管理**:智能体可以通过角色扮演模拟不同的市场情景,帮助用户评估和管理投资风险。 │
│ │
│ 4. **娱乐与游戏**: │
│ - **互动故事**:智能体可以参与创造互动故事,与用户进行动态对话,提供沉浸式的娱乐体验。 │
│ - **多人游戏**:在多人在线游戏中,智能体可以扮演NPC(非玩家角色),增加游戏的真实感和趣味性。 │
│ │
│ 5. **科研与实验**: │
│ - │
│ **社会行为研究**:通过角色扮演生成对话数据,研究社会行为和群体动态,为社会科学提供宝贵的数据资源 │
│ 。 │
│ - **技术验证**:智能体可以在模拟环境中验证新技术的效果,如自动驾驶算法、机器人协作等。 │
│ │
│ ### 总结 │
│ │
│ CAMEL框架的RolePlaying机制通过角色定义、交互规则、大语言模型、记忆、 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
================================================================================
💾 是否保存结果到文件? [y/n] (n): n
🔄 是否继续查询? [y/n] (y): y

💭 请输入您的问题 (): 详细说明camel框架roleplaying的特点以及使用场景

🔍 选择检索模式
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 模式 ┃ 描述 ┃ 特点 ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1. 快速检索 │ 基础向量检索 │ 速度快,适合简单查询 │
│ 2. 深度检索 │ 查询重写+HyDE+RRF │ 准确度高,适合复杂查询 │
│ 3. 主题检索 │ PDF+网页综合分析 │ 信息全面,适合研究性查询 │
└──────────────┴───────────────────┴──────────────────────────┘
请选择检索模式 [1/2/3] (1): 1
⏳ 正在执行快速检索...
⏱ 开始监控: enhanced_query_快速检索

🔍 执行快速检索: 详细说明camel框架roleplaying的特点以及使用场景
============================================================
⚡ 执行快速检索...
⏱ 开始监控: vector_query
✅ 检索到 3 个相关文档
✓ 操作完成: vector (耗时: 0.07s, 内存: 1864.9MB)
API调用尝试 1/3
✓ API调用成功
✓ 操作完成: enhanced (耗时: 11.97s, 内存: 1860.7MB)

================================================================================
╭──────────────────────────────────────────── 查询信息 ─────────────────────────────────────────────╮
│ 🔍 查询: 详细说明camel框架roleplaying的特点以及使用场景 │
│ 🔧 方法: 快速检索 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯

📄 检索到的文档 (共3个):
╭───────────────────────────────────────────── 文档 1 ──────────────────────────────────────────────╮
│ 相关度分数: 0.8732 │
│ 内容预览: 如果你无法回答问题就说我不知道。 │
│ """ │
│ │
│ model = ModelFactory.create( │
│ model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL, │
│ model_type="Qwen/Qwen2.5-72B-Instruct", │
│ url='https://api-infe... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 2 ──────────────────────────────────────────────╮
│ 相关度分数: 0.8648 │
│ 内容预览: │
│ 2. 使用API 调用模型 │
│ 类 Unix 系统(Linux / macOS) │
│ 在终端执行: │
│ export MODELSCOPE_SDK_TOKEN="你的ModelScope 令牌" │
│ Windows 系统 │
│ 命令提示符(CMD): │
│ set MODELSCOPE_SDK_TOKEN="你的ModelScope 令牌" │
│ PowerShell: │
│ $env:MODELSCOP... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── 文档 3 ──────────────────────────────────────────────╮
│ 相关度分数: 0.8580 │
│ 内容预览: 和结构化对话机制,实现智能体之间的有效协作。 │
│ 在CAMEL 框架中,ChatAgent 是最基础的智能体单元,负责处理对话逻辑和任务执行。而 │
│ RolePlaying 和Workforce 则是多智能体系统,用于协调多个智能体的协作。 │
│ 详见我们的开源仓库和项目主页 │
│ • │
│ 论文:https://ghli.org/camel.pdf │
│ • │
│ 项目主页:https://www.camel-ai.o... │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────────────────── 💡 生成答案 ───────────────────────────────────────────╮
│ **Camel框架RolePlaying的特点:** │
│ │
│ 1. │
│ **角色定义明确**:RolePlaying机制中,每个智能体都有明确的角色定义,如Assistant(执行任务)、User │
│ (提供指令)及特定领域的专家角色(如程序员、交易员等),确保智能体在对话中扮演合适的角色。 │
│ 2. │
│ **防止角色翻转**:通过预设的规则和提示词,智能体被设计为不会忘记自己的角色身份,避免了角色间的混 │
│ 淆,保证了对话的连贯性和逻辑性。 │
│ 3. │
│ **固定格式的回复**:为了提高交流的效率和清晰度,智能体的回复被要求采用固定的格式,例如以“Solution │
│ :”开头,“Next request.”结尾,使得用户能够快速理解智能体的回应。 │
│ 4. │
│ **解决常见问题**:RolePlaying机制还解决了智能体间可能遇到的其他问题,如助手重复指令、产生模糊回复 │
│ 、消息无限循环以及对话过早或不当终止等问题。 │
│ │
│ **使用场景:** │
│ │
│ 1. │
│ **多智能体协作**:在需要多个智能体协同工作的场景中,RolePlaying可以帮助这些智能体有效地分工合作, │
│ 比如在虚拟团队中模拟不同角色进行项目管理。 │
│ 2. │
│ **教育和培训**:在教育领域,RolePlaying可以用于创建模拟情景,让学生或员工在其中扮演特定角色,通过 │
│ 互动学习解决问题的方法和技巧。 │
│ 3. │
│ **客户服务**:在客服行业中,RolePlaying可以用来模拟客户与服务代表之间的对话,提高服务人员的应对能 │
│ 力和沟通技巧。 │
│ 4. │
│ **研究和开发**:对于研究对话系统和多智能体系统的学者和开发者,RolePlaying提供了一个强大的工具,用 │
│ 于测试和改进算法,研究智能体的社会行为和交互模式。 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
================================================================================
💾 是否保存结果到文件? [y/n] (n): n
🔄 是否继续查询? [y/n] (y): n

============================================================
📊 最终性能报告
============================================================

============================================================
性能监控报告
============================================================
总操作数: 12
整体成功率: 100.0%
总耗时: 284.34秒
平均耗时: 23.69秒
平均内存使用: 1902.5MB

操作详情:
------------------------------------------------------------
add:
调用次数: 1
成功率: 100.0%
平均耗时: 92.37秒
平均内存: 2280.5MB

setup:
调用次数: 1
成功率: 100.0%
平均耗时: 92.39秒
平均内存: 2280.5MB

vector:
调用次数: 7
成功率: 100.0%
平均耗时: 0.14秒
平均内存: 1818.0MB

enhanced:
调用次数: 3
成功率: 100.0%
平均耗时: 32.87秒
平均内存: 1847.9MB

============================================================
💾 是否保存结果到文件? [y/n] (n): n
✅ 感谢使用增强的交互式多模态RAG系统!