feat(知识库): 在生成描述时支持传入文件列表
在知识库描述生成功能中增加文件列表参数,使AI能参考文件内容生成更准确的描述 前端组件传递文件列表至API,后端处理时将其包含在提示词中
This commit is contained in:
parent
6a94b0626c
commit
fffe237780
@ -1284,6 +1284,7 @@ async def get_all_embedding_models_status(current_user: User = Depends(get_admin
|
|||||||
async def generate_description(
|
async def generate_description(
|
||||||
name: str = Body(..., description="知识库名称"),
|
name: str = Body(..., description="知识库名称"),
|
||||||
current_description: str = Body("", description="当前描述(可选,用于优化)"),
|
current_description: str = Body("", description="当前描述(可选,用于优化)"),
|
||||||
|
file_list: list[str] = Body([], description="文件列表"),
|
||||||
current_user: User = Depends(get_admin_user),
|
current_user: User = Depends(get_admin_user),
|
||||||
):
|
):
|
||||||
"""使用 LLM 生成或优化知识库描述
|
"""使用 LLM 生成或优化知识库描述
|
||||||
@ -1292,40 +1293,35 @@ async def generate_description(
|
|||||||
"""
|
"""
|
||||||
from src.models import select_model
|
from src.models import select_model
|
||||||
|
|
||||||
logger.debug(f"Generating description for knowledge base: {name}")
|
logger.debug(f"Generating description for knowledge base: {name}, files: {len(file_list)}")
|
||||||
|
|
||||||
|
# 构建文件列表文本
|
||||||
|
if file_list:
|
||||||
|
# 限制文件数量,避免 prompt 过长
|
||||||
|
display_files = file_list[:50]
|
||||||
|
files_str = "\n".join([f"- {f}" for f in display_files])
|
||||||
|
more_text = f"\n... (还有 {len(file_list) - 50} 个文件)" if len(file_list) > 50 else ""
|
||||||
|
current_description += f"\n\n知识库包含的文件:\n{files_str}{more_text}"
|
||||||
|
|
||||||
|
current_description = current_description or "暂无描述"
|
||||||
|
|
||||||
# 构建提示词
|
# 构建提示词
|
||||||
if current_description.strip():
|
prompt = textwrap.dedent(f"""
|
||||||
prompt = textwrap.dedent(f"""
|
请帮我优化以下知识库的描述。
|
||||||
请帮我优化以下知识库的描述。
|
|
||||||
|
|
||||||
知识库名称: {name}
|
知识库名称: {name}
|
||||||
当前描述: {current_description}
|
当前描述: {current_description}
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
1. 这个描述将作为智能体工具的描述使用
|
1. 这个描述将作为智能体工具的描述使用
|
||||||
2. 智能体会根据知识库的标题和描述来选择合适的工具
|
2. 智能体会根据知识库的标题和描述来选择合适的工具
|
||||||
3. 所以描述需要清晰、具体,说明该知识库包含什么内容、适合解答什么类型的问题
|
3. 所以描述需要清晰、具体,说明该知识库包含什么内容、适合解答什么类型的问题
|
||||||
4. 描述应该简洁有力,通常 2-4 句话即可
|
4. 描述应该简洁有力,通常 2-4 句话即可
|
||||||
5. 不要使用 Markdown 格式
|
5. 不要使用 Markdown 格式
|
||||||
|
{"6. 请参考提供的文件列表来准确概括知识库内容" if file_list else ""}
|
||||||
|
|
||||||
请直接输出优化后的描述,不要有任何前缀说明。
|
请直接输出优化后的描述,不要有任何前缀说明。
|
||||||
""").strip()
|
""").strip()
|
||||||
else:
|
|
||||||
prompt = textwrap.dedent(f"""
|
|
||||||
请为以下知识库生成一个描述。
|
|
||||||
|
|
||||||
知识库名称: {name}
|
|
||||||
|
|
||||||
要求:
|
|
||||||
1. 这个描述将作为智能体工具的描述使用
|
|
||||||
2. 智能体会根据知识库的标题和描述来选择合适的工具
|
|
||||||
3. 所以描述需要清晰、具体,说明该知识库可能包含什么内容、适合解答什么类型的问题
|
|
||||||
4. 描述应该简洁有力,通常 2-4 句话即可
|
|
||||||
5. 不要使用 Markdown 格式
|
|
||||||
|
|
||||||
请直接输出描述,不要有任何前缀说明。
|
|
||||||
""").strip()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
model = select_model()
|
model = select_model()
|
||||||
|
|||||||
@ -102,6 +102,7 @@ class UploadGraphService:
|
|||||||
async with minio_client.temp_file_from_url(
|
async with minio_client.temp_file_from_url(
|
||||||
file_path, allowed_extensions=[".jsonl"]
|
file_path, allowed_extensions=[".jsonl"]
|
||||||
) as actual_file_path:
|
) as actual_file_path:
|
||||||
|
|
||||||
def read_triples(file_path):
|
def read_triples(file_path):
|
||||||
with open(file_path, encoding="utf-8") as file:
|
with open(file_path, encoding="utf-8") as file:
|
||||||
for line in file:
|
for line in file:
|
||||||
@ -114,9 +115,7 @@ class UploadGraphService:
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
# 本地文件路径 - 拒绝不安全的本地路径
|
# 本地文件路径 - 拒绝不安全的本地路径
|
||||||
raise ValueError(
|
raise ValueError("不支持本地文件路径,只允许 MinIO URL。请先通过文件上传接口上传文件。")
|
||||||
"不支持本地文件路径,只允许 MinIO URL。请先通过文件上传接口上传文件。"
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"处理文件失败: {e}")
|
logger.error(f"处理文件失败: {e}")
|
||||||
|
|||||||
@ -59,12 +59,14 @@ export const databaseApi = {
|
|||||||
* 使用 AI 生成或优化知识库描述
|
* 使用 AI 生成或优化知识库描述
|
||||||
* @param {string} name - 知识库名称
|
* @param {string} name - 知识库名称
|
||||||
* @param {string} currentDescription - 当前描述(可选)
|
* @param {string} currentDescription - 当前描述(可选)
|
||||||
|
* @param {Array} fileList - 文件列表(可选)
|
||||||
* @returns {Promise} - 生成结果
|
* @returns {Promise} - 生成结果
|
||||||
*/
|
*/
|
||||||
generateDescription: async (name, currentDescription = '') => {
|
generateDescription: async (name, currentDescription = '', fileList = []) => {
|
||||||
return apiAdminPost('/api/knowledge/generate-description', {
|
return apiAdminPost('/api/knowledge/generate-description', {
|
||||||
name,
|
name,
|
||||||
current_description: currentDescription
|
current_description: currentDescription,
|
||||||
|
file_list: fileList
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,10 @@ const props = defineProps({
|
|||||||
autoSize: {
|
autoSize: {
|
||||||
type: [Boolean, Object],
|
type: [Boolean, Object],
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -65,7 +69,7 @@ const generateDescription = async () => {
|
|||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const result = await databaseApi.generateDescription(props.name, props.modelValue)
|
const result = await databaseApi.generateDescription(props.name, props.modelValue, props.files)
|
||||||
if (result.status === 'success' && result.description) {
|
if (result.status === 'success' && result.description) {
|
||||||
emit('update:modelValue', result.description)
|
emit('update:modelValue', result.description)
|
||||||
message.success('描述生成成功')
|
message.success('描述生成成功')
|
||||||
|
|||||||
@ -77,6 +77,7 @@
|
|||||||
<AiTextarea
|
<AiTextarea
|
||||||
v-model="editForm.description"
|
v-model="editForm.description"
|
||||||
:name="editForm.name"
|
:name="editForm.name"
|
||||||
|
:files="fileList"
|
||||||
placeholder="请输入知识库描述"
|
placeholder="请输入知识库描述"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
/>
|
/>
|
||||||
@ -120,6 +121,11 @@ const store = useDatabaseStore();
|
|||||||
|
|
||||||
const database = computed(() => store.database);
|
const database = computed(() => store.database);
|
||||||
|
|
||||||
|
const fileList = computed(() => {
|
||||||
|
if (!database.value?.files) return [];
|
||||||
|
return Object.values(database.value.files).map(f => f.filename).filter(Boolean);
|
||||||
|
});
|
||||||
|
|
||||||
// 复制数据库ID
|
// 复制数据库ID
|
||||||
const copyDatabaseId = async () => {
|
const copyDatabaseId = async () => {
|
||||||
if (!database.value.db_id) {
|
if (!database.value.db_id) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user