基于DeepSeek智能体+YOLO+ResNet的饮食健康分析系统技术实现

一、系统概述

本文实现一套LLM智能体驱动、多工具协同的饮食健康分析系统。系统以 DeepSeek 大模型为决策核心,将 YOLO 目标检测、ResNet 细粒度分类、营养数据库核算封装为可调用工具,依靠智能体自主完成任务拆解、工具调度、数据推理与结果生成,实现餐盘图像识别、热量量化计算、个性化饮食评估与菜品推荐的端到端智能化闭环。

二、系统整体技术架构

整体架构分为两层:智能决策层、工具支撑层,所有工具调用、流程执行均由 DeepSeek 智能体统一调度,无预设固定执行链路。

2.1 智能决策层

我们采用 DeepSeek 大模型为智能体主体,承载全局任务规划、工具调度决策、多维数据融合、逻辑推理、个性化输出等核心能力,是系统唯一的决策中枢,具备自主思考、动态纠错、场景自适应特性。

python 复制代码
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com")
DEEPSEEK_MODEL = os.getenv("DEEPSEEK_MODEL", "deepseek-chat")
SERVER_PORT = int(os.getenv("SERVER_PORT", "15007"))
SERVER_HOST = os.getenv("SERVER_HOST", "0.0.0.0")


SYSTEM_PROMPT = """你是"食慧",一个专业的健康饮食 AI 顾问,运行在食物识别系统中。

## 你的能力
1. **食材识别分析** --- 用户上传菜品图片后,系统会自动识别食物,你负责解读识别结果并给出营养分析
2. **个性化推荐** --- 根据用户的身体数据(身高、体重、年龄、性别)和健康目标推荐菜品
3. **营养计算** --- 计算 BMI、每日卡路里需求(BMR + TDEE),给出减脂/维持/增重三档建议
4. **饮食计划** --- 基于数据库中的真实菜品生成一日/多日饮食计划
5. **饮食历史分析** --- 查询用户的历史饮食记录,分析营养摄入趋势

## 工作原则
- **数据驱动**:所有推荐基于数据库中的真实菜品和用户真实数据,不编造菜品
- **主动使用工具**:遇到需要用户数据、菜品信息、营养计算的问题时,先调用对应工具获取数据
- **个性化**:回答要结合用户的具体情况(BMI、目标、活动水平),而非泛泛而谈
- **专业但通俗**:营养建议要专业准确,但表达方式要让普通人能理解
- **中文回复**:始终用中文回复

## 回答格式
- 营养数据用表格呈现,清晰对比
- 饮食计划按餐次组织(早餐/午餐/晚餐/加餐)
- 关键数据用粗体标注
- 避免冗长的开头结尾,直接进入正题"""


CONFIDENCE_THRESHOLD = float(os.getenv("CONFIDENCE_THRESHOLD", "0.3"))


def get_config():
    """获取配置摘要(用于日志/调试)"""
    return {
        "deepseek_model": DEEPSEEK_MODEL,
        "deepseek_base_url": DEEPSEEK_BASE_URL,
        "server_port": SERVER_PORT,
        "api_key_configured": bool(DEEPSEEK_API_KEY),
    }

2.2 工具支撑层

封装四类标准化功能工具,仅响应智能体调用指令,无自主执行权限,为智能体决策提供精准、结构化的底层数据支撑:

  • 视觉检测工具:YOLO,负责菜品目标定位与 ROI 裁剪
  • 视觉分类工具:ResNet,负责菜品细粒度特征提取与类别识别
  • 数据检索工具:菜品营养数据库,存储各类食材标准化热量、营养参数
  • 数值核算工具:实现单菜、整餐热量与营养占比量化计算

三、视觉工具技术实现(YOLO+ResNet两级协同)

针对餐盘多菜品重叠、遮挡、复杂背景干扰问题,系统采用「检测+分类」两级视觉架构,为 DeepSeek 智能体提供高精度图像感知能力,弥补大模型原生视觉细粒度识别短板。

3.1 YOLO 目标检测模块

由智能体主动调用,对输入餐盘图像做目标检测,输出菜品目标边界框坐标、置信度,完成背景过滤与目标提取。核心作用是解耦前景菜品与冗余背景,裁剪得到独立菜品 ROI 区域,规避整张图推理带来的特征干扰,为细分类提供标准化输入。

YOLO目标检测推理模块:

python 复制代码
class FoodDetector:
    """菜品目标检测器"""

    def __init__(self, model_path, class_names=None, conf_thres=0.45, iou_thres=0.2,cls_model="food_cls.onnx"):
        """
        :param model_path:  ONNX 模型路径
        :param class_names: 类别名列表(顺序与模型 class_id 一致,即 FOODS 表的 class_name)
        :param conf_thres:  置信度阈值(菜品场景建议 0.45)
        :param iou_thres:   NMS IoU 阈值
        """
        self.conf_thres = conf_thres
        self.iou_thres = iou_thres
        self.class_names = class_names or []
        self.food_cls=CommonClass(cls_model)

        cuda_options = {
            'device_id': 0,
            'gpu_mem_limit': int(1 * 1024 * 1024 * 1024),  # 1GB 上限
            'arena_extend_strategy': 'kSameAsRequested',   # 严格按需分配
            'cudnn_conv_algo_search': 'DEFAULT'            # 禁用穷举搜索,使用默认算法
        }
        providers = [('CUDAExecutionProvider', cuda_options), 'CPUExecutionProvider']
        # 无 CUDA 环境自动回退 CPU(代码级兜底,不影响现有 GPU 机器)
        try:
            self.session = onnxruntime.InferenceSession(model_path, providers=providers)
        except Exception:
            self.session = onnxruntime.InferenceSession(model_path, providers=['CPUExecutionProvider'])
        self.session.intra_op_num_threads = 1
        self.input_name = self.session.get_inputs()[0].name
        shape = self.session.get_inputs()[0].shape
        # 动态维度(shape 可能为 None)时兜底 640
        self.input_h = int(shape[2]) if len(shape) >= 4 and isinstance(shape[2], int) and shape[2] > 0 else 640
        self.input_w = int(shape[3]) if len(shape) >= 4 and isinstance(shape[3], int) and shape[3] > 0 else 640
        self.inference_lock = threading.Lock()

    @staticmethod
    def filter_by_roi(boxes, scores, class_ids, roi):
        """保留中心点位于 roi([x1, y1, x2, y2])内的检测框;roi 为 None/空时不过滤"""
        if roi is None or len(roi) == 0:
            return boxes, scores, class_ids
        x1, y1, x2, y2 = roi
        cx = (boxes[:, 0] + boxes[:, 2]) / 2
        cy = (boxes[:, 1] + boxes[:, 3]) / 2
        mask = (cx >= x1) & (cx <= x2) & (cy >= y1) & (cy <= y2)
        if not np.any(mask):
            return np.empty((0, 4)), np.empty(0), np.empty(0)
        return boxes[mask], scores[mask], class_ids[mask]

    def detect_objects(self, image, bbox=None):
        """
        检测图像中的菜品。
        :param image: BGR 图像(cv2 解码结果)
        :param bbox:  可选 [x1, y1, x2, y2] 感兴趣区域,仅保留区域内检测;None 表示全图
        :return: (boxes_xyxy, scores, class_ids)
        """
        img_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        img_letter, ratio, (pad_w, pad_h) = letterbox(img_rgb, (self.input_h, self.input_w))
        img_norm = img_letter.astype(np.float32) / 255.0
        input_tensor = np.expand_dims(img_norm.transpose(2, 0, 1), axis=0)
        with self.inference_lock:
            outputs = self.session.run(None, {self.input_name: input_tensor})

        # ---- 输出格式自适应 ----
        # ultralytics 标准导出是 (1, C, N);部分工具/自导出模型是 (1, N, C)。
        # 统一转成 (N, C):行 = [cx, cy, w, h, cls0..clsN-1]
        raw = outputs[0]
        if raw.ndim == 3 and raw.shape[0] == 1:
            if raw.shape[1] < raw.shape[2]:
                predictions = raw[0].T      # (1, C, N) -> (N, C)
            else:
                predictions = raw[0]        # (1, N, C) -> (N, C)
        else:
            predictions = np.squeeze(raw)
            if predictions.ndim == 2 and predictions.shape[0] < predictions.shape[1]:
                predictions = predictions.T
        predictions = np.ascontiguousarray(predictions, dtype=np.float32)

        if predictions.size == 0:
            return np.empty((0, 4)), np.empty(0), np.empty(0)

        # 坐标可能为相对输入图的归一化值(0~1)或像素值,按输入尺寸还原为像素
        if float(predictions[:, :2].max()) <= 1.0:
            predictions[:, 0] *= self.input_w
            predictions[:, 1] *= self.input_h
            predictions[:, 2] *= self.input_w
            predictions[:, 3] *= self.input_h

        scores = np.max(predictions[:, 4:], axis=1)
        mask = scores > self.conf_thres
        if not np.any(mask):
            return np.empty((0, 4)), np.empty(0), np.empty(0)

        predictions = predictions[mask]
        scores = scores[mask]
        class_ids = np.argmax(predictions[:, 4:], axis=1)
        boxes_xywh = predictions[:, :4]

        boxes_xywh[:, 0] -= pad_w
        boxes_xywh[:, 1] -= pad_h
        boxes_xywh[:, :4] /= ratio
        boxes_xyxy = xywh2xyxy(boxes_xywh)

        indices = multiclass_nms(boxes_xyxy, scores, class_ids, self.iou_thres)
        indices = np.asarray(indices, dtype=np.int64)  # utils 返回 list,统一转 ndarray
        if len(indices) == 0:
            return np.empty((0, 4)), np.empty(0), np.empty(0)

        final_boxes = boxes_xyxy[indices]
        final_scores = scores[indices]
        final_cls = class_ids[indices]

        # 可选:仅保留感兴趣区域(bbox)内的检测结果
        final_boxes, final_scores, final_cls = self.filter_by_roi(
            final_boxes, final_scores, final_cls, bbox
        )

        return final_boxes, final_scores, final_cls


    def detect(self, image_bytes, bbox=None):
        """
        适配 server/app.py 的 run_yolo 接口:图片字节流 -> 检测结果列表。
        :return: [{"class_id": int, "class_name": str, "confidence": float,
                   "bbox": [x1, y1, x2, y2]}, ...]
        """
        img = cv2.imdecode(np.frombuffer(image_bytes, np.uint8), cv2.IMREAD_COLOR)
        if img is None:
            raise ValueError("图片解码失败")

        boxes, scores, cls_ids = self.detect_objects(img, bbox)

        detections = []
        for box, score, cls_id in zip(boxes, scores, cls_ids):
            cls_id = int(cls_id)

            # 解析边界框坐标,并确保不超出图像边界
            x1, y1, x2, y2 = map(int, box)
            h, w = img.shape[:2]
            x1, y1 = max(0, x1), max(0, y1)
            x2, y2 = min(w, x2), min(h, y2)

            # 提取 ROI 区域
            roi = img[y1:y2, x1:x2]
            final_cls_id = cls_id
            final_conf = float(score)
            # 对每个 ROI 区域单独执行分类模型
            if roi.size > 0:
                # 调用分类模型,返回预测的类别 ID
                refined_cls_id,final_conf = self.food_cls(roi)
                final_cls_id = int(refined_cls_id)
            if final_conf>CONFIDENCE_THRESHOLD:
                detections.append({
                    "class_id": final_cls_id,
                    "class_name": self.class_names[final_cls_id] if final_cls_id < len(self.class_names) else f"class_{final_cls_id}",
                    "confidence": round(final_conf, 2),
                    "bbox": [float(round(v, 1)) for v in box],  # numpy -> python 原生类型,保证 jsonify 可序列化
                })
        return detections

3.2 ResNet 细粒度分类模块

智能体获取菜品 ROI 后,调度 ResNet 残差网络完成特征提取与菜品分类。依托残差跳跃连接结构,解决深层网络梯度消失问题,有效区分纹理、色彩高度相似的同类菜品,输出精准菜品类别标签,为后续营养检索提供可靠依据。

3.3 数据集与训练配置

本项目采用两阶段级联识别架构:首先通过目标检测模型对菜品进行空间定位,随后提取感兴趣区域(ROI)并输入分类模型以实现精细化识别。在数据构建方面,针对定位任务,我们自主采集并精细标注了310余张菜品图像作为训练集;针对分类任务,我们引入了ChineseFoodNet公开数据集,该数据集涵盖208个菜品类别,其中训练集包含15,124张图像,验证集包含5,129张图像。具体的208个菜品类别如下

powershell 复制代码
0	麻婆豆腐	Mapo Tofu
1	家常豆腐	Home style sauteed Tofu
2	煎豆腐	Fried Tofu
3	豆腐花	Bean curd
4	臭豆腐	Stinky tofu
5	酸辣土豆丝	Potato silk
6	土豆泥	Pan fried potato
7	香煎土豆	Pan fried potato
8	土豆焖豆角	Braised beans with potato
9	地三鲜	Fried Potato, Green Pepper & Eggplant
10	薯条	French fries
11	鱼香茄子	Yu-Shiang Eggplant
12	蒜泥茄子	Mashed garlic eggplant
13	肉末茄子	Eggplant with mince pork
14	辣白菜	Spicy cabbage
15	醋溜白菜	Sour cabbage
16	上汤娃娃菜	Steamed Baby Cabbage
17	手撕包菜	Shredded cabbage
18	蚝油生菜	Sauteed Lettuce in Oyster Sauce
19	炒青菜	Saute vegetable
20	炒空心菜	tumis kangkung
21	蒜蓉油麦菜	Lettuce with smashed garlic
22	清炒菠菜	Sauteed spainch
23	炒豆芽	Sauteed bean sprouts
24	炒蚕豆	Sauteed broad beans
25	毛豆	Soybean
26	蚝油西兰花	Broccoli with Oyster Sauce
27	香煎藕盒	Deep Fried lotus root
28	莲藕	Lotus root
29	凉拌西红柿	Tomato salad
30	鸡鸭胗	Gizzard
31	凉拌木耳	Black Fungus in Vinegar Sauce
32	口水黄瓜	Cucumber in Sauce
33	花生米	peanut
34	凉拌海带丝	Seaweed salad
35	拔丝山药	Chinese Yam in Hot Toffee
36	清炒山药	Fried Yam
37	干煸豆角	Fried beans
38	蚝油杏鲍菇	Oyster mushroom
39	酿苦瓜	stuffed bitter melon
40	炒苦瓜	sauteed bitter melon
41	虎皮青椒	pepper with tiger skin
42	凉拌腐竹	Yuba salad
43	炒花菜	fried cauliflower
44	松仁玉米	Sauteed Sweet Corn with Pine Nuts
45	香菇青菜	Sauted Chinese Greens with Mushrooms
46	椒盐蘑菇	Spiced mushroom
47	芹菜香干	Celery and tofu
48	西芹百合	Sauteed Lily Bulbs and Celery
49	韭菜炒香干	Leak and tofu
50	西红柿炒鸡蛋	Scrambled egg with tomato
51	韭菜炒鸡蛋	Scrambled Egg with Leek
52	黄瓜炒鸡蛋	Scrambled Egg with cucumber
53	鸡蛋羹	Steamed egg custard
54	猪肝	Pork liver
55	猪耳朵	Pig ears
56	叉烧	roast pork
57	粉蒸排骨	Steamed pork with rice powder
58	糖醋排骨	Sweet and sour spareribs
59	海带炖排骨	Braised spareribs with kelp
60	可乐鸡翅	Cola Chicken wings
61	泡椒凤爪	Chicken Feet with Pickled Peppers
62	红烧鸡爪	Chicken Feet with black bean sauce
63	口水鸡	Steamed Chicken with Chili Sauce
64	烤鸭烧鹅	Roast goose
65	白斩鸡	Boiled chicken
66	大盘鸡	Saute Spicy Chicken
67	香菇蒸鸡	Steamed Chicken with Mushroom
68	黄焖鸡	chicken braised with brown sauce
69	豉油鸡	Soy sauce chicken
70	辣子鸡	Spicy Chicken
71	宫保鸡丁	Kung Pao Chicken
72	三杯鸡	Stewed Chicken with Three Cups Sauce
73	鸡丝、鸡丝面	Shredded chicken
74	炸鸡腿	Fried chicken drumsticks
75	啤酒鸭	Beer duck
76	腰花	Scalloped pork or lamb kidneys
77	红烧肉	Braised pork
78	红烧牛肉	Braised beef
79	酱牛肉	Beef Seasoned with Soy Sauce
80	西红柿牛腩	Sirloin tomatoes
81	土豆炖牛腩	Stewed sirloin potatoes
82	杭椒牛柳	Sauteed Beef Fillet with Hot Green Pepper
83	梅菜扣肉	Pork with salted vegetable
84	回锅肉	Double cooked pork slices
85	猪肉炖粉条	Braised Pork with Vermicelli
86	水煮肉片	Boiled Shredded pork in chili oil
87	糖醋里脊	Fried Sweet and Sour Tenderloin
88	咕噜肉	Cripsy sweet & sour pork slices
89	锅包肉	Pot bag meat
90	农家小炒肉	Shredded Pork with Vegetables
91	培根金针菇卷	Tiger lily buds in Baconic
92	京酱肉丝	Sauteed Shredded Pork in Sweet Bean Sauce
93	豆角肉丝	Shredded pork with bean
94	酱焖猪蹄	Braised pig feet with soy sauce
95	肚丝	Tripe
96	青椒肉丝	Shredded pork and green pepper
97	鱼香肉丝	Yu-Shiang Shredded Pork
98	木耳炒肉丝	Braised Fungus with pork slice
99	木须肉	Sauteed Sliced Pork,Eggs and Black Fungus
100	莴笋肉丝	Lettuce shredded meat
101	蚂蚁上树	Sauteed Vermicelli with Spicy Minced Pork
102	孜然羊肉	Fried Lamb with Cumin
103	羊肉串	Lamb shashlik
104	葱爆羊肉	Sauteed Sliced Lamb with Scallion
105	红烧狮子头	Stewed Pork Ball in Brown Sauce
106	酸菜鱼	Boiled Fish with Picked Cabbage and Chili
107	烤鱼	grilled fish
108	糖醋鲤鱼	Sweet and sour fish
109	松鼠桂鱼	Sweet and Sour Mandarin Fish
110	红烧带鱼	Braised Hairtail in Brown Sauce
111	剁椒鱼头	Steamed Fish Head with Diced Hot Red Peppers
112	水煮鱼	Fish Filets in Hot Chili Oil
113	清蒸鲈鱼	Steamed Perch
114	芝士虾球	Cheese Shrimp Meat
115	虾仁西兰花	Shrimp broccoli
116	油焖大虾	Braised Shrimp in chili oil
117	香辣虾	Spicy shrimp
118	香辣小龙虾	Spicy crayfish
119	水晶虾饺	Shrimp Duplings
120	蒜茸粉丝蒸虾	Steamed shrimp with garlic and vermicelli
121	清炒虾仁	Sauteed Shrimp meat
122	皮皮虾	Pipi shrimp
123	扇贝	Scallop in Shell
124	生蚝	Oysters
125	鱿鱼	squid
126	鲍鱼	Abalone
127	螃蟹	Crab
128	甲鱼	Turtle
129	鳝鱼	eel
130	扬州炒饭	Yangzhou fried rice
131	蛋包饭	Omelette
132	小笼汤包	Steamed Bun Stuffed
133	烧麦	Steamed Pork Dumplings
134	家常早餐鸡蛋饼	egg omelet
135	土豆鸡蛋饼	Potato omelet
136	鸡蛋灌饼	Egg pie cake
137	卤蛋	Marinated Egg
138	荷包蛋	Poached Egg
139	葱花手抓饼	Pine cake with Diced Scallion
140	芝麻烧饼	Sesame seed cake
141	肉夹馍	Chinese hamburger
142	韭菜盒子	Leek box
143	南瓜紫薯馒头	steamed bun with purple potato and pumpkin
144	馒头	steamed bun
145	包子	Steamed stuffed bun
146	南瓜饼	Pumpkin pie
147	披萨	Pizza
148	油条	Deep-Fried Dough Sticks
149	炸酱面	sauteed noodles with minced meat
150	重庆酸辣粉	Chongqing Hot and Sour Rice Noodles
151	凉拌凉面	Cold noodles
152	西红柿鸡蛋面	Noodles with egg and tomato
153	肉酱意大利面	spaghetti with meat sauce
154	茄汁拌面	Noodles with tomato sauce
155	凉皮	Cold Rice Noodles
156	担担面	Sichuan noodles with peppery sauce
157	臊子面	Qishan noodles
158	炒面	fried noodles
159	饺子	Dumplings
160	玉米棒	Corn Cob
161	红烧牛肉面	Braised beef noodle
162	河粉	fried rice noodles
163	肠粉	Steamed vermicelli roll
164	鲜肉小馄饨	Pork wonton
165	煎饺	Fried Dumplings
166	汤圆	Tang-yuan
167	小米粥	Millet congee
168	红薯粥	Sweet potato porridge
169	海蛰	Jellyfish
170	皮蛋瘦肉粥	Minced Pork Congee with Preserved Egg
171	大米粥	Rice porridge
172	米饭	Rice
173	紫菜包饭	Laver rice
174	石锅饭	Stone pot of rice
175	乌鸡汤	Black bone chicken soup
176	鲫鱼豆腐汤	Crucian and Bean Curd Soup
177	疙瘩汤	Dough Drop and Assorted Vegetable Soup
178	酸辣汤	Hot and Sour Soup
179	萝卜排骨汤	Pork ribs soup with radish
180	西红柿鸡蛋汤	Tomato and Egg Soup
181	西湖牛肉羹	West Lake beef soup
182	莲藕排骨汤	Lotus Root and Rib soup
183	紫菜蛋花汤	Seaweed and Egg Soup
184	海带豆腐汤	Seaweed tofu soup
185	玉米排骨汤	Corn and sparerib soup
186	菠菜猪肝汤	Spinach and pork liver soup
187	罗宋汤	Borsch
188	银耳汤	White fungus soup
189	冬瓜汤	White gourd soup
190	酱汤	Miso soup
191	毛血旺	Duck Blood in Chili Sauce
192	夫妻肺片	Pork Lungs in Chili Sauce
193	麻辣香锅	Spicy pot
194	黄金如意肉卷	Golden meat rolls
195	蛋糕	Chiffon Cake
196	蛋挞	Egg Tart
197	面包	Bread
198	牛角包	Croissant
199	吐司	toast
200	饼干	Biscuits
201	曲奇饼干	cookies
202	苏打饼干	Soda biscuit
203	双皮奶	Double skin milk
204	冰激凌	ice cream
205	鸡蛋布丁	Egg pudding
206	冰糖雪梨	Sweet stewed snow pear
207	水果沙拉	Fruit salad

四、数据核算工具技术实现

该模块为智能体专属结构化算力工具,用于规避大模型模糊估算问题,输出可复现、高精度的量化营养数据,所有调用时机、数据校验逻辑由智能体自主决策。

技术流程:

  1. 智能体接收 ResNet 输出的菜品类别列表
  2. 调用营养数据库索引匹配,查询各类菜品每100g热量、蛋白质、脂肪、碳水化合物等标准化参数
  3. 结合分量预估算法,逐菜计算单菜品营养摄入数据
  4. 汇总生成整餐总热量、营养结构占比等结构化字段,封装为 Prompt 输入智能体

4.1 智能体工具

python 复制代码
TOOL_DEFINITIONS = [
    {
        "type": "function",
        "function": {
            "name": "query_user_profile",
            "description": "查询用户的身体资料(身高、体重、年龄、性别)和 BMI 评估",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_id": {"type": "integer", "description": "用户 ID"},
                },
                "required": ["user_id"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "search_foods",
            "description": "按关键词搜索菜品,支持中文名或英文类名模糊匹配",
            "parameters": {
                "type": "object",
                "properties": {
                    "keyword": {"type": "string", "description": "搜索关键词,如 '豆腐'、'pasta'"},
                },
                "required": ["keyword"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_food_nutrition",
            "description": "获取单个菜品的详细营养信息(卡路里、蛋白质、碳水、脂肪、纤维、份量)",
            "parameters": {
                "type": "object",
                "properties": {
                    "food_name": {"type": "string", "description": "菜品中文名,如 '麻婆豆腐'"},
                },
                "required": ["food_name"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_low_calorie_foods",
            "description": "获取低卡路里菜品推荐列表(按卡路里升序排列),适合减脂场景",
            "parameters": {
                "type": "object",
                "properties": {
                    "limit": {"type": "integer", "description": "返回数量,默认 10", "default": 10},
                },
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_high_protein_foods",
            "description": "获取高蛋白菜品推荐列表(按蛋白质降序排列),适合增肌场景",
            "parameters": {
                "type": "object",
                "properties": {
                    "limit": {"type": "integer", "description": "返回数量,默认 10", "default": 10},
                },
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_foods_by_calorie_range",
            "description": "按卡路里范围筛选菜品",
            "parameters": {
                "type": "object",
                "properties": {
                    "min_calories": {"type": "number", "description": "最低卡路里"},
                    "max_calories": {"type": "number", "description": "最高卡路里"},
                },
                "required": ["min_calories", "max_calories"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "calculate_bmi",
            "description": "计算 BMI 值并给出健康评估和建议",
            "parameters": {
                "type": "object",
                "properties": {
                    "height": {"type": "number", "description": "身高(cm)"},
                    "weight": {"type": "number", "description": "体重(kg)"},
                },
                "required": ["height", "weight"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "calculate_daily_calories",
            "description": "根据用户身体数据和活动水平计算每日卡路里需求(BMR + TDEE),返回减脂/维持/增重三档建议",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_id": {"type": "integer", "description": "用户 ID"},
                    "activity_level": {
                        "type": "string",
                        "enum": ["sedentary", "light", "moderate", "active", "very_active"],
                        "description": "活动水平: sedentary=久坐, light=轻度活动, moderate=中度活动, active=高度活动, very_active=极度活动",
                        "default": "moderate",
                    },
                },
                "required": ["user_id"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_diet_history",
            "description": "获取用户最近的饮食记录(通过食物识别上传的历史),包含每餐的菜品和卡路里",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_id": {"type": "integer", "description": "用户 ID"},
                    "days": {"type": "integer", "description": "查询最近几天的记录,默认 7", "default": 7},
                },
                "required": ["user_id"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_nutrition_stats",
            "description": "统计用户最近 N 天的日均营养摄入(卡路里、蛋白质、碳水、脂肪、纤维)",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_id": {"type": "integer", "description": "用户 ID"},
                    "days": {"type": "integer", "description": "统计天数,默认 7", "default": 7},
                },
                "required": ["user_id"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_all_foods",
            "description": "获取数据库中全部菜品列表及营养信息,用于食谱推荐和饮食计划",
            "parameters": {"type": "object", "properties": {}},
        },
    },
]


# ============================================================
#  函数名 -> 可调用对象
# ============================================================

TOOL_FUNCTIONS = {
    "query_user_profile": tool_query_user_profile,
    "search_foods": tool_search_foods,
    "get_food_nutrition": tool_get_food_nutrition,
    "get_low_calorie_foods": tool_get_low_calorie_foods,
    "get_high_protein_foods": tool_get_high_protein_foods,
    "get_foods_by_calorie_range": tool_get_foods_by_calorie_range,
    "calculate_bmi": tool_calculate_bmi,
    "calculate_daily_calories": tool_calculate_daily_calories,
    "get_diet_history": tool_get_diet_history,
    "get_nutrition_stats": tool_get_nutrition_stats,
    "get_all_foods": tool_get_all_foods,
}


def execute_tool(name: str, arguments: dict) -> str:
    """执行工具函数,返回结果字符串"""
    fn = TOOL_FUNCTIONS.get(name)
    if fn is None:
        return json.dumps({"error": f"未知工具: {name}"}, ensure_ascii=False)
    try:
        logger.info(f"执行工具: {name}({arguments})")
        result = fn(**arguments)
        logger.info(f"工具 {name} 返回 {len(result)} 字符")
        return result
    except Exception as e:
        logger.error(f"工具 {name} 执行异常: {e}", exc_info=True)
        return json.dumps({"error": f"工具执行异常: {e}"}, ensure_ascii=False)

五、DeepSeek智能体核心技术能

5.1 动态工具调度与任务规划

智能体具备零预设流程的自主调度能力,可根据图像质量、菜品数量、用户数据完整度,自主决策工具调用顺序、是否需要重复校验、是否需要过滤无效识别结果。相较于固定工作流,可自适应各类复杂餐盘场景,避免固定流程的机械执行缺陷。

ReAct架构大模型调度代码如下:

python 复制代码
def chat_stream(user_message: str, history: list, user_id: int = None,
                extra_context: str = "") -> Generator[str, None, None]:
    """
    流式 Agent 对话,yield SSE 格式的字符串。
    每条 yield 格式: "data: {json}\\n\\n"
    事件类型:
      - {"type":"token","content":"..."}     文本片段
      - {"type":"tool_start","name":"..."}    开始调用工具
      - {"type":"tool_end","name":"..."}      工具调用结束
      - {"type":"done","reply":"..."}         全部完成
      - {"type":"error","message":"..."}      出错
    """
    messages = _build_messages(user_message, history, user_id, extra_context)

    try:
        for round_idx in range(MAX_TOOL_ROUNDS):
            content_buf = []
            tool_calls_buf = {}  # index -> {"id":..., "name":..., "arguments":...}

            # 流式调用 LLM
            for chunk in chat_completion_stream(messages, tools=TOOL_DEFINITIONS):
                delta = chunk.get("choices", [{}])[0].get("delta", {})

                # 文本片段
                if delta.get("content"):
                    content_buf.append(delta["content"])
                    yield _sse({"type": "token", "content": delta["content"]})

                # 工具调用片段(逐步累积)
                if delta.get("tool_calls"):
                    for tc in delta["tool_calls"]:
                        idx = tc.get("index", 0)
                        if idx not in tool_calls_buf:
                            tool_calls_buf[idx] = {
                                "id": tc.get("id", ""),
                                "name": "",
                                "arguments": "",
                            }
                        if tc.get("function", {}).get("name"):
                            tool_calls_buf[idx]["name"] = tc["function"]["name"]
                        if tc.get("function", {}).get("arguments"):
                            tool_calls_buf[idx]["arguments"] += tc["function"]["arguments"]

            # 组装 assistant 消息
            assistant_msg: dict = {"role": "assistant", "content": "".join(content_buf) or None}
            if tool_calls_buf:
                assistant_msg["tool_calls"] = [
                    {
                        "id": v["id"],
                        "type": "function",
                        "function": {"name": v["name"], "arguments": v["arguments"]},
                    }
                    for _, v in sorted(tool_calls_buf.items())
                ]
            messages.append(assistant_msg)

            # 没有工具调用 → 最终回复
            if not tool_calls_buf:
                final_reply = "".join(content_buf)
                yield _sse({"type": "done", "reply": final_reply})
                return

            # 执行所有工具调用
            for _, tc_info in sorted(tool_calls_buf.items()):
                fn_name = tc_info["name"]
                try:
                    fn_args = json.loads(tc_info["arguments"] or "{}")
                except json.JSONDecodeError:
                    fn_args = {}

                # 注入 user_id
                if "user_id" in _get_tool_params(fn_name) and "user_id" not in fn_args and user_id:
                    fn_args["user_id"] = user_id

                yield _sse({"type": "tool_start", "name": fn_name})

                result = execute_tool(fn_name, fn_args)

                yield _sse({"type": "tool_end", "name": fn_name, "result": result[:500]})

                messages.append({
                    "role": "tool",
                    "tool_call_id": tc_info["id"],
                    "name": fn_name,
                    "content": result,
                })

        # 超过最大轮次
        messages.append({
            "role": "user",
            "content": "请基于已获取的信息,直接给出最终回复,不要再调用工具。",
        })
        for chunk in chat_completion_stream(messages, tools=None, tool_choice="none"):
            delta = chunk.get("choices", [{}])[0].get("delta", {})
            if delta.get("content"):
                yield _sse({"type": "token", "content": delta["content"]})

        yield _sse({"type": "done", "reply": ""})

    except Exception as e:
        logger.error(f"Agent 流式对话异常: {e}", exc_info=True)
        yield _sse({"type": "error", "message": str(e)})

5.2 多维度数据融合推理

智能体融合餐食营养数据、用户体征数据、运动属性、饮食目标多维特征,完成无规则模板的个性化推理。基于用户身高、体重计算基础代谢与每日推荐摄入热量,结合当前餐食热量盈余、营养配比缺陷,精准定位饮食问题,实现千人千面的量化评估,输出可追溯、可解释的推理逻辑。

5.3 自适应智能推荐算法

依托 DeepSeek 通用知识能力与场景 Prompt 约束,智能体根据当前餐食营养短板、用户身体代谢特征、健康目标,动态生成菜品替换、膳食搭配、热量优化方案,区别于传统系统的固定模板推荐,具备强场景适配性与个性化特征。

相关推荐
论文复现现场7 小时前
工业缺陷检测训练选 YOLO11 还是 RT-DETR?一张 24GB RTX 4090 跑通 PoC 的完整方案
yolo·计算机视觉·rtx4090
Είναι η κοπέλα7 小时前
YOLO 演进 v5→v11 与 2026 选型指南
人工智能·yolo
hans汉斯8 小时前
【计算机科学与应用】层级评论上下文依赖识别数据集构建与研究——以小红书旅游评论数据为例
人工智能·算法·yolo·目标检测·cnn·旅游
AI浩9 小时前
DroneScan-YOLO:针对无人机图像中微小目标的冗余感知轻量级检测
yolo·无人机
YOLO数据集集合1 天前
天空反无人机检测数据集 | 无人机检测 多旋翼识别 固定翼识别 低空安防 目标检测9063期
人工智能·yolo·目标检测·计算机视觉·无人机·反无人机
深度学习lover1 天前
<数据集>蚜虫识别<目标检测>
人工智能·深度学习·yolo·目标检测·计算机视觉·蚜虫识别
Together_CZ1 天前
YOLO-IOD: Towards Real Time Incremental Object Detection——迈向实时增量目标检测
yolo·目标检测·yolo-iod·迈向实时增量目标检测·增量检测·incremental·real time
YOLO数据集集合1 天前
固定翼无人机目标检测数据集 | 固定翼无人机 低空安防 目标检测 YOLO格式9062期
yolo·目标检测·无人机·固定翼无人机·固定翼·无人机识别·反无人机
深度学习lover1 天前
<数据集>番茄叶片病害识别<目标检测>
人工智能·yolo·目标检测·计算机视觉·数据集·番茄叶片病害识别