当前位置: 首页 > news >正文

从lightrag的prompt到基于openai Structured Outputs 的优化实现思路

LightRAG 是一个用于构建 RAG 系统核心组件的配置和管理类。它集成了文档处理、存储、向量化、图谱构建和 LLM 交互等功能。你可以通过配置 LightRAG 实例的各种参数来定制 RAG 系统的行为。

目前lightrag中的实体关系抽取实现如下

PROMPTS["entity_extraction"] = """---Goal---
Given a text document that is potentially relevant to this activity and a list of entity types, identify all entities of those types from the text and all relationships among the identified entities.
Use {language} as output language.---Steps---
1. Identify all entities. For each identified entity, extract the following information:
- entity_name: Name of the entity, use same language as input text. If English, capitalized the name.
- entity_type: One of the following types: [{entity_types}]
- entity_description: Comprehensive description of the entity's attributes and activities
Format each entity as ("entity"{tuple_delimiter}<entity_name>{tuple_delimiter}<entity_type>{tuple_delimiter}<entity_description>)2. From the entities identified in step 1, identify all pairs of (source_entity, target_entity) that are *clearly related* to each other.
For each pair of related entities, extract the following information:
- source_entity: name of the source entity, as identified in step 1
- target_entity: name of the target entity, as identified in step 1
- relationship_description: explanation as to why you think the source entity and the target entity are related to each other
- relationship_strength: a numeric score indicating strength of the relationship between the source entity and target entity
- relationship_keywords: one or more high-level key words that summarize the overarching nature of the relationship, focusing on concepts or themes rather than specific details
Format each relationship as ("relationship"{tuple_delimiter}<source_entity>{tuple_delimiter}<target_entity>{tuple_delimiter}<relationship_description>{tuple_delimiter}<relationship_keywords>{tuple_delimiter}<relationship_strength>)3. Identify high-level key words that summarize the main concepts, themes, or topics of the entire text. These should capture the overarching ideas present in the document.
Format the content-level key words as ("content_keywords"{tuple_delimiter}<high_level_keywords>)4. Return output in {language} as a single list of all the entities and relationships identified in steps 1 and 2. Use **{record_delimiter}** as the list delimiter.5. When finished, output {completion_delimiter}######################
---Examples---
######################
{examples}#############################
---Real Data---
######################
Entity_types: [{entity_types}]
Text:
{input_text}
######################
Output:"""

原始方式的痛点:

  • 自定义分隔符:如 tuple_delimiter, record_delimiter, completion_delimiter。这要求 LLM 严格遵守这些非标准的格式约定,LLM 很容易出错(例如,忘记分隔符,使用错误的分隔符,或者在不应该出现文本的地方添加额外文本)。
  • 解析复杂性:需要编写特定的解析器来处理这种自定义格式的文本输出,解析器可能很脆弱,难以维护。
  • 鲁棒性差:LLM 输出的微小偏差就可能导致解析失败。
  • 可读性和标准化:输出不是标准格式,不易于人工阅读或被其他标准工具直接使用。

在现代应用架构中,JSON 作为 API 通信和数据交换的事实标准,其重要性不言而喻。工程师们依赖精确的 JSON 结构来确保系统间的互操作性和数据的完整性。然而,将大型语言模型(LLM)集成到这些系统中时,一个普遍存在的痛点便是如何确保 LLM 的输出能够稳定、可靠地遵循预定义的 JSON 格式。传统的自由文本输出常常导致解析错误、字段不匹配、数据类型不一致等问题,迫使开发团队投入大量精力编写脆弱的解析逻辑、数据校验代码以及复杂的重试机制。

为了解决这一核心工程挑战,**结构化输出(Structured Outputs)**应运而生。该特性使您能够为 LLM 指定一个 JSON Schema,强制模型生成严格符合该 Schema 的响应。这不仅仅是格式上的规范,更是与 LLM 之间建立起一道清晰、可靠的数据契约。
我通过openai的Structured Outputs统一规范思想实现如下。

import json
from openai import OpenAI # 假设您会继续使用这个库# --- 1. 构建发送给大模型的文本提示 (修改版) ---
def _fill_placeholders_for_llm_prompt(text_template: str, values: dict) -> str:"""用提供的字典中的值填充文本模板中的占位符。占位符的格式可以是 {key} 或 [{key}]。"""filled_text = text_templatefor key, value in values.items():placeholder_curly = "{" + key + "}"if placeholder_curly in filled_text:filled_text = filled_text.replace(placeholder_curly, str(value))placeholder_square_curly = "[{" + key + "}]"  # 主要用于 entity_typesif placeholder_square_curly in filled_text:#确保在替换实体类型列表时,如果值本身不是字符串列表而是单个字符串,#它仍然被正确地格式化为JSON数组字符串的一部分。if isinstance(value, list):value_str = ", ".join([f'"{v}"' if isinstance(v, str) else str(v) for v in value])else:# 假定它是一个逗号分隔的字符串,或者单个类型value_str = str(value)filled_text = filled_text.replace(placeholder_square_curly, f"[{value_str}]")return filled_textdef build_llm_prompt_for_json_output(template_data: dict, document_text: str, task_params: dict) -> str:"""根据JSON模板、文档文本和固定任务参数构建发送给LLM的完整文本提示,并指示LLM输出JSON格式。task_params 包含: language, entity_types_string, examples"""prompt_lines = []# 对于 entity_types_string,我们需要将其转换为一个实际的列表以用于 _fill_placeholders_for_llm_prompt# 或者确保 _fill_placeholders_for_llm_prompt 能处理好它。# 鉴于当前 _fill_placeholders_for_llm_prompt 的实现,直接传递 entity_types_string 即可。placeholders_to_fill = {**task_params, "input_text": document_text, "entity_types": task_params.get("entity_types_string", "")}# ---目标---prompt_lines.append("---Goal---")goal_desc = _fill_placeholders_for_llm_prompt(template_data["goal"]["description"], placeholders_to_fill)prompt_lines.append(goal_desc)prompt_lines.append(f"Use {task_params.get('language', '{language}')} as output language for any textual descriptions within the JSON.") # {language} is a fallback if not in task_paramsprompt_lines.append("\nIMPORTANT: Your entire response MUST be a single, valid JSON object. Do not include any text or formatting outside of this JSON object (e.g., no markdown backticks like ```json ... ```).")prompt_lines.append("")# ---输出JSON结构说明---prompt_lines.append("---Output JSON Structure---")prompt_lines.append("The JSON object should have the following top-level keys: \"entities\", \"relationships\", and \"content_keywords\".")# 实体结构说明entity_step = next((step for step in template_data["steps"] if step["name"] == "Identify Entities"), None)if entity_step and "extraction_details" in entity_step:prompt_lines.append("\n1. The \"entities\" key should contain a JSON array. Each element in the array must be a JSON object representing an entity with the following keys:")for detail in entity_step["extraction_details"]:field_key = detail["field_name"]desc_filled = _fill_placeholders_for_llm_prompt(detail["description"], placeholders_to_fill)prompt_lines.append(f"    - \"{field_key}\": (string/number as appropriate) {desc_filled}")# 关系结构说明relationship_step = next((step for step in template_data["steps"] if step["name"] == "Identify Relationships"),None)if relationship_step and "extraction_details" in relationship_step:prompt_lines.append("\n2. The \"relationships\" key should contain a JSON array. Each element must be a JSON object representing a relationship with the following keys:")for detail in relationship_step["extraction_details"]:field_key = detail["field_name"]desc_filled = _fill_placeholders_for_llm_prompt(detail["description"], placeholders_to_fill)type_hint = "(string)"  # 默认if "strength" in field_key.lower(): type_hint = "(number, e.g., 0.0 to 1.0)"if "keywords" in field_key.lower() and "relationship_keywords" in field_key: type_hint = "(string, comma-separated, or an array of strings)"prompt_lines.append(f"    - \"{field_key}\": {type_hint} {desc_filled}")# 内容关键词结构说明keywords_step = next((step for step in template_data["steps"] if step["name"] == "Identify Content Keywords"), None)if keywords_step:prompt_lines.append("\n3. The \"content_keywords\" key should contain a JSON array of strings. Each string should be a high-level keyword summarizing the main concepts, themes, or topics of the entire text.")prompt_lines.append(f"   The description for these keywords is: {_fill_placeholders_for_llm_prompt(keywords_step['description'], placeholders_to_fill)}")prompt_lines.append("\nEnsure all string values within the JSON are properly escaped.")prompt_lines.append("")# ---示例---if task_params.get('examples'):prompt_lines.append("######################")prompt_lines.append("---Examples (Content Reference & Expected JSON Structure)---") # Clarified purpose of examplesprompt_lines.append("######################")# 示例应该直接是期望的JSON格式字符串,或者是一个结构体,然后我们在这里转换为JSON字符串examples_content = task_params.get('examples', '')if isinstance(examples_content, dict) or isinstance(examples_content, list):prompt_lines.append(json.dumps(examples_content, indent=2, ensure_ascii=False))else: # Assume it's already a string (hopefully valid JSON string)prompt_lines.append(_fill_placeholders_for_llm_prompt(str(examples_content), placeholders_to_fill))prompt_lines.append("\nNote: The above examples illustrate the type of content and the desired JSON output format. Your output MUST strictly follow this JSON structure.")prompt_lines.append("")# ---真实数据---prompt_lines.append("#############################")prompt_lines.append("---Real Data---")prompt_lines.append("######################")prompt_lines.append(f"Entity types to consider: [{_fill_placeholders_for_llm_prompt(task_params.get('entity_types_string', ''), {})}]") # Simpler fill for just thisprompt_lines.append("Text:")prompt_lines.append(document_text)prompt_lines.append("######################")prompt_lines.append("\nOutput JSON:")return "\n".join(prompt_lines)# --- 2. 调用大模型 (修改版) ---
def get_llm_response_json(api_key: str, user_prompt: str,system_prompt: str = "你是一个用于结构化数据抽取的助手,专门输出JSON格式。",model: str = "deepseek-chat", base_url: str = "https://api.deepseek.com/v1",use_json_mode: bool = True,stop_sequence: str | None = None) -> str | None:"""调用大模型并获取文本响应,尝试使用JSON模式。"""client = OpenAI(api_key=api_key, base_url=base_url)try:response_params = {"model": model,"messages": [{"role": "system", "content": system_prompt},{"role": "user", "content": user_prompt},],"stream": False,"temperature": 0.0,}if use_json_mode:try:response_params["response_format"] = {"type": "json_object"}except Exception as rf_e: # pylint: disable=broad-exceptprint(f"警告: 模型或SDK可能不支持 response_format 参数: {rf_e}. 将依赖提示工程获取JSON。")# 如果JSON模式失败,且有stop_sequence,则使用它if stop_sequence:response_params["stop"] = [stop_sequence]elif stop_sequence: # use_json_mode is False and stop_sequence is providedresponse_params["stop"] = [stop_sequence]response = client.chat.completions.create(**response_params)if response.choices and response.choices[0].message and response.choices[0].message.content:return response.choices[0].message.content.strip()return Noneexcept Exception as e:print(f"调用LLM时发生错误: {e}")return None# --- 3. 解析大模型的JSON响应 (修改版) ---
def parse_llm_json_output(llm_json_string: str) -> dict:"""解析LLM输出的JSON字符串。"""if not llm_json_string:return {"error": "LLM did not return any content."}try:# 有时LLM可能仍然会用markdown包裹JSONprocessed_string = llm_json_string.strip()if processed_string.startswith("```json"):processed_string = processed_string[7:]if processed_string.endswith("```"):processed_string = processed_string[:-3]processed_string = processed_string.strip()data = json.loads(processed_string)if not isinstance(data, dict) or \not all(k in data for k in ["entities", "relationships", "content_keywords"]):print(f"警告: LLM输出的JSON结构不符合预期顶层键: {processed_string}")return {"error": "LLM JSON output structure mismatch for top-level keys.", "raw_output": data if isinstance(data, dict) else processed_string} # Return original data if it parsed but mismatchedif not isinstance(data.get("entities"), list) or \not isinstance(data.get("relationships"), list) or \not isinstance(data.get("content_keywords"), list):print(f"警告: LLM输出的JSON中entities, relationships或content_keywords不是列表: {processed_string}")return {"error": "LLM JSON output type mismatch for arrays.", "raw_output": data}return dataexcept json.JSONDecodeError as e:print(f"错误: LLM输出的不是有效的JSON: {e}")print(f"原始输出 (尝试解析前): {llm_json_string}")print(f"处理后尝试解析的字符串: {processed_string if 'processed_string' in locals() else llm_json_string}") # Show what was attempted to parsereturn {"error": "Invalid JSON from LLM.", "details": str(e), "raw_output": llm_json_string}except Exception as e: # pylint: disable=broad-exceptprint(f"解析LLM JSON输出时发生未知错误: {e}")return {"error": "Unknown error parsing LLM JSON output.", "details": str(e), "raw_output": llm_json_string}# --- 4. 主协调函数 (修改版) ---
def extract_and_complete_json_direct_output(json_template_string: str,document_text: str,task_fixed_params: dict,llm_api_config: dict
) -> dict:"""主函数,协调整个抽取过程,期望LLM直接输出JSON。"""try:template_data = json.loads(json_template_string)except json.JSONDecodeError as e:print(f"错误: JSON模板解码失败: {e}")return {"error": "无效的JSON模板", "details": str(e)}llm_prompt = build_llm_prompt_for_json_output(template_data, document_text, task_fixed_params)# (可选) 打印生成的提示用于调试# print("--- 生成的LLM JSON提示 ---")# print(llm_prompt)# print("---提示结束---")use_json_mode_for_llm = task_fixed_params.get("use_json_mode_for_llm", True)# stop_sequence_val = task_fixed_params.get("completion_delimiter") if not use_json_mode_for_llm else None # completion_delimiter is removedllm_json_response_str = get_llm_response_json(api_key=llm_api_config["api_key"],user_prompt=llm_prompt,model=llm_api_config.get("model", "deepseek-chat"),base_url=llm_api_config.get("base_url", "https://api.deepseek.com/v1"),system_prompt=task_fixed_params.get("system_prompt_llm","你是一个专门的助手,负责从文本中提取信息并以JSON格式返回。"),use_json_mode=use_json_mode_for_llm,stop_sequence=None # Since completion_delimiter was removed from task_fixed_params)# 创建副本以填充结果,而不是修改原始模板数据结构本身# 我们将构建一个新的字典来存放结果,其中可能包含来自模板的元数据output_result = {"prompt_name": template_data.get("prompt_name", "unknown_extraction"),"goal_description_from_template": template_data.get("goal", {}).get("description"),# ... any other metadata from template_data you want to carry over}if not llm_json_response_str:output_result["extraction_results"] = {"error": "未能从LLM获取响应。"}output_result["llm_raw_output_debug"] = Nonereturn output_resultparsed_json_data = parse_llm_json_output(llm_json_response_str)output_result["extraction_results"] = parsed_json_dataoutput_result["llm_raw_output_debug"] = llm_json_response_strreturn output_result# --- 移除自定义分隔符后的模板 ---
json_template_str_input_no_delimiters = """{"prompt_name": "entity_extraction_json","goal": {"description": "Given a text document that is potentially relevant to this activity and a list of entity types [{entity_types}], identify all entities of those types from the text and all relationships among the identified entities. The output must be a single, valid JSON object.","output_language_variable": "{language}"},"steps": [{"step_number": 1,"name": "Identify Entities","description": "Identify all entities. For each identified entity, extract the information as specified in the Output JSON Structure section under 'entities'.","extraction_details": [{"field_name": "entity_name", "description": "Name of the entity, use same language as input text. If English, capitalize the name."},{"field_name": "entity_type", "description": "One of the types from the provided list: [{entity_types}]"},{"field_name": "entity_description", "description": "Comprehensive description of the entity's attributes and activities based on the input text."}]},{"step_number": 2,"name": "Identify Relationships","description": "From the entities identified, identify all pairs of clearly related entities. For each pair, extract the information as specified in the Output JSON Structure section under 'relationships'.","extraction_details": [{"field_name": "source_entity", "description": "Name of the source entity, as identified in the 'entities' list."},{"field_name": "target_entity", "description": "Name of the target entity, as identified in the 'entities' list."},{"field_name": "relationship_description", "description": "Explanation as to why the source entity and the target entity are related, based on the input text."},{"field_name": "relationship_strength", "description": "A numeric score indicating strength of the relationship (e.g., from 0.0 for weak to 1.0 for strong)."},{"field_name": "relationship_keywords", "description": "One or more high-level keywords summarizing the relationship, focusing on concepts or themes from the text."}]},{"step_number": 3,"name": "Identify Content Keywords","description": "Identify high-level keywords that summarize the main concepts, themes, or topics of the entire input text. This should be a JSON array of strings under the 'content_keywords' key in the output."}],"examples_section": {"placeholder": "{examples}"},"real_data_section": {"entity_types_variable": "[{entity_types}]", "input_text_variable": "{input_text}"},"output_format_notes": {"final_output_structure": "A single, valid JSON object as described in the prompt.","language_variable_for_output": "{language}"},"global_placeholders": ["{language}","{entity_types}","{examples}","{input_text}"]
}"""# --- 移除自定义分隔符后的任务参数 ---
task_configuration_params_json_output_no_delimiters = {"language": "简体中文","entity_types_string": "人物, 地点, 日期, 理论, 奖项, 组织", # This will be used to fill [{entity_types}]"examples": { # Example as a Python dict, will be converted to JSON string in prompt"entities": [{"entity_name": "阿尔伯特·爱因斯坦", "entity_type": "人物", "entity_description": "理论物理学家,创立了相对论,并因对光电效应的研究而闻名。"},{"entity_name": "狭义相对论", "entity_type": "理论", "entity_description": "由爱因斯坦在1905年提出的物理学理论,改变了对时间和空间的理解。"}],"relationships": [{"source_entity": "阿尔伯特·爱因斯坦", "target_entity": "狭义相对论", "relationship_description": "阿尔伯特·爱因斯坦发表了狭义相对论。", "relationship_strength": 0.9, "relationship_keywords": ["发表", "创立"]}],"content_keywords": ["物理学", "相对论", "爱因斯坦", "诺贝尔奖"]},"system_prompt_llm": "你是一个专门的助手,负责从文本中提取实体、关系和内容关键词,并且你的整个输出必须是一个单一的、有效的JSON对象。不要包含任何额外的文本或markdown标记。","use_json_mode_for_llm": True
}# --- 示例使用 ---
if __name__ == "__main__":# 使用已移除自定义分隔符的模板json_template_to_use = json_template_str_input_no_delimitersdocument_to_analyze = "爱因斯坦(Albert Einstein)于1879年3月14日出生在德国乌尔姆市一个犹太人家庭。他在1905年,即所谓的“奇迹年”,发表了四篇划时代的论文,其中包括狭义相对论的基础。后来,他因对理论物理的贡献,特别是发现了光电效应的定律,获得了1921年度的诺贝尔物理学奖。他的工作深刻影响了现代物理学,尤其是量子力学的发展。爱因斯坦在普林斯顿高等研究院度过了他的晚年,并于1955年4月18日逝世。"# 使用已移除自定义分隔符的任务参数task_params_to_use = task_configuration_params_json_output_no_delimitersllm_config = {"api_key": "YOUR_DEEPSEEK_API_KEY","base_url": "https://api.deepseek.com/v1","model": "deepseek-chat" # 或其他支持JSON模式的模型,如 gpt-4o, gpt-3.5-turbo-0125}if "YOUR_DEEPSEEK_API_KEY" in llm_config["api_key"] or not llm_config["api_key"]:print("错误:请在 llm_config 中设置您的真实 API 密钥以运行此示例。")print("您可以从 DeepSeek (https://platform.deepseek.com/api_keys) 或 OpenAI 获取密钥。")else:result_data = extract_and_complete_json_direct_output(json_template_string=json_template_to_use,document_text=document_to_analyze,task_fixed_params=task_params_to_use,llm_api_config=llm_config)print("\n--- 补全后的数据 (LLM直接输出JSON, 无自定义分隔符配置) ---")# 确保 extraction_results 存在且不是错误信息字符串extraction_results = result_data.get("extraction_results", {})if isinstance(extraction_results, dict) and "error" in extraction_results:print(f"发生错误: {extraction_results['error']}")if "details" in extraction_results:print(f"详情: {extraction_results['details']}")if "raw_output" in extraction_results: # raw_output might be in extraction_results on parsing errorprint(f"LLM原始(或部分)输出 (来自解析错误): {extraction_results['raw_output']}")elif "llm_raw_output_debug" in result_data: # Or it might be one level up if get_llm_response_json failedprint(f"LLM原始响应 (来自LLM调用): {result_data['llm_raw_output_debug']}")else:# 仅当没有错误时才尝试完整打印print(json.dumps(result_data, indent=2, ensure_ascii=False))# 即使成功,也打印原始LLM输出用于调试(如果之前没有因错误打印过)if not (isinstance(extraction_results, dict) and "error" in extraction_results and "raw_output" in extraction_results):if "llm_raw_output_debug" in result_data and result_data["llm_raw_output_debug"]:print("\n--- LLM 原始响应 (Debug) ---")print(result_data["llm_raw_output_debug"])
  • 改进方案(使用 OpenAI Structured Outputs/JSON Mode)的优势
    1. 标准化输出:直接要求 LLM 输出 JSON 对象。JSON 是一种广泛接受的、结构化的数据交换格式。
    2. LLM 内建支持:许多现代 LLM(如 OpenAI 的 gpt-3.5-turbo-0125 及更新版本, gpt-4o, 以及示例中使用的 DeepSeek 模型)提供了强制输出 JSON 的模式。这大大提高了 LLM 按预期格式输出的可靠性。
    3. 简化解析:可以直接使用标准的 JSON 解析库(如 Python 的 json.loads()),无需自定义解析逻辑。
    4. 提高鲁棒性:即使 LLM 偶尔在 JSON 外部添加少量文本(如 markdown 的 json ... ),的 parse_llm_json_output 函数也做了处理。并且,由于 LLM 被明确指示输出 JSON,其内部逻辑会更倾向于生成合法的 JSON。
    5. 清晰的 Schema 定义:的 build_llm_prompt_for_json_output 函数通过在提示中明确描述期望的 JSON 结构(顶层键、实体数组结构、关系数组结构等),为 LLM 提供了非常清晰的指引。
    6. 更好的可维护性和扩展性:修改输出结构通常只需要更新 JSON 模板中的描述和示例,代码层面的改动较小。
    7. 结构化的模板和参数:使用 json_template_str_input_no_delimiterstask_configuration_params_json_output_no_delimiters 使得提示工程本身更加结构化和易于管理。

对代码的几点具体分析和赞赏:

  • _fill_placeholders_for_llm_prompt: 灵活处理了不同格式的占位符,特别是对 entity_types 列表的处理。
  • build_llm_prompt_for_json_output: 非常出色地将结构化的模板、任务参数和动态文本结合起来,构建了一个详尽且清晰的、旨在获取 JSON 输出的提示。明确的 JSON 结构说明对 LLM 至关重要。
  • get_llm_response_json: 正确使用了 OpenAI 客户端的 response_format={"type": "json_object"} 参数,并包含了对不支持此参数情况的警告和潜在的 stop 序列回退(尽管在的最终调用中 stop_sequenceNone,因为 JSON 模式下通常不需要)。
  • parse_llm_json_output: 包含了对常见问题(如 markdown 包裹、顶层键缺失、期望数组不是数组)的检查和错误处理,非常实用。
  • extract_and_complete_json_direct_output: 很好地协调了整个流程。
  • 示例:提供的示例输入文本、JSON 模板和任务参数都非常清晰,有助于理解和测试。
  • 移除自定义分隔符:这是一个正确的方向,completion_delimiter 等在 JSON 模式下不再需要,因为 LLM 被期望返回一个完整的 JSON 对象。

总结:

LightRAG 之所以被描述为一个配置和管理类,是因为它旨在提供一个灵活的框架,用户可以通过定义各种组件(如 LLM 调用器、解析器、数据加载器)并配置其参数来构建和定制复杂的 RAG 系统。

使用 OpenAI Structured Outputs的 Python 代码和 JSON 模板完美地诠释了这一理念在“实体关系抽取”这一特定核心组件上的应用。通过:

  1. 配置(JSON 模板、任务参数)来定义任务细节。
  2. 管理(Python 函数协调构建提示、调用 LLM、解析结果)整个流程。
  3. 集成(与 LLM API 的交互)外部服务。

的实现利用了现代 LLM 的 JSON 输出能力,相比原始的基于自定义分隔符的提示,显著提高了输出的可靠性、可解析性和整体方案的鲁棒性。这是一个非常好的工程实践。

相关文章:

从lightrag的prompt到基于openai Structured Outputs 的优化实现思路

LightRAG 是一个用于构建 RAG 系统核心组件的配置和管理类。它集成了文档处理、存储、向量化、图谱构建和 LLM 交互等功能。你可以通过配置 LightRAG 实例的各种参数来定制 RAG 系统的行为。 目前lightrag中的实体关系抽取实现如下 PROMPTS["entity_extraction"] …...

论文阅读笔记——双流网络

双流网络论文 视频相比图像包含更多信息&#xff1a;运动信息、时序信息、背景信息等等。 原先处理视频的方法&#xff1a; CNN LSTM&#xff1a;CNN 抽取关键特征&#xff0c;LSTM 做时序逻辑&#xff1b;抽取视频中关键 K 帧输入 CNN 得到图片特征&#xff0c;再输入 LSTM&…...

Android清单文件

清单文件AndroidManifest.xml AndroidManifest.xml 配置清单文件是 每个 Android 应用的配置中心&#xff0c;系统在安装和运行应用时&#xff0c;首先会读取它。 它是 Android 应用的 “说明书”&#xff0c;主要作用是&#xff1a; 功能说明声明应用组件比如 Activity、Se…...

Single image dehazing论文阅读

Single image dehazing 1. 论文的研究目标与实际意义1.1 研究目标1.2 实际问题与产业意义2. 论文的创新方法、模型与公式2.1 改进的大气散射模型2.2 局部统计不相关性约束2.2.1 传输函数估计2.2.2 大气光颜色估计2.3 算法流程2.4 与传统方法的对比优势3. 实验设计与结果3.1 实验…...

数字信号处理-大实验1.3

MATLAB仿真实验目录 验证实验&#xff1a;常见离散信号产生和实现验证实验&#xff1a;离散系统的时域分析应用实验&#xff1a;语音信号的基音周期&#xff08;频率&#xff09;测定 说明&#xff1a;&#xff08;1&#xff09;本文是DSP大实验1的最后一篇&#xff0c;主要讲…...

【Pandas】pandas DataFrame describe

Pandas2.2 DataFrame Computations descriptive stats 方法描述DataFrame.abs()用于返回 DataFrame 中每个元素的绝对值DataFrame.all([axis, bool_only, skipna])用于判断 DataFrame 中是否所有元素在指定轴上都为 TrueDataFrame.any(*[, axis, bool_only, skipna])用于判断…...

C++GO语言微服务之Dockerfile docker-compose②

目录 01 12-yaml文件书写规则01 12-yaml文件书写规则 02 13-yaml中的数据类型 03 14-docker-compose配置文件格式 04 15-docker-compose中的关键字 05 16-prots和volumes关键字的使用 06 17-volumes_from的使用 07 18-extends的使用 08 19-networks的使用 09 20-docker…...

【计算机视觉】OpenCV实战项目:Face-Mask-Detection 项目深度解析:基于深度学习的口罩检测系统

Face-Mask-Detection 项目深度解析&#xff1a;基于深度学习的口罩检测系统 一、项目概述项目特点 二、项目运行方式与执行步骤&#xff08;一&#xff09;环境准备&#xff08;二&#xff09;项目结构&#xff08;三&#xff09;执行步骤 三、重要逻辑代码解析&#xff08;一&…...

鸿蒙OSUniApp 实现的语音输入与语音识别功能#三方框架 #Uniapp

UniApp 实现的语音输入与语音识别功能 最近在开发跨平台应用时&#xff0c;客户要求添加语音输入功能以提升用户体验。经过一番调研和实践&#xff0c;我成功在UniApp项目中实现了语音输入与识别功能&#xff0c;现将过程和方法分享出来&#xff0c;希望对有类似需求的开发者有…...

python:一个代理流量监控的媒体文件下载脚本

前言 一个mitmproxy代理服务应用&#xff0c;作用是监听系统流量&#xff0c;并自动下载可能的video媒体文件到本地。 如果你没有安装mitmproxy或没有做完准备工作&#xff0c;请参考我的这篇文章&#xff1a; python&#xff1a;mitmproxy代理服务搭建-CSDN博客 文件架构目录…...

openfeign与dubbo调用下载excel实践

一、前言 openfeign和dubbo均是rpc框架 RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;框架 是一种允许程序像调用本地方法一样调用远程服务器上函数的技术。它隐藏了底层网络通信的复杂性&#xff0c;让开发者可以专注于业务逻辑&#xff0c;实现…...

Android多媒体——媒体start流程分析(十三)

当多媒体的数据源准备好,并且完成调用准备结束流程后,接下来就开始是调用 start() 方法开始播放媒体了。这里我们就来分析一下媒体开始播放的整个流程。 一、媒体播放流程 对于媒体播放流程的 Java 层和 JNI 层与前面的示例基本相同,这里不再重复展示了,我们直接从 mediap…...

数据库系统概论(八)SQL单表查询语言超详细讲解(附带例题表格对比带你一步步掌握)

数据库系统概论&#xff08;八&#xff09;SQL单表查询语言超详细讲解&#xff08;附带例题表格对比带你一步步掌握&#xff09; 前言一、创建表&#xff08;了解一下就好&#xff0c;后面会详细讲&#xff09;二、数据查询的概念2.1 什么是数据查询&#xff1f;2.2 数据查询的…...

【IPMV】图像处理与机器视觉:Lec11 Keypoint Features and Corners

【IPMV】图像处理与机器视觉&#xff1a;Lec11 Keypoint Features and Corners 本系列为2025年同济大学自动化专业**图像处理与机器视觉**课程笔记 Lecturer: Rui Fan、Yanchao Dong Lec0 Course Description Lec3 Perspective Transformation Lec7 Image Filtering Lec8 I…...

C++23 中的 ranges::starts_with 与 ranges::ends_with

文章目录 功能介绍ranges::starts_withranges::ends_with 示例代码编译器支持总结 C23 标准引入了 ranges::starts_with 和 ranges::ends_with&#xff0c;这两个算法由提案 P1659R3 提出&#xff0c;旨在为任意范围提供检查前缀和后缀的功能。 功能介绍 ranges::starts_wit…...

2025 uniapp的请求封装工具类以及使用【拿来就用】

一、创建一个http请求封装的js文件&#xff0c;名字自定义&#xff1a;my_http.js /*** 基础API请求地址&#xff08;常量&#xff0c;全大写命名规范&#xff09;* type {string}* constant*/ let BASE_URL //通过环境来判断基础路径 if (process.env.NODE_ENV development…...

Axure设计之内联框架切换页面、子页面间跳转问题

在Axure中&#xff0c;你可以通过以下步骤实现主页面中的内联框架在点击按钮时切换页面内容&#xff0c;从A页面切换到B页面。&#xff08;误区&#xff1a;子页面之间切换不要设置“框架中打开链接”然后选“父级框架”这个交互&#xff09; 主框架页面&#xff08;左侧导航展…...

PyTorch 中神经网络相关要点(损失函数,学习率)及优化方法总结

笔记 1 神经网络搭建和参数计算 1.1 构建神经网络模型 import torch import torch.nn as nn # 线性模型和初始化方法 ​ ​ # todo:1-创建类继承 nn.module类 class ModelDemo(nn.Module):# todo:2-定义__init__构造方法, 构建神经网络def __init__(self):# todo:2-1 调用父…...

适用于 iOS 的 开源Ultralytics YOLO:应用程序和 Swift 软件包,用于在您自己的 iOS 应用程序中运行 YOLO

​一、软件介绍 文末提供程序和源码下载 该项目利用 Ultralytics 最先进的 YOLO11 模型将您的 iOS 设备转变为用于对象检测的强大实时推理工具。直接从 App Store 下载该应用程序&#xff0c;或浏览我们的指南&#xff0c;将 YOLO 功能集成到您自己的 Swift 应用程序中。 二、…...

why FPGA喜欢FMC子卡?

FMC 即 FPGA Mezzanine Card &#xff08; FPGA中间层板卡&#xff09;&#xff0c;由子板模块、载卡两构成。 FMC 载卡&#xff1a;为子板模块提供插槽&#xff0c;使用母座FMC连接器。载卡连接器引脚与具有可配置IO资源的芯片例如FPGA引脚通过PCB设计连接在一起。。 盘古100…...

【优选算法 | 字符串】字符串模拟题精选:思维+实现解析

算法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;双指针滑动窗口二分查找前缀和位运算模拟链表哈希表 在众多字符串算法题中&#xff0c;有一类题目看起来没有太多算法技巧&#xff0c;却经常让人“翻车”——那就是字符串模拟题。这类题型往往不依赖复杂的数据…...

比亚迪固态电池突破:王传福的技术哲学与产业重构|创客匠人热点评述

合肥某车间凌晨两点依然灯火通明&#xff0c;工程师正在调试的银白色设备&#xff0c;即将颠覆整个电动车行业 —— 比亚迪全固态电池产线的曝光&#xff0c;标志着中国新能源汽车产业正式迈入 “技术定义市场” 的新纪元。 一、技术突破的底层逻辑 比亚迪全固态电池的核心竞…...

UUG杭州站 | 团结引擎1.5.0 OpenHarmony新Feature介绍

PPT下载地址&#xff1a;https://u3d.sharepoint.cn/:b:/s/UnityChinaResources/EaZmiWfAAdFFmuyd6c-7_3ABhvZoaM69g4Uo2RrSzT3tZQ?e2h7RaL 在2025年4月12日的Unity User Group杭州站中&#xff0c;Unity中国OpenHarmony技术负责人刘伟贤带来演讲《团结引擎1.5.0 OpenHarmony新…...

OpenHarmony轻量系统--BearPi-Nano开发板网络程序测试

本文介绍RISC-V架构海思Hi3861开发板&#xff0c;通过Linux开发环境运行OpenHarmony轻量化系统&#xff0c;下载测试网络例程的过程与步骤。 OpenHarmony操作系统分类 轻量系统&#xff08;mini system&#xff09; 面向MCU类处理器例如Arm Cortex-M、RISC-V 32位的设备&#x…...

k8s 中使用 Service 访问时NetworkPolicy不生效问题排查

背景 针对一个服务如下NetworkPolicy, 表示只有n9e命名空间的POD才能访问 k8s-man 服务 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata:name: k8s-mannamespace: n9elabels:app: k8s-manversion: v1 spec:podSelector:matchLabels:app: k8s-manversion: v1…...

2025 AI如何重构网络安全产品

威胁检测与防御 利用机器学习算法提升威胁检测能力 &#xff1a;AI能够分析大量的网络数据和行为模式&#xff0c;通过机器学习算法自动识别出潜在的威胁和异常行为。例如&#xff0c;Darktrace的Cyber AI Analyst基于真实SOC数据训练&#xff0c;可推进威胁调查&#xff0c;提…...

ARM杂谈——临界段保护恢复的中断状态可靠吗

0 前言 在MCU中&#xff0c;临界段保护是指在多任务或多线程环境中&#xff0c;确保某段代码在执行时不会被其他任务或中断打断&#xff0c;从而避免数据竞争或不一致的问题。临界段保护通常用于共享资源的访问&#xff0c;如全局变量、硬件寄存器等。 我们有一些常用的临界段…...

数据库MySQL学习——day10()

文章目录 1. 什么是子查询&#xff08;Subquery&#xff09;&#xff1f;2. 创建样例表&#xff1a;商品表 products3. 插入示例数据4. 子查询的三种常用位置4.1 子查询在 WHERE 子句中&#xff08;最常见&#xff09;4.2 子查询在 FROM 子句中&#xff08;可以当成临时表&…...

YashanDB V23.4 LTS 正式发布|两地三中心、库级闪回重磅特性上线,生产级可用性再升级

近日&#xff0c;YashanDB V23.4 LTS&#xff08;Long-Term Support Release&#xff09;版本正式发布&#xff0c;新版本深度契合关键行业数字化转型对数据库“业务永续、风险可控”的核心诉求&#xff0c;打造两地三中心秒级容灾、库级闪回秒级恢复、MySQL全面兼容等重磅特性…...

AI规则引擎:解锁SQL数据分析新姿势

一、AI 规则引擎与 SQL 的奇妙邂逅 在当今数字化时代&#xff0c;数据如同石油&#xff0c;是企业发展和创新的核心驱动力。而如何从海量的数据中提取有价值的信息&#xff0c;成为了企业面临的关键挑战。人工智能规则引擎和 SQL&#xff0c;作为数据分析领域的两大重要工具&a…...

Kotlin Multiplatform与Flutter、Compose共存:构建高效跨平台应用的完整指南

简介 在移动开发领域,跨平台技术正在重塑开发范式。Kotlin Multiplatform (KMP) 作为 JetBrains 推出的多平台开发框架,结合了 Kotlin 的简洁性与原生性能优势,使开发者能够高效共享业务逻辑。而 Flutter 凭借其高性能渲染引擎(Skia)和丰富的组件库,成为混合开发的首选方…...

FunASR:语音识别与合成一体化,企业级开发实战详解

简介 FunASR是由阿里巴巴达摩院开源的高性能语音识别工具包,它不仅提供语音识别(ASR)功能,还集成了语音端点检测(VAD)、标点恢复、说话人分离等工业级模块,形成了完整的语音处理解决方案。 FunASR支持离线和实时两种模式,能够高效处理多语言音频,并提供高精度的识别结果。…...

【Spark分析HBase数据】Spark读取并分析HBase数据

Spark读取并分析HBase数据 一、摘要二、实现过程三、小结 一、摘要 Apache Spark 是一个快速、通用的大数据处理引擎&#xff0c;提供了丰富的 API 用于数据处理和分析。HBase 是一个分布式、可扩展的 NoSQL 数据库&#xff0c;适合存储海量结构化和半结构化数据。Spark 与 HB…...

探索直播美颜SDK的核心算法:图像增强与AI美颜技术详解

一款优秀的直播美颜SDK不仅能让主播拥有完美的在线形象&#xff0c;还能帮助平台吸引更多用户。然而&#xff0c;这背后的关键在于其核心算法——从基本的图像增强到前沿的AI美颜技术&#xff0c;每一步都至关重要。今天&#xff0c;我们就来深入探讨这些技术背后的秘密。 一、…...

全新linux网络配置工具nmcli:

1.Linux全新网络管理工具nmcli的使用 ,网络管理命令行工具nmcli 在nmcli中有2个命令最为常用&#xff1a; &#xff08;1&#xff09;nmcli connection 表示连接&#xff0c;可理解为配置文件&#xff0c;相当于ifcfg-ethX。可以简写为nmcli c &#xff08;2&#xff09;nmcl…...

LeetCode100.5 盛最多水的容器

对于这题&#xff0c;首先明确的是&#xff1a;盛水的体积取决于两垂线间的距离与两垂线中最短的长度。 那么使用双指针&#xff0c;在每次移动时&#xff0c;只移动其中最短的那个&#xff0c;因为若移动最长的那个&#xff0c;体积不会变大。 class Solution { public:int …...

AI开发者的算力革命:GpuGeek平台全景实战指南(大模型训练/推理/微调全解析)

目录 背景一、AI工业化时代的算力困局与破局之道1.1 中小企业AI落地的三大障碍1.2 GpuGeek的破局创新1.3 核心价值 二、GpuGeek技术全景剖析2.1 核心架构设计 三、核心优势详解‌3.1 优势1&#xff1a;工业级显卡舰队‌‌‌3.2 优势2&#xff1a;开箱即用生态‌3.2.1 预置镜像库…...

Java元注解

Java 元注解&#xff08;Meta-Annotations&#xff09; 元注解是指用于注解其他注解的注解&#xff0c;Java 提供了5个内置的元注解&#xff1a; 1. Target 指定注解可以应用的目标元素类型。 Target(ElementType.TYPE) // 只能用于类、接口或枚举 public interface MyAnno…...

FPGA:Xilinx Kintex 7实现DDR3 SDRAM读写

在Xilinx Kintex 7系列FPGA上实现对DDR3 SDRAM的读写&#xff0c;主要依赖Xilinx提供的Memory Interface Generator (MIG) IP核&#xff0c;结合Vivado设计流程。以下是详细步骤和关键点&#xff1a; 1. 准备工作 硬件需求&#xff1a; Kintex-7 FPGA&#xff08;如XC7K325T&…...

深度剖析 GpuGeek 实例:GpuGeek/Qwen3-32B 模型 API 调用实践与性能测试洞察

深度剖析 GpuGeek 实例&#xff1a;GpuGeek/Qwen3-32B 模型 API 调用实践与性能测试洞察 前言 GpuGeek专注于人工智能与高性能计算领域的云计算平台&#xff0c;致力于为开发者、科研机构及企业提供灵活、高效、低成本的GPU算力资源。平台通过整合全球分布式数据中心资源&#…...

散列表(1)

散列表概念 键通过散列函数后转换为数组的下标&#xff0c;在对应的下标位置上存储相应的信息 键------>散列函数-------->数组下标------->存储信息 散列函数 散列函数就是一个函数&#xff0c;能够将给定的key转换为特定散列值。hashValuehash&#xff08;key&…...

E. 23 Kingdom【Codeforces Round 1024 (Div. 2)】

E. 23 Kingdom 思路&#xff1a; 这道题的核心在于如何构造一个数组b&#xff0c;使得每个数的最远两个出现位置之差总和最大。通过分析&#xff0c;我们发现要最大化总美丽值&#xff0c;应尽可能让每个数的首次出现尽可能靠左、末次出现尽可能靠右。这样每个数的距离贡献j-i…...

TTS-Web-Vue系列:Vue3实现侧边栏与顶部导航的双向联动

&#x1f504; 本文是TTS-Web-Vue系列的最新文章&#xff0c;重点介绍如何在Vue3项目中实现侧边栏与顶部导航栏的双向联动功能。通过Vue3的响应式系统和组件通信机制&#xff0c;我们构建了一套高效、流畅的导航联动方案&#xff0c;让用户在不同入口都能获得一致的导航体验。 …...

【C++】模板(初阶)

一、模板与泛型编程 我们先来思考一下&#xff1a;如何实现一个通用的交换函数&#xff1f; void Swap(int& left, int& right) {int temp left;left right;right temp; }void Swap(double& left, double& right) {double temp left;left right;right te…...

大模型微调实战:基于GpuGeek平台的低成本高效训练方案

文章目录 引言一、GpuGeek平台使用入门1. 注册与账号设置2. 控制台功能概览3. 快速创建GPU实例3. 预置镜像与自定义环境 二、GpuGeek平台核心优势解析1. 显卡资源充足&#xff1a;多卡并行加速训练2. 镜像超多&#xff1a;开箱即用的开发环境3. 计费灵活&#xff1a;按需付费降…...

黑马k8s(六)

1.Deployment&#xff08;Pod控制器&#xff09; Selector runnginx 标签选择&#xff1a;会找pod打的标签 执行删除之后&#xff0c;pod也会删除&#xff0c;Terminating正在删除 如果想要访问其中的一个pod借助&#xff1a;IP地址端口号访问 假设在某一个瞬间&#xff0c;…...

WEB安全--Java安全--CC1利用链

一、梳理基本逻辑 WEB后端JVM通过readObject()的反序列化方式接收用户输入的数据 用户编写恶意代码并将其序列化为原始数据流 WEB后端JVM接收到序列化后恶意的原始数据并进行反序列化 当调用&#xff1a; ObjectInputStream.readObject() JVM 内部逻辑&#xff1a; → 反…...

16S18S_OTU分析(3)

OTU的定义 OTU&#xff1a;操作分类单元是在系统发生学研究或群体遗传学研究中&#xff0c;为了便于进行分析&#xff0c;人为给某一个分类单元&#xff08;如品系、种、属、分组等&#xff09;设置的同一标志。目的&#xff1a;OTU用于将相似的序列归为一类&#xff0c;以便于…...

嵌入式开发学习日志(数据结构--单链表)Day20

一、gdb调试 &#xff08;一&#xff09;一般调试步骤与命令 1、gcc -g &#xff08;调试版本&#xff0c;内含调试信息与源码&#xff1b;eg&#xff1a;gcc -g main.c linklist.c&#xff09; 2、gdb a.out&#xff08;调试可执行文件&#xff0c;eg&#xff1a;gdb …...

nginx报错-[emerg] getpwnam(“nginx“) failed in /etc/nginx/nginx.conf:2

报错 - nginx: [emerg] getpwnam(“nginx”) failed in /etc/nginx/nginx.conf:2 问题描述&#xff1a; nginx: [emerg] getpwnam(“nginx”) failed in /etc/nginx/nginx.conf:2 问题原因&#xff1a; 是因为配制文件中使用的启动账户在系统中并没有找到 解决方法&#x…...