mirror of
https://github.com/Tencent/WeKnora.git
synced 2026-09-01 14:53:07 +08:00
feat(website-docs): add quickstart sample data and local MCP demo
Provide demo documents and FAQ import JSON for onboarding tests, plus a minimal HTTP Streamable MCP server for validating WeKnora MCP integration.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
.venv/
|
||||
@@ -0,0 +1,85 @@
|
||||
# WeKnora 本地 MCP Demo
|
||||
|
||||
最小外部 MCP 服务,用来测试 WeKnora **作为 MCP 客户端**接入第三方工具。
|
||||
|
||||
提供 6 个演示工具:
|
||||
|
||||
| 工具 | 作用 |
|
||||
| --- | --- |
|
||||
| `echo` | 连通性自检 |
|
||||
| `add` | 两数相加 |
|
||||
| `server_time` | 返回服务器 UTC 时间 |
|
||||
| `lookup_policy` | 查询演示政策(保修、报销、POC 等,与 `website-docs/sample-data/` 一致) |
|
||||
| `list_team_contacts` | 列出演示项目团队成员 |
|
||||
| `send_demo_alert` | 模拟外发通知(适合测工具人工审批) |
|
||||
|
||||
## 1. 启动
|
||||
|
||||
```bash
|
||||
cd examples/mcp-demo
|
||||
chmod +x start.sh
|
||||
./start.sh
|
||||
```
|
||||
|
||||
`start.sh` 会自动创建 `.venv` 并安装依赖。默认监听 `http://127.0.0.1:8010/mcp`,鉴权令牌 `weknora-demo-token`。
|
||||
|
||||
自定义:
|
||||
|
||||
```bash
|
||||
export MCP_SERVER_AUTH_TOKEN=my-secret
|
||||
export MCP_PORT=9000
|
||||
./start.sh
|
||||
```
|
||||
|
||||
## 2. 自检
|
||||
|
||||
另开终端:
|
||||
|
||||
```bash
|
||||
cd examples/mcp-demo
|
||||
source .venv/bin/activate
|
||||
python test_tools.py
|
||||
```
|
||||
|
||||
应列出 6 个工具。
|
||||
|
||||
## 3. 接入 WeKnora
|
||||
|
||||
1. 打开 **设置 → MCP 服务 → 新建**
|
||||
2. 填写:
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| 名称 | `本地 MCP Demo` |
|
||||
| 传输 | **HTTP Streamable** |
|
||||
| URL | `http://127.0.0.1:8010/mcp` |
|
||||
| 认证 | **Bearer** |
|
||||
| 令牌 | `weknora-demo-token`(与 `MCP_SERVER_AUTH_TOKEN` 一致) |
|
||||
|
||||
3. 保存后点 **测试连接**,应发现 6 个工具。
|
||||
4. 在 **智能体** 配置里勾选该 MCP 服务(或选全部工具)。
|
||||
5. (可选)对 `send_demo_alert` 开启**人工审批**,对话时 Agent 调用前会弹出确认。
|
||||
|
||||
## 4. 建议试的问题
|
||||
|
||||
在 Agent 对话里问:
|
||||
|
||||
- 「调用 MCP 工具查一下智能家居中控保修多久」→ 应触发 `lookup_policy`
|
||||
- 「研发部 POC 负责人是谁」→ `lookup_policy` 或 `list_team_contacts`
|
||||
- 「现在 MCP Demo 服务器几点」→ `server_time`
|
||||
|
||||
若同时导入了 `website-docs/sample-data/` 里的文档,可以对比 **知识库检索答案** 与 **MCP 工具返回** 是否一致。
|
||||
|
||||
## 5. 注意事项
|
||||
|
||||
- WeKnora UI **不支持 stdio** 传输;必须用 **HTTP Streamable** 或 **SSE**。
|
||||
- Demo 只绑定 `127.0.0.1`,不要暴露到公网。
|
||||
- `send_demo_alert` 不会真正发送消息,仅返回模拟结果。
|
||||
|
||||
## 6. SSE 模式(可选)
|
||||
|
||||
```bash
|
||||
MCP_TRANSPORT=sse MCP_PORT=8011 ./start.sh
|
||||
```
|
||||
|
||||
WeKnora 里传输选 **SSE**,URL 填 `http://127.0.0.1:8011/sse`。
|
||||
@@ -0,0 +1,4 @@
|
||||
mcp>=2,<3
|
||||
starlette>=0.27.0
|
||||
uvicorn>=0.24.0
|
||||
httpx>=0.27.0
|
||||
@@ -0,0 +1,262 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
WeKnora 本地 MCP Demo Server
|
||||
|
||||
最小可运行的外部 MCP 服务,用于在 WeKnora「设置 → MCP 服务」里测试客户端接入。
|
||||
默认以 Streamable HTTP 监听 http://127.0.0.1:8010/mcp
|
||||
|
||||
启动:
|
||||
export MCP_SERVER_AUTH_TOKEN=weknora-demo-token
|
||||
python server.py
|
||||
|
||||
WeKnora 配置:
|
||||
传输:HTTP Streamable
|
||||
URL:http://127.0.0.1:8010/mcp
|
||||
认证:Bearer,令牌与 MCP_SERVER_AUTH_TOKEN 一致
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
import secrets
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from mcp.server import MCPServer
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
|
||||
logger = logging.getLogger("mcp-demo")
|
||||
|
||||
mcp = MCPServer("weknora-mcp-demo", version="0.1.0")
|
||||
|
||||
# 与 website-docs/sample-data/ 配套的演示语料,方便 Agent 调用后对照知识库答案。
|
||||
DEMO_POLICIES: dict[str, str] = {
|
||||
"warranty": "智能家居中控 Pro 整机保修 24 个月,电池类配件 12 个月;人为拆解、进水不在保修范围。",
|
||||
"offline_voice": "若语音走云端识别,断外网后仅支持 App 与本地触摸屏;配置本地语音包后可继续使用基础指令。",
|
||||
"device_limit": "个人版账号最多绑定 3 台中控;企业版按合同授权,默认 50 台。",
|
||||
"travel_hotel_tier1": "一线城市(北上广深)出差住宿报销上限 600 元/晚(含税)。",
|
||||
"travel_meal": "出差期间餐饮费不单独报销;一线城市差旅补贴 150 元/天。",
|
||||
"poc_owner": "售后知识库 POC 技术负责人是研发部张明,产品对接人是李薇,测试负责人是赵磊。",
|
||||
"poc_deadline": "售后知识库 POC 目标 2024-03-01 前完成内网演示。",
|
||||
"matter_cert": "固件 3.5 计划在 2024 年 3 月底前发布灰度,完成 Matter 1.2 认证。",
|
||||
}
|
||||
|
||||
DEMO_CONTACTS: list[dict[str, str]] = [
|
||||
{"name": "陈浩", "role": "产品总监", "department": "产品部"},
|
||||
{"name": "张明", "role": "知识库与 AI 模块负责人", "department": "研发部"},
|
||||
{"name": "李薇", "role": "产品运营", "department": "产品部"},
|
||||
{"name": "王雪", "role": "交互设计负责人", "department": "设计部"},
|
||||
{"name": "赵磊", "role": "测试经理", "department": "测试部"},
|
||||
]
|
||||
|
||||
|
||||
def network_transport_auth_token() -> str:
|
||||
return os.getenv("MCP_SERVER_AUTH_TOKEN", "").strip()
|
||||
|
||||
|
||||
def require_network_transport_auth(transport: str) -> str:
|
||||
token = network_transport_auth_token()
|
||||
if transport in ("sse", "http") and not token:
|
||||
logger.error(
|
||||
"MCP_SERVER_AUTH_TOKEN is required for %s transport. "
|
||||
"Example: export MCP_SERVER_AUTH_TOKEN=weknora-demo-token",
|
||||
transport,
|
||||
)
|
||||
sys.exit(1)
|
||||
return token
|
||||
|
||||
|
||||
class MCPAuthMiddleware:
|
||||
"""SSE / HTTP 传输的 Bearer 鉴权中间件。"""
|
||||
|
||||
def __init__(self, app, token: str):
|
||||
self.app = app
|
||||
self.token = token
|
||||
|
||||
async def __call__(self, scope, receive, send):
|
||||
if scope.get("type") != "http":
|
||||
await self.app(scope, receive, send)
|
||||
return
|
||||
|
||||
headers = {
|
||||
k.decode("latin-1").lower(): v.decode("latin-1")
|
||||
for k, v in scope.get("headers", [])
|
||||
}
|
||||
provided = ""
|
||||
auth = headers.get("authorization", "")
|
||||
if auth.lower().startswith("bearer "):
|
||||
provided = auth[7:].strip()
|
||||
elif "x-mcp-auth-token" in headers:
|
||||
provided = headers["x-mcp-auth-token"]
|
||||
|
||||
if not provided or not secrets.compare_digest(provided, self.token):
|
||||
body = b'{"error":"unauthorized"}'
|
||||
await send(
|
||||
{
|
||||
"type": "http.response.start",
|
||||
"status": 401,
|
||||
"headers": [[b"content-type", b"application/json"]],
|
||||
}
|
||||
)
|
||||
await send({"type": "http.response.body", "body": body})
|
||||
return
|
||||
|
||||
await self.app(scope, receive, send)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def echo(message: str) -> dict[str, Any]:
|
||||
"""回显一条消息,用于验证 MCP 连通性。"""
|
||||
return {"echo": message}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def add(a: float, b: float) -> dict[str, Any]:
|
||||
"""计算两个数字之和。"""
|
||||
return {"a": a, "b": b, "sum": a + b}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def server_time() -> dict[str, str]:
|
||||
"""返回 MCP Demo 服务器当前 UTC 时间。"""
|
||||
now = datetime.now(timezone.utc)
|
||||
return {
|
||||
"iso": now.isoformat(),
|
||||
"unix": str(int(now.timestamp())),
|
||||
}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def lookup_policy(topic: str) -> dict[str, Any]:
|
||||
"""查询演示政策/项目信息。topic 可用 warranty/offline_voice/device_limit/travel_hotel_tier1/travel_meal/poc_owner/poc_deadline/matter_cert,或中文关键词如「保修」「报销」「POC」。"""
|
||||
key = topic.strip().lower().replace(" ", "_")
|
||||
aliases = {
|
||||
"保修": "warranty",
|
||||
"质保": "warranty",
|
||||
"离线": "offline_voice",
|
||||
"语音": "offline_voice",
|
||||
"设备数": "device_limit",
|
||||
"住宿": "travel_hotel_tier1",
|
||||
"报销": "travel_hotel_tier1",
|
||||
"餐饮": "travel_meal",
|
||||
"补贴": "travel_meal",
|
||||
"负责人": "poc_owner",
|
||||
"张明": "poc_owner",
|
||||
"poc": "poc_owner",
|
||||
"验收": "poc_deadline",
|
||||
"matter": "matter_cert",
|
||||
"认证": "matter_cert",
|
||||
}
|
||||
for alias, mapped in aliases.items():
|
||||
if alias in topic:
|
||||
key = mapped
|
||||
break
|
||||
|
||||
if key in DEMO_POLICIES:
|
||||
return {"topic": key, "answer": DEMO_POLICIES[key], "source": "mcp-demo/static"}
|
||||
|
||||
matches = {
|
||||
k: v
|
||||
for k, v in DEMO_POLICIES.items()
|
||||
if key in k or any(ch in k for ch in key if len(key) >= 2)
|
||||
}
|
||||
if len(matches) == 1:
|
||||
only_key = next(iter(matches))
|
||||
return {"topic": only_key, "answer": matches[only_key], "source": "mcp-demo/static"}
|
||||
|
||||
return {
|
||||
"topic": topic,
|
||||
"available_topics": sorted(DEMO_POLICIES.keys()),
|
||||
"hint": "传入 topic 为上述键名,或中文关键词如「保修」「报销」「POC」。",
|
||||
}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def list_team_contacts(department: str = "") -> dict[str, Any]:
|
||||
"""列出演示项目团队成员;可按部门名过滤(产品部 / 研发部 / 设计部 / 测试部)。"""
|
||||
rows = DEMO_CONTACTS
|
||||
if department.strip():
|
||||
needle = department.strip()
|
||||
rows = [c for c in rows if needle in c["department"]]
|
||||
return {"count": len(rows), "contacts": rows}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def send_demo_alert(channel: str, message: str) -> dict[str, Any]:
|
||||
"""模拟向外部渠道发送通知(演示用,不会真正外发)。
|
||||
|
||||
适合在 WeKnora 里测试 MCP 工具人工审批:建议把此工具标记为需要审批。
|
||||
"""
|
||||
return {
|
||||
"ok": True,
|
||||
"simulated": True,
|
||||
"channel": channel,
|
||||
"message": message,
|
||||
"sent_at": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
|
||||
|
||||
async def run_http(host: str, port: int) -> None:
|
||||
auth_token = require_network_transport_auth("http")
|
||||
try:
|
||||
import uvicorn
|
||||
except ImportError as e:
|
||||
raise ImportError("HTTP transport requires: pip install starlette uvicorn") from e
|
||||
|
||||
starlette_app = MCPAuthMiddleware(
|
||||
mcp.streamable_http_app(host=host, stateless_http=True),
|
||||
auth_token,
|
||||
)
|
||||
logger.info("Streamable HTTP MCP demo listening on http://%s:%d/mcp", host, port)
|
||||
config = uvicorn.Config(starlette_app, host=host, port=port, log_level="info")
|
||||
server = uvicorn.Server(config)
|
||||
await server.serve()
|
||||
|
||||
|
||||
async def run_sse(host: str, port: int) -> None:
|
||||
auth_token = require_network_transport_auth("sse")
|
||||
try:
|
||||
import uvicorn
|
||||
except ImportError as e:
|
||||
raise ImportError("SSE transport requires: pip install starlette uvicorn") from e
|
||||
|
||||
starlette_app = MCPAuthMiddleware(
|
||||
mcp.sse_app(host=host, message_path="/sse/messages/"),
|
||||
auth_token,
|
||||
)
|
||||
logger.info("SSE MCP demo listening on http://%s:%d/sse", host, port)
|
||||
config = uvicorn.Config(starlette_app, host=host, port=port, log_level="info")
|
||||
server = uvicorn.Server(config)
|
||||
await server.serve()
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="WeKnora local MCP demo server")
|
||||
parser.add_argument(
|
||||
"--transport",
|
||||
choices=["http", "sse"],
|
||||
default=os.getenv("MCP_TRANSPORT", "http"),
|
||||
help="Network transport (default: http / Streamable HTTP)",
|
||||
)
|
||||
parser.add_argument("--host", default=os.getenv("MCP_HOST", "127.0.0.1"))
|
||||
parser.add_argument("--port", type=int, default=int(os.getenv("MCP_PORT", "8010")))
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
args = parse_args()
|
||||
if args.transport == "http":
|
||||
await run_http(args.host, args.port)
|
||||
else:
|
||||
await run_sse(args.host, args.port)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
asyncio.run(main())
|
||||
except KeyboardInterrupt:
|
||||
logger.info("stopped")
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
export MCP_SERVER_AUTH_TOKEN="${MCP_SERVER_AUTH_TOKEN:-weknora-demo-token}"
|
||||
export MCP_HOST="${MCP_HOST:-127.0.0.1}"
|
||||
export MCP_PORT="${MCP_PORT:-8010}"
|
||||
export MCP_TRANSPORT="${MCP_TRANSPORT:-http}"
|
||||
|
||||
VENV_DIR=".venv"
|
||||
if [[ ! -d "$VENV_DIR" ]]; then
|
||||
echo "Creating virtualenv in $VENV_DIR ..."
|
||||
python3 -m venv "$VENV_DIR"
|
||||
fi
|
||||
# shellcheck disable=SC1091
|
||||
source "$VENV_DIR/bin/activate"
|
||||
|
||||
if ! python -c "import mcp" 2>/dev/null; then
|
||||
echo "Installing dependencies..."
|
||||
pip install -r requirements.txt
|
||||
fi
|
||||
|
||||
echo "MCP Demo"
|
||||
echo " transport : ${MCP_TRANSPORT}"
|
||||
echo " endpoint : http://${MCP_HOST}:${MCP_PORT}/$([ "$MCP_TRANSPORT" = http ] && echo mcp || echo sse)"
|
||||
echo " auth token: ${MCP_SERVER_AUTH_TOKEN}"
|
||||
echo
|
||||
echo "WeKnora UI → 设置 → MCP 服务 → 新建"
|
||||
echo " 传输: HTTP Streamable"
|
||||
echo " URL : http://${MCP_HOST}:${MCP_PORT}/mcp"
|
||||
echo " 认证: Bearer / ${MCP_SERVER_AUTH_TOKEN}"
|
||||
echo
|
||||
|
||||
exec python server.py --transport "$MCP_TRANSPORT" --host "$MCP_HOST" --port "$MCP_PORT"
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python3
|
||||
"""列出 MCP Demo 暴露的工具(需先启动 server.py)。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
import httpx
|
||||
from mcp import ClientSession
|
||||
from mcp.client.streamable_http import streamable_http_client
|
||||
|
||||
|
||||
async def main() -> int:
|
||||
base = os.getenv("MCP_DEMO_URL", "http://127.0.0.1:8010/mcp")
|
||||
token = os.getenv("MCP_SERVER_AUTH_TOKEN", "weknora-demo-token")
|
||||
|
||||
async with httpx.AsyncClient(
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
timeout=30.0,
|
||||
) as http_client:
|
||||
async with streamable_http_client(base, http_client=http_client) as (read, write):
|
||||
async with ClientSession(read, write) as session:
|
||||
await session.initialize()
|
||||
tools = await session.list_tools()
|
||||
print(f"connected: {base}")
|
||||
print(f"tools ({len(tools.tools)}):")
|
||||
for tool in tools.tools:
|
||||
print(f" - {tool.name}: {tool.description}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
raise SystemExit(asyncio.run(main()))
|
||||
except Exception as exc: # noqa: BLE001
|
||||
print(f"failed: {exc}", file=sys.stderr)
|
||||
print("start the server first: ./start.sh", file=sys.stderr)
|
||||
raise SystemExit(1) from exc
|
||||
@@ -0,0 +1,75 @@
|
||||
# 智能家居中控 Pro 产品手册
|
||||
|
||||
**产品型号**:HUB-Pro-2024
|
||||
**文档版本**:v2.1
|
||||
**适用固件**:≥ 3.4.0
|
||||
|
||||
## 1. 产品概述
|
||||
|
||||
智能家居中控 Pro 是星云科技(NovaTech)推出的家庭物联网中枢,负责统一管理灯光、空调、窗帘、安防传感器等设备。用户可通过手机 App、语音助手或本地触摸屏完成场景联动。
|
||||
|
||||
核心卖点:
|
||||
|
||||
- 本地离线可用:断网后局域网内仍可执行已配置场景
|
||||
- 多协议兼容:同时支持 Matter、Zigbee 3.0、Wi-Fi 与蓝牙 Mesh
|
||||
- 边缘 AI:内置轻量模型,可识别「我回家了」「准备观影」等口语化指令
|
||||
|
||||
## 2. 技术规格
|
||||
|
||||
| 项目 | 参数 |
|
||||
| --- | --- |
|
||||
| 处理器 | 四核 ARM Cortex-A55,1.8 GHz |
|
||||
| 内存 / 存储 | 4 GB RAM / 32 GB eMMC |
|
||||
| 无线协议 | Wi-Fi 6、Zigbee 3.0、蓝牙 5.2、Thread |
|
||||
| 有线接口 | 千兆以太网 ×1、USB-C(调试)×1 |
|
||||
| 供电 | DC 12V / 2A,典型功耗 8W |
|
||||
| 工作温度 | 0℃ ~ 40℃ |
|
||||
| 最大接入设备数 | 256(推荐 ≤ 120 以保证响应速度) |
|
||||
|
||||
## 3. 首次配置
|
||||
|
||||
1. 将设备接通电源,指示灯呈蓝色慢闪表示等待配网。
|
||||
2. 打开 NovaHome App,选择「添加中控」,扫描机身二维码。
|
||||
3. 按向导连接家庭 Wi-Fi;若使用有线网络,可跳过 Wi-Fi 步骤。
|
||||
4. 完成固件检查;如有更新,建议先升级再添加子设备。
|
||||
|
||||
> **注意**:首次配网时手机需与中控处于同一 2.4 GHz 频段。5 GHz-only 路由器需先开启 2.4 GHz 兼容模式。
|
||||
|
||||
## 4. 场景联动示例
|
||||
|
||||
### 4.1 「回家模式」
|
||||
|
||||
触发条件(满足任一即可):
|
||||
|
||||
- 手机 GPS 进入家庭地理围栏
|
||||
- 大门指纹锁解锁
|
||||
- 语音说「我回来了」
|
||||
|
||||
执行动作:
|
||||
|
||||
- 客厅主灯调至 70% 暖白光
|
||||
- 空调设为 26℃ 制冷(仅夏季模板生效)
|
||||
- 关闭安防布防
|
||||
|
||||
### 4.2 「离家模式」
|
||||
|
||||
触发条件:所有家庭成员手机离开地理围栏超过 5 分钟。
|
||||
|
||||
执行动作:关闭全屋灯光、关闭空调、启动安防布防、关闭燃气机械手(如已接入)。
|
||||
|
||||
## 5. 常见问题
|
||||
|
||||
**Q:中控离线后语音还能用吗?**
|
||||
A:若语音模块走云端识别,断外网后仅支持 App 与本地触摸屏;若配置了本地语音包,可继续使用基础指令。
|
||||
|
||||
**Q:一个账号能绑定几台中控?**
|
||||
A:个人版最多 3 台;企业版按合同授权,默认 50 台。
|
||||
|
||||
**Q:保修政策?**
|
||||
A:整机保修 24 个月,电池类配件 12 个月。人为拆解、进水不在保修范围。
|
||||
|
||||
## 6. 相关文档
|
||||
|
||||
- 安装与接线说明见《中控 Pro 硬件安装指南》
|
||||
- 报销与出差携带设备规定见《员工手册 · 报销与资产》
|
||||
- Q1 功能路线图见《产品会议纪要 · Q1 规划》
|
||||
@@ -0,0 +1,70 @@
|
||||
# 产品会议纪要 · 2024 Q1 规划
|
||||
|
||||
**会议主题**:智能家居产品线 Q1 优先级评审
|
||||
**时间**:2024-01-15 14:00–16:30
|
||||
**地点**:总部 A 栋 3F 梧桐会议室
|
||||
**记录人**:李薇(产品运营)
|
||||
|
||||
## 参会人员
|
||||
|
||||
| 姓名 | 部门 | 角色 |
|
||||
| --- | --- | --- |
|
||||
| 陈浩 | 产品部 | 产品总监 |
|
||||
| 张明 | 研发部 | 知识库与 AI 模块负责人 |
|
||||
| 王雪 | 设计部 | 交互设计负责人 |
|
||||
| 赵磊 | 测试部 | 测试经理 |
|
||||
| 刘洋 | 销售部 | 华东区销售总监 |
|
||||
|
||||
## 一、Q1 核心目标
|
||||
|
||||
1. **中控 Pro 固件 3.5**:完成 Matter 1.2 认证,3 月底前发布灰度。
|
||||
2. **NovaHome App 4.0**:重构设备列表与场景编辑器,2 月中旬进入内测。
|
||||
3. **企业版知识助手**:基于自研 RAG 方案,为售后团队提供安装/排障问答(由张明团队承接 POC)。
|
||||
|
||||
## 二、功能优先级(MoSCoW)
|
||||
|
||||
| 优先级 | 功能 | 负责人 | 目标日期 |
|
||||
| --- | --- | --- | --- |
|
||||
| Must | Matter 桥接稳定性修复 | 硬件组 | 2024-02-01 |
|
||||
| Must | 场景编辑器拖拽改版 | 王雪 | 2024-02-15 |
|
||||
| Must | 售后知识库 POC 上线内网 | 张明 | 2024-03-01 |
|
||||
| Should | 本地语音包离线识别 | 语音组 | 2024-03-15 |
|
||||
| Could | 能耗统计周报 | 数据组 | Q2 再评 |
|
||||
|
||||
## 三、关键决议
|
||||
|
||||
### 3.1 售后知识库 POC 范围
|
||||
|
||||
- **首期语料**:产品手册、安装指南、Top 50 工单 FAQ,预计 200 篇左右。
|
||||
- **验收标准**:随机 100 道售后题,Top-3 命中率 ≥ 85%,回答必须带出处链接。
|
||||
- **技术选型**:采用私有化部署的 WeKnora 实例,Embedding 用本地模型,对话模型接公司统一 API 网关。
|
||||
- **负责人**:张明;产品对接人:李薇。
|
||||
|
||||
### 3.2 App 4.0 体验原则
|
||||
|
||||
- 设备列表默认按「房间」分组,支持一键切换「按类型」视图。
|
||||
- 场景编辑从「表单式」改为「卡片 + 时间轴」,降低新用户学习成本。
|
||||
|
||||
### 3.3 销售侧反馈
|
||||
|
||||
刘洋反馈:华东区客户最关心 **断网可用** 与 **多中控级联**(别墅场景)。级联方案列入 Q2 预研,本季度仅输出技术可行性报告。
|
||||
|
||||
## 四、风险与依赖
|
||||
|
||||
| 风险 | 影响 | 缓解措施 |
|
||||
| --- | --- | --- |
|
||||
| Matter 认证排期紧张 | 固件发布推迟 | 提前 2 周提交预认证材料 |
|
||||
| 售后语料质量参差 | 问答准确率不达标 | 由赵磊团队做抽样标注,每周复盘 |
|
||||
| 统一 API 网关限流 | POC 演示卡顿 | 申请专用配额,演示环境独立租户 |
|
||||
|
||||
## 五、待办事项
|
||||
|
||||
- [ ] 张明:1 月 20 日前完成 WeKnora 测试环境部署与首批语料导入(陈浩审批资源)
|
||||
- [ ] 王雪:1 月 25 日前输出场景编辑器高保真原型
|
||||
- [ ] 李薇:每周五发送 POC 进度邮件给参会人
|
||||
- [ ] 赵磊:2 月 1 日前提交 Top 50 FAQ 清洗版 Excel
|
||||
|
||||
## 六、下次会议
|
||||
|
||||
- **时间**:2024-02-05 14:00
|
||||
- **议题**:App 4.0 内测反馈、知识库 POC 中期评审
|
||||
@@ -0,0 +1,88 @@
|
||||
# 员工手册(节选)· 报销与休假
|
||||
|
||||
**生效日期**:2024-01-01
|
||||
**适用对象**:星云科技全体正式员工
|
||||
**归口部门**:人力资源部 · 财务部
|
||||
|
||||
## 1. 差旅报销
|
||||
|
||||
### 1.1 交通费
|
||||
|
||||
| 职级 | 飞机 | 高铁 / 动车 | 市内交通 |
|
||||
| --- | --- | --- | --- |
|
||||
| M3 及以上 | 经济舱 | 一等座 | 实报实销,单日上限 300 元 |
|
||||
| M1–M2 | 经济舱 | 二等座 | 实报实销,单日上限 200 元 |
|
||||
| 普通员工 | 经济舱(需提前 3 天审批) | 二等座 | 实报实销,单日上限 150 元 |
|
||||
|
||||
**规定**:
|
||||
|
||||
- 机票需通过公司指定商旅平台预订;自行购票报销需在行程结束后 7 个工作日内提交。
|
||||
- 连续乘坐超过 6 小时的高铁,可申请升级一等座,须直属主管邮件审批。
|
||||
|
||||
### 1.2 住宿费
|
||||
|
||||
| 城市级别 | 每晚上限(含税) |
|
||||
| --- | --- |
|
||||
| 一线城市(北上广深) | 600 元 |
|
||||
| 新一线城市 | 450 元 |
|
||||
| 其他城市 | 350 元 |
|
||||
|
||||
超标部分由个人承担,除非活动主办方统一安排且取得财务部特批。
|
||||
|
||||
### 1.3 餐饮与补贴
|
||||
|
||||
- 出差期间餐饮费 **不单独报销**,按天数领取差旅补贴:
|
||||
- 国内一线城市:150 元 / 天
|
||||
- 国内其他城市:120 元 / 天
|
||||
- 境外:按财务部当月汇率表执行
|
||||
- 客户招待餐费走 **业务招待费** 流程,与差旅报销分开。
|
||||
|
||||
## 2. 日常费用报销
|
||||
|
||||
### 2.1 提交时限
|
||||
|
||||
所有发票须在 **费用发生日起 30 日内** 提交 OA 报销单。逾期需直属主管 + 财务经理双签说明。
|
||||
|
||||
### 2.2 常见科目
|
||||
|
||||
| 科目 | 说明 | 附件要求 |
|
||||
| --- | --- | --- |
|
||||
| 办公用品 | 单价 < 500 元 | 发票 + 采购清单 |
|
||||
| 培训费 | 外部认证、行业会议 | 发票 + 培训通知 + 结业证明 |
|
||||
| 测试设备采购 | 研发测试用样机、传感器 | 发票 + 项目编号 + 资产入库单 |
|
||||
|
||||
**研发人员**购买测试用智能家居中控、传感器等硬件,须先在资产系统创建「研发样机」条目,再关联报销单。参考《产品手册 · 智能家居中控 Pro》中的型号与规格填写。
|
||||
|
||||
## 3. 年假与请假
|
||||
|
||||
### 3.1 年假天数
|
||||
|
||||
按工龄计算(以入职日期为准):
|
||||
|
||||
| 工龄 | 年假天数 |
|
||||
| --- | --- |
|
||||
| 1 年以下 | 5 天 |
|
||||
| 1–10 年 | 10 天 |
|
||||
| 10 年以上 | 15 天 |
|
||||
|
||||
当年 3 月 31 日前入职的员工,当年年假按剩余月份折算;之后入职次年才开始享受全额年假。
|
||||
|
||||
### 3.2 请假流程
|
||||
|
||||
1. 提前在 OA 提交请假单,选择类型(年假 / 病假 / 事假等)。
|
||||
2. 3 天以内:直属主管审批;3–7 天:部门总监审批;7 天以上:HR 备案。
|
||||
3. 病假连续超过 2 天需附二级以上医院证明。
|
||||
|
||||
### 3.3 与项目冲突
|
||||
|
||||
若请假期间有已定版的发布节点(如固件 3.5 灰度、知识库 POC 验收),须在项目群同步并指定 **工作交接人**。张明团队 POC 相关请假,需额外知会产品总监陈浩。
|
||||
|
||||
## 4. 违规处理
|
||||
|
||||
- 虚假发票、重复报销:一经查实,追回款项并按《员工奖惩制度》处理。
|
||||
- 未经审批的境外差旅:费用不予报销。
|
||||
|
||||
## 5. 联系方式
|
||||
|
||||
- 报销政策咨询:财务部 `finance@novatech.example`(示例邮箱)
|
||||
- OA 系统问题:IT 服务台分机 8800
|
||||
@@ -0,0 +1,95 @@
|
||||
# 技术方案 · 售后知识库 POC
|
||||
|
||||
**项目代号**:Nova-KB-POC
|
||||
**版本**:0.3 草案
|
||||
**作者**:张明(研发部)
|
||||
**评审人**:陈浩(产品部)、赵磊(测试部)
|
||||
**最后更新**:2024-01-18
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
星云科技售后团队每日处理约 400 条安装与排障工单。现有方案依赖 Confluence 全文搜索,一线工程师反馈「搜得到段落但不知道哪句能直接回复客户」。
|
||||
|
||||
本 POC 目标:
|
||||
|
||||
1. 导入产品手册、会议纪要、FAQ 等内部文档;
|
||||
2. 支持自然语言提问,返回答案 + **可追溯出处**;
|
||||
3. 4 周内完成内网演示,供 Q1 规划会中期评审。
|
||||
|
||||
## 2. 系统架构
|
||||
|
||||
```text
|
||||
[语料来源] Confluence 导出 / Markdown / PDF 手册
|
||||
↓
|
||||
[WeKnora] docreader 解析 → 分块 → 向量 + BM25 混合检索
|
||||
↓
|
||||
[模型层] Embedding:本地 bge-m3
|
||||
LLM:公司 API 网关 → DeepSeek-V3
|
||||
↓
|
||||
[接入] 售后工单系统 iframe 嵌入(二期)
|
||||
```
|
||||
|
||||
### 2.1 关键角色
|
||||
|
||||
| 角色 | 姓名 | 职责 |
|
||||
| --- | --- | --- |
|
||||
| 技术负责人 | 张明 | 部署、语料管道、检索调优 |
|
||||
| 产品对接 | 李薇 | 需求优先级、验收题库 |
|
||||
| 测试负责人 | 赵磊 | 标注 100 道验收题、准确率统计 |
|
||||
| 审批人 | 陈浩 | 资源申请、范围裁剪 |
|
||||
|
||||
### 2.2 与中控产品的关系
|
||||
|
||||
POC 首期语料以 **智能家居中控 Pro** 为主(参见《产品手册》),辅以《Q1 产品会议纪要》中的里程碑与责任人信息,便于回答「谁负责」「什么时候交付」类问题。
|
||||
|
||||
## 3. 语料清单(首批)
|
||||
|
||||
| 序号 | 文档 | 格式 | 预估分块 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | 智能家居中控 Pro 产品手册 | Markdown / PDF | 40 |
|
||||
| 2 | Q1 产品会议纪要 | Markdown | 25 |
|
||||
| 3 | 员工手册 · 报销与休假(售后出差场景) | Markdown | 30 |
|
||||
| 4 | Top 50 工单 FAQ | Excel 导入 | 50 |
|
||||
|
||||
**合计约 145 个知识单元**,满足 3 月 1 日内网演示最低要求。
|
||||
|
||||
## 4. 检索策略
|
||||
|
||||
- **默认**:向量 + BM25 混合检索,RRF 融合,Top-5 送入 LLM。
|
||||
- **可选**:开启 Rerank(`bge-reranker-v2-m3`)提升多义词场景准确率。
|
||||
- **暂不启用**:知识图谱(Neo4j 尚未纳入 POC 环境)、Wiki 自动生成。
|
||||
|
||||
### 4.1 分块参数(建议)
|
||||
|
||||
| 参数 | 值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| chunk_size | 512 | 与手册段落长度匹配 |
|
||||
| chunk_overlap | 64 | 保留表格上下文 |
|
||||
| 父子分块 | 开启 | 检索命中子块、生成用父块 |
|
||||
|
||||
## 5. 验收用例(示例)
|
||||
|
||||
| 问题 | 期望答案要点 | 期望出处 |
|
||||
| --- | --- | --- |
|
||||
| 中控 Pro 最多能接多少设备? | 256,推荐 ≤ 120 | 产品手册 · 技术规格 |
|
||||
| Q1 知识库 POC 什么时候验收? | 2024-03-01 内网上线 | Q1 会议纪要 |
|
||||
| 一线城市住宿报销上限? | 600 元 / 晚 | 员工手册 · 差旅报销 |
|
||||
| Matter 认证目标版本? | 固件 3.5,3 月底灰度 | Q1 会议纪要 |
|
||||
| 谁负责售后知识库 POC? | 张明 | 会议纪要 / 本方案 |
|
||||
|
||||
赵磊将据此扩展为 100 道正式验收题。
|
||||
|
||||
## 6. 风险
|
||||
|
||||
1. **语料过期**:产品手册 v2.1 与即将发布的 v2.2 冲突 → 建立「语料 Owner」机制,李薇每月核对。
|
||||
2. **幻觉**:强制 Prompt 要求「仅根据引用回答;无依据则回复不知道」。
|
||||
3. **权限**:POC 阶段单租户;生产需按区域售后组拆分知识库 ACL。
|
||||
|
||||
## 7. 里程碑
|
||||
|
||||
| 日期 | 交付物 |
|
||||
| --- | --- |
|
||||
| 2024-01-20 | WeKnora 测试环境可用,导入首批 3 份 Markdown |
|
||||
| 2024-02-01 | FAQ Excel 导入完成,混合检索 + Rerank 调参 |
|
||||
| 2024-02-05 | 中期评审演示 |
|
||||
| 2024-03-01 | 100 题验收报告 |
|
||||
@@ -0,0 +1,72 @@
|
||||
[
|
||||
{
|
||||
"tag_name": "售后",
|
||||
"standard_question": "智能家居中控保修多久?",
|
||||
"similar_questions": ["保修期几年", "质保多长时间"],
|
||||
"negative_questions": [],
|
||||
"answers": ["整机保修 24 个月,电池类配件 12 个月。人为拆解、进水不在保修范围。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "产品",
|
||||
"standard_question": "断网后语音还能用吗?",
|
||||
"similar_questions": ["没有网络能语音控制吗", "离线能用语音吗"],
|
||||
"negative_questions": [],
|
||||
"answers": ["若语音走云端识别,断外网后仅支持 App 与本地触摸屏;配置本地语音包后可继续使用基础指令。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "产品",
|
||||
"standard_question": "一个账号能绑几台中控?",
|
||||
"similar_questions": ["最多添加多少台中控", "账号设备数量限制"],
|
||||
"negative_questions": [],
|
||||
"answers": ["个人版最多 3 台;企业版按合同授权,默认 50 台。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "人事",
|
||||
"standard_question": "一线城市住宿报销上限是多少?",
|
||||
"similar_questions": ["北上广深酒店报销额度", "住宿标准"],
|
||||
"negative_questions": [],
|
||||
"answers": ["一线城市(北上广深)每晚上限 600 元/晚(含税),超标部分个人承担。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "人事",
|
||||
"standard_question": "出差餐饮怎么报?",
|
||||
"similar_questions": ["餐费能报销吗", "吃饭费用"],
|
||||
"negative_questions": [],
|
||||
"answers": ["出差期间餐饮费不单独报销,按天数领取差旅补贴:一线城市 150 元/天,其他城市 120 元/天。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "项目",
|
||||
"standard_question": "Q1 知识库 POC 什么时候上线?",
|
||||
"similar_questions": ["售后知识库什么时候验收", "POC 交付日期"],
|
||||
"negative_questions": [],
|
||||
"answers": ["目标 2024-03-01 前完成内网演示,由张明负责技术交付。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "项目",
|
||||
"standard_question": "谁负责售后知识库 POC?",
|
||||
"similar_questions": ["知识库项目负责人是谁", "POC 技术负责人"],
|
||||
"negative_questions": [],
|
||||
"answers": ["技术负责人是研发部张明,产品对接人是李薇,测试负责人是赵磊。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "产品",
|
||||
"standard_question": "中控 Pro 支持哪些协议?",
|
||||
"similar_questions": ["能连哪些智能设备协议", "Matter 支持吗"],
|
||||
"negative_questions": [],
|
||||
"answers": ["支持 Matter、Zigbee 3.0、Wi-Fi 与蓝牙 Mesh;固件 3.5 计划完成 Matter 1.2 认证。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "人事",
|
||||
"standard_question": "年假 10 年工龄有多少天?",
|
||||
"similar_questions": ["工作满十年年假", "工龄年假天数"],
|
||||
"negative_questions": [],
|
||||
"answers": ["工龄 1–10 年为 10 天年假,10 年以上为 15 天;按入职日期计算。"]
|
||||
},
|
||||
{
|
||||
"tag_name": "项目",
|
||||
"standard_question": "Matter 认证计划什么时候完成?",
|
||||
"similar_questions": ["Matter 1.2 什么时候过认证", "固件 3.5 发布时间"],
|
||||
"negative_questions": [],
|
||||
"answers": ["计划在 2024 年 3 月底前发布固件 3.5 灰度,完成 Matter 1.2 认证。"]
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user