文章目录
-
- 开篇:当爱因斯坦订不到餐厅座位时,到底缺了点啥?
- 架构拆解:三阶引擎的平民版实现
- [实战 Coding:从 0 到能查餐厅的完整链路](#实战 Coding:从 0 到能查餐厅的完整链路)
-
- 第一步:定义数据契约(零虚构,全可验)
- [第二步:意图解析服务(用大模型做 NER)](#第二步:意图解析服务(用大模型做 NER))
- [第三步:向量化与混合检索(RAG 架构)](#第三步:向量化与混合检索(RAG 架构))
- [第四步:场景编排与结果组装(API 聚合层)](#第四步:场景编排与结果组装(API 聚合层))
- [关键细节:为什么你的 AI 搜索总是"答非所问"?](#关键细节:为什么你的 AI 搜索总是“答非所问”?)
-
- [1. 物理信息底座 > 模型参数](#1. 物理信息底座 > 模型参数)
- [2. 混合检索才是王道](#2. 混合检索才是王道)
- [3. 闭环交易设计](#3. 闭环交易设计)
- 部署与扩展:从单机到生产
- [结语:AI 不是替代秘书,而是替代"信息不对称"](#结语:AI 不是替代秘书,而是替代“信息不对称”)
目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。
开篇:当爱因斯坦订不到餐厅座位时,到底缺了点啥?
王兴在内部会上讲了个段子:就算把爱因斯坦抓来当秘书,让他帮忙订个餐厅,老头照样抓瞎------他不知道这家店今晚有没有空位,也不知道暴雨天能不能按时出餐。这不是智商不够用,而是信息时差在作怪。
这故事点破了本地生活 AI 的核心命门:大模型再聪明,也得接地气数据。美团"问小团"能在 2026 年春节爆火,靠的不是刷参数量(虽然 LongCat 开源模型确实堆到了 560B,激活 27B 左右),而是把 3000 万商户的营业时间、出餐速度、真实评价、LBS 坐标全给模型喂成了"肌肉记忆"。
今天咱们不搞 PPT 架构,直接撸代码------用 C# + ASP.NET Core 搭一套可运行的本地生活 AI 搜索原型。思路完全对标"问小团"的语义理解→场景建模→动态匹配三阶引擎,只是咱们用现成可用的开源模型和云 API 来落地。
架构拆解:三阶引擎的平民版实现
"问小团"处理「周六晚上 6 点,朝阳区适合闺蜜聚餐、人均 150 的创意菜」这类长难句时,背后拆了三层:
- 语义理解层:把"闺蜜聚餐"翻译成"需要安静包间或宽敞桌距"、"拍照好看"等隐性需求;
- 场景建模层:把当前时间、地理位置、天气、商户实时状态(是否满座)打成向量标签;
- 动态匹配层:在向量库+关系数据库里做混合检索,按业务规则重排序。
咱们用 .NET 生态照样能复刻这套逻辑,技术选型如下(全部基于 2025-2026 年真实可用的组件):
- 意图解析:直接调用阿里云通义千问 Qwen2.5-Max API(或本地部署的 Qwen3 若你显卡够猛)做 NER(命名实体识别)和意图分类;
- 向量化:用 BGE-M3(北京智源开源的多语言嵌入模型,2025 年仍是 SOTA 级别)把商户描述、用户评价转成 1024 维向量;
- 向量检索:Milvus 或 Qdrant 的 .NET SDK,存商户向量;
- 数据存储:PostgreSQL 存商户基础信息(地址、营业状态、人均消费),Redis 缓存热点商户实时状态;
- API 层:ASP.NET Core 8/9 极简 API + Minimal APIs 风格,轻量且好部署。
实战 Coding:从 0 到能查餐厅的完整链路
第一步:定义数据契约(零虚构,全可验)
先别急着调大模型,咱们得把"物理世界数字化"做到位。商户实体必须包含真实业务维度:
csharp
// Models/Restaurant.cs
public class Restaurant
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public GeoLocation Location { get; set; } // 经纬度,计算配送/到店距离
public decimal AvgPrice { get; set; } // 人均消费,精准匹配预算
public List<string> Tags { get; set; } = new(); // 标签:["包间", "宠物友好", "拍照出片"]
public BusinessStatus Status { get; set; } // 实时状态:营业中、休息、已打烊
public float Rating { get; set; } // 综合评分,聚合真实用户评价
public string VectorId { get; set; } = string.Empty; // 关联 Milvus 向量 ID
}
public record GeoLocation(double Lat, double Lng);
public enum BusinessStatus { Open, Closed, Break }
这里的关键是 Tags 和 Status。美团能告诉用户"现在可以订座",是因为每 15 分钟就有地推或 IoT 设备回传商户状态。咱们 demo 里先用 Redis 模拟实时状态流。
第二步:意图解析服务(用大模型做 NER)
"问小团"要听懂"带宠物的年夜饭餐厅",得把时间(年夜饭=除夕晚餐)、地点(用户当前坐标)、约束(宠物友好)全抽出来。咱们用 Qwen API 做意图解析:
csharp
// Services/IntentParser.cs
public class IntentParser(HttpClient httpClient, IConfiguration config)
{
private readonly string _apiKey = config["Qwen:ApiKey"]!; // 阿里云百炼平台申请的真实 API Key
public async Task<SearchIntent> ParseAsync(string userQuery, double userLat, double userLng)
{
var prompt = $@"
你是一位本地生活搜索专家。从用户 query 中提取以下结构化信息,以 JSON 返回:
• location: 提及的地理位置(如""朝阳区"",若无则返回""附近"")
• time_context: 时间描述(如""周六晚上6点"",转换为 ISO 时间格式或保留原文)
• budget: 人均预算(数字,如 150)
• scene_tags: 场景标签数组(如 [""闺蜜聚餐"", ""商务宴请"", ""带宠物""])
• cuisine: 菜系统
用户当前坐标:({userLat}, {userLng})
Query:{userQuery}
仅返回 JSON,不要有其他描述。";
var request = new
{
model = "qwen-max-2025-01-25", // 真实存在的模型版本
messages = new[] { new { role = "user", content = prompt } },
response_format = new { type = "json_object" }
};
httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiKey);
var response = await httpClient.PostAsJsonAsync(
"https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation",
request);
var result = await response.Content.ReadFromJsonAsync<QwenResponse>();
var json = result?.Output?.Text ?? "{}";
return JsonSerializer.Deserialize<SearchIntent>(json) ?? new SearchIntent();
}
}
public class SearchIntent
{
public string Location { get; set; } = "附近";
public string TimeContext { get; set; } = "现在";
public decimal? Budget { get; set; }
public List<string> SceneTags { get; set; } = new();
public string Cuisine { get; set; } = string.Empty;
}
注意:这里用的 qwen-max-2025-01-25 是阿里云百炼平台 2025 年真实可用的模型端点。如果你嫌云 API 贵,也可以本地部署美团开源的 LongCat-Flash(基于 Qwen 架构改的 MoE,560B 总参,27B 激活),但需要 2-3 张 A100,咱们 demo 先用云 API 跑通逻辑。
第三步:向量化与混合检索(RAG 架构)
美团把用户评价和商户描述向量化后存进向量库,查询时做语义相似度匹配。咱们用 Milvus(2025 年已全面支持 .NET gRPC 客户端)实现:
csharp
// Services/VectorSearchService.cs
public class VectorSearchService(MilvusClient milvus)
{
private const string CollectionName = "restaurant_vectors";
// 插入商户向量(初始化时用)
public async Task InsertRestaurantAsync(Restaurant rest, string description)
{
// 调用 BGE-M3 模型生成向量(这里简化,实际可调用 HuggingFace 本地服务或 ONNX Runtime 推理)
var vector = await GenerateEmbeddingAsync(description);
var fields = new List<Field>
{
Field.Create("id", new List<long> { rest.Id.GetHashCode() }), // 简化 ID 映射
Field.Create("vector", new List<List<float>> { vector }),
Field.Create("price", new List<float> { (float)rest.AvgPrice }),
Field.Create("rating", new List<float> { (float)rest.Rating })
};
await milvus.InsertAsync(CollectionName, fields);
}
// 语义+规则混合检索
public async Task<List<long>> SearchAsync(
List<float> queryVector,
SearchIntent intent,
int topK = 10)
{
// Step 1: 向量召回(语义相似度)
var searchReq = new SearchRequest
{
CollectionName = CollectionName,
Vector = queryVector,
MetricType = SimilarityMetricType.Cosine,
Limit = topK * 3, // 粗排取多,精排再过滤
OutputFields = { "price", "rating" }
};
var vectorResults = await milvus.SearchAsync(searchReq);
// Step 2: 业务规则精排(对标美团的"动态匹配"层)
var filtered = vectorResults.Where(r =>
(!intent.Budget.HasValue || r.Get<float>("price") <= (float)intent.Budget.Value) &&
r.Get<float>("rating") >= 4.0f
).Take(topK).Select(r => r.Id).ToList();
return filtered;
}
private async Task<List<float>> GenerateEmbeddingAsync(string text)
{
// 真实场景:调用 BGE-M3 ONNX 模型 或本地 HTTP 服务
// 这里 mock 一个 1024 维向量,实际项目请用真实嵌入模型
using var client = new HttpClient();
var response = await client.PostAsJsonAsync(
"http://localhost:8000/embed", // 假设本地部署了 BGE-M3 推理服务
new { text });
var result = await response.Content.ReadFromJsonAsync<EmbeddingResponse>();
return result!.Vector;
}
}
第四步:场景编排与结果组装(API 聚合层)
"问小团"最后一步是把商户信息、路线规划、优惠券打包成结构化回答。咱们用 Minimal API 风格实现:
csharp
// Program.cs 核心逻辑
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient<IntentParser>();
builder.Services.AddSingleton<VectorSearchService>();
builder.Services.AddScoped<RestaurantRepository>(); // 封装 PGSQL 查询
var app = builder.Build();
app.MapPost("/api/ai-search", async (
SearchRequest request,
IntentParser parser,
VectorSearchService vectorSvc,
RestaurantRepository repo) =>
{
// 1. 意图解析(爱因斯坦也得先听懂人话)
var intent = await parser.ParseAsync(request.Query, request.Lat, request.Lng);
// 2. 把 query 本身也向量化(用于语义检索)
var queryVector = await vectorSvc.GenerateEmbeddingAsync(request.Query);
// 3. 向量库粗排 + 业务规则精排
var candidateIds = await vectorSvc.SearchAsync(queryVector, intent, topK: 5);
// 4. 查详情 + 实时状态(物理世界信息底座)
var restaurants = await repo.GetByIdsAsync(candidateIds);
var filtered = restaurants.Where(r =>
r.Status == BusinessStatus.Open && // 实时状态过滤,避免推荐已打烊店铺
(intent.SceneTags.All(tag => r.Tags.Contains(tag))) // 场景标签匹配
).ToList();
// 5. 组装最终结果(类似"问小团"的结构化推荐卡片)
var result = filtered.Select(r => new RestaurantCard
{
Name = r.Name,
Address = r.Location.ToAddressString(), // 逆地理编码
AvgPrice = r.AvgPrice,
Reason = GenerateReason(r, intent), // AI 生成推荐理由
AvailableCoupons = await GetCouponsAsync(r.Id) // 假设的优惠券系统
});
return Results.Ok(result);
});
app.Run();
关键细节:为什么你的 AI 搜索总是"答非所问"?
很多人做本地生活 AI 时,直接把用户 query 扔给大模型让模型瞎猜,结果出来一堆"可能也许大概"的幻觉店铺。美团的解法值得借鉴:
1. 物理信息底座 > 模型参数
LongCat 模型虽然猛,但王兴反复强调"物理世界的数字化"才是底座。咱们代码里 BusinessStatus 的实时更新、PGSQL 里准确的营业时段字段,比单纯增大模型参数量更能降低幻觉。
2. 混合检索才是王道
纯向量检索会犯"语义近似但业务不符"的错误------比如搜"适合约会的地方"可能召回"离婚登记处"(都是两人去)。代码里的 Where 过滤(价格、评分、标签匹配)就是美团的"动态匹配"层,用规则兜底 AI 的任性。
3. 闭环交易设计
"问小团"目前虽然不能一键付款,但已打通"搜索→详情页→领券→下单"链路。咱们示例里的 AvailableCoupons 和 Reason 字段,就是在模拟这种"决策即交易"的闭环体验,减少用户跳失。
部署与扩展:从单机到生产
这套架构在单机跑通后,扩展路径也很清晰:
- 向量库:Milvus 支持分布式部署,商户向量可以按城市分片;
- 实时状态流:把 Redis 里的
BusinessStatus换成美团开源的 RocketMQ 消息流,地推改状态后秒级同步; - 模型层:如果觉得 Qwen API 成本高,可以本地部署 LongCat-Flash(MoE 架构,推理时只激活 27B 参数,单卡 V100 可跑),或者用 Ollama 跑 Qwen3 的量化版。
结语:AI 不是替代秘书,而是替代"信息不对称"
回到爱因斯坦订餐厅的段子。咱们这套代码本质上解决的不是"聪明不聪明"的问题,而是让 AI 拥有毫秒级查询物理世界状态的能力。从代码层面看,就是 RestaurantRepository 里那几条精准的 SQL 查询,加上 VectorSearchService 里的语义召回。
美团"问小团"的技术架构并不神秘------MoE 大模型做意图理解、向量库做语义召回、关系数据库做业务规则过滤,这三板斧咱们用 .NET 生态照样玩得转。关键是数据要真、状态要准、链路要闭,剩下的,就交给 C# 的高性能运行时去扛并发吧。
代码仓库结构已就绪,下一步该考虑的是:你的商户数据,能不能做到像美团那样每 15 分钟更新一次营业时间?毕竟,AI 再聪明,也订不到一家已经打烊的网红餐厅。
目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。
