Skip to content

feat(demohouse/shop_assist): intro bp version shop assist #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions demohouse/shop_assist/backend/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
endpoint_id = os.getenv("LLM_ENDPOINT_ID", "doubao-1-5-pro-32k-250115")
bucket_name = os.getenv("BUCKET_NAME", "")
use_server_auth = os.getenv("USE_SERVER_AUTH", "False").lower() in ("true", "1", "t")
language = os.getenv("LANGUAGE", "zh") # 'zh' for Chinese, 'en' for English
2 changes: 1 addition & 1 deletion demohouse/shop_assist/backend/data/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
# Licensed under the 【火山方舟】原型应用软件自用许可协议
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# You may obtain a copy of the License at
# https://www.volcengine.com/docs/82379/1433703
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
Expand Down
2 changes: 1 addition & 1 deletion demohouse/shop_assist/backend/data/cache.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
# Licensed under the 【火山方舟】原型应用软件自用许可协议
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# You may obtain a copy of the License at
# https://www.volcengine.com/docs/82379/1433703
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 20 additions & 6 deletions demohouse/shop_assist/backend/data/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@
from typing import Dict, List, Optional

from .cache import LRUCache
import sys
import os

# Add the parent directory to sys.path to import config
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from config import language


class OrderStatus(str, Enum):
SHIPPED = "已发货"
PENDING = "未发货"
REFUNDED = "已退款"
SHIPPED = "已发货" if language == "zh" else "Shipped"
PENDING = "未发货" if language == "zh" else "Not Shipped"
REFUNDED = "已退款" if language == "zh" else "Refunded"


@dataclass
Expand Down Expand Up @@ -117,24 +123,32 @@ async def _initialize_account_orders(self, account_id: str) -> None:
# Get cached orders or initialize new ones
orders = self._orders.get(account_id)
if orders is None:
# Product names based on language setting

orders = {
f"{account_id}_1": Order(
order_id=f"{account_id}_1",
status=OrderStatus.SHIPPED,
product="车载收纳盒",
product="车载收纳盒"
if language == "zh"
else "Women's Floral Graphic T-Shirts",
account_id=account_id,
tracking_number=f"SF{account_id}10001", # Fake tracking number for shipped order
),
f"{account_id}_2": Order(
order_id=f"{account_id}_2",
status=OrderStatus.PENDING,
product="汽车遮阳挡",
product="汽车遮阳挡"
if language == "zh"
else "Long Sleeve V Neck Blouses",
account_id=account_id,
),
f"{account_id}_3": Order(
order_id=f"{account_id}_3",
status=OrderStatus.PENDING,
product="可爱风腰靠垫",
product="可爱风腰靠垫"
if language == "zh"
else "Unisex Vintage Baseball Cap",
account_id=account_id,
),
}
Expand Down
60 changes: 58 additions & 2 deletions demohouse/shop_assist/backend/data/product.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
# Licensed under the 【火山方舟】原型应用软件自用许可协议
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# You may obtain a copy of the License at
# https://www.volcengine.com/docs/82379/1433703
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

PRODUCTS = {
from config import language

# Chinese products
PRODUCTS_ZH = {
"栀子花车载香薰": {
"name": "栀子花车载香薰",
"description": "栀子花车载香薰是一款为汽车提供舒适和放松的香薰产品。它可以帮助用户缓解疲劳、缓解压力,提升驾驶体验。",
Expand Down Expand Up @@ -61,3 +64,56 @@
"cover_image": "tos://xiangyuxuan-test/custom_support/product/折叠旋转电动无线充车载支架.PNG",
},
}

# English products
PRODUCTS_EN = {
"Women's Floral Graphic T-Shirts": {
"name": "Women's Floral Graphic T-Shirts",
"description": "Women's Floral Graphic T-Shirts is a soft, breathable, and easy-to-style top featuring a charming wildflower design, perfect for everyday wear and any casual occasion",
"cover_image": "https://sf16-sg.tiktokcdn.com/obj/eden-sg/lm_sth/ljhwZthlaukjlkulzlp/ark/application/demo/shop_guide/product/Women's Floral Graphic T-Shirts.png",
},
"Men's Straight Cut Pants": {
"name": "Men's Straight Cut Pants",
"description": "Men's Straight Cut Pants is a comfortable, all-season essential, featuring a timeless fit and easy machine-wash care.",
"cover_image": "https://sf16-sg.tiktokcdn.com/obj/eden-sg/lm_sth/ljhwZthlaukjlkulzlp/ark/application/demo/shop_guide/product/Men's Straight Cut Pants.png",
},
"Long Sleeve V Neck Blouses": {
"name": "Long Sleeve V Neck Blouses",
"description": "Long Sleeve V Neck Blouses is a breathable and stylish blouse, perfect for versatile, year-round wear",
"cover_image": "https://sf16-sg.tiktokcdn.com/obj/eden-sg/lm_sth/ljhwZthlaukjlkulzlp/ark/application/demo/shop_guide/product/Long Sleeve V Neck Blouses.png",
},
"Women's Strap Flounce Long Dress": {
"name": "Women's Strap Flounce Long Dress",
"description": "Women's Strap Flounce Long Dress is a flowing, boho-inspired piece that blends effortless beauty with a flattering design for any occasion",
"cover_image": "https://sf16-sg.tiktokcdn.com/obj/eden-sg/lm_sth/ljhwZthlaukjlkulzlp/ark/application/demo/shop_guide/product/Women's Strap Flounce Long Dress.png",
},
"Adult Unisex T-Shirt": {
"name": "Adult Unisex T-Shirt",
"description": "Adult Unisex T-Shirt is a durable, heavyweight essential offering all-day comfort and timeless style for everyday wear or work",
"cover_image": "https://sf16-sg.tiktokcdn.com/obj/eden-sg/lm_sth/ljhwZthlaukjlkulzlp/ark/application/demo/shop_guide/product/Adult Unisex T-Shirt.png",
},
"Unisex Vintage Baseball Cap": {
"name": "Unisex Vintage Baseball Cap",
"description": "Unisex Vintage Baseball Cap is a relaxed, vintage-washed essential with an unstructured crown, available in 10 colors to match any style effortlessly",
"cover_image": "https://sf16-sg.tiktokcdn.com/obj/eden-sg/lm_sth/ljhwZthlaukjlkulzlp/ark/application/demo/shop_guide/product/Unisex Vintage Baseball Cap.png",
},
"Pink Large Shoulder Tote Bag": {
"name": "Pink Large Shoulder Tote Bag",
"description": "Pink Large Shoulder Tote Bag is a stylish and spacious everyday essential, crafted from soft, durable material with a charming bow accent for a perfect blend of fashion and function",
"cover_image": "https://sf16-sg.tiktokcdn.com/obj/eden-sg/lm_sth/ljhwZthlaukjlkulzlp/ark/application/demo/shop_guide/product/Pink Large Shoulder Tote Bag.png",
},
"Ballet Flat": {
"name": "Ballet Flat",
"description": "Ballet Flat is an elegant shoe featuring a sweet bow detail and a comfortable low heel for effortless style and comfort",
"cover_image": "https://sf16-sg.tiktokcdn.com/obj/eden-sg/lm_sth/ljhwZthlaukjlkulzlp/ark/application/demo/shop_guide/product/Ballet Flat.png",
},
}


# Get products based on language configuration
def get_products():
return PRODUCTS_ZH if language == "zh" else PRODUCTS_EN


# For backward compatibility
PRODUCTS = get_products()
2 changes: 1 addition & 1 deletion demohouse/shop_assist/backend/data/rag.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def retrieval_knowledge(
)
return (
f"""
# 参考资料
# {"参考资料" if config.language == "zh" else "References"}
<context>
{res["result_list"]}
{faq_res["result_list"]}
Expand Down
48 changes: 29 additions & 19 deletions demohouse/shop_assist/backend/data/tracking.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
# Licensed under the 【火山方舟】原型应用软件自用许可协议
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# You may obtain a copy of the License at
# https://www.volcengine.com/docs/82379/1433703
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
Expand All @@ -13,19 +13,20 @@
from dataclasses import dataclass
from datetime import datetime, timedelta
from enum import Enum
from typing import Dict
from typing import Dict, List

from .cache import LRUCache
from config import language


class TrackingStatus(str, Enum):
"""Tracking status enumeration"""

PENDING = "待揽收"
PICKED_UP = "已揽收"
IN_TRANSIT = "运输中"
DELIVERING = "派送中"
DELIVERED = "已签收"
PENDING = "待揽收" if language == "zh" else "Waiting for pickup"
PICKED_UP = "已揽收" if language == "zh" else "Picked Up"
IN_TRANSIT = "运输中" if language == "zh" else "In transit"
DELIVERING = "派送中" if language == "zh" else "Out for delivery"
DELIVERED = "已签收" if language == "zh" else "Delivered"


@dataclass
Expand Down Expand Up @@ -54,11 +55,11 @@ def _generate_tracking_info(tracking_number: str) -> Dict:
"""
# Random locations for demo
locations = [
"上海转运中心",
"杭州转运中心",
"北京转运中心",
"广州转运中心",
"深圳转运中心",
"上海转运中心" if language == "zh" else "Shanghai Transit Center",
"杭州转运中心" if language == "zh" else "Hangzhou Transit Center",
"北京转运中心" if language == "zh" else "Beijing Transit Center",
"广州转运中心" if language == "zh" else "Guangzhou Transit Center",
"深圳转运中心" if language == "zh" else "Shenzhen Transit Center",
]

# Base time for events (now - 3 days)
Expand All @@ -73,13 +74,22 @@ def _generate_tracking_info(tracking_number: str) -> Dict:
event_time = base_time + timedelta(hours=i * 8) # 8 hours between events
location = random.choice(locations)

description = {
TrackingStatus.PENDING: f"包裹在{location}等待揽收",
TrackingStatus.PICKED_UP: f"快递员已在{location}揽收",
TrackingStatus.IN_TRANSIT: f"包裹已到达{location}",
TrackingStatus.DELIVERING: f"包裹已到达{location},正在派送",
TrackingStatus.DELIVERED: f"包裹已在{location}签收",
}[status]
if language == "zh":
description = {
TrackingStatus.PENDING: f"包裹在{location}等待揽收",
TrackingStatus.PICKED_UP: f"快递员已在{location}揽收",
TrackingStatus.IN_TRANSIT: f"包裹已到达{location}",
TrackingStatus.DELIVERING: f"包裹已到达{location},正在派送",
TrackingStatus.DELIVERED: f"包裹已在{location}签收",
}[status]
else:
description = {
TrackingStatus.PENDING: f"The package is waiting for pickup at {location}",
TrackingStatus.PICKED_UP: f"The courier has picked up the package at {location}",
TrackingStatus.IN_TRANSIT: f"The package has arrived at {location}",
TrackingStatus.DELIVERING: f"The package has arrived at {location} and is out for delivery",
TrackingStatus.DELIVERED: f"The package has been delivered and signed for at {location}",
}[status]

events.append(
{
Expand Down
33 changes: 24 additions & 9 deletions demohouse/shop_assist/backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
from typing import AsyncIterable, List, Union

import pandas as pd
from config import endpoint_id
from volcenginesdkarkruntime import AsyncArk
from config import endpoint_id, language
from data import rag
from data.product import PRODUCTS
from data.product import get_products
from data.rag import retrieval_knowledge
from fastapi import HTTPException
from next_question import next_question_chat
Expand Down Expand Up @@ -61,7 +62,7 @@ async def custom_support_chat(
"support_functions",
[*FUNCTION_MAP],
)
products = meta_data.get("product_list", [*PRODUCTS])
products = meta_data.get("product_list", [*get_products()])

# insert knowledge
tools, system_prompt = register_support_functions(functions, products, account_id)
Expand All @@ -73,7 +74,11 @@ async def custom_support_chat(
"op": "or",
"conds": [
{"op": "must", "field": "account_id", "conds": [account_id]},
{"op": "must", "field": "产品名", "conds": products},
{
"op": "must",
"field": "产品名" if language == "zh" else "product_name",
"conds": products,
},
],
},
)
Expand All @@ -83,7 +88,6 @@ async def custom_support_chat(
parameters=parameters,
)

print(await build_tool_pool(tools).list_tools(False))
if request.stream:
async for resp in llm.astream(
functions=tools,
Expand All @@ -105,7 +109,7 @@ async def custom_support_chat(

class Product(BaseModel):
name: str
description: str = Field(..., max_length=100)
description: str
cover_image: str


Expand All @@ -115,9 +119,10 @@ class ProductListResponse(BaseModel):


async def list_products():
products_dict = get_products()
return ProductListResponse(
products=[Product(**v) for v in PRODUCTS.values()],
total=len(PRODUCTS),
products=[Product(**v) for v in products_dict.values()],
total=len(products_dict),
)


Expand Down Expand Up @@ -160,7 +165,17 @@ async def save_faq(faq: FAQRequest):
endpoint_config=get_endpoint_config(
"/api/v3/bots/chat/completions", custom_support_chat
),
clients=get_default_client_configs(),
clients={
"ark": (
AsyncArk,
{
"base_url": "https://ark.cn-beijing.volces.com/api/v3"
if language == "zh"
else "https://ark.ap-southeast.volces.com/api/v3",
"region": "cn-beijing" if language == "zh" else "ap-southeast-1",
},
),
},
)
server.app.add_api_route(
"/api/v3/bots/chat/completions",
Expand Down
35 changes: 32 additions & 3 deletions demohouse/shop_assist/backend/next_question.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from typing import AsyncIterable

from config import endpoint_id
from config import endpoint_id, language
from utils import get_auth_header, merge_msgs

from arkitect.core.component.llm import BaseChatLanguageModel
Expand All @@ -29,8 +29,8 @@ async def next_question_chat(request: ArkChatRequest) -> AsyncIterable[Response]
"""
Summarize the conversation between customer service and customer.
"""
# Add system prompt for summary
system_prompt = """# 角色
# Chinese system prompt
system_prompt_zh = """# 角色
你是一位在抖音车载用品网店购物的潜在消费者,正在与客服进行口语化的文字交流。现在收到的输入是,你(user)与客服(assistant)正在进行对话
# 任务描述与要求
1. 仔细阅读给出的上下文内容,精准把握其中的关键信息,聚焦已提及的信息。
Expand All @@ -53,6 +53,35 @@ async def next_question_chat(request: ArkChatRequest) -> AsyncIterable[Response]
查一下我的所有订单
订单编号查询"""

# English system prompt
system_prompt_en = """
# Role
You are a potential customer shopping on a Clothes & Fashion e-commerce platform, engaging in a conversation with a customer service. The input you are about to receive is a dialogue between you (user) and the customer service (assistant).
# Task Description and Requirements
1. Carefully read the given context and accurately grasp the key information, focusing only on the information already mentioned.
2. Based on the Clothes & Fashion e-commerce background and the conversation context, predict 3 potential follow-up questions from the perspective of the customer.
3. The questions should revolve around clothing, such as product descriptions, advantages, prices, usage scenarios, materials, precautions, logistics, orders, etc.
4. If the customer service (assistant) asks for an order number, you may follow up by asking the assistant to help look up all past order numbers you have placed.
5. Separate the 3 questions with line breaks. Do not use numbering.
# Relevant Constraints
1. Follow-up questions must focus on information related to clothing products.
2. Avoid vague or irrelevant questions unrelated to the current situation.
3. The questions should be clear and concise, avoiding complicated references.
4. Only output 3 questions — do not add anything else, and do not ask the user for clarification or attempt to answer the questions.
# Examples
## Example 1:
On what occasions can I wear the Ballet Flats?
What material is this Blouse made of?
Where to ship Floral Graphic T-Shirts from?
## Example 2:
Can you check what I have purchased from your store before?
Help me look up all my past orders.
Order number inquiry.
"""

# Select the appropriate system prompt based on language configuration
system_prompt = system_prompt_zh if language == "zh" else system_prompt_en

# Create new request with summary system prompt
messages = [
ArkMessage(role="system", content=system_prompt),
Expand Down
Loading
Loading