Explorar el Código

增加API_MAX_RETURN_ROWS 返回参数。

wangxq hace 3 semanas
padre
commit
dbcc1c11cc
Se han modificado 3 ficheros con 300 adiciones y 5 borrados
  1. 4 1
      app_config.py
  2. 9 4
      citu_app.py
  3. 287 0
      docs/全局log服务开发方案.md

+ 4 - 1
app_config.py

@@ -134,7 +134,7 @@ REWRITE_QUESTION_ENABLED = False
 # 是否在摘要中显示thinking过程
 # True: 显示 <think></think> 内容
 # False: 隐藏 <think></think> 内容,只显示最终答案
-DISPLAY_SUMMARY_THINKING = True
+DISPLAY_SUMMARY_THINKING = False
 
 # 是否启用向量查询结果得分阈值过滤
 # result = max((n + 1) // 2, 1)
@@ -146,3 +146,6 @@ RESULT_VECTOR_DOC_SCORE_THRESHOLD = 0.5
 
 ENABLE_ERROR_SQL_PROMPT = True
 RESULT_VECTOR_ERROR_SQL_SCORE_THRESHOLD = 0.8
+
+# 接口返回查询记录的最大行数
+API_MAX_RETURN_ROWS = 1000

+ 9 - 4
citu_app.py

@@ -6,6 +6,11 @@ import pandas as pd
 import common.result as result
 from datetime import datetime, timedelta
 from common.session_aware_cache import WebSessionAwareMemoryCache
+from app_config import API_MAX_RETURN_ROWS
+
+# 设置默认的最大返回行数
+DEFAULT_MAX_RETURN_ROWS = 200
+MAX_RETURN_ROWS = API_MAX_RETURN_ROWS if API_MAX_RETURN_ROWS is not None else DEFAULT_MAX_RETURN_ROWS
 
 vn = create_vanna_instance()
 
@@ -57,7 +62,7 @@ def ask_full():
         summary = None
         
         if isinstance(df, pd.DataFrame) and not df.empty:
-            rows = df.head(1000).to_dict(orient="records")
+            rows = df.head(MAX_RETURN_ROWS).to_dict(orient="records")
             columns = list(df.columns)
             
             # 生成数据摘要
@@ -98,7 +103,7 @@ def citu_run_sql():
         rows, columns = [], []
         
         if isinstance(df, pd.DataFrame) and not df.empty:
-            rows = df.head(1000).to_dict(orient="records")
+            rows = df.head(MAX_RETURN_ROWS).to_dict(orient="records")
             columns = list(df.columns)
         
         return jsonify(result.success(data={
@@ -180,7 +185,7 @@ def ask_cached():
         rows, columns = [], []
         
         if isinstance(df, pd.DataFrame) and not df.empty:
-            rows = df.head(1000).to_dict(orient="records")
+            rows = df.head(MAX_RETURN_ROWS).to_dict(orient="records")
             columns = list(df.columns)
 
         return jsonify(result.success(data={
@@ -202,7 +207,7 @@ def ask_cached():
     
 
 
-@app.flask_app.route('/api/v1/citu_train_question_sql', methods=['POST'])
+@app.flask_app.route('/api/v0/citu_train_question_sql', methods=['POST'])
 def citu_train_question_sql():
     """
     训练问题-SQL对接口

+ 287 - 0
docs/全局log服务开发方案.md

@@ -0,0 +1,287 @@
+# Vanna.ai 源码日志系统深入分析报告
+
+Vanna.ai 作为一个基于 RAG 的 SQL 生成框架,其日志系统设计相对简化且**主要针对 Jupyter Notebook 环境进行优化**。通过对源码的深入分析,我发现该项目采用了**最小化日志设计**,优先考虑交互式环境的用户体验而非传统的企业级日志管理。
+
+## 核心发现:简化的日志架构
+
+### VannaBase 中的日志方法
+
+在 `src/vanna/base/base.py` 的 VannaBase 抽象基类中,存在一个**可重写的日志方法**(第77-78行):
+
+```python
+def log(self, message: str):
+    """
+    可被子类重写的日志方法
+    默认使用 print 语句输出
+    """
+    print(message)
+```
+
+**设计特点分析:**
+- **方法签名简单**:仅接受 `message` 参数,不支持日志级别区分
+- **默认实现**:直接使用 `print()` 语句,无格式化或时间戳
+- **重写机制**:子类可完全自定义日志行为
+- **Jupyter 优化**:官方明确表示"由于 Jupyter notebooks 的行为特性,日志函数故意使用 print 语句"
+
+### 项目级别日志对象检查结果
+
+经过全面的源码结构分析,**vanna.ai 项目中不存在项目级别的统一日志对象**:
+
+- ❌ **无专门日志模块**:没有 `logging.py`、`logger.py` 等专门文件
+- ❌ **无全局日志配置**:缺乏统一的日志管理和配置机制  
+- ❌ **无标准日志级别**:不支持 `logger.debug()`、`logger.warning()` 等标准方法
+- ❌ **无日志导出接口**:无法获取全局 logger 对象用于统一管理
+
+## 当前日志使用模式分析
+
+### 实际使用场景
+
+通过对各模块的代码分析,发现日志使用主要集中在以下场景:
+
+**1. SQL 提取成功通知**
+```python
+def _extract_sql(self, llm_response: str) -> str:
+    # SQL 提取逻辑
+    if sqls:
+        sql = sqls[-1]
+        self.log(f"Extracted SQL: {sql}")  # 关键操作日志
+        return sql
+```
+
+**2. 模型调用信息**
+```python
+# 在 OpenAI_Chat 模块中
+print(f"Using model {model} for {num_tokens} tokens (approx)")
+```
+
+**3. 错误信息输出**
+```python
+# 嵌入生成错误
+print(f"Error generating embedding: {e}")
+```
+
+### 日志分布特征
+
+- **print 语句为主**:项目广泛使用 `print()` 而非标准 logging 模块
+- **无结构化设计**:缺乏统一的日志格式和级别管理
+- **调试导向**:主要用于开发调试和 Jupyter 环境的状态展示
+- **无持久化**:所有日志输出到标准输出,无文件存储能力
+
+## 日志配置和扩展能力分析
+
+### 当前配置支持
+
+**基础配置结构:**
+```python
+class VannaBase(ABC):
+    def __init__(self, config=None):
+        if config is None:
+            config = {}
+        self.config = config
+        # 无日志相关配置参数
+```
+
+**配置局限性:**
+- ❌ **无日志级别配置**:不支持 `log_level` 参数
+- ❌ **无输出路径配置**:无法配置日志文件输出路径
+- ❌ **无滚动策略配置**:不支持日志轮转和清理策略
+- ❌ **无格式化配置**:无法自定义日志输出格式
+
+### 扩展性设计优势
+
+尽管功能简化,vanna.ai 的架构具备良好的**扩展性基础**:
+
+**1. 策略模式支持**
+```python
+class CustomVanna(VannaBase):
+    def log(self, message: str):
+        # 自定义日志实现
+        import logging
+        logging.info(message)
+```
+
+**2. 多重继承兼容**
+```python
+class MyVanna(ChromaDB_VectorStore, OpenAI_Chat):
+    def log(self, message: str):
+        # 统一的日志策略
+        self._custom_logger.info(message)
+```
+
+## 企业级日志需求的实现方案
+
+### 推荐的自定义实现
+
+基于当前架构,为支持企业级日志管理,建议采用以下实现模式:
+
+**1. 基础日志增强**
+```python
+import logging
+import os
+from typing import Optional
+
+class EnhancedVannaBase(VannaBase):
+    def __init__(self, config=None):
+        super().__init__(config)
+        self._setup_logging()
+    
+    def _setup_logging(self):
+        """设置增强的日志系统"""
+        log_config = self.config.get('logging', {})
+        
+        # 日志级别配置
+        level = log_config.get('level', 'INFO')
+        
+        # 日志格式配置
+        format_str = log_config.get(
+            'format', 
+            '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
+        )
+        
+        # 输出配置
+        log_file = log_config.get('file_path')
+        
+        # 创建logger
+        self.logger = logging.getLogger(f'vanna.{self.__class__.__name__}')
+        self.logger.setLevel(getattr(logging, level.upper()))
+        
+        # 添加处理器
+        if log_file:
+            handler = logging.FileHandler(log_file)
+        else:
+            handler = logging.StreamHandler()
+        
+        formatter = logging.Formatter(format_str)
+        handler.setFormatter(formatter)
+        self.logger.addHandler(handler)
+    
+    def log(self, message: str, level: str = 'info'):
+        """增强的日志方法"""
+        log_method = getattr(self.logger, level.lower(), self.logger.info)
+        log_method(message)
+    
+    # 标准日志方法
+    def debug(self, message: str):
+        self.log(message, 'debug')
+    
+    def info(self, message: str):
+        self.log(message, 'info')
+    
+    def warning(self, message: str):
+        self.log(message, 'warning')
+    
+    def error(self, message: str):
+        self.log(message, 'error')
+```
+
+**2. 配置文件支持**
+```python
+# config.yaml
+logging:
+  level: DEBUG
+  format: "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
+  file_path: "/var/log/vanna/app.log"
+  rotation:
+    max_size: "10MB"
+    backup_count: 5
+```
+
+**3. 日志滚动策略实现**
+```python
+from logging.handlers import RotatingFileHandler
+
+def _setup_file_handler(self, log_config):
+    """设置带滚动的文件处理器"""
+    log_file = log_config.get('file_path')
+    rotation = log_config.get('rotation', {})
+    
+    max_bytes = self._parse_size(rotation.get('max_size', '10MB'))
+    backup_count = rotation.get('backup_count', 5)
+    
+    handler = RotatingFileHandler(
+        log_file, 
+        maxBytes=max_bytes,
+        backupCount=backup_count
+    )
+    return handler
+```
+
+## 社区需求和发展趋势
+
+### GitHub Issue #387 反馈分析
+
+社区对日志系统改进存在**强烈需求**:
+
+- **用户反馈**:"Vanna uses print instead of logging" 不利于生产环境使用
+- **改进建议**:升级到标准 logging 解决方案
+- **向后兼容需求**:需要在改进时保持 Jupyter 环境的友好性
+
+### 推荐的渐进式改进路径
+
+**阶段1:兼容性增强**
+- 在 VannaBase 中添加可选的标准 logging 支持
+- 通过配置参数在 print 和 logging 之间切换
+- 保持现有 API 完全向后兼容
+
+**阶段2:功能完善**
+- 添加日志级别管理和过滤能力
+- 支持结构化日志输出(JSON 格式)
+- 实现日志文件输出和滚动策略
+
+**阶段3:企业级特性**
+- 添加日志聚合和监控集成支持
+- 支持分布式日志追踪
+- 提供日志分析和可视化工具
+
+## 定制开发建议
+
+对于基于 vanna 框架进行定制开发的项目,建议采用以下策略:
+
+### 短期解决方案
+
+**1. 重写基类日志方法**
+```python
+class ProductionVanna(ChromaDB_VectorStore, OpenAI_Chat):
+    def __init__(self, config=None):
+        super().__init__(config)
+        self.setup_production_logging()
+    
+    def log(self, message: str):
+        self.logger.info(message)
+    
+    def setup_production_logging(self):
+        # 实现企业级日志配置
+        pass
+```
+
+**2. 环境变量配置**
+```python
+import os
+
+LOG_LEVEL = os.getenv('VANNA_LOG_LEVEL', 'INFO')
+LOG_FILE = os.getenv('VANNA_LOG_FILE', None)
+```
+
+### 长期架构规划
+
+**1. 独立日志模块设计**
+- 创建专门的 `vanna.logging` 模块
+- 提供统一的日志管理接口
+- 支持插件化的日志处理器
+
+**2. 配置驱动的日志系统**
+- 支持 YAML/JSON 配置文件
+- 动态日志级别调整
+- 运行时日志配置热更新
+
+## 总结与展望
+
+Vanna.ai 当前的日志系统体现了**简化设计**的理念,优先考虑 Jupyter 环境的用户体验。虽然缺乏企业级日志管理功能,但其**良好的架构扩展性**为自定义实现提供了坚实基础。
+
+**关键技术特征:**
+- **当前状态**:基于 print 的简化日志,主要服务于交互式环境
+- **扩展能力**:通过重写 `log()` 方法可实现完全自定义的日志策略
+- **发展趋势**:社区推动向标准 logging 模块迁移,同时保持向后兼容
+
+**定制开发建议:**
+对于需要企业级日志功能的项目,建议通过继承和配置的方式实现增强的日志系统,在保持 vanna.ai 核心功能的同时,添加生产环境所需的日志管理能力。这种方式既能利用现有的架构优势,又能满足复杂的日志需求。