【编者按】已安装、配置好Tensorflow Seving,调试客户端代码,全程在ChatGPT支持下完成。
最后一个问题是关于gRPC和REST API区别,可以作为知识点学习。
1问:已编写Tensorflow serving客户端代码,要求读入图片文件请求服务器识别图片,返回结果,修改一下代码。(附源代码,此处不贴出,另:隐藏了真实IP)
ChatGPT
你的客户端代码中出现了 DNS 解析错误,这是因为 grpc.insecure_channel 方法只接受主机名或 IP 地址和端口号的形式,而不接受带有 http:// 前缀的 URL。
请修改以下部分:
channel = grpc.insecure_channel('http://IP:8501/') channel = grpc.insecure_channel('IP:8501') 去掉 http:// 前缀后,再运行代码试试。
import grpc import tensorflow as tf from tensorflow_serving.apis import predict_pb2, prediction_service_pb2_grpc from google.protobuf import json_format from PIL import Image import numpy as np # 定义读取和预处理图片的函数 def load_image(image_path): img = Image.open(image_path).resize((224, 224)) img = np.array(img).astype(np.float32) img = np.expand_dims(img, axis=0) # 扩展维度以符合模型输入 return img # 创建 gRPC 频道和 stub channel = grpc.insecure_channel('IP:8501') stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) # 创建预测请求 request = predict_pb2.PredictRequest() request.model_spec.name = 'ai_flower' request.model_spec.signature_name = 'serving_default' # 读取并预处理图片 image_path = 'test_images/rose.jpg' input_image = load_image(image_path) # 将预处理后的图片设置为请求的输入张量 request.inputs['input_tensor_name'].CopyFrom( tf.make_tensor_proto(input_image, shape=input_image.shape)) # 发送请求并获取响应 response = stub.Predict(request) print(response) 运行此代码,应该会解决 DNS 解析错误的问题。如果还有其他问题,随时告诉我!
2问:有错:Traceback (most recent call last):
File “E:\WorkspacePython\TensorFlow_Serving\gRPC_client.py”, line 33, in
response = stub.Predict(request)
File “e:\ProgramData\Anaconda3\envs\tensorflow27\lib\site-packages\grpc_channel.py”, line 946, in call
return _end_unary_response_blocking(state, call, False, None)
File “e:\ProgramData\Anaconda3\envs\tensorflow27\lib\site-packages\grpc_channel.py”, line 849, in _end_unary_response_blocking
raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.UNAVAILABLE
details = “failed to connect to all addresses; last error: INTERNAL: ipv4:XXXX:8501: Trying to connect an http1.x server”
debug_error_string = “UNKNOWN:failed to connect to all addresses; last error: INTERNAL: ipv4:XXXX:8501: Trying to connect an http1.x server {grpc_status:14, created_time:“2024-07-31T15:29:54.366014749+00:00”}”
ChatGPT
看起来你正在使用的 TensorFlow Serving 服务器可能配置为使用 REST API 而不是 gRPC 服务。要使用 gRPC,你需要确保 TensorFlow Serving 服务器正确配置并运行在 gRPC 端口。
你可以尝试以下步骤来解决这个问题:
确保 TensorFlow Serving 使用 gRPC 端口运行:
启动 TensorFlow Serving 时,确保正确配置 gRPC 端口。例如:
tensorflow_model_server --port=8500 --rest_api_port=8501 --model_name=ai_flower --model_base_path=/xxxx/TensorFlow_Serving/saved_model/ 在这个示例中,--port=8500 是 gRPC 端口,--rest_api_port=8501 是 REST API 端口。
修改客户端代码以使用正确的 gRPC 端口:
确保客户端代码中的端口号与服务器上的 gRPC 端口号一致。例如:
channel = grpc.insecure_channel('XXXX:8500') 检查防火墙设置:
确保服务器的 gRPC 端口(如 8500)在防火墙中是开放的,并且可以从客户端计算机访问。
确保模型输入名称正确:
确保 request.inputs['input_tensor_name'] 中的 'input_tensor_name' 是你在 TensorFlow SavedModel 中定义的输入张量的名称。
import grpc import tensorflow as tf from tensorflow_serving.apis import predict_pb2, prediction_service_pb2_grpc from google.protobuf import json_format from PIL import Image import numpy as np # 定义读取和预处理图片的函数 def load_image(image_path): img = Image.open(image_path).resize((224, 224)) img = np.array(img).astype(np.float32) img = np.expand_dims(img, axis=0) # 扩展维度以符合模型输入 return img # 创建 gRPC 频道和 stub channel = grpc.insecure_channel('XXXX:8500') stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) # 创建预测请求 request = predict_pb2.PredictRequest() request.model_spec.name = 'ai_flower' request.model_spec.signature_name = 'serving_default' # 读取并预处理图片 image_path = 'test_images/rose.jpg' input_image = load_image(image_path) # 将预处理后的图片设置为请求的输入张量 request.inputs['input_tensor_name'].CopyFrom( tf.make_tensor_proto(input_image, shape=input_image.shape)) # 发送请求并获取响应 response = stub.Predict(request) print(response) 确保 TensorFlow Serving 服务器和客户端配置的一致性,并且服务器端正确运行 gRPC 服务。如果还有问题,请提供更多详细信息,以便进一步诊断。
3问:有新错误:Traceback (most recent call last):
File “E:\WorkspacePython\TensorFlow_Serving\gRPC_client.py”, line 33, in
response = stub.Predict(request)
File “e:\ProgramData\Anaconda3\envs\tensorflow27\lib\site-packages\grpc_channel.py”, line 946, in call
return _end_unary_response_blocking(state, call, False, None)
File “e:\ProgramData\Anaconda3\envs\tensorflow27\lib\site-packages\grpc_channel.py”, line 849, in _end_unary_response_blocking
raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.INVALID_ARGUMENT
details = “input tensor alias not found in signature: input_tensor_name. Inputs expected to be in the set {keras_layer_input}.”
debug_error_string = “UNKNOWN:Error received from peer ipv4:XXXX:8500 {created_time:“2024-07-31T15:33:22.315742596+00:00”, grpc_status:3, grpc_message:“input tensor alias not found in signature: input_tensor_name. Inputs expected to be in the set {keras_layer_input}.”}”
ChatGPT:
错误信息表明,在你的模型签名中,输入张量的名称是 keras_layer_input,而不是 input_tensor_name。你需要将客户端代码中请求输入张量的名称改为 keras_layer_input。
修改后的客户端代码如下:
import grpc import tensorflow as tf from tensorflow_serving.apis import predict_pb2, prediction_service_pb2_grpc from PIL import Image import numpy as np # 定义读取和预处理图片的函数 def load_image(image_path): img = Image.open(image_path).resize((224, 224)) img = np.array(img).astype(np.float32) img = np.expand_dims(img, axis=0) # 扩展维度以符合模型输入 return img # 创建 gRPC 频道和 stub channel = grpc.insecure_channel('XXXX:8500') stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) # 创建预测请求 request = predict_pb2.PredictRequest() request.model_spec.name = 'ai_flower' request.model_spec.signature_name = 'serving_default' # 读取并预处理图片 image_path = 'test_images/rose.jpg' input_image = load_image(image_path) # 将预处理后的图片设置为请求的输入张量 request.inputs['keras_layer_input'].CopyFrom( tf.make_tensor_proto(input_image, shape=input_image.shape)) # 发送请求并获取响应 response = stub.Predict(request) print(response) 如果你不确定输入张量的确切名称,可以使用以下命令来查看模型的签名信息:
saved_model_cli show --dir /xxxx/TensorFlow_Serving/saved_model --all 这个命令会输出模型的输入和输出签名信息。根据这个信息,你可以确认输入张量的正确名称并在客户端代码中使用它。
saved_model_cli 命令输出的签名信息,确认输入张量的名称。通过这些步骤,应该能解决输入张量名称不匹配的问题。如果还有问题,请提供更多详细信息,以便进一步诊断。
4问:正确了。下面是客户端代码,修改一下代码:要求:标签编号与类别名称对应文件在当前目录label_map-encn.json中,分析返回信心,print前5为的预测结果。
ChatGPT
下面是修改后的客户端代码,包含从 label_map-encn.json 文件中读取标签编号与类别名称的对应关系,并分析返回的结果,打印前5位的预测结果:
import grpc import tensorflow as tf from tensorflow_serving.apis import predict_pb2, prediction_service_pb2_grpc from PIL import Image import numpy as np import json # 定义读取和预处理图片的函数 def load_image(image_path): img = Image.open(image_path).resize((224, 224)) img = np.array(img).astype(np.float32) img = np.expand_dims(img, axis=0) # 扩展维度以符合模型输入 return img # 从JSON文件中加载标签映射 def load_label_map(label_map_path): with open(label_map_path, 'r', encoding='utf-8') as f: label_map = json.load(f) return label_map # 创建 gRPC 频道和 stub channel = grpc.insecure_channel('XXXX:8500') stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) # 创建预测请求 request = predict_pb2.PredictRequest() request.model_spec.name = 'ai_flower' request.model_spec.signature_name = 'serving_default' # 读取并预处理图片 image_path = 'test_images/rose.jpg' input_image = load_image(image_path) # 将预处理后的图片设置为请求的输入张量 request.inputs['keras_layer_input'].CopyFrom( tf.make_tensor_proto(input_image, shape=input_image.shape)) # 发送请求并获取响应 response = stub.Predict(request) # 解析响应 predictions = tf.make_ndarray(response.outputs['predictions']) # 加载标签映射 label_map = load_label_map('label_map-encn.json') # 获取前5位预测结果 top_k = 5 top_k_indices = np.argsort(predictions[0])[::-1][:top_k] top_k_labels = [label_map[str(index)] for index in top_k_indices] top_k_scores = predictions[0][top_k_indices] # 打印前5位预测结果 for i in range(top_k): print(f"Rank {i + 1}: {top_k_labels[i]} (score: {top_k_scores[i]:.4f})") load_image 函数读取并预处理图片。load_label_map 函数从 label_map-encn.json 文件中加载标签映射。确保 label_map-encn.json 文件在脚本的当前目录中,并且其内容格式正确。例如:
{ "0": "daisy", "1": "dandelion", "2": "roses", "3": "sunflowers", "4": "tulips" } 5问:Traceback (most recent call last):
File “E:\WorkspacePython\TensorFlow_Serving\gRPC_client.py”, line 42, in
predictions = tf.make_ndarray(response.outputs[‘predictions’])
File “e:\ProgramData\Anaconda3\envs\tensorflow27\lib\site-packages\tensorflow\python\framework\tensor_util.py”, line 662, in MakeNdarray
tensor_dtype = dtypes.as_dtype(tensor.dtype)
File “e:\ProgramData\Anaconda3\envs\tensorflow27\lib\site-packages\tensorflow\python\framework\dtypes.py”, line 852, in as_dtype
raise TypeError(f"Cannot convert the argument type_value: {type_value!r} "
TypeError: Cannot convert the argument type_value: 0 to a TensorFlow DType.
ChatGPT
这个错误通常表示在从响应中提取张量时,找不到指定的键。确保响应中的键名与模型导出的签名一致。
你可以通过调试代码来检查响应的具体内容,从而确定输出张量的名称。先打印响应内容,找到包含预测结果的键。修改如下:
import grpc import tensorflow as tf from tensorflow_serving.apis import predict_pb2, prediction_service_pb2_grpc from PIL import Image import numpy as np import json # 定义读取和预处理图片的函数 def load_image(image_path): img = Image.open(image_path).resize((224, 224)) img = np.array(img).astype(np.float32) img = np.expand_dims(img, axis=0) # 扩展维度以符合模型输入 return img # 从JSON文件中加载标签映射 def load_label_map(label_map_path): with open(label_map_path, 'r', encoding='utf-8') as f: label_map = json.load(f) return label_map # 创建 gRPC 频道和 stub channel = grpc.insecure_channel('XXXX:8500') stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) # 创建预测请求 request = predict_pb2.PredictRequest() request.model_spec.name = 'ai_flower' request.model_spec.signature_name = 'serving_default' # 读取并预处理图片 image_path = 'test_images/rose.jpg' input_image = load_image(image_path) # 将预处理后的图片设置为请求的输入张量 request.inputs['keras_layer_input'].CopyFrom( tf.make_tensor_proto(input_image, shape=input_image.shape)) # 发送请求并获取响应 response = stub.Predict(request) # 打印响应内容,检查输出张量的键名 print("Response outputs:", response.outputs) # 假设输出张量的键名是 'predictions',从响应中提取预测结果 # 如果键名不同,请根据打印结果进行修改 output_tensor_name = 'predictions' # 修改为实际的键名 if output_tensor_name in response.outputs: predictions = tf.make_ndarray(response.outputs[output_tensor_name]) else: print(f"Output tensor '{output_tensor_name}' not found in the response.") predictions = [] # 加载标签映射 label_map = load_label_map('label_map-encn.json') # 获取前5位预测结果 top_k = 5 if predictions.size > 0: top_k_indices = np.argsort(predictions[0])[::-1][:top_k] top_k_labels = [label_map[str(index + 1)] for index in top_k_indices] top_k_scores = predictions[0][top_k_indices] # 打印前5位预测结果 for i in range(top_k): print(f"Rank {i + 1}: {top_k_labels[i]} (score: {top_k_scores[i]:.4f})") else: print("No predictions found.") print("Response outputs:", response.outputs) 打印响应内容,找到包含预测结果的键。output_tensor_name 变量为实际的键名。执行此代码,观察打印的响应内容,确保找到了正确的键名。然后,修改 output_tensor_name 变量,重新运行代码进行预测和结果打印。
6问:正确了。再讨论下一个问题:gRPC与REST API有什么区别?
ChatGPT
gRPC 和 REST API 是两种用于服务间通信的不同协议。它们各有优缺点,适用于不同的场景。以下是它们的主要区别:
gRPC:
REST API:
gRPC:
REST API:
gRPC:
REST API:
gRPC:
.proto 文件)描述了服务、方法和消息格式。REST API:
gRPC:
REST API:
gRPC:
REST API:
gRPC:
REST API:
选择哪种技术取决于具体的应用需求和环境。
上一篇:大模型术语表
下一篇:学校公众满意度调查的开展方式