AI工具推荐——open-interpreter - mingupupup - 博客园

mikel阅读(85)

来源: AI工具推荐——open-interpreter – mingupupup – 博客园

前言

Open Interpreter 是一个能让大型语言模型在你本地电脑上运行代码的工具。 简单来说:

它提供了一个类似于 ChatGPT 的自然语言界面,让你能通过代码与电脑互动。 你可以用它来:

  • 创建和编辑各种类型的文件(照片、视频、PDF 等)。
  • 控制 Chrome 浏览器进行研究。
  • 分析数据集。

工作原理: Open Interpreter 为语言模型配备了一个函数,该函数可以在 Python、JavaScript 和 Shell 等各种语言中执行代码。 然后,它会将模型的消息、正在运行的代码和系统的输出流式传输到你的终端。

主要特点:

  • 它在本地运行,无需担心网络限制或文件大小限制。
  • 它通过自然语言界面简化了复杂的任务。

该项目目前已经收获了58.2kstars,GitHub地址:https://github.com/OpenInterpreter/open-interpreter

image-20250208094027464

我在体验之后,觉得是一个很棒的项目,因此推荐给大家。它的思路很好,我之前想的是创建很多工具,然后根据用户的意图,选择工具调用,但是用户需求是多变的,创建的工具不可能全部涵盖到,但是通过open-interpreter这种方式,就可以应对用户多变的需求了。

实践

首先创建一个python虚拟环境,安装open-interpreter:

pip install open-interpreter

虽然官方推荐使用gpt-40,但是为了在国内更多感兴趣的朋友能够方便体验,这里我以硅基流动提供的模型为例。现在硅基流动也有DeepSeek-R1并且邀请注册可得14元不过期额度,邀请链接:https://cloud.siliconflow.cn/i/Ia3zOSCU。

由于我硅基流动还有很多额度,接下来演示如何接入硅基流动的模型。

from interpreter import interpreter

interpreter.llm.model = "openai/deepseek-ai/DeepSeek-V3"
interpreter.llm.api_key = "sk-xxx"
interpreter.llm.api_base = "https://api.siliconflow.cn/v1"
interpreter.llm.context_window = 64000

# Start an interactive chat session
interpreter.chat()

第一个踩坑点,注意要加上openai表示是openai兼容的,不然报错如下:

image-20250208095153912

现在我以一个简单的办公需求来演示open-interpreter的效果。

我在项目目录,放入了一个excel,该excel中的数据,如下所示:

image-20250208095524855

现在根据这个excel随机提需求。

问题1:读取test.xlsx内容,商品A的累计销量是多少?

image-20250208095743329

给出计划,命令行操作与运行代码需要你的同意。

image-20250208095955211

模型假设列名是Product A,失败之后,请求获取列名。

image-20250208100052033

image-20250208100144833

答案是82正确!!

问题2:读取test.xlsx内容,以月份为横坐标,商品B为纵坐标,画一个折线图,需要能显示中文。

image-20250208100313341

模型列出了计划。

image-20250208100450196

模型给出代码。

image-20250208100524122

绘图结果正确。

对比硅基流动平台不同模型的效果。

deepseek-ai/DeepSeek-V3:

meta-llama/Llama-3.3-70B-Instruct:

Qwen/Qwen2.5-72B-Instruct:

视频效果在AI工具推荐——open-interpreter

最后

open-interpreter这个项目非常有意思,可玩性非常高,感兴趣的朋友快去试试吧!!!

将它与自己的日常需求结合看看能不能提高自己的效率。

浏览器自动化与AI Agent结合项目browser-use初探 - mingupupup - 博客园

mikel阅读(133)

来源: 浏览器自动化与AI Agent结合项目browser-use初探 – mingupupup – 博客园

browser-use介绍

browser-use是将您的 AI 代理连接到浏览器的最简单方式。它通过提供一个强大且简单的接口来实现 AI 代理访问网站的自动化。

GitHub地址:https://github.com/browser-use/browser-use。目前已经获得了27.3k颗stars,2.7kforks,看得出来是一个比较热门的项目。我在上手体验了之后,发现确实是一个很有趣的项目,因此推荐给大家。

实践

上手也非常简单,创建一个python虚拟环境,pip install browser-use,再playwright install即可。

现在需要进行LLM的配置,官方推荐使用gpt-4o,但是为了降低成本,方便让看了教程感兴趣的人能够方便上手,这里我使用的是硅基流动提供的模型。目前硅基流动注册送14元不过期额度,够用一段时间的了,邀请链接:https://cloud.siliconflow.cn/i/Ia3zOSCU。如果你的额度不够了,但是也想体验一下,可以私聊我,我可以提供一个api key暂时供你快速上手体验,额度用差不多了,我就停止了。

创建一个.env文件,这样写:

Silicon_Cloud_API_KEY=xxx
Base_URL=https://api.siliconflow.cn
Model=Qwen/Qwen2.5-72B-Instruct

创建一个test脚本,这样写:

from langchain_openai import ChatOpenAI
from browser_use import Agent
from dotenv import load_dotenv
import os
load_dotenv()

import asyncio

api_key = os.getenv('Silicon_Cloud_API_KEY')
base_url = os.getenv('Base_URL')
model = os.getenv('Model')

llm = ChatOpenAI(model=model, api_key=api_key, base_url=base_url)

async def main():
    agent = Agent(
        task="获取https://github.com/OpenInterpreter/open-interpreter仓库的前五个问题",
        llm=llm,
        use_vision=False,
    )
    result = await agent.run()
    print(result)

asyncio.run(main())

查看效果:

image-20250212085716642

image-20250212085758634

image-20250212085834372

还生成了一个agent_history.gif可以查看流程:

将结果与实际对比:

image-20250212090403603

可以发现browser-use非常准确的获取了。

再使用一个更普遍的例子,就是获取当前微博前十的热搜。

from langchain_openai import ChatOpenAI
from browser_use import Agent
from dotenv import load_dotenv
import os
load_dotenv()

import asyncio

api_key = os.getenv('Silicon_Cloud_API_KEY')
base_url = os.getenv('Base_URL')
model = os.getenv('Model')

llm = ChatOpenAI(model=model, api_key=api_key, base_url=base_url)

async def main():
    agent = Agent(
        task="获取当前微博前十的热搜",
        llm=llm,
        use_vision=False,
    )
    result = await agent.run()
    print(result)

asyncio.run(main())

image-20250212090822384

image-20250212090907000

最后

以上就是使用硅基流动中的Qwen/Qwen2.5-72B-Instruct快速体验browser-use的效果。初步体验感觉是一个很有潜力的项目,将AI Agent与浏览器自动化结合确实可以做很多事情。

如何让大模型安全地自动生成代码并执行? - mingupupup - 博客园

mikel阅读(128)

来源: 如何让大模型安全地自动生成代码并执行? – mingupupup – 博客园

前言

本文带来的分享是在crewai中使用代码解释器,为了安全,代码在docker中运行。

为什么要使用代码解释器呢?

之前的文章中使用的是function call + 各种工具 来完成一个任务,比如文件读取工具、文件保存工具等。

但是用户的需求是多变的,你很难提前写好所有的工具。

读取文件内容,使用代码解释器的效果如下所示:

image-20250224100624862

实践

首先需要看下crewai中提供的代码解释器工具代码,学习一下。

代码在:https://github.com/crewAIInc/crewAI-tools/tree/main/crewai_tools/tools/code_interpreter_tool

文件如下:

image-20250224100921024

先来看一下Dockerfile:

FROM python:3.12-alpine

RUN pip install requests beautifulsoup4 

# Set the working directory
WORKDIR /workspace

这是一个Dockerfile的片段,用于构建一个Python环境的Docker镜像。解释如下:

FROM python:3.12-alpine:这行指定了基础镜像为Python 3.12版本的Alpine Linux镜像。Alpine Linux是一种轻量级的Linux发行版,非常适合作为Docker镜像的基础。
RUN pip install requests beautifulsoup4:这行使用pip安装两个Python包:requests和beautifulsoup4。requests是一个用于发送HTTP请求的库,而beautifulsoup4是一个用于解析HTML和XML文档的库。
WORKDIR /workspace:这行设置了容器中的工作目录为/workspace。当容器启动时,会自动进入这个目录。
总的来说,这个Dockerfile构建了一个Python环境,安装了两个常用的库,并将工作目录设置为/workspace。这个镜像可以用于运行Python应用程序,尤其是那些需要解析HTML和发送HTTP请求的应用程序。

再来看一下code_interpreter_tool.py的代码:

import importlib.util
import os
from typing import List, Optional, Type
from crewai.tools import BaseTool
from docker import from_env as docker_from_env
from docker import DockerClient
from docker.models.containers import Container
from docker.errors import ImageNotFound, NotFound
from docker.models.containers import Container
from pydantic import BaseModel, Field


class CodeInterpreterSchema(BaseModel):
    """
    Input for CodeInterpreterTool.
    供代码解释工具输入。
    """

    code: str = Field(
        ...,
        # Python3代码原来是在Docker容器中被解释的。始终打印最终结果和代码的输出。
        description="Python3 code used to be interpreted in the Docker container. ALWAYS PRINT the final result and the output of the code",
    )

    libraries_used: Optional[List[str]] = Field(
        None,
        # 代码中使用的库列表,带有适当的安装名称,以逗号分隔。例如: numpy,pandas,beautifulsoup4
        description="List of libraries used in the code with proper installing names separated by commas. Example: numpy,pandas,beautifulsoup4",
    )


class CodeInterpreterTool(BaseTool):
    name: str = "Code Interpreter"
    description: str = "Interprets Python3 code strings with a final print statement."
    args_schema: Type[BaseModel] = CodeInterpreterSchema
    default_image_tag: str = "code-interpreter:latest"
    code: Optional[str] = None
    user_dockerfile_path: Optional[str] = None
    user_docker_base_url: Optional[str] = None
    unsafe_mode: bool = False

    @staticmethod
    def _get_installed_package_path():
        spec = importlib.util.find_spec("crewai_tools")
        return os.path.dirname(spec.origin)

    def _verify_docker_image(self) -> None:
        """
        Verify if the Docker image is available. Optionally use a user-provided Dockerfile.
        验证Docker镜像是否可用。可选地使用用户提供的Dockerfile。
        """

        client = (
            docker_from_env()
            if self.user_docker_base_url == None
            else DockerClient(base_url=self.user_docker_base_url)
        )

        try:
            client.images.get(self.default_image_tag)

        except ImageNotFound:
            if self.user_dockerfile_path and os.path.exists(self.user_dockerfile_path):
                dockerfile_path = self.user_dockerfile_path
            else:
                package_path = self._get_installed_package_path()
                dockerfile_path = os.path.join(
                    package_path, "tools/code_interpreter_tool"
                )
                if not os.path.exists(dockerfile_path):
                    raise FileNotFoundError(
                        f"Dockerfile not found in {dockerfile_path}"
                    )

            client.images.build(
                path=dockerfile_path,
                tag=self.default_image_tag,
                rm=True,
            )

    def _run(self, **kwargs) -> str:
        code = kwargs.get("code", self.code)
        libraries_used = kwargs.get("libraries_used", [])

        if self.unsafe_mode:
            return self.run_code_unsafe(code, libraries_used)
        else:
            return self.run_code_in_docker(code, libraries_used)

    def _install_libraries(self, container: Container, libraries: List[str]) -> None:
        """
        Install missing libraries in the Docker container
        """
        for library in libraries:
            container.exec_run(["pip", "install", library])

    def _init_docker_container(self) -> Container:
        container_name = "code-interpreter"
        client = docker_from_env()
        current_path = os.getcwd()

        # Check if the container is already running
        try:
            existing_container = client.containers.get(container_name)
            existing_container.stop()
            existing_container.remove()
        except NotFound:
            pass  # Container does not exist, no need to remove

        return client.containers.run(
            self.default_image_tag,
            detach=True,
            tty=True,
            working_dir="/workspace",
            name=container_name,
            volumes={current_path: {"bind": "/workspace", "mode": "rw"}},  # type: ignore
        )

    def run_code_in_docker(self, code: str, libraries_used: List[str]) -> str:
        self._verify_docker_image()
        container = self._init_docker_container()
        self._install_libraries(container, libraries_used)

        exec_result = container.exec_run(["python3", "-c", code])

        container.stop()
        container.remove()

        if exec_result.exit_code != 0:
            return f"Something went wrong while running the code: \n{exec_result.output.decode('utf-8')}"
        return exec_result.output.decode("utf-8")

    def run_code_unsafe(self, code: str, libraries_used: List[str]) -> str:
        """
        Run the code directly on the host machine (unsafe mode).
        """
        # Install libraries on the host machine
        for library in libraries_used:
            os.system(f"pip install {library}")

        # Execute the code
        try:
            exec_locals = {}
            exec(code, {}, exec_locals)
            return exec_locals.get("result", "No result variable found.")
        except Exception as e:
            return f"An error occurred: {str(e)}"

主要的参数与描述如下:

code: str = Field(
        ...,
        # Python3代码原来是在Docker容器中被解释的。始终打印最终结果和代码的输出。
        description="Python3 code used to be interpreted in the Docker container. ALWAYS PRINT the final result and the output of the code",
    )

    libraries_used: Optional[List[str]] = Field(
        None,
        # 代码中使用的库列表,带有适当的安装名称,以逗号分隔。例如: numpy,pandas,beautifulsoup4
        description="List of libraries used in the code with proper installing names separated by commas. Example: numpy,pandas,beautifulsoup4",
    )

测试这个工具的代码:

from crewai import LLM, Agent, Crew, Process, Task
# from crewai_tools import CodeInterpreterTool
from code_interpreter_tool import CodeInterpreterTool
import os
from dotenv import load_dotenv
load_dotenv()

api_key = os.getenv('SiliconCloud_API_KEY')
base_url = os.getenv('SiliconCloud_API_BASE')
model = os.getenv('SiliconCloud_MODEL_NAME', 'openai/Qwen/Qwen2.5-72B-Instruct')  # Provide a default model if not set

agent_llm = LLM(
model=model,
base_url=base_url,
api_key=api_key
	)

# Create an LLM with a temperature of 0 to ensure deterministic outputs
# llm = LLM(model="gpt-4o-mini", temperature=0)

# Create an agent with the knowledge store
agent = Agent(
    role="Tool User",
    goal="You know how to use the tool.",
    backstory="""
    You are a master at using the tool.
    使用代码执行工具时,如果没有使用库,则libraries_used参数为空列表,需要写成libraries_used=[]。
    """,
    verbose=True,
    allow_delegation=False,
    llm=agent_llm,
    tools=[CodeInterpreterTool()],
)
task = Task(
    description="""
    根据用户需求:{question}
    使用相应的工具。
    """,
    expected_output="获取本次工具输出的结果,无需其它内容。",
    agent=agent,
)

crew = Crew(
    agents=[agent],
    tasks=[task],
    verbose=True,
    process=Process.sequential,
)

result = crew.kickoff(
    inputs={
        "question": "获取test2.txt的内容"
    }
)

在这个地方可以输入你的需求看看代码解释器能不能实现。

先来一个最简单的:

result = crew.kickoff(
    inputs={
        "question": "输出你好世界"
    }
)

image-20250224101613286

再来一个创建文件的:

result = crew.kickoff(
    inputs={
        "question": "创建test3.txt,里面写入我是一只鱼。"
    }
)

image-20250224101933531

image-20250224102041955

再试一下需要使用库的:

result = crew.kickoff(
    inputs={
        "question": "画一个折线图,横坐标为1月、2月、3月,纵坐标为12、15、17,将结果保存到test.png。"
    }
)

image-20250224102742800

image-20250224102759227

中文字体没有正常显示,修改需求:

画一个折线图,横坐标为1月、2月、3月,纵坐标为121517,需要显示中文字体,将结果保存到test.png。

还是没有成功。

在docker环境中没有安装中文字体。

image-20250224103628011

并且使用代码解释器的一个缺点就是你无法保证AI生成的代码就是能用的,稍微复杂一点的需求,就有可能生成无法运行的代码。

image-20250224103800196

这样来看代码解释器的可玩性还是有很大的限制。

但是确实可以替代一些简单的工具了。

使用crewai创建属于你自己的AI团队 - mingupupup - 博客园

mikel阅读(118)

来源: 使用crewai创建属于你自己的AI团队 – mingupupup – 博客园

crewai介绍

CrewAI 是一个用于协调自主 AI 代理的前沿框架。

CrewAI 允许你创建 AI 团队,其中每个代理都有特定的角色、工具和目标,协同工作以完成复杂任务。

把它想象成组建你的梦之队——每个成员(代理)都带来独特的技能和专业知识,无缝协作以实现你的目标。

最近使用了crewai这个框架,我觉得是一个比较好用的AI Agent框架,因此推荐给大家。

在crewai中涵盖了AgentsTasksCrewsFlowsKnowledgeLLMsTools等这些核心概念。

接下来我将以一个具体的例子,介绍一下crewai的使用。

crewai的GitHub地址为:https://github.com/crewAIInc/crewAI

image-20250219164001573

使用crewai构建一个翻译代理

创建一个python虚拟环境,安装crewai与crewai-tools。

运行命令:

crewai create crew translation_agent

会出现一个模板项目。

在config目录下,使用yaml配置agent与task:

image-20250219164418938

先来设置一下代理:

file_reader:
  role: >
    读取文件代理
  goal: >
    根据文件路径,读取文件内容
  backstory: >
    你是一个文件读取代理,你的任务是根据文件路径,读取文件内容
​
translation_agent:
  role: >
    翻译代理
  goal: >
    根据用户需求翻译文本
  backstory: >
    你是一个翻译代理,你的任务是根据用户需求翻译文本
​
file_saver:
  role: >
    文件保存代理
  goal: >
    根据用户需求保存文件
  backstory: >
    你是一个文件保存代理,你的任务是根据用户需求保存文件

在这里设置了三个代理,分别是读取文件代理、翻译代理与文件保存代理。

再来配置一下task:

file_read_task:
  description: >
    根据用户需求:{question}
    获取需要读取的文件路径
    使用工具读取文件内容
  expected_output: >
    返回文件内容
  agent: file_reader
​
translation_task:
  description: >
    根据file_reader获取的文件内容,将文本翻译成英文
  expected_output: >
    返回翻译后的文本内容
  agent: translation_agent
​
file_save_task:
  description: >
   根据用户需求:{question}提取出需要保存到的文件路径及相关信息
   将translation_agent的翻译内容,保存至指定文件
  expected_output: >
    返回保存结果
  agent: file_saver

设置了三个任务,分别是file_read_task、translation_task与file_save_task。

完成这些任务,需要代理能够使用读取文件与保存文件的工具。

在tools目录下可以写工具代码:

image-20250219165027457

file_read_tool工具代码:

from typing import Any, Optional, Type
​
from crewai.tools import BaseTool
from pydantic import BaseModel, Field
​
​
class FileReadToolSchema(BaseModel):
    """Input for FileReadTool."""
​
    # Mandatory file full path to read the file
    # 必须的文件全路径,以读取文件
    file_path: str = Field(..., description="Mandatory file full path to read the file")
​
​
class FileReadTool(BaseTool):
    """A tool for reading file contents.
​
    This tool inherits its schema handling from BaseTool to avoid recursive schema
    definition issues. The args_schema is set to FileReadToolSchema which defines
    the required file_path parameter. The schema should not be overridden in the
    constructor as it would break the inheritance chain and cause infinite loops.
​
    The tool supports two ways of specifying the file path:
    1. At construction time via the file_path parameter
    2. At runtime via the file_path parameter in the tool's input
​
    Args:
        file_path (Optional[str]): Path to the file to be read. If provided,
            this becomes the default file path for the tool.
        **kwargs: Additional keyword arguments passed to BaseTool.
​
    Example:
        >>> tool = FileReadTool(file_path="/path/to/file.txt")
        >>> content = tool.run()  # Reads /path/to/file.txt
        >>> content = tool.run(file_path="/path/to/other.txt")  # Reads other.txt
​
    用于读取文件内容的工具。
​
    该工具继承自 BaseTool 的 schema 处理,以避免递归 schema 定义问题。args_schema 设置为 FileReadToolSchema,定义了必需的 file_path 参数。构造函数中不应该覆盖 schema,否则会破坏继承链并导致无限循环。
​
    该工具支持两种指定文件路径的方法:
​
    在构造时通过 file_path 参数
    在运行时通过工具的输入参数 file_path
​
    参数:
    file_path (可选[str]): 要读取的文件路径。如果提供,则成为工具的默认文件路径。
    **kwargs: 传递给 BaseTool 的其他关键字参数。
​
    示例:
    >>> tool = FileReadTool(file_path="/path/to/file.txt")
    >>> content = tool.run()  # 读取 /path/to/file.txt
    >>> content = tool.run(file_path="/path/to/other.txt")  # 读取 other.txt
    """
​
    name: str = "Read a file's content"
    description: str = "A tool that reads the content of a file. To use this tool, provide a 'file_path' parameter with the path to the file you want to read."
    args_schema: Type[BaseModel] = FileReadToolSchema
    file_path: Optional[str] = None
​
    def __init__(self, file_path: Optional[str] = None, **kwargs: Any) -> None:
        """
        Initialize the FileReadTool.
​
        Args:
            file_path (Optional[str]): Path to the file to be read. If provided,
                this becomes the default file path for the tool.
            **kwargs: Additional keyword arguments passed to BaseTool.
​
        初始化 FileReadTool。
​
        参数:
        file_path(可选[str]):要读取的文件路径。如果提供,则此路径成为工具的默认文件路径。
        **kwargs:传递给 BaseTool 的其他关键字参数。
        """
​
        if file_path is not None:
            kwargs['description'] = f"A tool that reads file content. The default file is {file_path}, but you can provide a different 'file_path' parameter to read another file."
​
        super().__init__(**kwargs)
        self.file_path = file_path
​
    def _run(
        self,
        **kwargs: Any,
    ) -> str:
        file_path = kwargs.get("file_path", self.file_path)
        if file_path is None:
            return "Error: No file path provided. Please provide a file path either in the constructor or as an argument."
​
        try:
            with open(file_path, "r",encoding='utf-8') as file:
                return file.read()
        except FileNotFoundError:
            return f"Error: File not found at path: {file_path}"
        except PermissionError:
            return f"Error: Permission denied when trying to read file: {file_path}"
        except Exception as e:
            return f"Error: Failed to read file {file_path}. {str(e)}"

file_writer_tool工具代码:

import os
from ast import literal_eval
from typing import Any, Optional, Type
​
from crewai.tools import BaseTool
from pydantic import BaseModel
​
​
class FileWriterToolInput(BaseModel):
    filename: str
    directory: Optional[str] = "./"
    overwrite: str = "False"
    content: str
​
​
class FileWriterTool(BaseTool):
    name: str = "File Writer Tool"
    description: str = "A tool to write content to a specified file. Accepts filename, content, and optionally a directory path and overwrite flag as input,overwrite flag is True or False."
    args_schema: Type[BaseModel] = FileWriterToolInput
​
    def _run(self, **kwargs: Any) -> str:
        try:
            # Create the directory if it doesn't exist
            if kwargs.get("directory") and not os.path.exists(kwargs["directory"]):
                os.makedirs(kwargs["directory"])
​
            # Construct the full path
            filepath = os.path.join(kwargs.get("directory") or "", kwargs["filename"])
​
            # Convert overwrite to boolean
            kwargs["overwrite"] = bool(literal_eval(kwargs["overwrite"]))
​
            # Check if file exists and overwrite is not allowed
            if os.path.exists(filepath) and not kwargs["overwrite"]:
                return f"File {filepath} already exists and overwrite option was not passed."
​
            # Write content to the file
            mode = "w" if kwargs["overwrite"] else "x"
            with open(filepath, mode) as file:
                content = kwargs["content"]
                file.write(content)
            return f"Content successfully written to {filepath}"
        except FileExistsError:
            return (
                f"File {filepath} already exists and overwrite option was not passed."
            )
        except KeyError as e:
            return f"An error occurred while accessing key: {str(e)}"
        except Exception as e:
            return f"An error occurred while writing to the file: {str(e)}"

现在需要构建一个团队。

构建团队的代码:

from crewai import Agent, Crew, Process, Task,LLM
from crewai.project import CrewBase, agent, crew, task
from translation_agent.tools.file_read_tool import FileReadTool
from translation_agent.tools.file_writer_tool import FileWriterTool
import os
from dotenv import load_dotenv
load_dotenv()
​
file_read_tool = FileReadTool()
file_writer_tool = FileWriterTool()
​
api_key = os.getenv('OPENAI_API_KEY')
base_url = os.getenv('OPENAI_API_BASE')
model = os.getenv('OPENAI_MODEL_NAME', 'Qwen/Qwen2.5-72B-Instruct')  # Provide a default model if not set
agent_llm = LLM(
    model=model,
    base_url=base_url,
    api_key=api_key
    )
​
# If you want to run a snippet of code before or after the crew starts, 
# you can use the @before_kickoff and @after_kickoff decorators
# https://docs.crewai.com/concepts/crews#example-crew-class-with-decorators
​
​
@CrewBase
class TranslationAgent():
    """TranslationAgent crew"""
​
    # Learn more about YAML configuration files here:
    # Agents: https://docs.crewai.com/concepts/agents#yaml-configuration-recommended
    # Tasks: https://docs.crewai.com/concepts/tasks#yaml-configuration-recommended
    agents_config = 'config/agents.yaml'
    tasks_config = 'config/tasks.yaml'
    
    # If you would like to add tools to your agents, you can learn more about it here:
    # https://docs.crewai.com/concepts/agents#agent-tools
    # @agent
    # def researcher(self) -> Agent:
    #   return Agent(
    #       config=self.agents_config['researcher'],
    #       verbose=True
    #   )
​
    # @agent
    # def reporting_analyst(self) -> Agent:
    #   return Agent(
    #       config=self.agents_config['reporting_analyst'],
    #       verbose=True
    #   )
    
    @agent
    def file_reader(self) -> Agent:     
        return Agent(
            config=self.agents_config['file_reader'],
            verbose=True,
            llm=agent_llm,
            tools=[file_read_tool],
        )
    
    @agent
    def translation_agent(self) -> Agent:       
        return Agent(
            config=self.agents_config['translation_agent'],
            verbose=True,
            llm=agent_llm,      
        )
    
    @agent
    def file_saver(self) -> Agent:      
        return Agent(
            config=self.agents_config['file_saver'],
            verbose=True,
            llm=agent_llm,
            tools=[file_writer_tool],
        )
    
    # To learn more about structured task outputs, 
    # task dependencies, and task callbacks, check out the documentation:
    # https://docs.crewai.com/concepts/tasks#overview-of-a-task
    @task
    def file_read_task(self) -> Task:
        return Task(
            config=self.tasks_config['file_read_task'],
        )
​
    @task
    def translation_task(self) -> Task:
        return Task(
            config=self.tasks_config['translation_task'],
        )
    
    @task
    def file_save_task(self) -> Task:
        return Task(
            config=self.tasks_config['file_save_task'],
        )
​
    @crew
    def crew(self) -> Crew:
        """Creates the TranslationAgent crew"""
        # To learn how to add knowledge sources to your crew, check out the documentation:
        # https://docs.crewai.com/concepts/knowledge#what-is-knowledge
​
        return Crew(
            agents=self.agents, # Automatically created by the @agent decorator
            tasks=self.tasks, # Automatically created by the @task decorator
            process=Process.sequential,
            verbose=True,
            # process=Process.hierarchical, # In case you wanna use that instead https://docs.crewai.com/how-to/Hierarchical/
        )

其中我想让代理使用硅基流动的模型可以这样写:

image-20250219165445665

需要在模型名称前加上openai才行,不如会报错。

如果你还没注册的话,可以点击邀请链接进行注册:https://cloud.siliconflow.cn/i/Ia3zOSCU

这里我以具有工具调用能力的meta-llama/Llama-3.3-70B-Instruct为例。

然后可以这样使用:

import os
from dotenv import load_dotenv
load_dotenv()
​
file_read_tool = FileReadTool()
file_writer_tool = FileWriterTool()
​
api_key = os.getenv('OPENAI_API_KEY')
base_url = os.getenv('OPENAI_API_BASE')
model = os.getenv('OPENAI_MODEL_NAME', 'Qwen/Qwen2.5-72B-Instruct')  # Provide a default model if not set
agent_llm = LLM(
    model=model,
    base_url=base_url,
    api_key=api_key
    )

在创建代理时,记得使用这个大模型,并且记得使用工具:

@agent
def file_reader(self) -> Agent:     
        return Agent(
            config=self.agents_config['file_reader'],
            verbose=True,
            llm=agent_llm,
            tools=[file_read_tool],
        )

这样这个团队就构建成功了。

在main.py中这样写:

#!/usr/bin/env python
import sys
import warnings
​
from datetime import datetime
​
from translation_agent.crew import TranslationAgent
​
warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")
​
# This main file is intended to be a way for you to run your
# crew locally, so refrain from adding unnecessary logic into this file.
# Replace with inputs you want to test with, it will automatically
# interpolate any tasks and agents information
​
def run():
    """
    Run the crew.
    """
    inputs = {
        'question': '读取test.txt文件内容,将其翻译为英文,然后写入test4.txt文件',
    }
    
    try:
        TranslationAgent().crew().kickoff(inputs=inputs)
    except Exception as e:
        raise Exception(f"An error occurred while running the crew: {e}")
​
​
def train():
    """
    Train the crew for a given number of iterations.
    """
    inputs = {
        "topic": "AI LLMs"
    }
    try:
        TranslationAgent().crew().train(n_iterations=int(sys.argv[1]), filename=sys.argv[2], inputs=inputs)
​
    except Exception as e:
        raise Exception(f"An error occurred while training the crew: {e}")
​
def replay():
    """
    Replay the crew execution from a specific task.
    """
    try:
        TranslationAgent().crew().replay(task_id=sys.argv[1])
​
    except Exception as e:
        raise Exception(f"An error occurred while replaying the crew: {e}")
​
def test():
    """
    Test the crew execution and returns the results.
    """
    inputs = {
        "topic": "AI LLMs"
    }
    try:
        TranslationAgent().crew().test(n_iterations=int(sys.argv[1]), openai_model_name=sys.argv[2], inputs=inputs)
​
    except Exception as e:
        raise Exception(f"An error occurred while testing the crew: {e}")

主要关注这里:

def run():
    """
    Run the crew.
    """
    inputs = {
        'question': '读取test.txt文件内容,将其翻译为英文,然后写入test4.txt文件',
    }
    
    try:
        TranslationAgent().crew().kickoff(inputs=inputs)
    except Exception as e:
        raise Exception(f"An error occurred while running the crew: {e}")

在inputs中输入task中的question占位符的内容。

现在创建一个test.txt,输入内容为:

CrewAI:用于编排复杂 AI 代理系统的生产级框架。从简单的自动化到复杂的现实世界应用,CrewAI 提供精确控制和深度定制。通过灵活的、可投入生产的架构促进协作智能,CrewAI 使代理能够无缝协作,以可预测和一致的结果解决复杂的商业挑战。

现在输入crewai run,看看这个翻译代理的效果。

image-20250219171523468

可以发现读取文件代理做的不够好的地方是多了一些内容。

需要进行改进。

改成这样再试试:

file_reader:
  role: >
    读取文件代理
  goal: >
    根据文件路径,读取文件内容
  backstory: >
    你是一个文件读取代理,你的任务是根据文件路径,读取文件内容,只需返回文件内容即可

现在效果就很好了,如下所示:

image-20250219172033798

翻译代理很好地进行翻译了,如下所示:

image-20250219172055009

文件保存代理将翻译结果进行保存,如下所示:

image-20250219172229853

image-20250219172317889

最后

这就是使用crewai构建一个翻译代理的步骤与效果。在crewai中还有很多很有趣的工具值得探索,下期介绍代码解释器工具的使用。

Manus的开源复刻OpenManus初探 - mingupupup - 博客园

mikel阅读(114)

来源: Manus的开源复刻OpenManus初探 – mingupupup – 博客园

OpenManus介绍

Manus需要邀请码才能体验,目前大部分人都体验不到。

有几个大佬花3个小时就复现了一个简单的原型OpenManus,让我们体验体验吧!!

截至目前,该项目已经获得了25.9k颗星标,是一个非常热门的项目。

GitHub地址:https://github.com/mannaandpoem/OpenManus

image-20250311100212446

实践

话不多说,直接上手实践。

git clone https://github.com/mannaandpoem/OpenManus.git
cd OpenManus
uv venv
.venv\Scripts\activate
uv pip install -r requirements.txt

上手配置:

image-20250311100600763

将config.example.toml复制一份重命名为config.toml。

或者直接运行命令:

cp config/config.example.toml config/config.toml

我先使用硅基流动的Qwen/Qwen2.5-72B-Instruct模型试试水。

image-20250311100938940

直接运行main.py即可。

运行之后如下所示:

image-20250311101034092

需要你输入一个任务。

我就以“导航至https://github.com/mannaandpoem/OpenManus获取star数量”为例。

image-20250311101318649

image-20250311101355429

确实打开了浏览器,但是报错了没有能够完成这个任务。

可能跟模型的能力有关。

我这次使用gemini-2.0-flash再试试。

配置文件如下所示:

image-20250311101838068

再试试刚刚那个任务:

image-20250311102306312

再试试获取这个仓库的前五个问题:

image-20250311102448597

image-20250311102516892

接下来测试一下生成文件的功能,输入“生成一个test.txt文件,里面写入小铭同学AI工具学习记录”。

image-20250311102747068

image-20250311102806589

简单测试了一个OpenManus用Gemini可以跑通了。

还有一个类似的项目叫OWL,目前遇到的一个问题就是一直没有看到浏览器出现。

目前还没有解决,试了Gemini也还是不行。

等等看有没有什么解决方案吧!!

以上就是今天的分享,希望对你有所帮助。

前端订单编辑明细加载速度优化经验总结

mikel阅读(85)

现在有个订单表单布局如下

头部和明细的组合布局,现在出现的问题是明细加载很慢,前端用的是layui实现的,因为form初始化和table都是异步加载,通过谷歌的开发者工具查看页面加载的过程发现明细的异步加载需要10秒以上,尽管后端加了redis缓存,前端的效率还是上不去,开始以为是数据库查询太慢了,不过通过后台执行查询SQL语句,发现并不慢1秒就完成了,那是什么原因呢?!

首先,还是从前端加载开始分析,开始总是盯着明细的异步加载慢的优化,一直改善不了,包括IIS服务器的应用程序池的最大进程数量的调整,提高并发的响应速度,调整了,有效果但是不明显。

然后,开始查看页面的加载顺序,发现了一个比明细加载还慢的异步请求,如图

这个getEntity的异步请求7秒多,比明细加载还慢,于是追查下去发现这个请求了一个跨数据库的查询24万条记录的视图,查询很慢,于是初步分析判断是不是因为这个查询慢的异步请求在明细异步请求getList之前导致,明细的请求被后台数据库处理堵塞在了慢查询的后面等待队列中,导致整个明细查询结果返回慢,于是将慢查询的getEntity放在table明细的异步加载成功后再处理,是不是会提高加载速度?!于是调整了顺序,如上图所示,结果560ms就加载完明细了!尽管getEntiy还是7秒多,但是不影响整体页面呈现效果了!

下一步就是对getEntity整个慢查询的优化了。

总结,现在前端如果响应慢很多时候总是固化的思维模式“哪慢查哪的问题”这么来解决问题,对于常规的问题的确可以找到问题原因,但是特殊情况会如这个问题一样,很多因素导致加载慢的问题出现,这样往往忽略了问题的真正根源在哪?需要跳出固化思维从全局来看待,这才是更好的解决思路!

C#/.NET/.NET Core优秀项目和框架2025年2月简报 - 追逐时光者 - 博客园

mikel阅读(78)

来源: C#/.NET/.NET Core优秀项目和框架2025年2月简报 – 追逐时光者 – 博客园

前言

公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的详细介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。

eShop

Bulk Crap Uninstaller

  • 项目简介: Bulk Crap Uninstaller 是一款基于 .NET 开源(Apache License)、免费、功能强大的Windows应用卸载工具,旨在帮助用户快速且有效地移除系统中不再需要的大量应用程序。支持批量和强制卸载、清理残留文件、检测隐藏或受保护的已注册应用等功能。虽然面向 IT 专业人员设计,但其简单的默认设置,让任何人都能轻松上手。
  • 项目源码地址: https://github.com/Klocman/Bulk-Crap-Uninstaller
  • 项目详细介绍: https://mp.weixin.qq.com/s/jZCDMcjnpj-_N52jxHgxKw

Netnr.Login

  • 项目简介: Netnr.Login是一个基于 C# 开源(MIT License)的第三方 OAuth2 授权登录整合库,集成了QQ、微信开放平台(Weixin)、微信公众平台(WeixinMP)、微博(Weibo)、淘宝(Taobao)、支付宝(Alipay)、钉钉(DingTalk)、飞书(Feishu)、华为(Huawei)、小米(Xiaomi)、AtomGit、码云(Gitee)、GitHub、GitLab、微软(Microsoft )、StackOverflow等授权登录功能,可以帮助大家快速完成常见的第三方平台的登录授权功能。
  • 项目源码地址: https://gitee.com/netnr/Netnr.Login
  • 项目详细介绍: https://mp.weixin.qq.com/s/XT8WeRxa-_qmrOAs8odj5w

BYSerial

V-Control

Plotly.NET

NetPad

WinformDevFramework

MatBlazor

Cofoundry

mom

  • 项目简介: tmom是一款基于 .NET 开源、通用的生产制造系统,支持多厂区/多项目级的MOM/MES系统,计划排程、工艺路线设计、在线低代码报表、大屏看板、移动端、AOT客户端…… 目标是尽可能打造一款通用的生产制造系统。前端基于最新的vue3、ts、ant design vue, 后端使用.net8、SQLsugar,支持多种数据库切换、数据隔离与聚合。
  • 项目源码地址: https://gitee.com/thgao/tmom
  • 项目详细介绍: https://mp.weixin.qq.com/s/KOxtnNRUngeaSb5vZ86Z-Q

大人的玩具:我用100块做了一个AI眼镜【上篇】

mikel阅读(73)

来源: 大人的玩具:我用100块做了一个AI眼镜【上篇】

自己动手做一个AI 眼镜

5月13日,正好看到Nik Shevchenko分享了一个视频,展示他用20 美元制作了一个外设,挂在眼镜边上,就可以做一个AI智能眼镜,于是我准备复刻一个。

首先是准备工作

项目地址:https://github.com/BasedHardware/OpenGlass

你需要的硬件是一台电脑(我用的是MacPro M2芯片),一个开发板、一个电池、一个3D打印的外壳。

  • Seeed Studio XIAO ESP32 S3 Sense(带蓝牙、摄像头和麦克风)
  • EEMB LP502030 3.7v 250mAH battery
  • 3D printed glasses mount case

这些国内都能买到,需要购买清单的可以滴滴我

(😄我找开发板老板,化缘了一个618粉丝专属福利,备注Rocket)

图片

等硬件都拿到手后,可以开始开发板软件工作了。

01 下载Arduino IDE

Arduino产品地址:https://www.arduino.cc/en/software

这个软件我在整合包里准备好了,大家可以直接回复“Glass”下载

02 设置ESP32S3主板程序

打开Terminal,输入下面代码,把OpenGlass项目代码下载到本地,你也可以手动下载。

git clone <https://github.com/BasedHardware/OpenGlass.git>
然后打开找到OpenGlass文件夹里的 firmware folder 文件夹,并在 Arduino IDE 中打开 .ino 文件。

为ESP32S3 Sense主板设置 Arduino IDE:

图片

将 ESP32S3 板 添加到您的 Arduino IDE

  • 菜单栏,选择“文件”>“首选项”(File > Preferences),然后在“其他 Boards Manager URL”(“Additional Boards Manager URLs” )填写这个链接:https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  • 导航到“工具”>“开发板”>“开发板管理器…”(Tools > Board > Boards Manager),在搜索框中输入关键字 esp32 ,选择最新版本的 esp32 并安装它。我这两个都安了一下,但任意选一个就行。图片
  • 最近这个更新到3.0.0版本,但是会引起烧录时报错,建议安装2.0.17版本
  • 选择您的主板和端口:
    • 在 Arduino IDE 顶部,选择开发板和端口。
    • 弹窗中搜索 xiao 并选择 XIAO_ESP32S3 。

图片

“PSRAM:”设置为“PSRAM:”“OPI PSRAM”

在刷机之前,转到Arduino IDE中的“工具”下拉列表,并确保将“PSRAM:”设置为“PSRAM:”“OPI PSRAM”

图片

官方的教程就到这了,但如果你这个时候进行编译,一定会发现哐哐报错。

因为还有一些依赖库没有安装。

我们还需要点击左边菜单的库,搜索并安装 ArduinoBLE、esp_camera

图片安装完后,基本就ok了,如果还有报错,可以看看是否还有依赖库没安上。

现在你可以选一根质量好一点的type c数据线把板子和电脑连接,进行烧录程序。

  • 点击 验证 按钮(对号图标),检查代码是否有错误。
  • 点击 上传 按钮(箭头图标),将代码上传到XIAO ESP32S3开发板。

03 验证功能

  1. 打开Arduino IDE的 串口监视器,检查输出信息。
  2. 确保设备连接到蓝牙。
  3. 检查摄像头是否能够拍照,并通过蓝牙发送数据。

按照这些步骤进行操作,你应该能够成功地将固件上传到XIAO ESP32S3开发板,并实现摄像头和蓝牙的功能。

到这一步,软件工作基本开发结束了,这个时候还有2个步骤需要完成。

04 完善硬件:XIAO ESP32S3开发板连接天线、摄像头、电池

天线的安装

在XIAO ESP32S3的正面左下角,设计了一个独立的“WiFi/BT天线连接器”。

安装天线小窍门:轻轻地将天线连接器的一侧嵌入到连接器块内,从另一侧轻轻下压,就能轻松安装。

同样地,当需要拆卸天线时,也只需在一侧施力,轻轻地提起。图片

安装扩展板

XIAO ESP32S3 Sense,还包括一个扩展板。此扩展板具有1600*1200 OV2640摄像头传感器、板载SD卡插槽和数字麦克风。

安装扩展板非常简单,只需将扩展板上的连接器与XIAO ESP32S3上的B2B连接器对齐,用力按压并听到“咔嗒”一声,即可完成安装。

图片

 

焊接电池

其实如果你不真的戴着这个眼镜出门,可以不用接电池。这块需要用电烙铁焊接,没有焊接技能的人不推荐自己动手,容易把板子搞坏。

焊接电池方法,电池负极焊接到开发板的负极,将正极焊接到开关上,然后再焊接回开发板的正极。这个部分我会在下篇里详细讲到。

05 启动照片的页面程序

烧录完主板,还需要设置一下 Groq 和OpenAI的API。

1. 在位于sources/keys.ts keys.ts 的文件中添加 Groq 和 OpenAI 的 API 密钥。

2. 对于 Ollama,从存储库中自行托管 https://github.com/ollama/ollama 的 REST API,并将 URL 添加到 keys.ts 文件中。

3.启动应用程序:

npm start

如果使用 yarn 启动应用程序


yarn start

启动成功,你在Terminal能看到web页面地址,复制到浏览器可以打开。

图片

目前到这个阶段,我可以通过这个AI设备,实现的功能是可以每隔4秒自动拍照照片,并自动上传记录在本地电脑上。

SQL Server 2025 AI相关能力初探 - CareySon - 博客园

mikel阅读(103)

来源: SQL Server 2025 AI相关能力初探 – CareySon – 博客园

SQL Server 在2024年11月开始进行社区私有预览(链接),由于涉及AI能力,我也是第一时间申请了内侧资格,悲剧的是,直到2025年2月,才拿到预览版的测试资格-.-,此时已经是CTP1.3了,也就是内侧的第四个版本了。

但whatever,late better than never。下面根据我的初步测试,做一些分享。

当前的测试的版本为:

 

原生向量支持与DiskANN向量索引

SQL Server作为一个典型的商业数据库,一直喜欢搞大而全,各种全家桶全塞进来,现在流行的说法叫“一站式”。基本逻辑是每个sql server版本都会结合当时流行的趋势和技术,将该技术集成进SQL Server,下面是一个简单的回顾

 

历代SQL Server结合当时背景的新增功能分析

SQL Server 2008 – 层级结构 (HierarchyID) 和地理信息 (Spatial Data):

 Web 2.0 兴起,层级数据和位置服务应用普及。HierarchyID 高效管理组织结构等层级数据,Spatial Data 支持位置服务,满足 Web 2.0 时代对复杂数据管理和地理位置应用的需求。

 

SQL Server 2012 – 内存数据库 (In-Memory OLTP):

电商等高并发 OLTP 应用爆发,磁盘 I/O 成性能瓶颈。另外这个时代SSD还是贵的没边,稳定性还没这么靠谱的存储。内存优化表 减少磁盘 I/O,大幅提升高并发 OLTP 性能,应对电商、金融等对极致性能的迫切需求。

但目前来看,这个功能使用率并不是很高,该功能通常通过外挂的缓存系统实现,比如Redis。

 

SQL Server 2014 – 列存储 (Columnstore):

大数据分析兴起,传统行式存储分析查询效率低下。列式索引优化分析查询,大幅提升大数据仓库性能,顺应大数据分析流行趋势,满足企业数据洞察需求。

 

SQL Server 2016 – JSON 支持 (JSON Support):

Web 服务和 NoSQL 流行,JSON 成 Web 数据交换主流格式。JSON 支持 允许存储和查询 JSON 数据,灵活适应 Web 服务和半结构化数据,拥抱 NoSQL 趋势,拓展应用场景。

 

SQL Server 2017 – 图数据库 (Graph Database):

社交网络、推荐系统等关系复杂应用兴起,传统关系数据库效率不高。图数据库 支持建模复杂关系,高效处理社交网络、推荐系统等应用。

 

SQL Server 2019 – HTAP (Hybrid Transactional/Analytical Processing):

实时数据分析需求强烈,传统数据仓库延迟高。HTAP 能力 支持实时分析,提升决策效率,符合实时业务监控和快速决策需求,顺应混合处理趋势。

 

SQL Server 2022 – 账本 (Ledger Tables):

数据安全和合规性日益重要,区块链技术火的一塌糊涂(比特币价格起飞),需要防篡改数据记录。账本表 提供防篡改数据记录,增强数据完整性和可信度,满足审计、合规等对数据可信有高要求的场景,拥抱区块链技术,提升数据安全水平。

 

SQL Server 2025 – 向量数据库 (Vector Database):

当下AI的爆发年代来看,需要向量数据库的背景无需多说,向量数据库在应用层面主要用于RAG、语义理解、大规模向量数据处理和多模态融合,并能显著降低向量检索计算成本。是AI应用中最重要的基础设施之一。

 

原生向量类型支持

SQL Server增加内置的Vector字段,最高支持1998维度(猜想是因为每个向量都是32精度的float,1998维度正好不超过SQL Server每页的8K存储,从而不溢出),通过测试可以发现,内部存储使用varbinary数据作为底层数据,做了一个简单的测试,通过新增变量类型为Vector,或表列定义为Vector列实现,如图所示:

 

基于DiskANN的向量相似度检索

DiskANN介绍

DiskANN基于微软2019年发表的论文《DiskANN: Fast Accurate Billion-point Nearest Neighbor Search on a Single Node》。在此之前,向量搜索领域中一个流行的主要算法是HNSW(分层可导航小世界图),这是一种利用多层图结构进行搜索的算法。HNSW的核心特点是涉及大量的随机内存访问,因此该算法需要消耗大量内存资源,要求原始向量和图数据都必须常驻内存中。

图.HNSW图查找示例

 

我们以阿里云的Millivs托管服务为例,如果涉及1千万的512维向量数据为例,推荐资源如下:

图. Millivs对于千万级512维向量的推荐资源

 

这种资源要求所带来的成本较高,会比较多限制AI的落地。针对于此,DisnANN的核心目标是,用有限的内存(几十GB)+大容量的SSD盘,支撑单节点存储和搜索十亿级别的数据集,同时保持高性能(低延迟、高召回率)。

DiskANN的核心算法是Vamana图,本质上是一种构建近似最近邻图的方法,它为每个节点构建一个有限数量的出边,这些出边连接到该节点的近似最近邻。与HNSW的多层结构不同,Vamana构建单层图,但通过精心设计的图构建过程确保搜索效率。举个例子理解是Vamana图就像一张城市地图,每个数据点是地图上的一个地点,边代表地点之间的邻近关系。DiskANN 的搜索过程就像在地图上导航,从某个起始点出发,沿着边不断“走”到离目标地点最近的位置。

同时DiskANN还做了一些优化,来适应磁盘换内存的场景,例如:

  • k-means聚类(分而治之),降低建图的内存需求。
  • PQ量化(数据压缩),减少内存和计算量。
  • SSD定长数据(高效存储),加速读取。
  • 入口节点和邻居放内存(缓存热点),减少SSD访问。
  • beam-search(并行搜索),提升搜索效率。

 下面是根据论文,做了一个DiskANN的简单数据:

 

SQL Server中相似度搜索使用方式

当前在SQL Server的CTP1.3版本中,向量搜索的核心函数主要是VECTOR_DISTENCE,可以结合在传统的T-SQL中使用,目前该函数还比较初级,当前仅支持余弦相似度、欧式距离和点积。一个简单的示例如下:

-- 创建一个包含向量字段的表
CREATE TABLE VectorTable (
    ID INT PRIMARY KEY IDENTITY(1,1),
    Description NVARCHAR(100),
    EmbeddingVector VECTOR(10) -- 创建10维向量字段
);

INSERT INTO VectorTable (Description, EmbeddingVector)
VALUES 
    ('示例项目1', '[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]'),
    ('示例项目2', '[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]'),
    ('示例项目3', '[0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0]');


DECLARE @queryVector VECTOR(10) = '[0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0.1]';



-- 使用余弦相似度查找最相似的向量
SELECT 
    ID, 
    Description,
    vector_distance('cosine' , @queryVector, EmbeddingVector)
FROM VectorTable

余弦相似度的结果如下:

图. 计算余弦相似度

 

同时SQL Server也支持使用和传统的关系数据共同作用,进行相似度查询,例如该例子,结合where条件,帮助用户通过where做过滤,同时选出top 5相似度的产品:

  -- 假设我们有一个查询向量(可能来自用户当前正在查看的产品)
DECLARE @query_vector VECTOR(512) = CAST(CONCAT('[', REPLICATE('0.15,', 511), '0.15]') AS VECTOR(512));

-- 查找与当前产品最相似的5个产品(使用余弦相似度)
SELECT top 5
    id,
    category,
    description,
    vector_distance('cosine' , @query_vector, vector) AS similarity_score
FROM 
    VectorDemo
where category = 'Clothing'
ORDER BY 
    similarity_score

结果如下:

图.余弦相似度计算结果

 

相似度搜索的性能

由于当前我拿到的是私有预览版的sql server,并没有合适的帮助文档,因此不确定我的使用方式是否正确,按我的理解,可能需要针对向量列单独加索引,但目前没看到加索引的方式,下面的测试是基于没有加索引的测试。测试的数据量如下:

当前我们的测试表大约是200W+的数据,每列包含512维的向量,大约数据占用是6G左右,当我做一个简单的相似度搜索时,可以看到

 

虽然查询完成时间在334毫秒,从逻辑读(80万的逻辑读*8K每次读取,基本等于数据量大小)来看,基本走了全表扫描,而CPU使用也是非常高,基本需要1个CPU 100%,2.3S时间。

当前查询完成快是数据已经常驻内存,那么如果我将sql server使用内存调低,涉及到IO读写呢?比如当前数据量维6.9G,我将内存使用上限调整为6G会发生什么:

 

由于开始涉及物理读写,我们看到整个查询时间来到不可接受的节奏。大量的预读和IO操作使得CPU时间翻倍,同时整体时间增长50倍倍。

那么我们使用选择性很高的索引呢?

 

可以看到,category=’test’的选择性非常高,导致向量相似度搜索成本直接通过IndexSeek+向量搜索完成。

后续等待更多文档出来再进一步观察,当前的观察是,如果没有对向量增加索引,则搜索基本需要全量比对+排序。如果用于实际生产,基本难以接受。

 

其他AI相关函数支持

VECTOR_NORM(向量标准化)

本例中VECTOR_NORM(image_embedding, ‘norm2’) > 3 主要作用:

  • 去除纯色背景(因向量范数接近零)
  • 去除模糊图像(因特征信息少,范数较小)
  • 去除异常数据(因数据录入错误,导致范数极小或无效)

 

 VECTOR_NORMALIZE(向量归一化)

该函数解释也比较简单,就是将向量的上限变为1,比如当前最大值是5,则对应的4变为0.8。一个简单的例子:

 

 

 

AI服务集成与T-SQL扩展

sp_invoke_external_rest_endpoint

直接通过 T-SQL 调用外部的 HTTPS REST 或 GraphQL 接口。简单来说,它让 SQL Server 数据库可以像客户端一样,直接和外部服务(比如 Azure Functions、Power BI、OpenAI API 、DeepSeek API等)交互。

想象你在 SQL Server 里写了个脚本,但需要外部服务(比如翻译文本、计算汇率、调用大模型等)。以前你得写个外部程序(比如用 Python 或 C#)去调用服务,再把结果写回数据库。现在,sp_invoke_external_rest_endpoint 可以做到数据不出数据库即可完成服务。

其实外部调用的优势和劣势我也简单做了一个总结,

优势:

  • 数据就地处理,减少数据搬运(同时减少安全面)
  • 统一的事务与安全机制(ACID支持,数据库权限、证书支持)
  • 简化架构与减少依赖(集中化带来开发便利)
  • 方便运维(集中化带来运维便利)
  • 快速原型验证(验证后迁移服务层)

  劣势:

  • 数据库负载与性能冲突
  • 数据库难以Scale-out
  • 难以调试(T-SQL相比编程语言难以调试)
  • 语言/生态局限(支持的Python包有限)
  • 安全问题(需要数据库能够访问外部服务,需要额外启用防火墙)
  • 数据库中生态极差(主流语言支持丰富的AI/ML库)

 

下面是一个简单的例子,我将SQL Server数据库的日志发送给大模型,寻求性能优化建议:

 

DECLARE 
    @endpoint_url NVARCHAR(200) = N'https://',
    @api_key NVARCHAR(100) = N'sk-or-v1',
    @logs_context NVARCHAR(MAX),
    @payload NVARCHAR(MAX),
    @response_status_code INT,
    @response_message NVARCHAR(MAX);

-- 步骤1:获取最新的 SQL Server 日志信息作为上下文
SET @logs_context = N'2025-02-26 14:35:15.45 spid51 Query execution time exceeded 1s for SELECT * FROM Sales.Orders JOIN Sales.OrderDetails ON Orders.OrderID = OrderDetails.OrderID WHERE OrderDate > ''2025-01-01''. Table scan detected on Sales.OrderDetails due to missing index on OrderID. + 2025-02-26 14:35:18.19 spid47 CPU usage reached 92% for 30 seconds. High lock contention detected on table Sales.Orders. + 2025-02-26 14:35:19.19 spid47 Buffer pool hit ratio dropped to 7%. Memory pressure detected, available memory: 512 MB.';

-- 步骤2:构造请求体
SET @payload = N'{
    "model": "google/gemini-2.0-flash-001",
    "messages": [
        {"role": "system", "content": "You are a SQL Server expert."},
        {"role": "user", "content": "以下是我的SQL服务器日志信息:' 
         + @logs_context 
         + N'。请给出可能的性能优化或故障排查建议。"}
    ]
}';

-- 步骤3:构造请求头
DECLARE @headers NVARCHAR(MAX);
SET @headers = CONCAT(N'{"Content-Type": "application/json", "Authorization": "Bearer ', @api_key, '"}');

-- 步骤3:调用 sp_invoke_external_rest_endpoint 发送 POST 请求
EXEC sp_invoke_external_rest_endpoint
     @url = @endpoint_url,
     @payload = @payload,
     @method = 'POST',
     @headers = @headers,
     @response = @response_message OUTPUT,
     @timeout = 60; 

-- 步骤5:查看返回结果
SELECT @response_message AS [OpenRouter Response];

看到结果:

图. 调用外部模型返回的结果

返回的部分JSON截图:

图. 部分返回结果JSON化

sp_execute_external_script

在使用库数据库层直接完成推理或特征提取,sp_execute_external_script是 SQL Server 提供的一个系统存储过程,允许在 SQL Server 中直接执行外部脚本语言(如 R、Python 或 Java)的代码,并且可以与数据库中的数据无缝交互。它是 SQL Server 集成机器学习和高级分析能力的核心组件之一。

 

一个简单的例子:调用 Python + Hugging Face Transformer 做情感分析

图. 使用T-SQL调用外部Python包

 

结果:

图. 情感分析场景结果

支持 LangChain、Semantic Kernel、EF 等流行 AI 框架

这部分是在SQL Server之外完成的,本质上就是在这些流行的框架中,增加了对SQL Server的驱动支持,其实没什么好说的,例如:

 

在langchain中,直接支持SQL Server作为数据存储。

图. 将SQL Server作为向量数据源

 

直接在langchain中进行相似度搜索

图. SDK直接进行相似度搜索

图. 在C#的ORM直接支持相似度搜索

 

小结

  本文基于SQL Server 2024年11月社区私有预览(CTP1.3版本)的初步测试,分享了新功能的体验。SQL Server 2025新增了原生向量支持和DiskANN向量索引,适应当前AI应用需求,可用于RAG、语义理解等场景,支持最高1998维向量存储及余弦、欧氏距离等相似度检索。测试中发现,向量搜索性能可能因缺乏索引或数据未驻留内存而下降,特别是在IO密集场景下表现不理想,但这可能与测试时缺乏官方文档、使用方法不当有关,待后续资料完善后再进一步验证。此外,新功能还包括向量标准化

   通过sp_invoke_external_rest_endpoint和sp_execute_external_script实现外部服务调用和脚本执行,扩展了应用场景,但也带来了一些性能和调试上的挑战。同时,SQL Server对LangChain、Semantic Kernel等框架的支持也增强了其生态兼容性。总的来说,SQL Server 2025在功能整合上迈出了重要一步,但实际效果还有待更多文档支持和优化验证。

全程不用写代码,我用AI程序员写了一个飞机大战 - 北京-宏哥 - 博客园

mikel阅读(93)

来源: 全程不用写代码,我用AI程序员写了一个飞机大战 – 北京-宏哥 – 博客园

前言

还在为写代码薅头发吗?还在为给出的需求无处下手而发愁吗?今天宏哥分享一款开发工具的插件,让你以后的编程变得简单起来。 作为一个游戏编程小白,能完成自己工作就不错了,还能玩别的,这在以前想都不敢想,现在就可以轻松实现了。来跟随宏观的脚步,通过简单几步成功开发出了一款飞机大战小游戏! 是的,你没听错,就是那种你可以控制一架小飞机,在屏幕上闪躲子弹,击败敌人的游戏。听起来是不是很酷呢!

1.环境准备

1.1操作系统

1.宏哥的环境是Windows 11版本 64位系统(32位的同学自己想办法哦,当然了现在32位的一般很少见),如下图所示:

1.2Python版本

Python版本:python:3.7.2,如下图所示:

1.3IDE开发工具

1.PyCharm 2021.3.3开发平台,如下图所示:

1.4 AI工具

1.通义灵码插件。

2.资源准备

链接:资源下载 提取码:n8ey ,就是游戏需要的一些图片和音频文件,如下图所示:

3.安装AI插件

1.首先是安装通义灵码,直接在pycharm的文件(File)下拉菜单中选择选项(Settings),如下图所示:

2.点击“选项(Settings)”后,在对话框中选择插件(plugin)在此界面上面的搜索框中,输入tongyi,就出来了,如下图所示:

3.已经安装上了,显示的是installed,没安装就是绿色的install,点击后,稍等一会,即可完成安装。如下图所示:

4.安装好以后,要想使用就得登录,点击“登录”,如下图所示:

5.一般注册过社区的,直接登录社区账号,然后通义灵码就会单点登录成功,很方便的,如下图所示:

6.通义灵码插件登录成功,如下图所示:

7.点击右下角图标,点击“高级设置”,可以根据自己癖好进行一些设置,如下图所示:

8.点击右侧的“通义灵码”,可以弹出AI对话框,点击“智能问答”和“AI程序员”进行切换,也可以点击最下边的下拉按钮切换大模型(qwen-2.5,deepseek-v3,deepseek-r1),如下图所示:

好了,到此一切准备工作就绪,下边就开始游戏编程之旅。

4.开启游戏编程之旅

4.1AI程序员交互过程

1.写出你的需求,发送给AI程序员,提示词如下:

生成飞机大战游戏完整代码,用pygame运行,记得不是简单的游戏框架代码哦,而是完整代码,利用飞机大战文件夹中的游戏素材: bullte.svg(子弹图), enemy.svg(敌机图),explosion.svg(爆炸素材图)、player.svg(我方机图)、sound.wav(子弹声音)、background_music.mp3(背景音乐),如下图所示:

2.好家伙一口气给我生成这么多,一气呵成啊,那我接下来点击“接受”,如下图所示:

3.点击“接受”后,自动创建python代码文件,如下图所示:

4.2AI程序员解决bug

1.运行代码出错,直接复制错误丢给AI程序员,帮你直接解决bug,如下图所示:

2.从上图我们可以看到,AI程序员直接定位到有问题代码的地方,同时给出了解决方案 :检查是否有未安装的模块,如何有,则通过命令进行安装,如果你觉得没有问题,点击“接受”就可以了,如下图所示:

3.再次运行修改后代码,控制台可以看到,在安装缺少的pygame模块,如下图所示:

4.稍等一会,安装完缺少的模块,代码运行成功,出现飞机大战的游戏界面(键盘方向键左右移动我放飞机,空格键发射子弹),如下图所示:

4.3AI程序员完善代码

1.实际运行中交互效果问题,直接向AI程序员提问,帮你完善。比如我遇到的问题:”子弹不跟着飞机移动”,给出的修复代码直接采用即可!如下图所示:

4.4AI程序员解决新需求

1.当然我们也可以通过AI程序员不断地完善我们游戏的需求如下:

(1)增加玩家命的概念,几条命就能继续玩几次,而不是直接退出。如下图所示:

(2)一条生命结束并重新开始时,要有5秒的无敌时间,如下图所示:

(3)增加紧张的背景音乐,如下图所示:

(4)增加积分功能,每打掉一个敌人增加一分,如下图所示:

2.按照以上需求,我们将这4条需求喂给AI程序员,它会自动将需求转换成代码,你可以傻瓜式的接受即可,完成以上需求后,运行代码后游戏界面,如下图所示:

4.5AI程序员代码优化

1.整体运行正常后,看着代码一大坨太难受,我们就让AI程序员这个老司机帮我们优化下,如下图所示:

4.6AI程序员编写单元测试

1.当然,你也可以让AI程序员编写单元测试,来验证代码的健壮性!解释代码,帮助你学习代码!生成注释,提高代码的可读性。如下图所示:

4.7AI打包成可执行文件

1.如何想打成exe软件直接运行,直接问AI程序员,他会详细告诉你每一步!提示词:“如何把程序打成.exe”,如下图所示:

5.个人愚见

5.1输出结果不稳定

1.由于时间关系,文章一天没有写完,第二天再次互动同样的提示词,结果却不一样,如下图所示:

2.运行代码,结果如下:

5.2提示词的准确理解

1.宏哥的那个提示词,没有说到背景图片,结果代码里有,然后运行代码提示我缺少背景图片,如下图所示:

5.3响应时间慢

1.在使用AI程序员的时候,添加提示词后,切换不同的模型,明显感觉deepseek的响应比qwen-2.5的速度慢,但总体感觉速度都不是很快(生成中,一直在转圈),如下图所示:

✨通过这次体验,大家是否感受到AI的强大和便捷。无论你是编程新手还是有经验的开发者,AI程序员都能为你提供极大的帮助,提升你的开发效率。希望这次分享能激发更多人尝试编程,感受创造的乐趣!赶快动手试试吧,说不定你也能轻松开发出属于自己的游戏哦!(为了增加趣味性,我就不附件代码了!自己体验吧)

6.使用感受

1.上边说了一些使用过程中的不足,下边再夸一下,最重要的是:免费,免费无敌,呵呵!

2.体验亮点‌:

  1. ‌代码智能生成‌:快速生成高质量代码,显著缩短开发周期。
  2. ‌跨语言编程‌:轻松实现代码跨语言转换,打破语言壁垒。
  3. ‌单元测试生成‌:自动生成测试用例,提升代码可靠性。
  4. ‌研发智能问答‌:即时解答技术难题,提高开发效率。

‌3.体验感受‌:

通义灵码2.0作为AI编程助手,功能强大且易用。在新功能开发、跨语言编程等场景下表现出色,显著提升了开发效率和代码质量。

‌建议‌:

  • 进一步优化代码生成风格和安全性。
  • 增加对更多编程语言的支持。
  • 提高响应时间和对提示词理解
  • 提示互动结果的稳定性

‌总结‌:

通义灵码2.0的AI程序员是一款值得推荐的智能编码搭子,为开发者带来高效、便捷的编程体验。期待未来更多创新功能。