上一篇 下一篇 分享链接 返回 返回顶部

企业知识库别再只存文档了:一套可落地的 AI 搭建方案与配置示例

发布人:慈云数据-客服中心 发布时间:4小时前 阅读量:0

AI编程 企业知识库搭建|附配置文件

在企业数字化转型过程中,知识管理一直是一个绕不开的话题。无论是研发文档、产品手册、售后案例、销售话术,还是制度规范、项目复盘、客户资料,企业每天都会产生大量非结构化知识。如果这些知识只是散落在飞书、钉钉、语雀、Confluence、Word、PDF、Excel、代码仓库和个人电脑里,那么它们很难真正转化为组织能力。

随着大模型和 AI 编程工具的发展,企业知识库的建设方式正在发生变化。过去我们搭建知识库,更多关注“文档存储”和“关键词搜索”;现在则更关注“语义理解”“智能问答”“研发辅助”“自动生成代码”“自动分析业务资料”等能力。

本文将从企业实战角度,介绍如何基于 AI 编程思路搭建一个可用、可扩展、可私有化部署的企业知识库系统,并附上常用配置文件示例,帮助你快速完成从 0 到 1 的搭建。


一、为什么企业需要 AI 知识库?

传统企业知识库通常存在以下问题:

  1. 资料分散,查找困难
    文档分布在不同平台、不同项目、不同人员手中,员工需要反复搜索、询问、翻历史记录。

  2. 关键词搜索效果差
    传统搜索依赖关键词匹配。如果用户不知道准确术语,就很难找到答案。例如用户搜索“报销标准”,但文档里写的是“费用报销管理办法”,搜索结果可能并不理想。

  3. 知识更新不及时
    老版本制度、废弃接口文档、过期产品方案仍然存在,容易造成误用。

  4. 新人培训成本高
    新员工往往需要花大量时间熟悉业务背景、技术架构、流程规范,而这些内容未必有统一入口。

  5. 研发效率低
    对于技术团队来说,接口文档、数据库设计、代码规范、部署流程、故障案例如果不能快速查询,会直接影响开发和排障效率。

AI 知识库的价值在于,它不仅可以“存知识”,还可以“理解知识”和“生成答案”。员工不需要精确知道文档在哪里,只需要像提问同事一样向系统提问,例如:

“我们公司的差旅报销标准是什么?”
“订单系统的退款流程涉及哪些接口?”
“这个报错在历史故障里出现过吗?”
“请根据已有接口文档生成一段 Java 调用示例。”
“帮我总结这个项目的部署步骤。”

这就是 AI 知识库相比传统知识库最大的变化:从“人找文档”,变成“AI 根据企业资料组织答案”。


二、整体技术架构

一个典型的企业 AI 知识库系统,可以分为以下几个核心模块:

用户入口
  ├── Web 管理后台
  ├── 企业微信 / 飞书 / 钉钉机器人
  ├── IDE 插件 / AI 编程助手
  └── API 接口

应用服务层
  ├── 用户认证与权限管理
  ├── 知识库管理
  ├── 文档上传与解析
  ├── 向量检索
  ├── 大模型问答
  ├── 对话历史管理
  └── 日志审计

AI 能力层
  ├── Embedding 模型
  ├── Chat 大语言模型
  ├── RAG 检索增强生成
  ├── Prompt 模板
  └── Agent 工具调用

数据存储层
  ├── MySQL / PostgreSQL:业务数据
  ├── Redis:缓存与会话
  ├── MinIO:原始文件存储
  ├── Milvus / pgvector / Elasticsearch:向量检索
  └── 本地或对象存储:日志与备份

其中最关键的是 RAG,也就是 Retrieval-Augmented Generation,中文通常叫“检索增强生成”。

简单来说,RAG 的工作流程如下:

  1. 用户提出问题;
  2. 系统将问题转成向量;
  3. 到企业知识库向量数据库中检索相关片段;
  4. 将检索到的内容和用户问题一起交给大模型;
  5. 大模型基于企业资料生成回答;
  6. 返回答案,并附带引用来源。

这样可以有效减少大模型“胡说”的概率,也可以让模型回答企业内部特定知识。


三、技术选型建议

企业知识库的技术选型可以根据团队能力、部署环境和预算灵活调整。下面是一套较常见的开源技术栈:

模块 推荐技术 说明
后端服务 Python FastAPI / Java Spring Boot Python 更适合快速集成 AI,Java 更适合企业级系统
前端 Vue / React / Next.js 用于后台管理和问答页面
向量数据库 Milvus / pgvector / Qdrant Milvus 性能强,pgvector 简单易维护
关系数据库 PostgreSQL / MySQL 保存用户、权限、文档元数据
缓存 Redis 保存会话、限流、热点数据
文件存储 MinIO 私有化对象存储,兼容 S3 协议
大模型 Qwen / DeepSeek / GLM / OpenAI API 可根据合规要求选择私有化或云端 API
Embedding 模型 bge-large-zh / text-embedding-v3 中文语义检索效果较好
部署 Docker Compose / Kubernetes 中小团队可先用 Docker Compose

如果企业对数据安全要求较高,建议使用私有化模型和内网部署。例如使用 Qwen、DeepSeek、Baichuan、GLM 等开源或可私有化部署模型,再配合 Ollama、vLLM 或 Xinference 提供模型推理服务。


四、知识库核心流程设计

1. 文档采集

企业资料来源通常包括:

  • PDF 文档;
  • Word 文档;
  • Excel 表格;
  • Markdown 文档;
  • HTML 页面;
  • Git 仓库代码;
  • API 文档;
  • 数据库表结构;
  • 工单系统;
  • 客服聊天记录;
  • 飞书 / 语雀 / Confluence 页面。

文档采集的重点不是“能不能上传”,而是“能不能持续同步”。企业知识每天都在变化,如果知识库不能自动更新,很快就会失效。

建议设计以下机制:

  • 支持手动上传;
  • 支持定时同步;
  • 支持 API 接入;
  • 支持增量更新;
  • 支持文档版本管理;
  • 支持删除与重建索引。

2. 文档解析

不同格式的文档需要使用不同解析方式:

文件类型 解析方式
PDF PyMuPDF、pdfplumber、OCR
Word python-docx、Apache POI
Excel pandas、openpyxl
Markdown 直接解析标题结构
HTML BeautifulSoup、Readability
代码文件 AST、正则、Tree-sitter
图片扫描件 OCR 识别

解析时应尽量保留文档结构,例如标题、段落、表格、列表、代码块。因为企业知识中的上下文非常重要,如果只把文本粗暴拼接,后续检索质量会明显下降。

例如接口文档中常见结构:

# 创建订单接口

## 请求地址
POST /api/order/create

## 请求参数
- userId:用户 ID
- productId:商品 ID
- quantity:购买数量

## 返回参数
- orderId:订单 ID
- status:订单状态

如果切分时把“请求地址”和“请求参数”分散到不同片段,大模型可能无法完整理解接口含义。


3. 文本切分

文档进入向量数据库前,通常需要切分成较小的 Chunk。切分太大,会影响检索精度;切分太小,会丢失上下文。

常见配置如下:

chunk:
  size: 800
  overlap: 120
  separators:
    - "\n## "
    - "\n### "
    - "\n\n"
    - "。"
    - "\n"

建议中文知识库采用 500~1000 字左右的切片,并设置 80~150 字的重叠内容。对于技术文档,可以优先按标题、代码块、接口模块进行结构化切分。


4. 向量化与索引

文本切分之后,需要调用 Embedding 模型将每个片段转换成向量,然后写入向量数据库。

一条向量记录通常包含:

{
  "doc_id": "doc_10001",
  "chunk_id": "chunk_0001",
  "content": "员工出差住宿标准按照城市等级划分,一线城市每晚不超过600元……",
  "embedding": [0.012, -0.031, 0.087],
  "metadata": {
    "title": "差旅报销管理制度",
    "department": "财务部",
    "permission": "internal",
    "version": "2024.03",
    "source": "制度文档"
  }
}

企业级知识库一定要重视 metadata。因为后续权限过滤、来源引用、版本控制、分类检索都依赖元数据。


5. 检索与重排序

用户提问后,系统一般会执行以下步骤:

  1. 将问题向量化;
  2. 根据权限筛选可访问知识库;
  3. 在向量数据库中召回 Top K 文档片段;
  4. 使用 Reranker 模型重新排序;
  5. 选择最相关的若干片段进入 Prompt;
  6. 调用大模型生成回答。

推荐配置:

retrieval:
  top_k: 8
  rerank_top_n: 4
  score_threshold: 0.35
  enable_hybrid_search: true

如果只使用向量搜索,有时会漏掉专有名词、接口名称、订单号、错误码等精准信息。因此企业知识库建议使用“混合检索”,也就是向量检索 + 关键词检索。对于技术文档、代码文档、运维故障库来说,混合检索尤其重要。


五、AI 编程场景下的知识库应用

企业知识库不只是给行政、人事、财务使用,对研发团队也非常有价值。尤其在 AI 编程场景下,它可以成为开发者的“企业上下文”。

1. 代码规范问答

开发者可以直接提问:

“我们后端接口返回格式规范是什么?”
“Java 项目中异常码如何定义?”
“前端请求封装用哪个库?”

AI 可以根据内部规范文档回答,并给出示例代码。


2. 接口文档生成代码

例如用户输入:

“根据订单创建接口文档,生成一个 Spring Boot 调用示例。”

AI 可以从知识库中检索订单接口文档,然后生成类似代码:

RestTemplate restTemplate = new RestTemplate();

Map request = new HashMap<>();
request.put("userId", 10001);
request.put("productId", 20002);
request.put("quantity", 1);

String url = "https://api.example.com/api/order/create";

ResponseEntity response = restTemplate.postForEntity(
    url,
    request,
    String.class
);

System.out.println(response.getBody());

这类能力可以大幅减少开发者查文档和写样板代码的时间。


3. 故障排查助手

企业可以将历史故障报告、监控告警、日志分析结果沉淀到知识库中。当生产环境再次出现类似问题时,开发者可以询问:

“支付回调超时可能是什么原因?”
“错误码 ORDER_5003 在历史故障中出现过吗?”
“Redis 连接池耗尽怎么处理?”

AI 可以从历史案例中总结排查路径、影响范围和解决方案。


4. 数据库设计辅助

将数据字典、ER 图说明、表结构文档接入知识库后,AI 可以帮助开发者理解数据模型:

“订单表和支付表通过哪个字段关联?”
“用户积分流水表有哪些状态?”
“帮我写一个查询用户最近 30 天订单金额的 SQL。”

当然,涉及生产数据库操作时,需要增加权限控制和安全审计,避免 AI 生成危险 SQL 后被直接执行。


六、项目目录结构示例

下面给出一个基于 FastAPI + PostgreSQL + Redis + MinIO + Milvus 的知识库项目结构示例:

enterprise-ai-kb/
├── app/
│   ├── api/
│   │   ├── chat.py
│   │   ├── document.py
│   │   ├── knowledge_base.py
│   │   └── user.py
│   ├── core/
│   │   ├── config.py
│   │   ├── security.py
│   │   └── logging.py
│   ├── services/
│   │   ├── document_parser.py
│   │   ├── chunk_service.py
│   │   ├── embedding_service.py
│   │   ├── retrieval_service.py
│   │   ├── llm_service.py
│   │   └── rag_service.py
│   ├── models/
│   │   ├── document.py
│   │   ├── user.py
│   │   └── chat_session.py
│   ├── repositories/
│   │   ├── document_repo.py
│   │   └── user_repo.py
│   └── main.py
├── config/
│   ├── application.yml
│   ├── prompt.yml
│   └── logging.yml
├── docker-compose.yml
├── requirements.txt
├── Dockerfile
└── README.md

这个结构把接口、配置、服务、数据模型和存储访问进行了分层,便于后续扩展。


七、核心配置文件示例

1. application.yml

server:
  host: 0.0.0.0
  port: 8080
  env: production

database:
  type: postgresql
  host: postgres
  port: 5432
  username: kb_user
  password: kb_password
  database: enterprise_kb
  pool_size: 20
  max_overflow: 10

redis:
  host: redis
  port: 6379
  password: ""
  db: 0
  ttl_seconds: 3600

minio:
  endpoint: http://minio:9000
  access_key: minioadmin
  secret_key: minioadmin
  bucket: enterprise-kb
  secure: false

vector_store:
  type: milvus
  host: milvus
  port: 19530
  collection: enterprise_kb_chunks
  dimension: 1024
  metric_type: COSINE
  index_type: HNSW
  index_params:
    M: 16
    efConstruction: 200
  search_params:
    ef: 64

embedding:
  provider: local
  model: bge-large-zh-v1.5
  endpoint: http://embedding-service:8001/v1/embeddings
  batch_size: 32
  timeout_seconds: 60

llm:
  provider: openai_compatible
  model: qwen2.5-32b-instruct
  base_url: http://llm-service:8000/v1
  api_key: sk-local-placeholder
  temperature: 0.2
  max_tokens: 2048
  timeout_seconds: 120

chunk:
  size: 800
  overlap: 120
  separators:
    - "\n## "
    - "\n### "
    - "\n\n"
    - "。"
    - "\n"

retrieval:
  top_k: 8
  rerank_enabled: true
  rerank_model: bge-reranker-large
  rerank_top_n: 4
  score_threshold: 0.35
  hybrid_search_enabled: true

security:
  jwt_secret: please-change-this-secret
  jwt_expire_minutes: 720
  enable_document_permission: true
  enable_audit_log: true

upload:
  max_file_size_mb: 100
  allowed_extensions:
    - pdf
    - docx
    - xlsx
    - md
    - txt
    - html
    - json
    - java
    - py
    - js
    - ts

2. prompt.yml

system_prompt: |
  你是企业内部 AI 知识库助手。
  你必须严格基于提供的企业知识片段回答问题。
  如果知识片段中没有相关内容,请明确说明“当前知识库中未找到可靠依据”,不要编造答案。
  回答时请尽量结构化,必要时使用列表、表格或代码块。
  如果问题涉及制度、流程、接口、代码规范,请引用对应来源。
  如果内容存在多个版本,请优先使用最新版本。

rag_prompt_template: |
  请根据以下企业知识片段回答用户问题。

  【企业知识片段】
  {context}

  【用户问题】
  {question}

  【回答要求】
  1. 优先给出直接答案;
  2. 如果有步骤,请按顺序列出;
  3. 如果涉及代码,请给出可读性较好的示例;
  4. 如果依据不足,请明确说明;
  5. 最后列出参考来源。

code_assistant_prompt: |
  你是企业研发团队的 AI 编程助手。
  请结合企业内部技术文档、接口规范、代码规范和历史故障案例,为开发者提供帮助。
  生成代码时必须遵守以下原则:
  - 优先遵循企业已有规范;
  - 不输出明显危险的生产操作命令;
  - 涉及数据库修改、数据删除、权限变更时必须提醒用户谨慎确认;
  - 如果缺少上下文,不要假设关键业务规则。

3. docker-compose.yml

version: "3.9"

services:
  postgres:
    image: postgres:15
    container_name: kb-postgres
    restart: always
    environment:
      POSTGRES_USER: kb_user
      POSTGRES_PASSWORD: kb_password
      POSTGRES_DB: enterprise_kb
    ports:
      - "5432:5432"
    volumes:
      - ./data/postgres:/var/lib/postgresql/data

  redis:
    image: redis:7
    container_name: kb-redis
    restart: always
    ports:
      - "6379:6379"

  minio:
    image: minio/minio:latest
    container_name: kb-minio
    restart: always
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - ./data/minio:/data

  etcd:
    image: quay.io/coreos/etcd:v3.5.5
    container_name: kb-etcd
    restart: always
    environment:
      - ETCD_AUTO_COMPACTION_MODE=revision
      - ETCD_AUTO_COMPACTION_RETENTION=1000
      - ETCD_QUOTA_BACKEND_BYTES=4294967296
    command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls=http://0.0.0.0:2379
    volumes:
      - ./data/etcd:/etcd

  milvus:
    image: milvusdb/milvus:v2.4.0
    container_name: kb-milvus
    restart: always
    command: ["milvus", "run", "standalone"]
    environment:
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    ports:
      - "19530:19530"
      - "9091:9091"
    depends_on:
      - etcd
      - minio
    volumes:
      - ./data/milvus:/var/lib/milvus

  api:
    build: .
    container_name: kb-api
    restart: always
    ports:
      - "8080:8080"
    volumes:
      - ./config:/app/config
    depends_on:
      - postgres
      - redis
      - minio
      - milvus

4. requirements.txt

fastapi==0.111.0
uvicorn==0.30.1
pydantic==2.7.4
sqlalchemy==2.0.30
psycopg2-binary==2.9.9
redis==5.0.4
pymilvus==2.4.3
minio==7.2.7
python-multipart==0.0.9
pypdf==4.2.0
python-docx==1.1.2
openpyxl==3.1.4
beautifulsoup4==4.12.3
httpx==0.27.0
pyyaml==6.0.1
loguru==0.7.2

八、关键代码示例

1. 配置读取

import yaml
from pathlib import Path

class Settings:
    def __init__(self, config_path: str = "config/application.yml"):
        with open(config_path, "r", encoding="utf-8") as f:
            self.config = yaml.safe_load(f)

    def get(self, key: str, default=None):
        keys = key.split(".")
        value = self.config
        for k in keys:
            if not isinstance(value, dict):
                return default
            value = value.get(k)
            if value is None:
                return default
        return value

settings = Settings()

print(settings.get("llm.model"))

2. 文本切分示例

def split_text(text: str, chunk_size: int = 800, overlap: int = 120):
    chunks = []
    start = 0
    text = text.strip()

    while start < len(text):
        end = start + chunk_size
        chunk = text[start:end]

        if chunk.strip():
            chunks.append(chunk.strip())

        start = end - overlap

        if start < 0:
            start = 0

        if start >= len(text):
            break

    return chunks

实际生产中不建议只使用固定长度切分,最好结合标题、段落和表格结构进行优化。


3. RAG 问答流程伪代码

async def rag_chat(question: str, user_id: str):
    # 1. 校验用户权限
    permissions = await get_user_permissions(user_id)

    # 2. 问题向量化
    query_embedding = await embedding_service.embed(question)

    # 3. 向量检索
    candidates = await vector_store.search(
        embedding=query_embedding,
        top_k=8,
        filters={
            "permission": permissions
        }
    )

    # 4. 重排序
    reranked_docs = await rerank_service.rerank(
        query=question,
        documents=candidates,
        top_n=4
    )

    # 5. 组装上下文
    context = "\n\n".join([
        f"来源:{doc.metadata.get('title')}\n内容:{doc.content}"
        for doc in reranked_docs
    ])

    # 6. 构造 Prompt
    prompt = prompt_template.format(
        context=context,
        question=question
    )

    # 7. 调用大模型
    answer = await llm_service.chat(prompt)

    # 8. 保存审计日志
    await audit_log_service.save(
        user_id=user_id,
        question=question,
        sources=[doc.metadata for doc in reranked_docs]
    )

    return answer

九、权限与安全设计

企业知识库和普通个人知识库最大的区别之一,就是权限复杂度更高。不是所有员工都能访问所有知识。

建议至少设计以下权限维度:

  1. 用户权限
    不同用户拥有不同角色,如普通员工、部门管理员、系统管理员。

  2. 部门权限
    财务制度可能对全员开放,但薪酬明细只能 HR 或管理层访问。

  3. 知识库权限
    按知识库划分访问范围,如研发知识库、销售知识库、法务知识库。

  4. 文档权限
    对敏感文档单独设置权限级别。

  5. 字段脱敏
    对手机号、身份证号、客户合同金额等敏感内容进行脱敏处理。

  6. 审计日志
    记录谁在什么时候查询了什么问题,系统返回了哪些来源。

尤其要注意:权限过滤必须在检索阶段完成,而不是等大模型生成答案后再过滤。否则敏感内容可能已经进入 Prompt,存在泄露风险。


十、提升回答质量的几个关键点

1. 不要只依赖大模型

企业知识库的核心不是“模型越大越好”,而是“数据质量越高越好”。如果文档混乱、过期、重复、权限错误,再强的模型也很难给出可靠答案。


2. 做好文档清洗

常见清洗工作包括:

  • 删除页眉页脚;
  • 去除重复目录;
  • 去除无意义空白;
  • 修复 OCR 错误;
  • 统一标题层级;
  • 标准化表格内容;
  • 删除过期版本;
  • 补充文档元数据。

3. 维护高质量 Prompt

Prompt 不是一次写完就结束,而是需要随着业务持续优化。例如企业可以针对不同场景准备不同 Prompt:

  • 制度问答 Prompt;
  • 研发助手 Prompt;
  • 售后客服 Prompt;
  • 销售方案 Prompt;
  • 运维排障 Prompt。

4. 增加引用来源

AI 回答企业问题时,最好始终附带来源。例如:

参考来源:
1. 《差旅报销管理制度》v2024.03,财务部
2. 《费用审批流程说明》,行政部

引用来源可以提高可信度,也方便用户进一步查看原文。


5. 建立反馈机制

用户可以对回答进行反馈:

  • 有帮助;
  • 答案不准确;
  • 文档过期;
  • 没有找到想要的内容;
  • 权限不足。

这些反馈可以帮助管理员持续优化知识库内容和检索策略。


十一、上线部署建议

企业首次搭建 AI 知识库时,不建议一开始就追求“大而全”。更推荐采用小步快跑的方式:

第一阶段:内部试点

选择一个资料相对规范、需求明确的部门,例如研发部或客服部。先接入 100~500 篇核心文档,验证问答质量。

第二阶段:扩展场景

接入更多文档类型和数据源,例如工单系统、代码仓库、接口平台、项目管理系统。

第三阶段:权限治理

完善组织架构同步、部门权限、文档密级、审计日志和敏感信息脱敏。

第四阶段:AI 编程集成

将知识库能力接入 IDE、代码平台、CI/CD 系统,让开发者在编码过程中直接调用企业知识。

例如:

  • 在 VS Code 插件中提问内部规范;
  • 在 GitLab Merge Request 中自动检查代码是否符合规范;
  • 根据接口文档生成单元测试;
  • 根据故障案例生成排障建议;
  • 根据数据库表结构生成 DAO 和 DTO 草稿。

十二、常见问题与解决方案

1. AI 回答不准确怎么办?

优先检查以下问题:

  • 检索到的文档是否相关;
  • 文档是否过期;
  • Chunk 是否切得太碎;
  • Prompt 是否约束不够;
  • 是否缺少 Rerank;
  • 是否需要混合检索;
  • 用户问题是否过于模糊。

很多时候,问题不是大模型能力不够,而是检索阶段没有找到正确上下文。


2. 文档很多,向量库会不会很慢?

向量数据库通常可以支持较大规模数据,但需要合理配置索引。对于百万级 Chunk,可以考虑:

  • 使用 Milvus、Qdrant 等专业向量数据库;
  • 按部门或知识库分 Collection;
  • 对历史归档文档降低检索优先级;
  • 设置合理的 Top K;
  • 增加缓存;
  • 对热点问题预生成答案。

3. 是否必须私有化部署?

不一定。是否私有化取决于企业合规要求和数据敏感程度。

如果知识库包含客户数据、合同、源代码、财务、人事资料,建议优先私有化部署。如果只是公开产品文档或非敏感内容,可以使用云端大模型 API,以降低运维成本。


十三、总结

AI 编程时代,企业知识库不再只是一个“文档仓库”,而是企业智能化基础设施的一部分。它可以帮助员工快速获取制度流程,帮助客服总结解决方案,帮助销售生成方案材料,更重要的是,它可以成为研发团队的企业上下文,让 AI 编程助手真正理解企业内部架构、规范、接口和历史经验。

搭建企业 AI 知识库时,技术重点并不只是调用大模型,而是围绕以下几个方面建立完整体系:

  • 文档采集与持续同步;
  • 文档解析与结构化切分;
  • 向量化与混合检索;
  • RAG 问答与来源引用;
  • 权限控制与审计日志;
  • Prompt 模板与场景优化;
  • 用户反馈与知识治理;
  • AI 编程工具集成。

如果企业刚开始建设,建议先选择一个业务价值明显的场景试点,例如研发知识库、客服知识库或制度知识库。通过小范围验证,逐步沉淀配置、流程和最佳实践,再扩展到全公司范围。

最终,一个高质量的企业 AI 知识库,不只是“让员工少翻文档”,而是让企业知识真正流动起来,让经验可以复用,让新人更快成长,让研发更高效,让组织具备持续进化的智能能力。

目录结构
全文