Commit 927d9c1c authored by Hoanganhvu123's avatar Hoanganhvu123

update: latest code

parent 1fcace51
...@@ -88,6 +88,13 @@ This ecosystem operates through structured workflows. Always route work through ...@@ -88,6 +88,13 @@ This ecosystem operates through structured workflows. Always route work through
| `workflow-audit.md` | Auto (from Autopilot) | QA Gatekeeper: security, performance, UI/UX, agent compliance | | `workflow-audit.md` | Auto (from Autopilot) | QA Gatekeeper: security, performance, UI/UX, agent compliance |
| `workflow-autopilot.md` | `"Autopilot: [task]"` | God Mode: classifies intent → routes to Pipeline A/B/C/D | | `workflow-autopilot.md` | `"Autopilot: [task]"` | God Mode: classifies intent → routes to Pipeline A/B/C/D |
### Skills Registry (Active)
| Skill | Path | Purpose |
|---|---|---|
| `huashu-design` | `.agent/skills/huashu-design/SKILL.md` | HTML-native hi-fi design, animations, and expert review |
| `frontend-design` | `.agent/skills/frontend-design/SKILL.md` | Production-ready Web UI components |
| `ai-agents-architect` | `.agent/skills/ai-agents-architect/SKILL.md` | Agent system design and orchestration |
### Autopilot Pipelines ### Autopilot Pipelines
``` ```
Pipeline A (Feature): Idea → Evaluate → Build → Audit Pipeline A (Feature): Idea → Evaluate → Build → Audit
......
huashu-design @ 23f60d9b
Subproject commit 23f60d9b4304f20851469987c6e2c92242b94a45
This diff is collapsed.
...@@ -15,7 +15,7 @@ from fastapi.responses import StreamingResponse ...@@ -15,7 +15,7 @@ from fastapi.responses import StreamingResponse
from pydantic import BaseModel from pydantic import BaseModel
from common.starrocks_connection import get_db_connection from common.starrocks_connection import get_db_connection
from agent.lead_stage_agent.lead_search_tool import ( from agent.lead_stage_agent.product_search_engine import (
LeadSearchInput, LeadSearchInput,
_build_fixed_clauses, _build_fixed_clauses,
_build_search_clause, _build_search_clause,
......
This diff is collapsed.
...@@ -81,10 +81,19 @@ class LLMFactory: ...@@ -81,10 +81,19 @@ class LLMFactory:
raise raise
def _create_gemini(self, model_name: str, streaming: bool, json_mode: bool, api_key: str | None) -> BaseChatModel: def _create_gemini(self, model_name: str, streaming: bool, json_mode: bool, api_key: str | None) -> BaseChatModel:
"""Create Google Gemini model instance. Always uses GOOGLE_API_KEY (ignores api_key param which may be OpenAI key).""" """Create Google Gemini model instance. Uses GOOGLE_API_KEY if available, otherwise falls back to Gemini CLI (OAuth)."""
key = GOOGLE_API_KEY key = GOOGLE_API_KEY
if not key: if not key:
raise ValueError("GOOGLE_API_KEY is required for Gemini models. Set it in .env") # Fallback: dùng Gemini CLI (OAuth local) thay vì crash
logger.info("🔄 No GOOGLE_API_KEY — falling back to ChatGeminiCLI (OAuth)")
from common.gemini_cli_wrapper import ChatGeminiCLI
llm = ChatGeminiCLI(
model=model_name,
temperature=0,
max_output_tokens=1500,
streaming=streaming,
)
return llm
llm_kwargs = { llm_kwargs = {
"model": model_name, "model": model_name,
......
import json
import logging
from agent.helper import extract_product_ids
from langchain_core.messages import ToolMessage
# Mock ToolMessage from sku_search_tool (Current buggy format)
sku_search_output = {
"status": "success",
"products": [
{
"sku": "6TS25S003",
"sku_color": "6TS25S003-SB055",
"name": "Áo thun nam",
"image": "https://canifa.com/image1.jpg",
"url": "https://canifa.com/p1"
}
]
}
# Mock ToolMessage from data_retrieval_tool (Working format)
data_retrieval_output = {
"status": "success",
"results": [
{
"sku": "6TS25S003",
"name": "Áo thun nam",
"thumbnail_image_url": "https://canifa.com/image1.jpg",
"url": "https://canifa.com/p1"
}
]
}
def test_extraction():
print("Testing SKU Search Tool Extraction...")
msg_sku = ToolMessage(content=json.dumps(sku_search_output), tool_call_id="1")
products_sku = extract_product_ids([msg_sku])
print(f"Extracted from SKU Search: {json.dumps(products_sku, indent=2, ensure_ascii=False)}")
# Check if thumbnail_image_url is present
if products_sku and products_sku[0].get("thumbnail_image_url"):
print("✅ SKU Search Extraction: SUCCESS")
else:
print("❌ SKU Search Extraction: FAILED (thumbnail_image_url missing)")
print("\nTesting Data Retrieval Tool Extraction...")
msg_data = ToolMessage(content=json.dumps(data_retrieval_output), tool_call_id="2")
products_data = extract_product_ids([msg_data])
print(f"Extracted from Data Retrieval: {json.dumps(products_data, indent=2, ensure_ascii=False)}")
if products_data and products_data[0].get("thumbnail_image_url"):
print("✅ Data Retrieval Extraction: SUCCESS")
else:
print("❌ Data Retrieval Extraction: FAILED")
if __name__ == "__main__":
test_extraction()
B<svg width="83" height="44" viewBox="0 0 83 44" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M46.5503 30.4271V13.5729H48.8924V30.4271H46.5503ZM34.6931 30.4271V13.5729C36.3033 13.5729 37.9136 13.5729 39.5238 13.5729C41.5732 13.5729 43.1834 15.2136 43.1834 17.3017V30.4271H40.9877V17.3017C40.9877 16.5559 40.4021 15.8102 39.5238 15.8102C38.6455 15.8102 37.9136 15.8102 37.0353 15.8102V30.4271H34.6931ZM16.9806 30.4271C14.9312 30.4271 13.321 28.7864 13.321 26.6983V17.4508C13.321 15.3627 14.9312 13.722 16.9806 13.722H20.3474V16.1085H16.9806C16.2487 16.1085 15.5168 16.7051 15.5168 17.6V26.8475C15.5168 27.5932 16.1023 28.339 16.9806 28.339H20.3474V30.4333H16.9609L16.9806 30.4271ZM29.1305 21.9254V17.3017C29.1305 16.5559 28.545 15.8102 27.6667 15.8102H26.642C25.9101 15.8102 25.1781 16.4068 25.1781 17.3017V21.9254H29.1305ZM67.3369 24.3119H63.3845V30.4271H61.0423V17.3017C61.0423 15.2136 62.6526 13.5729 64.7019 13.5729H65.7266C67.776 13.5729 69.3862 15.2136 69.3862 17.3017V30.4271H67.3369V24.3119ZM63.5309 21.9254H67.3369V17.3017C67.3369 16.5559 66.7513 15.8102 65.873 15.8102H64.8483C64.1164 15.8102 63.3845 16.4068 63.3845 17.3017V21.9254H63.5309ZM54.6014 21.9254H58.7002V24.3119H54.6014V30.4271H52.2593V24.3119V21.9254V17.3017C52.2593 15.2136 53.8695 13.5729 55.9189 13.5729H58.7002V15.9593H55.9189C55.1869 15.9593 54.455 16.5559 54.455 17.4508V21.9254H54.6014ZM22.836 30.4271V17.3017C22.836 15.2136 24.4462 13.5729 26.4956 13.5729H27.5203C29.5697 13.5729 31.1799 15.2136 31.1799 17.3017V30.4271H28.8377V24.3119H24.8854V30.4271H22.836ZM0 0H83V44H0V0Z" fill="#E2231A"></path></svg> B<svg width="83" height="44" viewBox="0 0 83 44" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M46.5503 30.4271V13.5729H48.8924V30.4271H46.5503ZM34.6931 30.4271V13.5729C36.3033 13.5729 37.9136 13.5729 39.5238 13.5729C41.5732 13.5729 43.1834 15.2136 43.1834 17.3017V30.4271H40.9877V17.3017C40.9877 16.5559 40.4021 15.8102 39.5238 15.8102C38.6455 15.8102 37.9136 15.8102 37.0353 15.8102V30.4271H34.6931ZM16.9806 30.4271C14.9312 30.4271 13.321 28.7864 13.321 26.6983V17.4508C13.321 15.3627 14.9312 13.722 16.9806 13.722H20.3474V16.1085H16.9806C16.2487 16.1085 15.5168 16.7051 15.5168 17.6V26.8475C15.5168 27.5932 16.1023 28.339 16.9806 28.339H20.3474V30.4333H16.9609L16.9806 30.4271ZM29.1305 21.9254V17.3017C29.1305 16.5559 28.545 15.8102 27.6667 15.8102H26.642C25.9101 15.8102 25.1781 16.4068 25.1781 17.3017V21.9254H29.1305ZM67.3369 24.3119H63.3845V30.4271H61.0423V17.3017C61.0423 15.2136 62.6526 13.5729 64.7019 13.5729H65.7266C67.776 13.5729 69.3862 15.2136 69.3862 17.3017V30.4271H67.3369V24.3119ZM63.5309 21.9254H67.3369V17.3017C67.3369 16.5559 66.7513 15.8102 65.873 15.8102H64.8483C64.1164 15.8102 63.3845 16.4068 63.3845 17.3017V21.9254H63.5309ZM54.6014 21.9254H58.7002V24.3119H54.6014V30.4271H52.2593V24.3119V21.9254V17.3017C52.2593 15.2136 53.8695 13.5729 55.9189 13.5729H58.7002V15.9593H55.9189C55.1869 15.9593 54.455 16.5559 54.455 17.4508V21.9254H54.6014ZM22.836 30.4271V17.3017C22.836 15.2136 24.4462 13.5729 26.4956 13.5729H27.5203C29.5697 13.5729 31.1799 15.2136 31.1799 17.3017V30.4271H28.8377V24.3119H24.8854V30.4271H22.836ZM0 0H83V44H0V0Z" fill="#E2231A"></path></svg>
This diff is collapsed.
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canifa Chatbot Concept v2</title>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Montserrat', sans-serif; background: #F5F5F5; }
.canifa-red { background-color: #E2231A; }
.canifa-text-red { color: #E2231A; }
.glass-header { background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(10px); }
.message-ai { background: #FFFFFF; border: 1px solid #E5E7EB; border-radius: 20px 20px 20px 4px; }
.message-user { background: #E2231A; color: white; border-radius: 20px 20px 4px 20px; }
.custom-shadow { box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1); }
.typing-dot { width: 4px; height: 4px; background: #E2231A; border-radius: 50%; animation: blink 1.4s infinite both; }
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes blink { 0%, 80%, 100% { opacity: 0.2; } 40% { opacity: 1; } }
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect, useRef } = React;
// Mock Icons
const SendIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></svg>
);
const CalendarIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect width="18" height="18" x="3" y="4" rx="2" ry="2"/><line x1="16" x2="16" y1="2" y2="6"/><line x1="8" x2="8" y1="2" y2="6"/><line x1="3" x2="21" y1="10" y2="10"/></svg>
);
const App = () => {
const [messages, setMessages] = useState([
{ role: 'ai', content: 'Chào bạn! Mình là CuCu, trợ lý ảo của Canifa. Bạn cần hỗ trợ gì về trang phục hay đơn hàng không? 😊' },
{ role: 'user', content: 'Cho mình xem các mẫu áo thun mới nhất' },
{ role: 'ai', content: 'Dưới đây là một số mẫu áo thun mới nhất trong bộ sưu tập **Trạm Hè Đa Sắc 2026**:\n\n1. Áo thun Cotton USA in hình (2026-04-25)\n2. Áo thun Canifa S phong cách Streetwear (2026-04-28)\n3. Áo Polo thoáng khí cho gia đình (2026-04-29)\n\nBạn có muốn xem chi tiết mẫu nào không?' }
]);
const [input, setInput] = useState('');
return (
<div className="flex flex-col h-screen max-w-md mx-auto bg-white border-x custom-shadow relative">
{/* Header */}
<header className="glass-header border-b p-4 flex items-center gap-3 sticky top-0 z-10">
<div className="w-10 h-10 canifa-red rounded-lg flex items-center justify-center overflow-hidden">
<img src="canifa-brand/logo.svg" alt="Canifa" className="w-8 h-8" />
</div>
<div>
<h1 className="font-bold text-sm">CuCu Assistant</h1>
<div className="flex items-center gap-1">
<span className="w-2 h-2 bg-green-500 rounded-full"></span>
<span className="text-[10px] text-gray-500 uppercase tracking-wider font-semibold">Fashion for All</span>
</div>
</div>
</header>
{/* Messages */}
<main className="flex-1 overflow-y-auto p-4 space-y-6">
{messages.map((msg, i) => (
<div key={i} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-[85%] p-4 text-sm leading-relaxed shadow-sm ${msg.role === 'user' ? 'message-user' : 'message-ai'}`}>
<div className="whitespace-pre-wrap">
{msg.content.split('\n').map((line, li) => (
<p key={li} className={li > 0 ? 'mt-2' : ''}>
{line.split(/(2026-\d{2}-\d{2})/).map((part, pi) => (
part.match(/^\d{4}-\d{2}-\d{2}$/) ? (
<span key={pi} className="inline-flex items-center gap-1 px-2 py-0.5 bg-gray-100 canifa-text-red rounded-full text-[11px] font-bold cursor-pointer hover:bg-gray-200 transition-colors">
<CalendarIcon /> {part}
</span>
) : part
))}
</p>
))}
</div>
</div>
</div>
))}
<div className="flex justify-start">
<div className="message-ai p-4 flex items-center gap-1">
<div className="typing-dot"></div>
<div className="typing-dot"></div>
<div className="typing-dot"></div>
</div>
</div>
</main>
{/* Input */}
<footer className="p-4 bg-white border-t">
<div className="flex items-center gap-2 bg-gray-100 rounded-2xl p-1 pr-2 border focus-within:border-red-300 focus-within:ring-2 focus-within:ring-red-100 transition-all">
<input
type="text"
placeholder="Hỏi CuCu về thời trang..."
className="flex-1 bg-transparent border-none outline-none px-4 py-2 text-sm"
/>
<button className="w-10 h-10 canifa-red text-white rounded-xl flex items-center justify-center hover:opacity-90 transition-all shadow-md">
<SendIcon />
</button>
</div>
<div className="text-[9px] text-center text-gray-400 mt-3 uppercase tracking-tighter">
© 2026 CANIFA - Powered by Huashu Design
</div>
</footer>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
</script>
</body>
</html>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
[
{
"idx": 1,
"question": "có áo mặc mùa hè thoáng mát không",
"verdict": "ERROR",
"reason": "All connection attempts failed"
},
{
"idx": 2,
"question": "tìm áo phông nam mùa hè dưới 300k",
"verdict": "ERROR",
"reason": "All connection attempts failed"
},
{
"idx": 3,
"question": "váy đi biển cho nữ có không bạn",
"verdict": "ERROR",
"reason": "All connection attempts failed"
},
{
"idx": 4,
"question": "quần short nam đi chơi hè",
"verdict": "ERROR",
"reason": "All connection attempts failed"
},
{
"idx": 5,
"question": "áo ba lỗ tập gym mùa hè",
"verdict": "ERROR",
"reason": "All connection attempts failed"
}
]
\ No newline at end of file
# Canifa · Brand Spec
> 采集日期:2026-04-30
> 资产来源:canifa.com 官网提取
> 资产完整度:完整
## 🎯 核心资产(一等公民)
### Logo
- 主版本:`backend/static/canifa-brand/logo.svg`
- 使用场景:Chatbot Header, Watermark, App Launcher
- 视觉特征:经典的 "CANIFA" 无衬线字标,置于红色圆角矩形块中。
### 品牌气质
- 核心关键词:Fashion for All, Gia đình, Năng động, Tin cậy.
- 2026 夏季主题:Trạm Hè Đa Sắc (Vibrant Summer Station)
## 🎨 辅助资产
### 色板
- **Canifa Red (Primary)**: `#E2231A` (Logo & CTA)
- **Deep Navy/Black**: `#333F48` (Typography & Secondary elements)
- **Summer Yellow/Lime**: `#C4FF1C` (Highlighter / New Campaign)
- **White**: `#FFFFFF` (Background)
- **Light Gray**: `#F5F5F5` (Container background)
### 字型
- **Display**: Sans-serif (Clean, modern like Montserrat or Inter)
- **Body**: Sans-serif (Highly readable)
### 交互签名
- 极简、流畅、圆角适中(8px - 12px)。
- 强调 "Joy" (Niềm vui) thông qua các hiệu ứng chuyển cảnh nhẹ nhàng.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment