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

SpringAi整合大模型(进阶版)

进阶版是在基础的对话版之上进行新增功能。

如果还没弄出基础版的,请参考

https://blog.csdn.net/weixin_54925172/article/details/144143523?sharetype=blogdetail&sharerId=144143523&sharerefer=PC&sharesource=weixin_54925172&spm=1011.2480.3001.8118

一,进阶版需要实现的功能

  1. 给AI进行功能预设
  2. 记忆对话,能自动联系上下文语境
  3. 结合业务,通过对话操作系统业务

简单解释一下

给AI进行功能预设

比如当客户发送特定消息时,ai需要做出什么回应

或者

让ai充当淘宝客服之类的角色

记忆对话,能自动联系上下文语境

同一时间多个用户访问时,分别可以对应多个用户,不会混淆上下文语境。

比如用户A说了自己是A,用户B说了自己是B,那么A在问自己是谁时,AI能准确回答出用户是A,而不会混淆说A是B。

结合业务,通过对话操作系统业务

类似于现在的手机助手,叫声“小艺,帮我买杯霸王别姬的奶茶”。小艺就会自动下单购买奶茶。

二,代码编写

首先整合一下上次的样例代码,做一下简单的调整。

简单调整上次的代码

controller

package org.example.springaidemo.controller;import org.example.springaidemo.impl.SimpleControllerImpl;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;@RestController
public class SimpleController {private final SimpleControllerImpl simpleControllerimpl;@Autowiredpublic SimpleController(OpenAiChatModel openAiChatModel, SimpleControllerImpl simpleControllerimpl) {this.simpleControllerimpl = simpleControllerimpl;}@GetMapping("/ai/generate")public String generate(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {return simpleControllerimpl.generate(message);}@GetMapping("/ai/generateStream")public Flux<String> generateStream(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {return simpleControllerimpl.generateStream(message);}}

impl

package org.example.springaidemo.impl;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;@Service
public class SimpleControllerImpl {private final ChatClient client;@Autowiredpublic SimpleControllerImpl(ChatClient.Builder clientBuilder) {this.client = clientBuilder.build();}public String generate(String msg) {return this.client.prompt().user(msg).call().content();}public Flux<String> generateStream(String msg) {return this.client.prompt().user(msg).stream().content();}
}

测试

给AI进行功能预设

修改我们的impl类

package org.example.springaidemo.impl;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;@Service
public class SimpleControllerImpl {private final ChatClient client;@Autowiredpublic SimpleControllerImpl(ChatClient.Builder clientBuilder) {this.client = clientBuilder.defaultSystem("""你是一家名叫“Rojer”的淘宝客服。当用户语句中包含“退款”时,你需要回复“不好意思,本店不支持7天无理由退款”""").build();}public String generate(String msg) {return this.client.prompt().user(msg).call().content();}public Flux<String> generateStream(String msg) {return this.client.prompt().user(msg).stream().content();}
}

这里需要注意,大模型是经过特定训练后的,它无法做出一些本身禁止于大模型的回复,

比如说污言秽语,比如说民族纠纷,比如说反人类语言。

这个时候,我们再进行一些简单测试

记忆对话,能自动联系上下文语境

这里有两个方面

  1. 需要开启ai的记忆功能
  2. 需要对不同用户进行分别的处理

别的不多说,都在代码中,注释中

impl

package org.example.springaidemo.impl;import org.example.springaidemo.config.MychatMemory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;/*** SimpleControllerImpl 是一个服务类,用于处理基于 AI 的对话。* 它利用 Spring AI Chat 框架,通过会话 ID(token)管理不同用户的上下文和对话。*/
@Service
public class SimpleControllerImpl {// AI 对话客户端实例private final ChatClient client;// 自定义的对话存储实现,用于保存用户会话上下文private final MychatMemory mychatMemory;/*** 构造方法,初始化 ChatClient 和自定义的对话存储。** @param clientBuilder 用于构建 ChatClient 的构建器* @param mychatMemory  自定义的对话存储实现*/@Autowiredpublic SimpleControllerImpl(ChatClient.Builder clientBuilder, MychatMemory mychatMemory) {this.mychatMemory = mychatMemory;// 初始化 ChatClient,并设置默认系统提示和对话存储this.client = clientBuilder.defaultSystem("""你是一家名叫“Rojer”的淘宝客服。当用户语句中包含“退款”时,你需要回复“不好意思,本店不支持7天无理由退款”""").defaultAdvisors(new PromptChatMemoryAdvisor(mychatMemory)).build();}/*** 生成基于用户消息和会话 token 的 AI 回复。** @param msg   用户输入的消息* @param token 表示会话唯一标识,用于区分不同用户的上下文* @return AI 的回复内容*/public String generate(String msg, String token) {return this.client.prompt().user(msg) // 用户的输入.advisors(adv -> adv// 设置检索的上下文记录条数.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)// 指定会话唯一标识,用于区分不同的用户对话.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, token)).call() // 调用 AI 服务,生成回复.content(); // 获取生成的文本内容}/*** 以流式方式生成基于用户消息和会话 token 的 AI 回复。* 适用于需要逐步接收回复内容的场景,例如聊天应用中的实时响应。** @param msg   用户输入的消息* @param token 表示会话唯一标识,用于区分不同用户的上下文* @return Flux<String> 流式的回复内容*/public Flux<String> generateStream(String msg, String token) {return this.client.prompt().user(msg) // 用户的输入.advisors(adv -> adv// 设置检索的上下文记录条数.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)// 指定会话唯一标识,用于区分不同的用户对话.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, token)).stream() // 以流式模式调用 AI 服务.content(); // 获取生成的文本流内容}
}

自定义的chatMemory

package org.example.springaidemo.config;import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Component
public class MychatMemory implements ChatMemory {Map<String, List<Message>> conversationHistory = new ConcurrentHashMap<>();@Overridepublic void add(String conversationId, List<Message> messages) {this.conversationHistory.computeIfAbsent(conversationId, id -> Collections.synchronizedList(new ArrayList<>())).addAll(messages);}@Overridepublic void add(String conversationId, Message message) {this.conversationHistory.computeIfAbsent(conversationId, id -> Collections.synchronizedList(new ArrayList<>())).add(message);}@Overridepublic List<Message> get(String conversationId, int lastN) {List<Message> allMessages = conversationHistory.get(conversationId);if (allMessages == null || allMessages.isEmpty()) {return List.of(); // 如果没有历史记录,返回空列表}// 计算获取的起始位置int start = Math.max(0, allMessages.size() - lastN);return new ArrayList<>(allMessages.subList(start, allMessages.size())); // 返回一个新列表,避免外部修改}@Overridepublic void clear(String conversationId) {conversationHistory.remove(conversationId); // 移除该会话的历史记录}
}

看看 实际对话是否有分别存储到自定义的chatMemory中

这里可以看出已经按照我的需求将两条不同的会话进行分别处理了。

这里可以根据自己的需要,使用标准的token,或者直接使用sessionID都可以。

结合业务,通过对话操作系统业务

这里需要用到springAI提供的fuction方法

详细都在注释 中

SimpleFunction
package org.example.springaidemo.config;import org.example.springaidemo.impl.SimpleControllerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;import java.util.function.Function;/*** SimpleFunction 是一个 Spring 配置类,定义了应用中使用的函数 Bean。* 主要用于暴露基于 Lambda 表达式的业务逻辑函数。*/
@Configuration
public class SimpleFunction {// 引用业务逻辑实现类 SimpleControllerImplprivate final SimpleControllerImpl simpleImpl;/*** 构造方法,注入 SimpleControllerImpl 实例。** @param simpleImpl SimpleControllerImpl 的实例*/@Autowiredpublic SimpleFunction(SimpleControllerImpl simpleImpl) {this.simpleImpl = simpleImpl;}/*** 内部静态记录类,用于封装输入参数。* 在这里,PriceAll 用于传递商品的数量。** @param count 商品的数量*/public record PriceAll(int count){}/*** 定义一个 Function 类型的 Bean,用于计算总价格。** @return 一个函数,接收 PriceAll 类型的输入,返回计算结果(总价格)的字符串表示*/@Bean@Description("获取总价格")public Function<PriceAll, String> getPrice(){return priceCount -> {// 从输入中获取商品数量,并调用业务逻辑计算总价格Double pricedAll = simpleImpl.priceAll(priceCount.count);// 返回总价格的字符串表示return pricedAll.toString();};}
}

修改我们的Impl

package org.example.springaidemo.impl;import org.example.springaidemo.config.MychatMemory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Description;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;/*** SimpleControllerImpl 是一个服务类,用于处理基于 AI 的对话。* 它利用 Spring AI Chat 框架,通过会话 ID(token)管理不同用户的上下文和对话。*/
@Service
public class SimpleControllerImpl {// AI 对话客户端实例private final ChatClient client;// 自定义的对话存储实现,用于保存用户会话上下文private final MychatMemory mychatMemory;/*** 构造方法,初始化 ChatClient 和自定义的对话存储。** @param clientBuilder 用于构建 ChatClient 的构建器* @param mychatMemory  自定义的对话存储实现*/@Autowiredpublic SimpleControllerImpl(ChatClient.Builder clientBuilder, MychatMemory mychatMemory) {this.mychatMemory = mychatMemory;// 初始化 ChatClient,并设置默认系统提示和对话存储this.client = clientBuilder.defaultSystem("""你是一家名叫“Rojer”的淘宝客服。当用户语句中包含“退款”时,你需要回复“不好意思,本店不支持7天无理由退款”""").defaultAdvisors(new PromptChatMemoryAdvisor(mychatMemory)).build();}/*** 生成基于用户消息和会话 token 的 AI 回复。** @param msg   用户输入的消息* @param token 表示会话唯一标识,用于区分不同用户的上下文* @return AI 的回复内容*/public String generate(String msg, String token) {return this.client.prompt().user(msg) // 用户的输入.advisors(adv -> adv// 设置检索的上下文记录条数.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)// 指定会话唯一标识,用于区分不同的用户对话.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, token)).call() // 调用 AI 服务,生成回复.content(); // 获取生成的文本内容}/*** 以流式方式生成基于用户消息和会话 token 的 AI 回复。* 适用于需要逐步接收回复内容的场景,例如聊天应用中的实时响应。** @param msg   用户输入的消息* @param token 表示会话唯一标识,用于区分不同用户的上下文* @return Flux<String> 流式的回复内容*/public Flux<String> generateStream(String msg, String token) {return this.client.prompt().user(msg) // 用户的输入.advisors(adv -> adv// 设置检索的上下文记录条数.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)// 指定会话唯一标识,用于区分不同的用户对话.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, token)).functions("getPrice")// 指定需要调用的功能.stream() // 以流式模式调用 AI 服务.content(); // 获取生成的文本流内容}public Double priceAll(int count) {double price = 3.25;double re = price * count;System.out.println("打印这条内容,代表已经执行了priceAll该方法。");return re;}
}

看看测试结果

以上,后面还会出AI的进一步详细且方便的使用。欢迎各位大佬持续关注

相关文章:

SpringAi整合大模型(进阶版)

进阶版是在基础的对话版之上进行新增功能。 如果还没弄出基础版的&#xff0c;请参考 https://blog.csdn.net/weixin_54925172/article/details/144143523?sharetypeblogdetail&sharerId144143523&sharereferPC&sharesourceweixin_54925172&spm1011.2480.30…...

为什么爱用低秩矩阵

目录 为什么爱用低秩矩阵 一、定义与性质 二、区别与例子 为什么爱用低秩矩阵 我们更多地提及低秩分解而非满秩分解,主要是因为低秩分解在数据压缩、噪声去除、模型简化和特征提取等方面具有显著的优势。而满秩分解虽然能够保持数据的完整性,但在实际应用中的场景较为有限…...

React 自定义钩子:useOnlineStatus

我们今天的重点是 “useOnlineStatus” 钩子&#xff0c;这是 React 自定义钩子集合中众多精心制作的钩子之一。 Github 的&#xff1a;https://github.com/sergeyleschev/react-custom-hooks import { useState } from "react" import useEventListener from &quo…...

uniapp 小程序 监听全局路由跳转 获取路由参数

uniapp 小程序 监听全局路由跳转 获取路由参数 app.vue中 api文档 onLaunch: function(options) {let that this;let event [navigateTo, redirectTo, switchTab, navigateBack];event.forEach(item > {uni.addInterceptor(item, { //监听跳转//监听跳转success(e) {tha…...

12.02 深度学习-卷积

# 卷积 是用于图像处理 能够保存图像的一些特征 卷积层 如果用全连接神经网络处理图像 计算价格太大了 图像也被转为线性的对象导致失去了图像的空间特征 只有在卷积神经网络cnn的最后一层使用全连接神经网络 # 图像处理的三大任务 # 目标检测 对图像中的目标进行框出来 # 图…...

MySQL 主从同步一致性详解

MySQL主从同步是一种数据复制技术&#xff0c;它允许数据从一个数据库服务器&#xff08;主服务器&#xff09;自动同步到一个或多个数据库服务器&#xff08;从服务器&#xff09;。这种技术主要用于实现读写分离、提升数据库性能、容灾恢复以及数据冗余备份等目的。下面将详细…...

Spring源码导入idea时gradle构建慢问题

当我们将spring源码导入到idea进行构建的时候&#xff0c;spring采用的是gradle进行构建&#xff0c;默认下注在依赖是从https://repo.maven.apache.org会特别慢&#xff0c;需要改为国内的镜像地址会加快速度。 将项目中build.gradle配置进行调整&#xff1a; repositories …...

Dockerfile 安装echarts插件给java提供服务

java调用echarts插件&#xff0c;生成图片保存到磁盘然后插入到pptx中报表。 Dockerfile文件内容&#xff1a; #基础镜像&#xff0c;如果本地仓库没有&#xff0c;会从远程仓库拉取 openjdk:8 FROM docker.io/centos:centos7 #暴露端口 EXPOSE 9311 # 避免centos 日志输出 …...

Springboot小知识(1):启动类与配置

一、启动类&#xff08;引导类&#xff09; 在通常情况下&#xff0c;你创建的Spring应用项目都会为你自动生成一个启动类&#xff0c;它是这个应用的起点。 在Spring Boot中&#xff0c;引导类&#xff08;也称为启动类&#xff0c;通常是main方法所在的类&#xff09;是整个…...

[CISCN 2019华东南]Web11

[CISCN 2019华东南]Web11 给了两个链接但是都无法访问 这里我们直接抓包试一下 我们插入X-Forwarded-For:127.0.0.1 发现可以修改了右上角的IP地址&#xff0c;从而可以进行注入 {$smarty.version} 查看版本号 if标签执行PHP命令 {if phpinfo()}{/if} 查看协议 {if system(…...

Cypress内存溢出奔溃问题汇总

内存溢出报错信息 <--- Last few GCs ---> [196:0xe58001bc000] 683925 ms: Scavenge 1870.7 (1969.9) -> 1865.6 (1969.9) MB, 6.07 / 0.00 ms (average mu 0.359, current mu 0.444) task; [196:0xe58001bc000] 683999 ms: Scavenge 1872.4 (1969.9) -> 1867.1…...

树莓派4B--OpenCV安装踩坑

报错&#xff1a; Source directory: /tmp/pip-install-pv7l9r25/opencv-python_08fdf5a130a5429f89b0e0eaab39a329 Working directory: /tmp/pip-install-pv7l9r25/opencv-python_08fdf5a130a5429f89b0e0eaab39a329/_skbuild/linux-armv7l-3.7/cmake-build Please check the i…...

电子电气架构 --- 面向服务的汽车诊断架构

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…...

Pytest --capture 参数详解:如何控制测试执行过程中的输出行为

--capture 选项用于控制测试用例执行过程中标准输出&#xff08;stdout&#xff09;和标准错误输出&#xff08;stderr&#xff09;的捕获行为。 --capture 的选项值&#xff1a; fd&#xff08;默认&#xff09; 捕获文件描述符级别的输出&#xff08;stdout 和 stderr&#x…...

IS-IS的原理

IS-IS的基本概念&#xff1a; 概述&#xff1a; IS-IS&#xff0c;中间系统到中间系统&#xff0c;是ISO国际标准化组织为它的无连接网络协议设计的一种动态路由协议 IS-IS支持CLNP网络和IP网络&#xff0c;采用数据链路层封装&#xff0c;区别于ospf只支持IP网络&#xff0…...

C++(4个类型转换)

1. C语言中的类型转换 1. 隐式 类型转换&#xff1a; 具有相近的类型才能进行互相转换&#xff0c;如&#xff1a;int,char,double都表示数值。 2. 强制类型转换&#xff1a;能隐式类型转换就能强制类型转换&#xff0c;隐式类型之间的转换类型强相关&#xff0c;强制类型转换…...

Ubuntu20.04安装NVIDIA显卡驱动

Ubuntu20.04安装NVIDIA显卡驱动 参考资料&#xff1a;https://blog.csdn.net/weixin_39244242/article/details/136282614?fromshareblogdetail&sharetypeblogdetail&sharerId136282614&sharereferPC&sharesourceqq_37397652&sharefromfrom_link 成功配置…...

速盾:介绍一下高防cdn的缓存响应事什么功能?

高防CDN&#xff08;Content Delivery Network&#xff09;是一种基于分布式缓存技术的网络加速服务&#xff0c;能够提供强大的缓存响应功能。它的缓存响应功能主要包括缓存加速和智能缓存两个方面。 首先&#xff0c;高防CDN的缓存加速功能是指通过在全球范围内部署大量的缓…...

Nuclei-快速漏洞扫描器

Nuclei-快速漏洞扫描器 声明 学习内容来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3f…...

linux网络抓包工具

linux网络抓包工具 一、tcpdump1.1 基本用法1.2 龙芯平台实例操作 二、wireshark2.1 主要功能2.2 龙芯平台实例操作 一、tcpdump tcpdump 指令可列出经过指定网络界面的数据包文件头&#xff0c;可以将网络中传送的数据包的 “头” 完全截获下来提供分析。它支持针对网络层、协…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...