智能BI项目第三期

news2024/11/15 2:10:53

AIGC

AI 提问技巧

为了让 Al 更好地理解我们的输入,并给出预期精确的输出,需要严格控制我们的提问词。

1.使用系统预设 + 控制输入格式(便于Al精确地理解我们的需求)

你是一个数据分析师和前端开发专家,接下来我会按照以下固定格式给你提供内容:
分析需求:
{数据分析的需求或者目标}
原始数据:
{csv格式的原始数据,用,作为分隔符}
请根据以上内容,帮我生成数据分析结论和可视化图表代码
2.控制输出格式(便于 AI 返回的内容能够更加方便地为我们所用)
你是一个数据分析师和前端开发专家,接下来我会按照以下固定格式给你提供内容:
分析需求:
{数据分析的需求或者目标}
原始数据:
{csv格式的原始数据,用,作为分隔符}

请根据这两部分内容,按照以下指定格式生成内容(此外不要输出任何多余的开头、结尾、注释)
----------------------------------------------------------------------------------
{前端 Echarts V5 的 option 配置对象js代码,合理地将数据进行可视化,不要生成任何多余的内容,比如注释}
----------------------------------------------------------------------------------
{明确的数据分析结论、越详细越好,不要生成多余的注释}



----------------------------------------------------------------------------------
{
    title: {
        text: '网站用户增长情况',
        subtext: ''
        },
    tooltip: {
        trigger: 'axis',
        axisPointer: {
            type: 'shadow'
            }
    },
    legend: {
        data: ['用户数']
        },
    xAxis: {
        data: ['1号', '2号', '3号']
    },
    yAxis: {},
    series: [{
        name: '用户数',
        type: 'bar',
        data: [10, 20, 30]
    }]
}
----------------------------------------------------------------------------------
根据数据分析可得,该网站用户数量逐日增长,时间越长,用户数量增长越多。
3.指定一个示例问答,one-shot 或者 few-shot

one-shot:给 AI 一轮示例问答

few-shot:给 AI 多轮示例问答

之后就可以慢慢训练这个模型,哪里不对就在预设和提示词里限制,训练成功后再放入示例。

如何调用AI
1.调用官方接口

比如 OpenAI 或者其他 AI 原始大模型官网的接口 👉 官方文档

  • 优点:不经封装,最灵活,最原始
  • 缺点:要钱、要魔法

本质上 OpenAI 就是提供了 HTTP 接口,我们可以用任何语言去调用

1)在请求头中指定 OPENAI_API_KEY → Authorization: Bearer OPENAI_API_KEY。

 2)找到你要使用的接口,比如 AI 对话接口。

3)按照接口文档的示例,构造 HTTP 请求,比如用 Hutool 工具类、或者 HTTPClient。 

/**
 * AI 对话(需要自己创建请求响应对象)
 *
 * @param request
 * @param openAiApiKey
 * @return
 */
public CreateChatCompletionResponse createChatCompletion(CreateChatCompletionRequest request, String openAiApiKey) {
    if (StringUtils.isBlank(openAiApiKey)) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未传 openAiApiKey");
    }
    String url = "https://api.openai.com/v1/chat/completions";
    String json = JSONUtil.toJsonStr(request);
    String result = HttpRequest.post(url)
    .header("Authorization", "Bearer " + openAiApiKey)
    .body(json)
    .execute()
    .body();
    return JSONUtil.toBean(result, CreateChatCompletionResponse.class);
}

最终结果可能返回以下内容:

2 使用云服务商提供的封装接口 

比如:Azure 云(微软官方)

  • 优点:本地都能用
  • 缺点:依然要钱,而且可能比直接调用原始的接口更贵
3 鱼聪明 AI 开放平台

使用星球 AI 助手 —— 鱼聪明 AI  移动端搜索公众号【鱼聪明AI】。

鱼聪明 AI 提供现成的 SDK,让用户更便捷地利用 AI 能力。

具体调用方式可查看:--- SDK项目文档

  • 优点:目前不要钱,而且有很多现成的模型(prompt 系统预设)给大家用
  • 缺点:不完全灵活,但是可以定义自己的模型
1.到上面的文档里引入依赖
2.在application.yml填加上你的accessKey和secretKey

3.创建一个类,注入client,并写入模型Id

package com.yupi.springbootinit.manager;

import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.yucongming.dev.client.YuCongMingClient;
import com.yupi.yucongming.dev.common.BaseResponse;
import com.yupi.yucongming.dev.model.DevChatRequest;
import com.yupi.yucongming.dev.model.DevChatResponse;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 用于对接 AI 平台
 */
@Service
public class AiManager {

    @Resource
    private YuCongMingClient yuCongMingClient;

    /**
     * AI 对话
     *
     * @param message
     * @return
     */
    public String doChat(String message) {
        // 第三步,构造请求参数
        DevChatRequest devChatRequest = new DevChatRequest();
        // 模型id,尾后加L,转成long类型
        devChatRequest.setModelId(1651468516836098050L);
        devChatRequest.setMessage(message);
        // 第四步,获取响应结果
        BaseResponse<DevChatResponse> response = yuCongMingClient.doChat(devChatRequest);
        // 如果响应为null,就抛出系统异常,提示“AI 响应错误”
        if (response == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "AI 响应错误");
        }
        return response.getData().getContent();
    }
}

 然后创建一下测试类,按你预期设定的格式输入数据,便可以调用AI了

4.封装返回类接收
package com.ptu.api.model.vo;

import lombok.Data;

@Data
public class BiResponse {
    /**
     * 生成的图表代码
     */
    private String genChart;

    /**
     * 生成的分析结论
     */
    private String genResult;

    /**
     * 图表id
     */
    private Long chartId;
}
5.编写代码

之前我们是拼接用户的输入,现在可以对之前的输入方式进行优化;

通过设定一个提示语(prompt)的方式来输入用户信息,而不必自己编写提示语。

这种优化方式使得我们可以直接调用现有模型来进行处理。

注入刚刚封装好的对象,

// 指定一个模型id(把id写死,也可以定义成一个常量)
    long biModelId = 1659171950288818178L;
    /*
    * 用户的输入(参考)
      分析需求:
      分析网站用户的增长情况
      原始数据:
      日期,用户数
      1号,10
      2号,20
      3号,30
    * */

    // 构造用户输入
    StringBuilder userInput = new StringBuilder();
    userInput.append("分析需求:").append("\n");

    // 拼接分析目标
    String userGoal = goal;
    // 如果图表类型不为空
    if (StringUtils.isNotBlank(chartType)) {
        // 就将分析目标拼接上“请使用”+图表类型
        userGoal += ",请使用" + chartType;
    }
    userInput.append(userGoal).append("\n");
    userInput.append("原始数据:").append("\n");
    // 压缩后的数据(把multipartFile传进来)
    String csvData = ExcelUtils.excelToCsv(multipartFile);
    userInput.append(csvData).append("\n");

    // 拿到返回结果
    String result = aiManager.doChat(biModelId,userInput.toString());
    // 对返回结果做拆分,按照5个中括号进行拆分
    String[] splits = result.split("【【【【【");
    // 拆分之后还要进行校验
    if (splits.length < 3) {
        throw new BusinessException(ErrorCode.SYSTEM_ERROR,"AI 生成错误");
}

String genChart = splits[1].trim();
        String genResult = splits[2].trim();
        // 插入到数据库
        Chart chart = new Chart();
        chart.setName(name);
        chart.setGoal(goal);
        chart.setChartData(csvData);
        chart.setChartType(chartType);
        chart.setGenChart(genChart);
        chart.setGenResult(genResult);
        chart.setUserId(loginUser.getId());
        boolean saveResult = chartService.save(chart);
        ThrowUtils.throwIf(!saveResult, ErrorCode.SYSTEM_ERROR, "图表保存失败");
        BiResponse biResponse = new BiResponse();
        biResponse.setGenChart(genChart);
        biResponse.setGenResult(genResult);
        biResponse.setChartId(chart.getId());
        return ResultUtils.success(biResponse);
6总结
  1. 构造用户请求(用户消息、csv 数据、图表类型)
  2. 调用鱼聪明 sdk,得到 AI 响应结果
  3. 从 AI 响应结果中,取出需要的信息
  4. 保存图表到数据库

前端开发

前端就大概过一下,不深究

1.开发用户表单

修改路由

把主页重定向至/add_chart,将/add_chart指定到/AddChart

复用写好的页面

复制User目录,粘贴至srcpages目录下;

并改名为AddChart,把其他文件删掉,留下index.tsx

 

index.tsx进行修改,删掉多余的内容。(比如::获取用户信息、处理提交.....)

import { listChartByPageUsingPOST } from '@/services/yubi/chartController';
import { useModel } from '@umijs/max';
import React, { useEffect, useState } from 'react';

const Login: React.FC = () => {
  const [type, setType] = useState<string>('account');
  const { setInitialState } = useModel('@@initialState');

  useEffect(() => {
    listChartByPageUsingPOST({}).then((res) => {
      console.error('res', res);
    });
  });

  return (
    // 把页面内容指定一个类名add-chart
    <div className="add-chart">
      
    </div>
  );
};
export default Login;
去官网找模板

怎么去开发表单?去 ant.design 组件库 找一个表单组件;

我们需要用到多行输入(你的目标)、下拉输入(图表类型)、文件上传(原始数据)三个组件。

把这些内容放到return里面的div标签里

这部分内容放在return的外面(点击提交后的业务六级)

onFinishconst onFinish = (values: any) => {
  console.log('Received values of form: ', values);
};
简化内容

删除不必要的代码。

(比如:表格布局、样式,最大宽度,普通输入框、slider 滚动选项...)

import { listChartByPageUsingPOST } from '@/services/yubi/chartController';
import { UploadOutlined } from '@ant-design/icons';
import { useModel } from '@umijs/max';
import { Button, Form, Select, Space, Upload } from 'antd';
import TextArea from 'antd/es/input/TextArea';
import React, { useEffect, useState } from 'react';

const Login: React.FC = () => {
  const [type, setType] = useState<string>('account');
  const { setInitialState } = useModel('@@initialState');

  useEffect(() => {
    listChartByPageUsingPOST({}).then((res) => {
      console.error('res', res);
    });
  });

  const onFinish = (values: any) => {
    console.log('Received values of form: ', values);
  };

  return (
    // 把页面内容指定一个类名add-chart
    <div className="add-chart">
      <Form
        // 表单名称改为addChart
        name="addChart"
        onFinish={onFinish}
        // 初始化数据啥都不填,为空
        initialValues={{  }}
  >
  <Form.Item name="rate" label="Rate">
      <TextArea />
  </Form.Item>
  
  <Form.Item
    name="select"
    label="Select"
    hasFeedback
    rules={[{ required: true, message: 'Please select your country!' }]}
    >
    <Select placeholder="Please select a country">
      <Option value="china">China</Option>
      <Option value="usa">U.S.A</Option>
    </Select>
  </Form.Item>
  
  <Form.Item
      name="upload"
      label="Upload"
      valuePropName="fileList"
      extra="longgggggggggggggggggggggggggggggggggg"
    >
      <Upload name="logo" action="/upload.do" listType="picture">
        <Button icon={<UploadOutlined />}>Click to upload</Button>
      </Upload>
    </Form.Item>

    
    <Form.Item wrapperCol={{ span: 12, offset: 6 }}>
      <Space>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
        <Button htmlType="reset">reset</Button>
      </Space>
    </Form.Item>
  </Form>
    </div>
  );
};
export default Login;

编写前端代码
import { listChartByPageUsingPOST } from '@/services/yubi/chartController';
import { UploadOutlined } from '@ant-design/icons';
import { useModel } from '@umijs/max';
import { Button, Form, Input, Select, Space, Upload } from 'antd';
import TextArea from 'antd/es/input/TextArea';
import React, { useEffect, useState } from 'react';

const Login: React.FC = () => {
  const [type, setType] = useState<string>('account');
  const { setInitialState } = useModel('@@initialState');

  useEffect(() => {
    listChartByPageUsingPOST({}).then((res) => {
      console.error('res', res);
    });
  });

  const onFinish = (values: any) => {
    // 看看能否得到用户的输入
    console.log('表单内容: ', values);
  };

  return (
    // 把页面内容指定一个类名add-chart
    <div className="add-chart">
      <Form
        // 表单名称改为addChart
        name="addChart"
        onFinish={onFinish}
        // 初始化数据啥都不填,为空
        initialValues={{  }}
  >
  {/* 前端表单的name,对应后端接口请求参数里的字段,
  此处name对应后端分析目标goal,label是左侧的提示文本,
  rules=....是必填项提示*/}
  <Form.Item name="goal" label="分析目标" rules={[{ required: true, message: '请输入分析目标!' }]}>
      {/* placeholder文本框内的提示语 */}
      <TextArea placeholder="请输入你的分析需求,比如:分析网站用户的增长情况"/>
  </Form.Item>

  {/* 还要输入图表名称 */}
  <Form.Item name="name" label="图表名称">
      <Input placeholder="请输入图表名称" />
  </Form.Item>

  {/* 图表类型是非必填,所以不做校验 */}
  <Form.Item
    name="selchartTypeect"
    label="图表类型"
    >
    <Select
    options={[
      { value: '折线图', label: '折线图' },
      { value: '柱状图', label: '柱状图' },
      { value: '堆叠图', label: '堆叠图' },
      { value: '饼图', label: '饼图' },
      { value: '雷达图', label: '雷达图' },
    ]}
    />
  </Form.Item>

  {/* 文件上传 */}
  <Form.Item
      name="file"
      label="原始数据"
    >
      {/* action:当你把文件上传之后,他会把文件上传至哪个接口。
      这里肯定是调用自己的后端,先不用这个 */}
      <Upload name="file">
        <Button icon={<UploadOutlined />}>上传 CSV 文件</Button>
      </Upload>
    </Form.Item>
    
    <Form.Item wrapperCol={{ span: 12, offset: 6 }}>
      <Space>
        <Button type="primary" htmlType="submit">
          提交
        </Button>
        <Button htmlType="reset">重置</Button>
      </Space>
    </Form.Item>
  </Form>
    </div>
  );
};
export default Login;

对接后端

使用openAPI生成后端接口,并且把src/services/ant-design-pro删掉,对应的引用也删掉

page下的Tablelist和对应的路由也删掉

代码
import { genChartByAiUsingPOST } from '@/services/yubi/chartController';
import { UploadOutlined } from '@ant-design/icons';
import { Button, Form, Input, message, Select, Space, Upload } from 'antd';
import TextArea from 'antd/es/input/TextArea';
import React from 'react';

/**
 * 添加图表页面
 * @constructor
 */
// 把多余的状态删掉,页面名称改为AddChart
const AddChart: React.FC = () => {
  /**
   * 提交
   * @param values
   */
    const onFinish = async (values: any) => {
      // 对接后端,上传数据
      const params = {
        ...values,
        file: undefined,
      };
      try {
        // 需要取到上传的原始数据file→file→originFileObj(原始数据)
        const res = await genChartByAiUsingPOST(params, {}, values.file.file.originFileObj);
        // 正常情况下,如果没有返回值就分析失败,有,就分析成功
        if (!res?.data) {
          message.error('分析失败');
        } else {
          message.success('分析成功');  
        }  
      // 异常情况下,提示分析失败+具体失败原因
      } catch (e: any) {
        message.error('分析失败,' + e.message);
      }
    };  
  
.....此处省略,代码不变.....

export default AddChart;

生成图表

使用库 —— ECharts

根据文档提示,使用命令进行安装。

npm install echarts-for-react
使用ECharts和优化前端代码
import { genChartByAiUsingPOST } from '@/services/yubi/chartController';
import { UploadOutlined } from '@ant-design/icons';
import { Button, Card, Col, Divider, Form, Input, message, Row, Select, Space, Spin, Upload } from 'antd';
import TextArea from 'antd/es/input/TextArea';
import React, { useState } from 'react';
import ReactECharts from 'echarts-for-react';

/**
 * 添加图表页面
 * @constructor
 */
// 把多余的状态删掉,页面名称改为AddChart
const AddChart: React.FC = () => {
  // 定义状态,用来接收后端的返回值,让它实时展示在页面上
  const [chart, setChart] = useState<API.BiResponse>();
  const [option, setOption] = useState<any>();
  // 提交中的状态,默认未提交
  const [submitting, setSubmitting] = useState<boolean>(false);

  /**
   * 提交
   * @param values
   */
    const onFinish = async (values: any) => {
      // 如果已经是提交中的状态(还在加载),直接返回,避免重复提交
    if (submitting) {
      return;
    }
    // 当开始提交,把submitting设置为true
    setSubmitting(true);
    // 如果提交了,把图表数据和图表代码清空掉,防止和之前提交的图标堆叠在一起
    // 如果option清空了,组件就会触发重新渲染,就不会保留之前的历史记录
    setChart(undefined);
    setOption(undefined);

      // 对接后端,上传数据
      const params = {
        ...values,
        file: undefined,
      };
      try {
        // 需要取到上传的原始数据file→file→originFileObj(原始数据)
        const res = await genChartByAiUsingPOST(params, {}, values.file.file.originFileObj);
        // 正常情况下,如果没有返回值就分析失败,有,就分析成功
        if (!res?.data) {
          message.error('分析失败');
        } else {
          message.success('分析成功');  
          // 解析成对象,为空则设为空字符串
          const chartOption = JSON.parse(res.data.genChart ?? '');
          // 如果为空,则抛出异常,并提示'图表代码解析错误'
          if (!chartOption) {
            throw new Error('图表代码解析错误')
          // 如果成功
          } else {
            // 从后端得到响应结果之后,把响应结果设置到图表状态里
            setChart(res.data);
            setOption(chartOption);
          }
        }  
      // 异常情况下,提示分析失败+具体失败原因
      } catch (e: any) {
        message.error('分析失败,' + e.message);
      }
      // 当结束提交,把submitting设置为false
      setSubmitting(false);
    };  

  return (
    // 把页面内容指定一个类名add-chart
    <div className="add-chart">
      {/* 变成两列 gutter列与列之间的间隔*/}
      <Row gutter={24}>
        {/* 表单放在第一列,卡片组件里 */}
        <Col span={12}>
          <Card title="智能分析">
            <Form
            // 表单名称改为addChart
            name="addChart"
            // label标签的文本对齐方式
            labelAlign="left" 
            // label标签布局,同<Col>组件,设置 span offset 值,如 {span: 3, offset: 12} 
            labelCol={{ span: 4 }}
            // 设置控件布局样式
            wrapperCol={{ span: 16 }}
            onFinish={onFinish}
            // 初始化数据啥都不填,为空
            initialValues={{  }}
            >
            {/* 前端表单的name,对应后端接口请求参数里的字段,
            此处name对应后端分析目标goal,label是左侧的提示文本,
            rules=....是必填项提示*/}
            <Form.Item name="goal" label="分析目标" rules={[{ required: true, message: '请输入分析目标!' }]}>
                {/* placeholder文本框内的提示语 */}
                <TextArea placeholder="请输入你的分析需求,比如:分析网站用户的增长情况"/>
            </Form.Item>

            {/* 还要输入图表名称 */}
            <Form.Item name="name" label="图表名称">
                <Input placeholder="请输入图表名称" />
            </Form.Item>

            {/* 图表类型是非必填,所以不做校验 */}
            <Form.Item
              name="chartType"
              label="图表类型"
              >
              <Select
              options={[
                { value: '折线图', label: '折线图' },
                { value: '柱状图', label: '柱状图' },
                { value: '堆叠图', label: '堆叠图' },
                { value: '饼图', label: '饼图' },
                { value: '雷达图', label: '雷达图' },
              ]}
              />
            </Form.Item>

            {/* 文件上传 */}
            <Form.Item
                name="file"
                label="原始数据"
              >
                {/* action:当你把文件上传之后,它会把文件上传至哪个接口。
                    这里肯定是调用自己的后端,先不用这个;
                    maxCount={1} 限制文件上传数量为1 */}
                <Upload name="file" maxCount={1}>
                  <Button icon={<UploadOutlined />}>上传 CSV 文件</Button>
                </Upload>
              </Form.Item>
              {/* offset设置和label标签一样的宽度,这样就能保持对齐;
                  其他占用的列设置成16 */}
              <Form.Item wrapperCol={{ span: 16, offset: 4 }}>
                <Space>
                  {/* 加个loading:就是把submitting的状态加入进来,
                  加个disabled:如果正在提交,就让这个按钮禁用,不允许重复点击*/}
                  <Button type="primary" htmlType="submit" loading={submitting} disabled={submitting}>
                    提交
                  </Button>
                  <Button htmlType="reset">重置</Button>
                </Space>
              </Form.Item>
            </Form>
          </Card>
               </Col>
        {/* 分析结论和图表放在第二列 */}
        <Col span={12}>
        <Card title="分析结论">
            {/* 如果分析结论存在,就展示分析结论;
                不存在则显示'请先在左侧进行提交' */}
            {chart?.genResult ?? <div>请先在左侧进行提交</div>}
             {/* 提交中,还未返回结果,分析结论就显示加载中的组件 */}
            <Spin spinning={submitting}/>
        </Card>
        {/* 加一个间距 */}
        <Divider />
        <Card title="可视化图表">
            {/* 如果它存在,才渲染这个组件 */}
            {
              // 后端返回的代码是字符串,不是对象,用JSON.parse解析成对象
              option ? <ReactECharts option={option} /> : <div>请先在左侧进行提交</div>
            }
            {/* 提交中,还未返回结果,图表就显示加载中的组件 */}
            <Spin spinning={submitting}/>
        </Card>
        </Col>
      </Row>
    </div>
  );
};
export default AddChart;

主要代码:option ? <ReactECharts option={option} /> : <div>请先在左侧进行提交</div>

修改页面的名字name和图标icon

ps.图标可以去组件库内挑选,点击图标就可复制。

最终成品:

 后期会引入多线程、消息队列等机制来优化这个网站

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

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

相关文章

《深度学习》PyTorch框架 优化器、激活函数讲解

目录 一、深度学习核心框架的选择 1、TensorFlow 1&#xff09;概念 2&#xff09;优缺点 2、PyTorch 1&#xff09;概念 2&#xff09;优缺点 3、Keras 1&#xff09;概念 2&#xff09;优缺点 4、Caffe 1&#xff09;概念 2&#xff09;优缺点 二、pytorch安装 1、安装 2、…

传输层协议 —— UDP协议

目录 0.前言 1.UDP协议格式 16位源端口和目的端口 16位UDP长度 16位校验和 2.UDP协议特点 无连接 不可靠 面向数据报 3.UDP的缓冲区 0.前言 首先&#xff0c;我们得明确一点&#xff0c;网络模型是分层的。自底向上分别是物理层、数据链路层、网络层、传输层、应用层…

Nginx反向代理出现502 Bad Gateway问题的解决方案

&#x1f389; 前言 前一阵子写了一篇“关于解决调用百度翻译API问题”的博客&#xff0c;近日在调用其他API时又遇到一些棘手的问题&#xff0c;于是写下这篇博客作为记录。 &#x1f389; 问题描述 在代理的遇到过很多错误码&#xff0c;其中出现频率最高的就是502&#x…

JavaEE:网络编程(套接字)

文章目录 Socket套接字TCP和UDP的区别有连接/无连接可靠传输/不可靠传输面向字节流/面向数据报全双工/半双工 UDP/TCP api的使用UDPDatagramSocketDatagramPacketInetSocketAddress练习 TCPServerSocketSocket练习 Socket套接字 Socket是计算机网络中的一种通信机制&#xff0…

驱动开发知识点

裸机开发 ——————————————linux驱动 SOC&#xff1a; 定义&#xff1a;SOC&#xff0c;全称System on Chip&#xff0c;是一种集成了多个功能模块的芯片&#xff0c;包括处理器、内存、外设、接口等。它将原本分散在多个芯片上的功能集成到一个芯片上&#xff0…

一个基于 laravel 和 amis 开发的后台框架, 友好的组件使用体验,可轻松实现复杂页面(附源码)

前言 随着互联网应用的发展&#xff0c;后台管理系统的复杂度不断增加&#xff0c;对于开发者而言&#xff0c;既要系统的功能完备&#xff0c;又要追求开发效率的提升。然而&#xff0c;传统的开发方式往往会导致大量的重复劳动&#xff0c;尤其是在构建复杂的管理页面时。有…

不限学历!这个证书在上海太香了!利于积分、落户、抵扣个税...

一、软考是什么&#xff1f; “软考”全称&#xff1a;计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;关于它你需要知道&#xff1a; 1、软考是全国性考试&#xff1a;软考实行全国统一规划&#xff0c;实行统一大纲&#xff0c;统一试题&#xff…

【vulhub】Os-hackNos-1

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【vulhub】Os-hackNos-1 环境搭建漏洞复现 环境搭建 进入vulnhub官网 https://vulnhub.com 下载镜像 在虚拟机中打开镜像文件…

100行Python代码实现FastAPI Websocket 聊天室(纯协程方案)

本文发表于入职啦(公众号: ruzhila) 大家可以访问入职啦学习更多的编程实战。 项目地址 代码已经开源&#xff0c; fastapi_chatroom &#x1f44f; 欢迎Star 代码运行效果&#xff1a; 所有的项目都在github上开源&#xff1a;100-line-code 欢迎Star &#x1f44f; 用100行…

open sora1.1容器构建教程指南

一、介绍 Open-Sora 1.1 项目是 Colossal AI 团队开发的一个完全开源的视频生成项目&#xff0c;该项目致力于高效制作高质量视频&#xff0c;并通过开源原则实现先进视频生成技术的低成本普及。 1. 项目背景与目标 Open-Sora 项目旨在通过提供开源的模型、工具和内容&#…

idea使用阿里云服务器运行jar包

说明&#xff1a;因为我用的阿里云服务器不是自己的&#xff0c;所以一些具体的操作可能不太全面。看到一个很完整的教程&#xff0c;供参考。 0. 打包项目 这里使用的是maven打包。 在pom.xml中添加以下模块。 <build><plugins><plugin><groupId>org…

JDBC导图

思维歹徒 一、使用步骤 二、SQL注入 三、数据库查询&#xff08;查询&#xff09; 四、数据库写入&#xff08;增删改&#xff09; 五、Date日期对象处理 六、连接池使用 创建连接是从连接池拿&#xff0c;释放连接是放回连接池 七、事务和批次插入 八、Apache Commons DBUtil…

进程监控与管理详解

一、进程的定义: 进程process是正在运行的程序,包括: 分配的内存地址空间 安全属性、包括所有权和特权 一个或多个线程 进程状态 进程的环境包括: 本地和全局变量 当前调度上下文…

多目标优化算法(Multi-Objective Optimization Algorithms, MOOA)介绍

在现实世界中&#xff0c;许多问题都涉及到多个目标的权衡和优化。例如&#xff0c;在工程设计中&#xff0c;可能需要同时考虑成本、效率和可靠性&#xff1b;在资源管理中&#xff0c;可能需要平衡环境保护和经济效益。多目标优化算法&#xff08;Multi-Objective Optimizati…

bmp格式图片怎么转换jpg?这几种转换方法超级好用!

bmp格式图片怎么转换jpg&#xff1f;BMP格式&#xff0c;这一历史悠久的图像编码方式&#xff0c;正逐渐在数字时代的浪潮中显得力不从心&#xff0c;其边缘化的趋势愈发明显&#xff0c;这一现象的根源&#xff0c;在于BMP格式固有的局限性难以匹配现代用户对于图像处理的多元…

【Python】探索Magenta:音乐与艺术的机器智能创作

下班了&#xff0c;今天的苦就先吃到这里。 在人工智能的浪潮中&#xff0c;机器学习技术正逐渐渗透到艺术创作的各个领域。今天&#xff0c;我们来探索一个特别的项目——Magenta&#xff0c;它是由Google Brain团队发起的&#xff0c;旨在使用机器智能生成音乐和艺术。这个项…

Lucene详解介绍以及底层原理说明

文章目录 什么是Lucene?示意图1. 倒排索引2. 索引创建过程3. 数据存储4. 搜索过程5. 相关性评分 Lucene底层原理1. 倒排索引2. 索引创建过程3. 数据存储4. 搜索过程5. 相关性评分 什么是Lucene? Lucene是一个高性能的全文搜索引擎库&#xff0c;它基于倒排索引技术实现快速、…

Threejs之看房案例(下)

本文目录 前言最终效果1、点精灵1.1 添加点精灵1.2 点精灵效果2、添加事件2.1 鼠标移动事件2.1.1 效果2.2 鼠标点击事件2.2.1 效果2.3 切换互通3. 完整代码前言 在Threejs之看房案例(上)这篇博客中我们已经完成了大厅的3d观看效果,但是我们会发现如果想去其他房间观看,没有…

vue3+ant design vue 中弹窗自定义按钮设置及以冒号为基准布局

1、自定义弹窗按钮&#xff0c;去除取消和确定按钮。&#xff08;网上很多方法都是说通过插槽来实现&#xff0c;但是试了下不生效&#xff0c;那既然插槽不生效的话&#xff0c;干脆直接写按钮就好了&#xff09; <a-modalv-model:open"open"title"人员信息…

为什么现在都流行开放式耳机?四款性能出色的蓝牙耳机推荐

在当下&#xff0c;开放式耳机逐渐成为众多消费者的新宠。与传统入耳式耳机相比&#xff0c;开放式耳机展现出诸多独特之处。它可以呈现出更清晰的音质效果&#xff0c;让用户有更美妙的听觉体验。在佩戴感上&#xff0c;开放式耳机更为舒适&#xff0c;不会给耳朵带来压迫感。…