feat: finalize backend readiness (config, limits, docs)
- Expose API Gateway port 4000 in docker-compose for local dev - Enable dynamic API_GATEWAY_URL in Next.js config - Add 64K context hard limit in report-generator to avoid LLM errors - Add backend API readiness report
This commit is contained in:
parent
6c880f51dd
commit
4881ac8603
@ -80,6 +80,8 @@ services:
|
|||||||
dockerfile: services/api-gateway/Dockerfile
|
dockerfile: services/api-gateway/Dockerfile
|
||||||
container_name: api-gateway
|
container_name: api-gateway
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "4000:4000"
|
||||||
environment:
|
environment:
|
||||||
SERVER_PORT: 4000
|
SERVER_PORT: 4000
|
||||||
NATS_ADDR: nats://nats:4222
|
NATS_ADDR: nats://nats:4222
|
||||||
|
|||||||
@ -0,0 +1,68 @@
|
|||||||
|
# 后端 API 就绪性与接口验证报告
|
||||||
|
|
||||||
|
**日期**: 2025-11-21
|
||||||
|
**状态**: ✅ Backend Ready for Frontend Integration (全链路通过)
|
||||||
|
**作者**: AI Assistant
|
||||||
|
|
||||||
|
## 1. 概述
|
||||||
|
|
||||||
|
本报告总结了对 Fundamental Analysis System 后端进行的全面 API 级端到端测试结果。
|
||||||
|
我们通过 CURL 脚本完全模拟了前端的用户行为(配置加载、工作流触发、SSE 事件监听、数据回读),验证了后端的契约实现和稳定性。
|
||||||
|
|
||||||
|
测试表明,后端核心功能已经就绪,前端可以开始进行对接和调试。所有关键数据源接口(包括此前不稳定的 Profile 获取)均已修复并验证通过。
|
||||||
|
|
||||||
|
## 2. 测试结果摘要
|
||||||
|
|
||||||
|
| 测试项 | 描述 | 结果 | 备注 |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **System Health** | API Gateway 健康检查 | ✅ PASS | HTTP 200 |
|
||||||
|
| **Configuration** | LLM Providers & Templates 配置读取 | ✅ PASS | 成功加载配置 |
|
||||||
|
| **Workflow Core** | 启动工作流 -> 任务调度 -> 完成 | ✅ PASS | 无超时,无卡死 |
|
||||||
|
| **SSE Streaming** | 实时事件推送 (Started, TaskUpdate, Completed) | ✅ PASS | 前端进度条可正常驱动 |
|
||||||
|
| **LLM Integration** | 提示词组装 -> 调用 OpenRouter -> 生成报告 | ✅ PASS | **已修复 64K Context 限制问题** |
|
||||||
|
| **Data Persistence** | 分析报告 (AnalysisResult) 入库 | ✅ PASS | 最终结果可查 |
|
||||||
|
| **Data Fetching** | 财务数据 (Financials) 入库 | ✅ PASS | 成功拉取并解析数据 |
|
||||||
|
| **Company Profile** | 公司基本信息入库 | ✅ PASS | **已修复并发限流问题** |
|
||||||
|
|
||||||
|
## 3. 关键修复与改进
|
||||||
|
|
||||||
|
在验证过程中,我们发现并修复了以下阻碍性问题:
|
||||||
|
|
||||||
|
1. **Docker 网络与端口暴露**:
|
||||||
|
* 修改 `docker-compose.yml`,暴露 `api-gateway` 的 `4000` 端口。
|
||||||
|
* 修改 `frontend/next.config.mjs`,支持动态配置后端地址 (`API_GATEWAY_URL`)。
|
||||||
|
|
||||||
|
2. **LLM Context 溢出保护**:
|
||||||
|
* 发现 `report-generator-service` 在处理大量财务数据时可能生成超过 LLM 上下文限制的 Prompt。
|
||||||
|
* **修复**: 实施了 **64K 字符硬截断** 策略。如果 Prompt 过长,会自动截断并附加系统警告,确保 LLM 请求永远不会因为 Payload 过大而超时或被拒。
|
||||||
|
|
||||||
|
3. **AlphaVantage 数据源稳定性 (Profile 404 修复)**:
|
||||||
|
* **现象**: 免费版 Key 存在 5次/分钟 的 API 速率限制,并发请求导致 Profile 接口频繁失败。
|
||||||
|
* **修复**: 重构了 `alphavantage-provider-service` 的 Worker 逻辑,将并发请求改为 **串行执行**,并在每个请求间增加了 **2秒强制延迟**。同时引入了显式的错误检查机制("Early Fail"),确保不会静默吞掉 API 错误。验证证实现在可以稳定获取 `CompanyProfile`。
|
||||||
|
|
||||||
|
4. **测试脚本竞态条件**:
|
||||||
|
* 优化了 E2E 测试脚本,解决了 SSE 连接建立与工作流启动之间的微小时序问题,确保能稳定捕获所有事件。
|
||||||
|
|
||||||
|
## 4. 工具与资源
|
||||||
|
|
||||||
|
### 4.1 调试工具 (Baseline Script)
|
||||||
|
我们交付了一个强大的 API 测试脚本,可用作未来的回归测试基准:
|
||||||
|
* 路径: `tests/api-e2e/run_api_test.sh`
|
||||||
|
* 用法: `./tests/api-e2e/run_api_test.sh http://localhost:4000/v1`
|
||||||
|
|
||||||
|
## 5. 下一步 (前端对接指南)
|
||||||
|
|
||||||
|
前端开发环境已准备就绪。您可以直接启动前端进行联调:
|
||||||
|
|
||||||
|
1. **确保后端运行**: `tilt up` 或 `docker-compose up -d`。
|
||||||
|
2. **启动前端**:
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
# 指向本地暴露的 4000 端口
|
||||||
|
export API_GATEWAY_URL=http://localhost:4000
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
3. **验证**: 打开浏览器访问 `http://localhost:3000`,尝试输入 "AAPL" 或 "IBM" 进行分析。
|
||||||
|
|
||||||
|
---
|
||||||
|
**结论**: 后端 API 契约稳定,逻辑闭环,数据源集成问题已解决,已完全具备与前端集成的条件。
|
||||||
@ -17,10 +17,11 @@ const nextConfig = {
|
|||||||
output: process.env.NODE_ENV === 'production' ? 'standalone' : undefined,
|
output: process.env.NODE_ENV === 'production' ? 'standalone' : undefined,
|
||||||
|
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
|
const apiUrl = process.env.API_GATEWAY_URL || 'http://api-gateway:4000';
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: '/api/:path*',
|
source: '/api/:path*',
|
||||||
destination: 'http://api-gateway:4000/v1/:path*',
|
destination: `${apiUrl}/v1/:path*`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
@ -121,8 +121,26 @@ pub async fn run_report_generation_workflow(
|
|||||||
info!(module_id = %module_id, "Rendering prompt template...");
|
info!(module_id = %module_id, "Rendering prompt template...");
|
||||||
let prompt = match Tera::one_off(&module_config.prompt_template, &context, true) {
|
let prompt = match Tera::one_off(&module_config.prompt_template, &context, true) {
|
||||||
Ok(p) => {
|
Ok(p) => {
|
||||||
info!(module_id = %module_id, "Prompt rendered successfully. Length: {} chars", p.len());
|
let p_len = p.len();
|
||||||
p
|
info!(module_id = %module_id, "Prompt rendered successfully. Length: {} chars", p_len);
|
||||||
|
|
||||||
|
// Hard Context Limit: 64K chars (~16K tokens)
|
||||||
|
// This is a temporary protection until we have a Deep Research / Summarization module.
|
||||||
|
const MAX_CONTEXT_CHARS: usize = 64_000;
|
||||||
|
if p_len > MAX_CONTEXT_CHARS {
|
||||||
|
let trunc_msg = "\n\n[SYSTEM WARNING: Input data truncated to fit context limits. Analysis may be partial.]";
|
||||||
|
let safe_len = MAX_CONTEXT_CHARS.saturating_sub(trunc_msg.len());
|
||||||
|
let truncated_prompt = format!("{}{}", &p[..safe_len], trunc_msg);
|
||||||
|
|
||||||
|
tracing::warn!(
|
||||||
|
module_id = %module_id,
|
||||||
|
"Prompt size ({} chars) exceeded limit ({} chars). Truncated.",
|
||||||
|
p_len, MAX_CONTEXT_CHARS
|
||||||
|
);
|
||||||
|
truncated_prompt
|
||||||
|
} else {
|
||||||
|
p
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Prompt rendering failed: {}", e);
|
let err_msg = format!("Prompt rendering failed: {}", e);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user