文章目录
- [1. Sping AI ChatClient](#1. Sping AI ChatClient)
-
- 1.1 ToolCallback#call()
- 1.2 DefaultToolCallingManager#executeToolCall()
- [1.3 ToolExecutionExceptionProcessor](#1.3 ToolExecutionExceptionProcessor)
-
- [1.3.1 直接抛出](#1.3.1 直接抛出)
- [1.3.2 格式化后返回给大模型](#1.3.2 格式化后返回给大模型)
- [2. Spring AI Alibaba ReactAgent](#2. Spring AI Alibaba ReactAgent)
-
- 2.1 AgentToolNode#executeToolByType
- [2.2 异常处理](#2.2 异常处理)
-
- [2.2.1 ToolExecutionException](#2.2.1 ToolExecutionException)
- [2.2.2 Exception](#2.2.2 Exception)
- [2.3 执行流程](#2.3 执行流程)
- [3. 演示案例](#3. 演示案例)
-
- [3.1 RuntimeException](#3.1 RuntimeException)
- [3.1 Exception](#3.1 Exception)
- [3.3 ServiceException](#3.3 ServiceException)
- [3.4 强制抛出异常](#3.4 强制抛出异常)
- [3.5 选择性抛出异常](#3.5 选择性抛出异常)
- [3.6 强制不抛出异常](#3.6 强制不抛出异常)
1. Sping AI ChatClient
1.1 ToolCallback#call()
ToolCallback 工具对象在调用时,会进行异常捕获和转换,方法型、函数型工具内部抛出的异常,都会被包装为 ToolExecutionException 。
方法型工具 MethodToolCallback 在反射执行时,会将工具方法内部抛出的异常包装为 ToolExecutionException :
java
/**
* 【核心方法】反射调用AI工具的具体方法
* 负责:权限处理 + 反射执行 + 异常包装(将反射异常转为业务异常)
* @param methodArguments 工具方法的入参数组
* @return 工具方法执行结果,允许返回null
*/
@Nullable
private Object callMethod(Object[] methodArguments) {
// 如果工具类 或 工具方法 不是public修饰,强制开启反射访问权限(突破Java访问检查)
if (isObjectNotPublic() || isMethodNotPublic()) {
this.toolMethod.setAccessible(true);
}
// 定义工具方法执行结果
Object result;
try {
// ===================== 核心执行 =====================
// 通过Java反射,调用目标工具方法(如 WeatherTool.getWeather())
// toolObject:工具实例(WeatherTool对象)
// methodArguments:方法入参(如城市名)
result = this.toolMethod.invoke(this.toolObject, methodArguments);
}
// 捕获:反射权限访问异常(无法调用方法时抛出)
catch (IllegalAccessException ex) {
throw new IllegalStateException("Could not access method: " + ex.getMessage(), ex);
}
// 捕获:【反射包装异常】工具方法内部抛出的异常,都会被反射包装成此异常
catch (InvocationTargetException ex) {
// 解包!获取工具方法内部【真实抛出的异常】
// 并将其包装为【业务专属异常】ToolExecutionException 抛出
// 外层就能直接捕获 ToolExecutionException 处理业务异常
throw new ToolExecutionException(this.toolDefinition, ex.getCause());
}
// 返回工具方法执行成功的结果
return result;
}
函数型工具 FunctionToolCallback 在执行时,也会将方法内部抛出的异常包装为 ToolExecutionException :
java
/**
* 【函数式工具核心执行方法】
* 泛型说明:I=工具入参类型,O=工具出参类型
* 负责:调用函数式工具(BiFunction)+ 统一异常包装
* @param request 工具入参对象(如天气工具的城市参数)
* @param toolContext 工具执行上下文(可为null,传递执行环境信息)
* @return 工具执行结果
*/
private <I, O> O callMethod(I request, @Nullable ToolContext toolContext) {
try {
// 核心:直接执行 函数式工具(BiFunction)的 apply 方法
// 对应你 WeatherTool 实现的 BiFunction.apply() 逻辑
return this.toolFunction.apply(request, toolContext);
}
// 捕获:已经是【业务专属异常】ToolExecutionException,直接抛出,不重复包装
catch (ToolExecutionException ex) {
throw ex;
}
// 捕获:工具执行中抛出的【所有其他异常】(未知异常、运行时异常、系统异常)
catch (Exception ex) {
// 统一包装为 业务专属异常 ToolExecutionException 抛出
// 保证外层代码只需要捕获这一种异常,统一处理
throw new ToolExecutionException(this.toolDefinition, ex);
}
}
重点:
- 如果工具内部主动抛出
ToolExecutionException→ 直接抛出 - 如果工具抛出其他任何异常(如空指针、
API调用失败、网络异常)→ 统一包装成ToolExecutionException
1.2 DefaultToolCallingManager#executeToolCall()
在 Sping AI 中,当工具执行抛出异常时,DefaultToolCallingManager 会捕获 ToolExecutionException ,然后调用 ToolExecutionExceptionProcessor 进行处理:
java
// 1. 开启工具调用的观测(Micrometer 监控/追踪),构建观测上下文
String toolCallResult = ToolCallingObservationDocumentation.TOOL_CALL
// 初始化观测器:使用约定、注册中心、当前工具调用的观测上下文
.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
this.observationRegistry)
// 2. 执行工具调用逻辑,并自动完成观测的开始/停止/上报
.observe(() -> {
// 定义工具执行结果
String toolResult;
try {
// 3. 执行实际的工具回调(核心业务逻辑:调用第三方接口/本地方法)
toolResult = toolCallback.call(finalToolInputArguments, toolContext);
}
catch (ToolExecutionException ex) {
// 4. 捕获工具执行异常(Spring AI 标准工具异常)
// 调用异常处理器,将异常转为 LLM 能理解的文本信息
toolResult = this.toolExecutionExceptionProcessor.process(ex);
}
// 5. 将工具执行结果(成功/异常)设置到观测上下文,用于监控日志记录
observationContext.setToolCallResult(toolResult);
// 6. 返回最终工具结果(成功结果 or 异常处理后的文本)
return toolResult;
});
注意事项:
- 只捕获
ToolExecutionException异常,然后调用异常处理器 - 非
ToolExecutionException不会被捕获直接向外抛出
1.3 ToolExecutionExceptionProcessor
Spring AI 默认工具异常处理器中有两种分支结果:
- 第一种:抛出异常(
throw) - 第二种:返回格式化后的错误信息,交给大模型
LLM解析理解
处理逻辑:
java
/**
* 处理工具执行异常,将异常转换为LLM可读的错误信息,支持指定异常直接抛出
* @param exception 工具执行抛出的ToolExecutionException
* @return 格式化后的错误信息
*/
@Override
public String process(ToolExecutionException exception) {
// 断言:异常对象不能为空,为空则直接抛出参数异常
Assert.notNull(exception, "exception cannot be null");
// 获取原始异常根源(即工具方法中真正抛出的业务异常)
Throwable cause = exception.getCause();
// 判断根异常是否是运行时异常
if (cause instanceof RuntimeException runtimeException) {
// 遍历配置的【需要直接重新抛出】的异常列表
// 如果根异常属于列表中的异常类型,则直接抛出该运行时异常(不做包装处理)
if (this.rethrownExceptions.stream().anyMatch(rethrown -> rethrown.isAssignableFrom(cause.getClass()))) {
throw runtimeException;
}
}
else {
// 如果根异常不是运行时异常(例如IOException、Error等)
// 直接抛出外层的ToolExecutionException,不进行友好转换
throw exception;
}
// 如果配置了 alwaysThrow = true,则无论什么情况,都直接抛出异常
if (this.alwaysThrow) {
throw exception;
}
// 获取异常的提示信息
String message = exception.getMessage();
// 如果异常信息为空或空白字符串,构建默认的标准化错误信息
if (message == null || message.isBlank()) {
message = "Exception occurred in tool: " + exception.getToolDefinition().name() + " ("
+ cause.getClass().getSimpleName() + ")";
}
// 打印DEBUG级别日志:记录工具名称、错误信息、完整异常堆栈
logger.debug("Exception thrown by tool: {}. Message: {}", exception.getToolDefinition().name(), message,
exception);
// 返回格式化后的错误信息,交给大模型LLM解析理解
return message;
}
1.3.1 直接抛出
触发条件:
- 根异常不是
RuntimeException(如IOException、SQLException) - 根异常是
RuntimeException,但在rethrownExceptions列表里 - 配置
alwaysThrow=true,强制抛出
注意事项 :如果直接 throw 异常,会直接中断流程,不会返回任何信息给大模型,适用于严重不应该让 LLM 处理的错误。
1.3.2 格式化后返回给大模型
触发条件:
- 根异常是
RuntimeException - 不在重抛异常列表里
alwaysThrow=false(默认值)
异常中包含错误信息,会直接返回错误字符串,示例:
java
API 调用失败
如果,原异常没有错误信息,会添加默认,示例:
java
Exception occurred in tool: xxxTool (RuntimeException)
最后包装为 ToolResponse 返回:
java
public record ToolResponse(String id, String name, String responseData) {
}
注意事项:如果是普通业务错误,格式化后的错误消息可以让大模型读懂并友好回复用户,流程正常继续,不会中断。
2. Spring AI Alibaba ReactAgent
2.1 AgentToolNode#executeToolByType
在 ReactAgent#AgentToolNode 工具执行节点中,最终的同步或异步工具执行方法中,都会捕获异常并处理:
catch ToolExecutionException:调用ToolExecutionExceptionProcessor进行处理,返回ToolCallResponse.of()包装的响应结果catch Exception: 返回ToolCallResponse.error()包装的响应结果
捕获逻辑:
java
/**
* 同步执行工具调用的核心方法
* 负责调用具体的工具回调对象,处理执行结果、异常,并返回标准化的工具响应
*
* @param callback 工具回调对象(Spring AI 标准工具执行器)
* @param request 工具调用请求对象,包含工具名、参数、调用ID等
* @param toolContextMap 工具执行上下文参数(会话信息、用户信息等)
* @param config 运行时配置(包含线程ID、Agent配置等)
* @return 工具调用的标准化响应对象(成功/失败结果)
*/
private ToolCallResponse executeSyncTool(ToolCallback callback, ToolCallRequest request,
Map<String, Object> toolContextMap, RunnableConfig config) {
// 1. 构建工具执行上下文,封装传入的上下文参数
ToolContext context = new ToolContext(toolContextMap);
try {
// 2. 核心:调用工具的执行方法,传入JSON格式的参数和上下文,获取执行结果
String result = callback.call(request.getArguments(), context);
// 3. 判断是否开启Agent执行日志,打印工具执行成功日志
if (enableActingLog) {
// 打印基础执行日志:线程ID、Agent名称、执行完成的工具名
logger.info("[ThreadId {}] Agent {} acting, tool {} finished",
config.threadId().orElse(THREAD_ID_DEFAULT), agentName, request.getToolName());
// Debug级别:打印工具返回的详细结果
if (logger.isDebugEnabled()) {
logger.debug("Tool {} returned: {}", request.getToolName(), result);
}
}
// 4. 构建并返回【成功】的工具调用响应
return ToolCallResponse.of(request.getToolCallId(), request.getToolName(), result);
}
catch (ToolExecutionException e) {
// 5. 捕获【工具执行专属异常】:使用自定义异常处理器处理业务异常
logger.error("Tool {} execution failed, handling with processor: {}", request.getToolName(),
toolExecutionExceptionProcessor.getClass().getName(), e);
// 调用异常处理器生成友好的错误结果
String result = toolExecutionExceptionProcessor.process(e);
// 返回处理后的异常响应
return ToolCallResponse.of(request.getToolCallId(), request.getToolName(), result);
}
catch (Exception e) {
// 6. 捕获【所有未知/系统异常】:通用异常处理
logger.error("Tool {} execution failed: {}", request.getToolName(), e.getMessage(), e);
// 构建并返回【错误】的工具调用响应(自动封装异常信息)
return ToolCallResponse.error(request.getToolCallId(), request.getToolName(), e);
}
}
2.2 异常处理
2.2.1 ToolExecutionException
在 AgentToolNode 构建方法中,如果没有配置 ToolExecutionExceptionProcessor ,默认使用也是 Spring AI 中的 DefaultToolExecutionExceptionProcessor :
java
public Builder toolExecutionExceptionProcessor(
ToolExecutionExceptionProcessor toolExecutionExceptionProcessor) {
if (toolExecutionExceptionProcessor == null) {
toolExecutionExceptionProcessor = DefaultToolExecutionExceptionProcessor.builder()
.alwaysThrow(false)
.build(); }
this.toolExecutionExceptionProcessor = toolExecutionExceptionProcessor;
return this;
}
如果工具执行返回 ToolExecutionException ,进入异常处理器中,处理逻辑和 Spring AI 一致:
- 直接
throw异常 - 返回格式化后的异常信息
比如没有抛出异常,处理器返回结果:
java
API 调用失败
然后再调用 of 方法返回统一的工具执行结果:
java
public static ToolCallResponse of(String toolCallId, String toolName, String result) {
return new ToolCallResponse(result, toolName, toolCallId);
}
最终返回给 LLM 的工具执行失败示例:
java
{
"toolCallId": "call_123",
"toolName": "weatherTool",
"result": "API 调用失败",
}
2.2.2 Exception
如果工具执行返回 Exception ,会调用 error 方法构建错误消息。
处理逻辑:
java
/**
* 根据异常 Throwable 构建工具执行失败的错误响应
* 作用:统一封装工具异常,返回给大模型 LLM 标准格式
* 如果异常消息为null,则保留异常类名(保证LLM一定能读到错误)
*
* @param toolCallId 工具调用ID(LLM生成的唯一标识)
* @param toolName 工具名称
* @param cause 工具执行抛出的异常
* @return 封装好的工具错误响应
*/
public static ToolCallResponse error(String toolCallId, String toolName, Throwable cause) {
// 构建错误消息:
// 异常有消息 → 使用异常消息
// 异常无消息 → 使用异常类名(例如 NullPointerException)
String errorMessage = cause.getMessage() != null ? cause.getMessage() : cause.getClass().getSimpleName();
// 调用重载方法,统一封装成 ToolCallResponse
return error(toolCallId, toolName, errorMessage);
}
最后调用统一的 error 统一封装工具执行失败的错误响应:
java
/**
* 根据错误字符串构建工具执行失败的响应
* 统一格式:固定前缀 + 错误信息 + 元数据
*
* @param toolCallId 工具调用ID
* @param toolName 工具名称
* @param errorMessage 错误提示文本
* @return 标准错误格式的 ToolCallResponse
*/
public static ToolCallResponse error(String toolCallId, String toolName, String errorMessage) {
// 构建并返回错误响应:
// 1. 内容:"Error: " + 错误信息
// 2. 工具名、toolCallId 原样带回
// 3. 状态:error
// 4. 元数据:标记 error=true,存储错误消息
return new ToolCallResponse(
"Error: " + errorMessage, // 给LLM看的错误内容
toolName, // 工具名
toolCallId, // 工具调用ID
"error", // 状态:错误
Map.of( // 扩展元数据
"error", true,
"errorMessage", errorMessage
)
);
最终返回给 LLM 的工具执行失败示例:
java
{
"toolCallId": "call_123",
"toolName": "weatherTool",
"content": "Error: 连接天气服务超时",
"status": "error",
"metadata": {
"error": true,
"errorMessage": "连接天气服务超时"
}
}
2.3 执行流程
流程极简说明:
- 工具调用:
- 正常→ 直接返回成功结果
- 异常→ 包装为
ToolExecutionException
- 工具执行:
- 捕获
ToolExecutionException→ 走异常处理器- 直接抛出异常→ 流程中断
- 异常处理器生成友好文案→ 统一通用响应封装→ 大模型处理
- 捕获
Exception(系统异常)→ 统一通用错误封装→ 大模型处理
- 捕获

3. 演示案例
3.1 RuntimeException
定义一个天气查询工具,内部抛出 RuntimeException :
java
public class WeatherTool {
@Tool(description = "查询指定城市的天气")
public String getWeather(@ToolParam String city) {
if (1==1){
throw new RuntimeException("天气 API 调用失败");
}
return "%s 天气:晴天,26℃,空气质量优".formatted(city);
}
}
执行调用:
java
ReactAgent chatAgent = ReactAgent.builder()
.name("my-agent")
.model(zhiPuAiChatModel)
.methodTools(new WeatherTool())
.build();
String text = chatAgent.call("查询长沙的天气情况").getText();
System.out.println(text);
RuntimeException 在执行时会包装为 ToolExecutionException ,根异常是 RuntimeException ,默认的异常处理器中,则会格式化并回复给大模型处理。
控制台输出示例:
java
Caused by: java.lang.RuntimeException: 天气 API 调用失败
at com.example.aialibaba.config.WeatherTool.getWeather(WeatherTool.java:28) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.ai.tool.method.MethodToolCallback.callMethod(MethodToolCallback.java:185) ~[spring-ai-model-1.1.2.jar:1.1.2]
... 116 common frames omitted
很抱歉,查询长沙天气时遇到了技术问题,无法获取到天气信息。可能是天气服务暂时不可用或网络连接问题。
建议您:
1. 稍后再试查询天气
2. 或者可以通过其他天气应用、网站获取长沙的天气信息
3. 如果您有其他需要帮助的地方,请告诉我
工具调用响应结果如下:

3.1 Exception
如果工具内部抛出 Exception :
java
@Tool(description = "查询指定城市的天气")
public String getWeather(@ToolParam String city) throws Exception {
if (1==1){
throw new Exception("天气 API 调用失败");
}
return "%s 天气:晴天,26℃,空气质量优".formatted(city);
}
Exception 在执行时也会包装为 ToolExecutionException ,根异常是 Exception ,默认的异常处理器中,由于根异常不是 RuntimeException ,则会直接抛出异常,流程中断。
控制台输出示例:
java
Caused by: java.lang.Exception: 天气 API 调用失败
at com.example.aialibaba.config.WeatherTool.getWeather(WeatherTool.java:28) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.ai.tool.method.MethodToolCallback.callMethod(MethodToolCallback.java:185) ~[spring-ai-model-1.1.2.jar:1.1.2]
... 116 common frames omitted
Disconnected from the target VM, address: '127.0.0.1:60077', transport: 'socket'
3.3 ServiceException
在实际企业开发中,一般都会定义一个通用业务异常,例如业务操作中的参数类错误、数据 / 业务规则错误等异常信息。
ServiceException 简单示例:
java
public class ServiceException extends RuntimeException {
private static final long serialVersionUID = 1L;
/** 异常提示信息 */
private String message;
/** 异常编码(业务错误码) */
private String code;
/** 占位符参数(用于国际化/格式化消息) */
private Object[] args;
/** 异常详细信息 */
private String detailMessage;
// ===================== 保留你原有构造函数 =====================
public ServiceException() {
}
public ServiceException(String message) {
// 修复:调用父类构造,保证Throwable.getMessage()生效
super(message);
this.message = message;
}
public ServiceException(String message, String code) {
super(message);
this.message = message;
this.code = code;
}
public ServiceException(String message, Object... args) {
super(message);
this.message = message;
this.args = args;
}
public ServiceException(String message, String code, String detailMessage) {
super(message);
this.message = message;
this.code = code;
this.detailMessage = detailMessage;
}
// ===================== 生产级新增:带根异常的构造器(必备) =====================
public ServiceException(String message, String code, Throwable cause) {
super(message, cause);
this.message = message;
this.code = code;
}
// ===================== 保留你原有链式方法 =====================
public ServiceException setCode(String code) {
this.code = code;
return this;
}
public ServiceException setDetailMessage(String detailMessage) {
this.detailMessage = detailMessage;
return this;
}
// ===================== 生产级新增:Getter方法(外部必须读取异常信息) =====================
@Override
public String getMessage() {
return this.message;
}
public String getCode() {
return code;
}
public Object[] getArgs() {
return args;
}
public String getDetailMessage() {
return detailMessage;
}
}
模拟工具调用时,出现的业务异常:
java
@Tool(description = "查询指定城市的天气")
public String getWeather(@ToolParam String city) {
if (1==1){
// 调用某个业务类,出现业务异常
throw new ServiceException("天气 API 调用失败");
}
return "%s 天气:晴天,26℃,空气质量优".formatted(city);
}
}
执行时包装为 ToolExecutionException 如下:

工具调用响应结果如下:

3.4 强制抛出异常
DefaultToolExecutionExceptionProcessor 可以通过 alwaysThrow 配置只要是发生异常,就中断流程直接抛出。
示例:
java
DefaultToolExecutionExceptionProcessor exceptionProcessor = DefaultToolExecutionExceptionProcessor.builder()
.alwaysThrow(true) // 总是抛出异常
//.rethrowExceptions()
.build();
ReactAgent chatAgent = ReactAgent.builder()
.name("my-agent")
.toolExecutionExceptionProcessor(exceptionProcessor)
.model(zhiPuAiChatModel)
.methodTools(new WeatherTool())
.build();
String text = chatAgent.call("查询长沙的天气情况").getText();
System.out.println(text);
3.5 选择性抛出异常
DefaultToolExecutionExceptionProcessor 可以通过 rethrowExceptions 配置哪些异常直接抛出。
示例:
java
DefaultToolExecutionExceptionProcessor exceptionProcessor = DefaultToolExecutionExceptionProcessor.builder()
.rethrowExceptions(List.of(ServiceException.class)) // ServiceException 直接抛出
.build();
ReactAgent chatAgent = ReactAgent.builder()
.name("my-agent")
.toolExecutionExceptionProcessor(exceptionProcessor)
.model(zhiPuAiChatModel)
.methodTools(new WeatherTool())
//.interceptors(toolEmulatorInterceptor)
.build();
String text = chatAgent.call("查询长沙的天气情况").getText();
System.out.println(text);
注意 :此时,抛出的是根异常,不是包装后的 ToolExecutionException 。
3.6 强制不抛出异常
ToolErrorInterceptor(错误处理拦截器)最简单的错误处理拦截器,捕获所有异常并返回错误消息,而非抛出异常中断 流程。
示例:
java
ToolErrorInterceptor toolErrorInterceptor = ToolErrorInterceptor.builder().build();
DefaultToolExecutionExceptionProcessor exceptionProcessor = DefaultToolExecutionExceptionProcessor.builder()
.alwaysThrow(false) // 总是抛出异常
.rethrowExceptions(List.of(ServiceException.class)) // ServiceException 直接抛出
.build();
ReactAgent chatAgent = ReactAgent.builder()
.name("my-agent")
.toolExecutionExceptionProcessor(exceptionProcessor)
.model(zhiPuAiChatModel)
.methodTools(new WeatherTool())
.interceptors(toolErrorInterceptor)
.build();
String text = chatAgent.call("查询长沙的天气情况").getText();
System.out.println(text);
此时,无论是 ServiceException 、 ToolExecutionException 、Exception 都不会直接抛出异常:
java
Caused by: com.example.aialibaba.config.ServiceException: 天气 API 调用失败
at com.example.aialibaba.config.WeatherTool.getWeather(WeatherTool.java:29) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.ai.tool.method.MethodToolCallback.callMethod(MethodToolCallback.java:185) ~[spring-ai-model-1.1.2.jar:1.1.2]
... 118 common frames omitted
很抱歉,查询长沙天气时出现了技术问题,无法获取到天气信息。这可能是由于天气服务暂时不可用或网络连接问题导致的。
建议您可以:
1. 稍后再试查询
2. 使用其他天气应用或网站查看长沙的天气情况
3. 如果您需要其他帮助,我很乐意为您提供其他服务