[Datawheel学习]用Llama-index创建Agent、数据库对话Agent和RAG接入Agent

news2025/1/18 21:59:02

1.Llama-index创建Agent

1.0 背景知识

  1. 什么是Llama-index?
    LlamaIndex(原名GPT Index)是一个专为大语言模型(LLMs)设计的数据框架,旨在帮助用户将外部数据与LLMs结合,实现更高效的数据检索和知识增强生成(RAG)。它通过构建索引和提供查询接口,使LLMs能够访问和利用私有或特定领域的数据,从而提升模型的准确性和实用性。
  2. LlamaIndex 的核心功能
    数据连接器(Data Connectors) 支持从多种数据源(如本地文件、PDF、API、SQL数据库、Notion、Google文档等)摄取数据,并将其转换为统一的文档表示形式。
    索引结构(Index Structures) 将数据组织成可查询的索引形式,支持多种索引类型,包括:
    1)向量索引(Vector Store Index):基于向量相似度检索数据。
    2)列表索引(List Index):按顺序存储节点,支持关键字过滤。
    3)树形索引(Tree Index):构建层次化结构,支持从根节点到叶节点的查询。
    4)关键字表索引(Keyword Table Index):通过关键字映射快速检索节点。
    查询接口(Query Interface) 提供与大模型对话的接口,支持自然语言查询。通过检索索引和组合Prompt,使LLMs能够生成基于外部数据的准确回答。
    检索增强生成(RAG) LlamaIndex的核心应用场景是RAG,它通过以下步骤实现:
    1)索引阶段:将外部数据构建为知识库。
    2)查询阶段:从知识库中检索相关上下文,并将其与用户查询结合,生成增强后的响应。
  3. LlamaIndex 的优势
    扩展性: 支持多种数据源和格式,扩展了LLMs的应用范围。
    灵活性: 允许用户自定义索引和查询逻辑,适应不同场景需求。
    实时性: 通过实时检索外部数据,确保模型提供最新信息。

4.Llamaindex的竞品
1) LangChain

  • 特点:是一个多功能框架,支持构建复杂的 LLM 应用,包括聊天机器人、自动化工作流和多步骤任务处理。提供模块化设计,支持与多种数据源和工具集成,适合需要灵活性和复杂功能的场景。强调上下文记忆和任务编排能力,适合需要长时间交互和多步骤推理的应用。
  • 适用场景:需要复杂交互和上下文保留的应用(如客户支持、聊天机器人)。需要与其他系统广泛集成的通用应用程序。

2) Flowise AI

  • 特点:提供无代码(No-Code)开发界面,支持通过拖放组件快速构建 LLM 应用。与 LangChain 深度整合,支持其核心功能(如链式操作、数据增强等),但降低了开发门槛。
  • 适用场景:适合非技术用户或快速原型开发。需要可视化工作流和低代码解决方案的场景。

3)AutoChain

  • 特点:轻量级框架,专注于对话式智能代理的开发。强调简单性、自定义能力和自动化评估,适合快速构建和测试对话系统。
  • 适用场景:需要快速构建对话代理的场景。适合初学者或需要高度定制化的对话系统。

4)Haystack

  • 特点:专注于文档检索和问答系统,支持多种数据源和检索算法。提供强大的文档处理和检索功能,适合需要高效信息提取的应用。
  • 适用场景:文档问答系统、知识库检索。需要高效处理非结构化数据的场景。

5)Weaviate

  • 特点:是一个向量数据库,支持语义搜索和高效的数据检索。提供与 LLM 的集成能力,适合需要高性能向量检索的应用15。
  • 适用场景:需要高效向量检索和语义搜索的场景。适合与 LLM 结合使用的知识库和推荐系统。

6)Pinecone

  • 特点:专注于向量搜索和存储,支持大规模数据的高效检索。提供与 LLM 的集成能力,适合需要实时检索和上下文感知的应用。
  • 适用场景:实时推荐系统、语义搜索。需要高性能向量检索的场景。

7)OpenAI Embeddings + FAISS

  • 特点:结合 OpenAI 的嵌入模型和 FAISS 向量搜索库,提供高效的语义检索能力。适合需要自定义检索逻辑和高性能搜索的场景。
  • 适用场景:需要高度定制化检索逻辑的应用。适合技术团队构建高性能搜索系统。

1.1 准备模型

import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()
# 从环境变量中读取api_key
api_key = os.getenv('ZISHU_API_KEY')
base_url = "http://43.200.7.56:8008/v1"
chat_model = "glm-4-flash"
emb_model = "embedding-3"

1.2自定义LLM类

from openai import OpenAI
from pydantic import Field  # 导入Field,用于Pydantic模型中定义字段的元数据
from llama_index.core.llms import (
    CustomLLM,
    CompletionResponse,
    LLMMetadata,
)
from llama_index.core.embeddings import BaseEmbedding
from llama_index.core.llms.callbacks import llm_completion_callback
from typing import List, Any, Generator
# 定义OurLLM类,继承自CustomLLM基类
class OurLLM(CustomLLM):
    api_key: str = Field(default=api_key)
    base_url: str = Field(default=base_url)
    model_name: str = Field(default=chat_model)
    client: OpenAI = Field(default=None, exclude=True)  # 显式声明 client 字段

    def __init__(self, api_key: str, base_url: str, model_name: str = chat_model, **data: Any):
        super().__init__(**data)
        self.api_key = api_key
        self.base_url = base_url
        self.model_name = model_name
        self.client = OpenAI(api_key=self.api_key, base_url=self.base_url)  # 使用传入的api_key和base_url初始化 client 实例

    @property
    def metadata(self) -> LLMMetadata:
        """Get LLM metadata."""
        return LLMMetadata(
            model_name=self.model_name,
        )

    @llm_completion_callback()
    def complete(self, prompt: str, **kwargs: Any) -> CompletionResponse:
        response = self.client.chat.completions.create(model=self.model_name, messages=[{"role": "user", "content": prompt}])
        if hasattr(response, 'choices') and len(response.choices) > 0:
            response_text = response.choices[0].message.content
            return CompletionResponse(text=response_text)
        else:
            raise Exception(f"Unexpected response format: {response}")

    @llm_completion_callback()
    def stream_complete(
        self, prompt: str, **kwargs: Any
    ) -> Generator[CompletionResponse, None, None]:
        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=[{"role": "user", "content": prompt}],
            stream=True
        )

        try:
            for chunk in response:
                chunk_message = chunk.choices[0].delta
                if not chunk_message.content:
                    continue
                content = chunk_message.content
                yield CompletionResponse(text=content, delta=content)

        except Exception as e:
            raise Exception(f"Unexpected response format: {e}")

llm = OurLLM(api_key=api_key, base_url=base_url, model_name=chat_model)

1.3测试大模型是否可用

response = llm.stream_complete("你是谁?")
for chunk in response:
    print(chunk, end="", flush=True)

1.4测试结果

在这里插入图片描述

1.5 编写工具函数并引入

这里重新定义了加法和乘法,在提问后要求大模型调用工具函数完成任务而不是直接回答。这里注意:大模型会根据函数的注释来判断使用哪个函数来完成任务。所以,注释一定要写清楚函数的功能和返回值。

import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))

from llama_index.core.agent import ReActAgent
from llama_index.core.tools import FunctionTool


def multiply(a: float, b: float) -> float:
    """Multiply two numbers and returns the product"""
    return a * b


def add(a: float, b: float) -> float:
    """Add two numbers and returns the sum"""
    return a + b


def main():

    multiply_tool = FunctionTool.from_defaults(fn=multiply)
    add_tool = FunctionTool.from_defaults(fn=add)

    # 创建ReActAgent实例
    agent = ReActAgent.from_tools([multiply_tool, add_tool], llm=llm, verbose=True)

    response = agent.chat("20+(2*4)等于多少?使用工具计算每一步")

    print(response)


if __name__ == "__main__":
    main()

1.6 结果展示

在这里插入图片描述

1.7 写一个查询天气的工具函数,实现天气查询agent

def get_weather(city: str) -> int:
    """
    Gets the weather temperature of a specified city.

    Args:
    city (str): The name or abbreviation of the city.

    Returns:
    int: The temperature of the city. Returns 20 for 'NY' (New York),
         30 for 'BJ' (Beijing), and -1 for unknown cities.
    """

    # Convert the input city to uppercase to handle case-insensitive comparisons
    city = city.upper()

    # Check if the city is New York ('NY')
    if city == "NY":
        return 20  # Return 20°C for New York

    # Check if the city is Beijing ('BJ')
    elif city == "BJ":
        return 30  # Return 30°C for Beijing

    # If the city is neither 'NY' nor 'BJ', return -1 to indicate unknown city
    else:
        return -1

weather_tool = FunctionTool.from_defaults(fn=get_weather)

agent = ReActAgent.from_tools([multiply_tool, add_tool, weather_tool], llm=llm, verbose=True)

response = agent.chat("纽约天气怎么样?")

这里写了一个伪函数,当然也可以去调用天气查询的api。
在这里插入图片描述
在这里插入图片描述

2.数据库对话Agent

2.1 创建数据库并写入数据

import sqlite3
# 创建数据库
sqllite_path = 'llmdb.db'
con = sqlite3.connect(sqllite_path)

# 创建表
sql = """
CREATE TABLE `section_stats` (
  `部门` varchar(100) DEFAULT NULL,
  `人数` int(11) DEFAULT NULL
);
"""
c = con.cursor()
cursor = c.execute(sql)
c.close()
con.close()

2.2 构建llm和embedding模型

这里稍微有点麻烦,我这里使用的是本地部署的llm,然后embeeding模型调用的是智谱的api,感觉是在我的场景下比较简单的方式了

2.2.1 llm构建

import os
from dotenv import load_dotenv

from openai import OpenAI
from pydantic import Field  # 导入Field,用于Pydantic模型中定义字段的元数据
from llama_index.core.llms import (
    CustomLLM,
    CompletionResponse,
    LLMMetadata,
)
from llama_index.core.embeddings import BaseEmbedding
from llama_index.core.llms.callbacks import llm_completion_callback
from typing import List, Any, Generator

# 加载环境变量
load_dotenv()
# 从环境变量中读取api_key
api_key = os.getenv('ZISHU_API_KEY')
base_url = os.getenv('base_url')
chat_model = os.getenv('chat_model')
emb_model = "embedding-2"

## 自定义对话模型
# 导入必要的库和模块
from openai import OpenAI
from pydantic import Field  # 导入Field,用于Pydantic模型中定义字段的元数据
from typing import Optional, List, Mapping, Any, Generator
import os

from llama_index.core import SimpleDirectoryReader, SummaryIndex
from llama_index.core.callbacks import CallbackManager
from llama_index.core.llms import (
    CustomLLM,
    CompletionResponse,
    CompletionResponseGen,
    LLMMetadata,
)
from llama_index.core.llms.callbacks import llm_completion_callback
from llama_index.core import Settings

# 定义OurLLM类,继承自CustomLLM基类
class OurLLM(CustomLLM):
    api_key: str = Field(default=api_key)
    base_url: str = Field(default=base_url)
    model_name: str = Field(default=chat_model)
    client: OpenAI = Field(default=None, exclude=True)  # 显式声明 client 字段

    def __init__(self, api_key: str, base_url: str, model_name: str = chat_model, **data: Any):
        super().__init__(**data)
        self.api_key = api_key
        self.base_url = base_url
        self.model_name = model_name
        self.client = OpenAI(api_key=self.api_key, base_url=self.base_url)  # 使用传入的api_key和base_url初始化 client 实例

    @property
    def metadata(self) -> LLMMetadata:
        """Get LLM metadata."""
        return LLMMetadata(
            model_name=self.model_name,
        )

    @llm_completion_callback()
    def complete(self, prompt: str, **kwargs: Any) -> CompletionResponse:
        response = self.client.chat.completions.create(model=self.model_name, messages=[{"role": "user", "content": prompt}])
        if hasattr(response, 'choices') and len(response.choices) > 0:
            response_text = response.choices[0].message.content
            return CompletionResponse(text=response_text)
        else:
            raise Exception(f"Unexpected response format: {response}")

    @llm_completion_callback()
    def stream_complete(
        self, prompt: str, **kwargs: Any
    ) -> Generator[CompletionResponse, None, None]:
        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=[{"role": "user", "content": prompt}],
            stream=True
        )

        try:
            for chunk in response:
                chunk_message = chunk.choices[0].delta
                if not chunk_message.content:
                    continue
                content = chunk_message.content
                yield CompletionResponse(text=content, delta=content)

        except Exception as e:
            raise Exception(f"Unexpected response format: {e}")


llm = OurLLM(api_key=api_key, base_url=base_url, model_name=chat_model)
# 测试对话模型
# response = llm.complete("你是谁?")
# print(response)

2.2.2构建embedding模型

from llama_index.embeddings.zhipuai import ZhipuAIEmbedding
embedding = ZhipuAIEmbedding(
    api_key = 'your_api_key',
    model = emb_model,
)

2.3 导入Llama-index相关的库,并配置对话模型和嵌入模型,构建数据库对话agent

from llama_index.core.agent import ReActAgent  
from llama_index.core.tools import FunctionTool  
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, Settings  
from llama_index.core.tools import QueryEngineTool   
from llama_index.core import SQLDatabase  
from llama_index.core.query_engine import NLSQLTableQueryEngine  
from sqlalchemy import create_engine, select  


# 配置默认大模型  
Settings.llm = llm
Settings.embed_model = embedding

## 创建数据库查询引擎  
engine = create_engine("sqlite:///llmdb.db")  
# prepare data  
sql_database = SQLDatabase(engine, include_tables=["section_stats"])  
query_engine = NLSQLTableQueryEngine(  
    sql_database=sql_database,   
    tables=["section_stats"],   
    llm=Settings.llm  
)

# 创建工具函数  
def multiply(a: float, b: float) -> float:  
    """将两个数字相乘并返回乘积。"""  
    return a * b  

multiply_tool = FunctionTool.from_defaults(fn=multiply)  

def add(a: float, b: float) -> float:  
    """将两个数字相加并返回它们的和。"""  
    return a + b

add_tool = FunctionTool.from_defaults(fn=add)

# 把数据库查询引擎封装到工具函数对象中  
staff_tool = QueryEngineTool.from_defaults(
    query_engine,
    name="section_staff",
    description="查询部门的人数。"  
)

# 构建ReActAgent
agent = ReActAgent.from_tools([multiply_tool, add_tool, staff_tool], verbose=True)  
# 通过agent给出指令
response = agent.chat("请从数据库表中获取`专利部``商标部`的人数,并将这两个部门的人数相加!")  

2.4 结果

在这里插入图片描述

2.5 理解

这里对于初学者比较难理解embedding模型起到了什么作用,目前推测是在NLSQLTableQueryEngine类中用于为文本生成向量表示,支持语义理解和检索任务。此外,QueryEngineTool 是 LlamaIndex 框架中的一个工具类,它的作用是将一个 查询引擎(Query Engine)封装成一个 工具(Tool),以便在更高层次的组件(如 ReActAgent 或其他代理)中使用。通过这种方式,查询引擎可以被集成到更复杂的任务流程中,例如多步骤推理、任务分解或工具调用。

这里还有个问题:为什么这里一定要用到embedding模型来理解自然语言llm做不到吗?
虽然 LLM 能够直接理解自然语言,但在某些场景下,Embedding 模型仍然是必要的。以下是 Embedding 模型的主要作用:

  1. 向量化表示
  • Embedding 模型将文本转换为固定长度的向量表示,这些向量可以用于计算文本之间的相似度。
  • 例如,在文档检索、语义搜索等任务中,Embedding 模型可以快速找到与查询文本最相关的文档。
  1. 高效检索
  • 在大规模数据集中,直接使用 LLM 进行检索可能会非常低效。Embedding 模型可以将文本转换为向量后,使用向量检索技术(如余弦相似度、近似最近邻搜索)快速找到相关结果。
  • 例如,如果你有一个包含数百万条记录的数据库,使用 Embedding 模型进行向量检索会比直接使用 LLM 更高效。
  1. 语义理解
  • Embedding 模型能够捕捉文本的语义信息,使得语义相似的文本在向量空间中距离较近。
  • 例如,在问答系统中,Embedding 模型可以用于找到与用户问题最相关的答案。
  1. 任务分离
  • 在某些任务中,LLM 和 Embedding 模型可以分工合作:
  • LLM 负责复杂的推理和任务分解。
  • Embedding 模型负责高效的检索和语义匹配。

从代码来看,Embedding 模型并不是必需的,因为:使用的是 NLSQLTableQueryEngine,它直接依赖 LLM 将自然语言查询转换为 SQL 查询,而不需要 Embedding 模型。Embedding 模型的主要优势在于高效的向量化表示和检索能力,适用于大规模数据集或需要语义匹配的场景。如果后续扩展代码(如引入文档检索或语义搜索功能),可以考虑使用 Embedding 模型来增强系统的能力。

3.RAG接入Agent

接下来尝试把RAG当作Agent可以调用的一个工具。引入llm和embedding模型的过程和上面一样不赘述。

3.1 构建索引

# 从指定文件读取,输入为List
from llama_index.core import SimpleDirectoryReader,Document
documents = SimpleDirectoryReader(input_files=['../docs/问答手册.txt']).load_data()

# 构建节点
from llama_index.core.node_parser import SentenceSplitter
transformations = [SentenceSplitter(chunk_size = 512)]

from llama_index.core.ingestion.pipeline import run_transformations
nodes = run_transformations(documents, transformations=transformations)

# 构建索引
from llama_index.vector_stores.faiss import FaissVectorStore
import faiss
from llama_index.core import StorageContext, VectorStoreIndex

emb = embedding.get_text_embedding("你好呀呀")
vector_store = FaissVectorStore(faiss_index=faiss.IndexFlatL2(len(emb)))
storage_context = StorageContext.from_defaults(vector_store=vector_store)

index = VectorStoreIndex(
    nodes = nodes,
    storage_context=storage_context,
    embed_model = embedding,
)

3.2 构建问答引擎

# 构建检索器
from llama_index.core.retrievers import VectorIndexRetriever
# 想要自定义参数,可以构造参数字典
kwargs = {'similarity_top_k': 5, 'index': index, 'dimensions': len(emb)} # 必要参数
retriever = VectorIndexRetriever(**kwargs)

# 构建合成器
from llama_index.core.response_synthesizers  import get_response_synthesizer
response_synthesizer = get_response_synthesizer(llm=llm, streaming=True)

# 构建问答引擎
from llama_index.core.query_engine import RetrieverQueryEngine
engine = RetrieverQueryEngine(
      retriever=retriever,
      response_synthesizer=response_synthesizer,
        )

尝试直接使用RAG回答

# 提问
question = "What are the applications of Agent AI systems ?"
response = engine.query(question)
for text in response.response_gen:
    print(text, end="")

在这里插入图片描述## 3.3 配置问答工具并创建Agent
把这个RAG当作一个工具给Agent调用,让它去思考

# 配置查询工具
from llama_index.core.tools import QueryEngineTool
from llama_index.core.tools import ToolMetadata
query_engine_tools = [
    QueryEngineTool(
        query_engine=engine,
        metadata=ToolMetadata(
            name="RAG工具",
            description=(
                "用于在原文中检索相关信息"
            ),
        ),
    ),
]

# 创建ReAct Agent
from llama_index.core.agent import ReActAgent
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
# 让Agent完成任务
response = agent.chat("What are the applications of Agent AI systems ?")
print(response)

输出:
在这里插入图片描述

4.构建search agent

这里使用了Bocha Web Search API,大家可以直接去官网注册然后申请api,注意这个是收费的。
完事开始构建search agent

from llama_index.core.tools import FunctionTool
import requests
# 需要先把BOCHA_API_KEY填写到.env文件中去。
BOCHA_API_KEY = os.getenv('BOCHA_API_KEY')

# 定义Bocha Web Search工具
def bocha_web_search_tool(query: str, count: int = 8) -> str:
    """
    使用Bocha Web Search API进行联网搜索,返回搜索结果的字符串。
    
    参数:
    - query: 搜索关键词
    - count: 返回的搜索结果数量

    返回:
    - 搜索结果的字符串形式
    """
    url = 'https://api.bochaai.com/v1/web-search'
    headers = {
        'Authorization': f'Bearer {BOCHA_API_KEY}',  # 请替换为你的API密钥
        'Content-Type': 'application/json'
    }
    data = {
        "query": query,
        "freshness": "noLimit", # 搜索的时间范围,例如 "oneDay", "oneWeek", "oneMonth", "oneYear", "noLimit"
        "summary": True, # 是否返回长文本摘要总结
        "count": count
    }

    response = requests.post(url, headers=headers, json=data)

    if response.status_code == 200:
        # 返回给大模型的格式化的搜索结果文本
        # 可以自己对博查的搜索结果进行自定义处理
        return str(response.json())
    else:
        raise Exception(f"API请求失败,状态码: {response.status_code}, 错误信息: {response.text}")

search_tool = FunctionTool.from_defaults(fn=bocha_web_search_tool)
from llama_index.core.agent import ReActAgent
agent = ReActAgent.from_tools([search_tool], llm=llm, verbose=True)

测试一下

# 测试用例
query = "阿里巴巴2024年的ESG报告主要讲了哪些内容?"
response = agent.chat(f"请帮我搜索以下内容:{query}")
print(response)

结果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2278657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA:Quartus软件与操作系统版本对照表

文章目录 1.软件概述2.软件版本3.设计流程4.支持的设备5.新特性6.版本对照 1.软件概述 Quartus软件是由英特尔(Intel)公司开发的一款功能强大的FPGA(现场可编程逻辑门阵列)设计工具,广泛应用于数字电路设计、仿真、综…

【网络协议】【http】【https】AES-TLS1.2

【网络协议】【http】【https】AES-TLS1.2 https并不是一个协议 而是在传输层之间添加了SSL/TLS协议TLS TLS 协议用于应用层协议(如 HTTP)和传输层(如 TCP)之间,增加了一层安全性来解决 HTTP 存在的问题,H…

数智化转型 | 星环科技Defensor 助力某银行数据分类分级

在数据驱动的金融时代,数据安全和隐私保护的重要性日益凸显。某银行作为数字化转型的先行者,面临着一项艰巨的任务:如何高效、准确地对分布在多个业务系统、业务库与数仓数湖中的约80万个字段进行数据分类和分级。该银行借助星环科技数据安全…

微信小程序:播放音频

在小程序开发中,音频播放是一个重要的功能。本文将详细介绍小程序音频播放的相关知识点,帮助开发者更好地掌握小程序音频播放的实现方法。 一、小程序音频播放的基本流程 在小程序中,音频播放的基本流程如下: 获取音频数据&#…

U盘被格式化后的数据救赎与防范策略

一、U盘格式化后的数据困境 在日常的工作与生活中,U盘作为数据传输与存储的重要工具,扮演着不可或缺的角色。然而,当U盘不幸遭遇格式化操作后,存储在其中的宝贵数据瞬间化为乌有,给用户带来极大的困扰。格式化后的U盘…

关于 Cursor 的一些学习记录

文章目录 1. 写在最前面2. Prompt Design2.1 Priompt v0.1:提示设计库的首次尝试2.2 注意事项 3. 了解 Cursor 的 AI 功能3.1 问题3.2 答案 4. cursor 免费功能体验5. 写在最后面6. 参考资料 1. 写在最前面 本文整理了一些学习 Cursor 过程中读到的或者发现的感兴趣…

基于Oracle与PyQt6的电子病历多模态大模型图形化查询系统编程构建

一、引言 1.1 研究背景阐述 在当今数字化时代,医疗行业正经历着深刻的变革,数字化转型的需求日益迫切。电子病历(EMR)作为医疗信息化的核心,其管理的高效性和数据利用的深度对于提升医疗服务质量、优化临床决策以及推动医学研究具有至关重要的意义。传统的电子病历管理系…

算法(蓝桥杯)贪心算法7——过河的最短时间问题解析

一、题目描述 在漆黑的夜里,N位旅行者来到了一座狭窄且没有护栏的桥边。他们只带了一只手电筒,且桥窄得只够让两个人同时过。如果各自单独过桥,N人所需的时间已知;若两人同时过桥,则所需时间是走得较慢的那个人单独行动…

《贪心算法:原理剖析与典型例题精解》

必刷的贪心算法典型例题! 算法竞赛(蓝桥杯)贪心算法1——数塔问题-CSDN博客 算法竞赛(蓝桥杯)贪心算法2——需要安排几位师傅加工零件-CSDN博客 算法(蓝桥杯)贪心算法3——二维数组排序与贪心算…

SQL2000在win10上安装的方法

安装前最好先关闭防火墙和一些杀毒软件,因为这些软件在安装过程中可能会碰到注册表等一下杀毒软件比较敏感的地带,如果违反杀毒软件的规则会被当做病毒强行终止删除 首相找到C盘下window文件中的sysWOW64文件 鼠标右键,点击属性、安全、高级 …

【12】Word:张老师学术论文❗

目录 题目 ​NO2 NO3 NO4 NO5 NO6 NO7.8 题目 NO2 布局→页面设置→纸张:A4→页边距:上下左右边距→文档网格:只指定行网格→版式:页眉和页脚:页脚距边界:1.4cm居中设置论文页码:插入…

软件授权管理中的软件激活向导示例

软件激活向导示例 在软件许可中,提供许可应该是简单和安全的。这适用于想要在中央许可证服务器上创建新许可证的软件开发人员,也适用于需要在其设备上获得许可证的最终用户。如果所讨论的系统有互联网连接,或是暂时的连接,就可以…

基于微信小程序的摄影竞赛系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…

在IDEA中使用通义灵码插件:全面提升开发效率的智能助手

在IDEA中使用通义灵码插件:全面提升开发效率的智能助手 随着软件开发行业对效率和质量要求的不断提高,开发者们一直在寻找能够简化工作流程、提升代码质量的工具。阿里云推出的通义灵码插件正是这样一个旨在帮助开发者更高效地编写高质量代码的强大工具…

【Unity3D】利用Hinge Joint 2D组件制作绳索效果

目录 一、动态绳索 (可移动根节点) 二、静态绳索 三、利用Skinning Editor(Unity2022.3.15f1正常使用) 四、注意事项 一、动态绳索 (可移动根节点) 动态绳索 DynamicRope空物体 Anchor和whitecircle是相同位置的物体&#xff…

游戏引擎学习第80天

Blackboard:增强碰撞循环,循环遍历两种类型的 t 值 计划对现有的碰撞检测循环进行修改,以便实现一些新的功能。具体来说,是希望处理在游戏中定义可行走区域和地面的一些实体。尽管这是一个2D游戏,目标是构建一些更丰富…

2025.1.15——四、布尔注入

题目来源:ctfhub技能树 目录 一、基本操作:整理已知信息,得到本题为布尔注入 方法一:手工盲注(不推荐) step 1:判断具体形式 step 2:查询字段数 step 3:通过回显判…

PE文件:节表-添加节

在所有节的空白区域都不够存放我们想要添加的数据时,这个时候可以通过添加节来扩展我们可操作的空间去存储新的数据(如导入表、代码或资源)。 过程步骤 1.判断是否有足够的空间添加节表 PE文件的节表紧跟在PE头之后,每个节表的…

【前端动效】HTML + CSS 实现打字机效果

目录 1. 效果展示 2. 思路分析 2.1 难点 2.2 实现思路 3. 代码实现 3.1 html部分 3.2 css部分 3.3 完整代码 4. 总结 1. 效果展示 如图所示,这次带来的是一个有趣的“擦除”效果,也可以叫做打字机效果,其中一段文本从左到右逐渐从…

Python基于Django的图像去雾算法研究和系统实现(附源码,文档说明)

博主介绍:✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&#x1f3…