Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42a1bfe4d7 | |||
| aace9ce292 | |||
| e0fc5381d8 | |||
| 4ab7941fe0 | |||
| f7260da6d9 | |||
| 092f7230c1 | |||
| 03586a9b0d | |||
| f2df0d894a | |||
| 67b1959d80 | |||
| 6de6cc201e | |||
| a532b642f4 | |||
| c45462354e | |||
| eb9f590571 | |||
| 0720c6dfcd | |||
| 2b17e44120 | |||
| a8f99adaca | |||
| df7ebf3d4f | |||
| e18e4f22db | |||
| c262aec6bd | |||
| 47437044cb | |||
| 5edfecef30 | |||
| f4b1f40173 | |||
| 0bf2799acf | |||
| 0fe60a7963 | |||
| a66ba3c48e | |||
| a165d55822 | |||
| 6f5548ee61 | |||
| 331595cc57 | |||
| cb34fde995 | |||
| 123693c9a0 | |||
| a897f0c6de | |||
| adce2a3809 | |||
| 7875e2cbcc | |||
| 95fbc820b9 | |||
| 54f19a20fc | |||
| bc124c5513 | |||
| 1c773924db | |||
| 60b0f11ca2 | |||
| 21fdc16259 | |||
| 64ba7efcdc | |||
| 9a09e9f79f | |||
| 9ac53011e0 | |||
| f171282a0c | |||
| 626ff1e632 | |||
| 5189d4368f | |||
| 5f182075aa | |||
| b1ef410638 | |||
| 7b040ae248 | |||
| 7023b54246 | |||
| aee6aa3c04 | |||
| 786c4d05f6 | |||
| a8db51e844 | |||
| 545fbc732b | |||
| 56cb36dfc9 | |||
| a6c5988408 | |||
| c4cf09a28f | |||
| 75fde3598b | |||
| aba6475c5a | |||
| ae19725d72 | |||
| 97a486e631 | |||
| 728ee06c5a | |||
| a4dd385368 | |||
| 24c808d66d | |||
| ced3199550 | |||
| 680e24c516 | |||
| 6663ee8976 | |||
| c4088fe963 | |||
| e7628809ad | |||
| 73565b26e4 | |||
| 0a5f335981 | |||
| 2901bd9eaf | |||
| 453b3ca55c | |||
| 03c4eb1af1 | |||
| 480a1f7fdc | |||
| cdc9d84a1e | |||
| 50f35bb0c9 | |||
| 4a8c79e83d | |||
| f0afd1a4bb | |||
| de34c3938c | |||
| eb572eff27 | |||
| 2706cf9d5a | |||
| 5fa4752d6e | |||
| aff1793c4e | |||
| 0db159ac89 | |||
| 131d6ef1d1 | |||
| e9ccd7db35 | |||
| 4020b603b1 | |||
| 3ee1ba529f | |||
| 576a2ae737 | |||
| 9b47e1a6e1 | |||
| 20510a937b | |||
| a7c79df339 | |||
| 327bba75d5 | |||
| d1242d2080 | |||
| 0f09551f5d | |||
| 8a5facb5b6 | |||
| 0f7c900c1e | |||
| b008ad9766 | |||
| 56459c164e | |||
| 07a3b2a147 | |||
| b4c571cddb | |||
| 7068b058e8 | |||
| 33b2281b7b | |||
| 1704b61609 | |||
| afccaf6eb5 | |||
| b052d373f1 | |||
| 7462244f01 | |||
| 2b64aca26b |
@@ -0,0 +1,3 @@
|
||||
[submodule "webapp"]
|
||||
path = webapp
|
||||
url = https://git.97id.com/ly/webapp.git
|
||||
+91
-22
@@ -2,35 +2,83 @@
|
||||
# LLAMA_CLOUD_API_KEY=
|
||||
SQL_DATABASE_URL=mysql+pymysql://zjinfo1:Dy2Bcr53Hm5xRkba@110.42.234.166:3306/zjinfo1
|
||||
#SQL_DATABASE_URL=mysql+pymysql://zjinfo2:GSKcziSdBixDXwcd@110.42.234.166:3306/zjinfo2
|
||||
SQLITE_DATABASE_URL=sqlite:///./source.db
|
||||
|
||||
DASHSCOPE_API_KEY=sk-02c8540e86d84b7ca0e6f4f51bac6e60
|
||||
# The provider for the AI models to use.
|
||||
MODEL_PROVIDER=dashscope
|
||||
# The name of LLM model to use.
|
||||
MODEL=qwen-max
|
||||
# The number of similar embeddings to return when retrieving documents.
|
||||
TOP_K=10
|
||||
#--------------------------
|
||||
# 是否启用混合检索
|
||||
HYBRID_ENABLED = true
|
||||
# 混合检索阈值
|
||||
HYBRID_ALPHA = 0.6
|
||||
# 是否启用检索重排功能
|
||||
ENABLE_RERANK=true
|
||||
# Name of the embedding model to use.
|
||||
EMBEDDING_MODEL=text-embedding-v2
|
||||
RERANK_ENABLED=true
|
||||
|
||||
# Dimension of the embedding model to use.
|
||||
#---------- rerank- Xinference ----------------
|
||||
#RERANK_PROVIDER=xinference
|
||||
#RERANK_MODEL=bge-reranker-v2-m3
|
||||
#RERANK_BASE_URL=http://10.1.16.39:9995
|
||||
#RERANK_TOP_N=5
|
||||
#RERANK_THRESHOLD=0.3
|
||||
|
||||
|
||||
#---------- rerank- ollama ----------------
|
||||
RERANK_PROVIDER=ollama
|
||||
RERANK_MODEL= /models/bge-reranker-base
|
||||
RERANK_TOP_N=5
|
||||
RERANK_THRESHOLD=0.3
|
||||
|
||||
#---------- model - Xinference ----------------
|
||||
#MODEL_PROVIDER=xinference
|
||||
#OPENAI_API_KEY=xinference
|
||||
#BASE_URL=http://172.20.0.145:9995
|
||||
#MODEL=Qwen2-72B-Instruct-GPTQ-Int8
|
||||
## Temperature for sampling from the model.
|
||||
#LLM_TEMPERATURE=0.1
|
||||
|
||||
#---------- model - dashscope ----------------
|
||||
MODEL_PROVIDER=dashscope
|
||||
DASHSCOPE_API_KEY=sk-221d2d202e104618a56002ce2e7dc0d0
|
||||
MODEL=qwen2-math-72b-instruct
|
||||
|
||||
# #---------- model - openai ----------------
|
||||
MODEL_PROVIDER=openai
|
||||
OPENAI_API_KEY=
|
||||
BASE_URL=https://api.siliconflow.cn/v1
|
||||
MODEL=alibaba/Qwen1.5-110B-Chat
|
||||
LLM_TEMPERATURE=0.1
|
||||
CONTEXT_WINDOW = 8192
|
||||
IS_CHAT_MODEL = true
|
||||
IS_FUN_CALL_MODEL = false
|
||||
|
||||
#---------- embedding - openai ----------------
|
||||
EMBEDDING_PROVIDER=openai
|
||||
OPENAI_API_KEY=
|
||||
EMBEDDING_MODEL=BAAI/bge-m3
|
||||
EMBEDDING_BASE_URL=https://api.siliconflow.cn/v1
|
||||
EMBEDDING_DIM=1024
|
||||
|
||||
RERANK_PROVIDER=openai
|
||||
OPENAI_API_KEY=sk-hhoqttvhibirwheyponjifsqwssgxotoqlcjufkidytwxngi
|
||||
RERANK_MODEL=BAAI/bge-reranker-v2-m3
|
||||
RERANK_BASE_URL=https://api.siliconflow.cn/v1
|
||||
RERANK_TOP_N=5
|
||||
|
||||
|
||||
#---------- embedding - Xinference ----------------
|
||||
#EMBEDDING_PROVIDER=xinference
|
||||
#EMBEDDING_MODEL=bge-m3
|
||||
#EMBEDDING_BASE_URL=http://10.1.16.39:9995
|
||||
#EMBEDDING_DIM=1024
|
||||
|
||||
---------- embedding - dashscope ----------------
|
||||
EMBEDDING_PROVIDER=dashscope
|
||||
EMBEDDING_MODEL=text-embedding-v1
|
||||
|
||||
|
||||
# The questions to help users get started (multi-line).
|
||||
CONVERSATION_STARTERS=本工程指什么?\n总算表有哪些费用?\n项目划分哪些内容构成?\n其他费用表有哪些内容?
|
||||
|
||||
# The OpenAI API key to use.
|
||||
# OPENAI_API_KEY=
|
||||
|
||||
# Temperature for sampling from the model.
|
||||
# LLM_TEMPERATURE=
|
||||
|
||||
# Maximum number of tokens to generate.
|
||||
# LLM_MAX_TOKENS=
|
||||
|
||||
# The number of similar embeddings to return when retrieving documents.
|
||||
TOP_K=5
|
||||
|
||||
# The time in milliseconds to wait for the stream to return a response.
|
||||
STREAM_TIMEOUT=60000
|
||||
|
||||
@@ -39,6 +87,17 @@ VECTOR_STORE_TYPE=chroma
|
||||
# The name of the collection in your vector database
|
||||
VECTOR_STORE_COLLECTION=default
|
||||
|
||||
#模型查询方式:graph、rag
|
||||
LLM_QUERY_WAY = graph
|
||||
|
||||
#属性图存储类型:本地属性图库(默认),neo4j
|
||||
GRAPH_STORE_TYPE =
|
||||
|
||||
#---------- neo4j - PropertyGraph ----------------
|
||||
NEO4J_USERNAME = neo4j
|
||||
NEO4J_PASSWORD = neo4j
|
||||
NEO4J_URL = bolt://10.1.6.40:7687
|
||||
|
||||
# The API endpoint for your vector database
|
||||
# VECTOR_STORE_HOST=
|
||||
|
||||
@@ -50,7 +109,7 @@ VECTOR_STORE_COLLECTION=default
|
||||
# Otherwise, use VECTOR_STORE__HOST and VECTOR_STORE__PORT config above
|
||||
VECTOR_STORE_PATH=./storage_vector
|
||||
BM_RETRIEVER_PATH =./storage_bm
|
||||
|
||||
GRAPH_STORAGE_PATH =./storage_graph
|
||||
|
||||
|
||||
PHOENIX_API_KEY=123456
|
||||
@@ -79,3 +138,13 @@ SYSTEM_PROMPT="You are a weather forecast agent. You help users to get the weath
|
||||
- You can install any pip package (if it exists) by running a cell with pip install.
|
||||
"
|
||||
|
||||
PRJTOJSON_URL = 'http://10.1.6.60:8092'
|
||||
PROJECT_TITLE = "您好,我是博微工程理解小助手,您可以问我有关[线路工程]工程数据的相关问题!"
|
||||
|
||||
CHAT_UPLOAD_FILECACHE = "./output/uploaded"
|
||||
|
||||
JIEBA_DATA=./nltk_data
|
||||
NLTK_DATA=./nltk_data
|
||||
|
||||
#IO流默认的编码格式
|
||||
PYTHONUTF8=1
|
||||
+24
-13
@@ -1,7 +1,13 @@
|
||||
JIEBA_DATA=./nltk_data
|
||||
NLTK_DATA=./nltk_data
|
||||
SQLITE_DATABASE_URL=sqlite:///./source.db
|
||||
DATA_SOURCE_CACHE=./restapi
|
||||
|
||||
# The Llama Cloud API key.
|
||||
# LLAMA_CLOUD_API_KEY=
|
||||
SQL_DATABASE_URL=mysql+pymysql://zjinfo1:Dy2Bcr53Hm5xRkba@110.42.234.166:3306/zjinfo1
|
||||
#SQL_DATABASE_URL=mysql+pymysql://zjinfo2:GSKcziSdBixDXwcd@110.42.234.166:3306/zjinfo2
|
||||
SQLITE_DATABASE_URL=sqlite:///./source.db
|
||||
|
||||
# The number of similar embeddings to return when retrieving documents.
|
||||
TOP_K=10
|
||||
@@ -13,27 +19,28 @@ HYBRID_ALPHA = 0.6
|
||||
#--------------------------
|
||||
# 是否启用检索重排功能
|
||||
RERANK_ENABLED=true
|
||||
# Rerank model
|
||||
|
||||
#---------- rerank- Xinference ----------------
|
||||
RERANK_PROVIDER=xinference
|
||||
RERANK_MODEL=bge-reranker-v2-m3
|
||||
RERANK_BASE_URL=http://10.1.16.39:9995
|
||||
RERANK_TOP_N=5
|
||||
RERANK_THRESHOLD=0.3
|
||||
#---------- Xinference ----------------
|
||||
# The provider for the AI models to use.
|
||||
MODEL_PROVIDER=xinference
|
||||
# The OpenAI API key to use.
|
||||
OPENAI_API_KEY=xinference
|
||||
|
||||
#---------- model - Xinference ----------------
|
||||
MODEL_PROVIDER=xinference # The provider for the AI models to use.
|
||||
OPENAI_API_KEY=xinference # The OpenAI API key to use.
|
||||
BASE_URL=http://10.1.0.142:9995
|
||||
MODEL=Qwen2-72B-Instruct-GPTQ-Int8
|
||||
# Temperature for sampling from the model.
|
||||
LLM_TEMPERATURE=0.1
|
||||
# Maximum number of tokens to generate.
|
||||
#LLM_MAX_TOKENS=
|
||||
# Name of the embedding model to use.
|
||||
LLM_TEMPERATURE=0.1 # Temperature for sampling from the model.
|
||||
#LLM_MAX_TOKENS= # Maximum number of tokens to generate.
|
||||
|
||||
|
||||
#---------- embedding - Xinference ----------------
|
||||
EMBEDDING_PROVIDER=xinference
|
||||
EMBEDDING_MODEL=bge-m3
|
||||
EMBEDDING_BASE_URL=http://10.1.16.39:9995
|
||||
# Dimension of the embedding model to use.
|
||||
EMBEDDING_DIM=1024
|
||||
EMBEDDING_DIM=1024 # Dimension of the embedding model to use.
|
||||
|
||||
##---------- OpenAI ----------------
|
||||
## The provider for the AI models to use.
|
||||
@@ -110,3 +117,7 @@ SYSTEM_PROMPT="You are a weather forecast agent. You help users to get the weath
|
||||
- You can install any pip package (if it exists) by running a cell with pip install.
|
||||
"
|
||||
|
||||
|
||||
PRJTOJSON_URL = 'http://10.1.6.60:8092'
|
||||
PROJECT_TITLE = "您好,我是博微工程理解小助手,您可以问我有关[线路工程]工程数据的相关问题!"
|
||||
CHAT_UPLOAD_FILECACHE = "./output/uploaded"
|
||||
@@ -1,61 +0,0 @@
|
||||
from llama_index.embeddings.openai import OpenAIEmbedding
|
||||
from llama_index.core.settings import Settings
|
||||
from typing import Dict
|
||||
import os
|
||||
|
||||
DEFAULT_MODEL = "gpt-3.5-turbo"
|
||||
DEFAULT_EMBEDDING_MODEL = "text-embedding-3-large"
|
||||
|
||||
class TSIEmbedding(OpenAIEmbedding):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._query_engine = self._text_engine = self.model_name
|
||||
|
||||
def llm_config_from_env() -> Dict:
|
||||
from llama_index.core.constants import DEFAULT_TEMPERATURE
|
||||
|
||||
model = os.getenv("MODEL", DEFAULT_MODEL)
|
||||
temperature = os.getenv("LLM_TEMPERATURE", DEFAULT_TEMPERATURE)
|
||||
max_tokens = os.getenv("LLM_MAX_TOKENS")
|
||||
api_key = os.getenv("T_SYSTEMS_LLMHUB_API_KEY")
|
||||
api_base = os.getenv("T_SYSTEMS_LLMHUB_BASE_URL")
|
||||
|
||||
config = {
|
||||
"model": model,
|
||||
"api_key": api_key,
|
||||
"api_base": api_base,
|
||||
"temperature": float(temperature),
|
||||
"max_tokens": int(max_tokens) if max_tokens is not None else None,
|
||||
}
|
||||
return config
|
||||
|
||||
|
||||
def embedding_config_from_env() -> Dict:
|
||||
from llama_index.core.constants import DEFAULT_EMBEDDING_DIM
|
||||
|
||||
model = os.getenv("EMBEDDING_MODEL", DEFAULT_EMBEDDING_MODEL)
|
||||
dimension = os.getenv("EMBEDDING_DIM", DEFAULT_EMBEDDING_DIM)
|
||||
api_key = os.getenv("T_SYSTEMS_LLMHUB_API_KEY")
|
||||
api_base = os.getenv("T_SYSTEMS_LLMHUB_BASE_URL")
|
||||
|
||||
config = {
|
||||
"model_name": model,
|
||||
"dimension": int(dimension) if dimension is not None else None,
|
||||
"api_key": api_key,
|
||||
"api_base": api_base,
|
||||
}
|
||||
return config
|
||||
|
||||
def init_llmhub():
|
||||
from llama_index.llms.openai_like import OpenAILike
|
||||
|
||||
llm_configs = llm_config_from_env()
|
||||
embedding_configs = embedding_config_from_env()
|
||||
|
||||
Settings.embed_model = TSIEmbedding(**embedding_configs)
|
||||
Settings.llm = OpenAILike(
|
||||
**llm_configs,
|
||||
is_chat_model=True,
|
||||
is_function_calling_model=False,
|
||||
context_window=4096,
|
||||
)
|
||||
@@ -1,20 +0,0 @@
|
||||
import os
|
||||
|
||||
import llama_index.core
|
||||
|
||||
def init_observability():
|
||||
|
||||
PHOENIX_API_KEY = os.getenv("PHOENIX_API_KEY")
|
||||
if not PHOENIX_API_KEY:
|
||||
raise ValueError("PHOENIX_API_KEY environment variable is not set")
|
||||
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"api_key={PHOENIX_API_KEY}"
|
||||
PHOENIX_URL = os.getenv("PHOENIX_URL")
|
||||
llama_index.core.set_global_handler(
|
||||
"arize_phoenix", endpoint=PHOENIX_URL, eval_params={}
|
||||
)
|
||||
|
||||
#debugHandle=[]
|
||||
# llama_debug = LlamaDebugHandler(print_trace_on_end=True)
|
||||
# debugHandle.append(llama_debug)
|
||||
# callback_manager = CallbackManager(debugHandle)
|
||||
# settings.Settings.callback_manager = callback_manager
|
||||
@@ -1,235 +0,0 @@
|
||||
import os
|
||||
from typing import Dict
|
||||
|
||||
from llama_index.core.constants import DEFAULT_TEMPERATURE
|
||||
from llama_index.core.settings import Settings
|
||||
from llama_index.llms.xinference import Xinference
|
||||
from llama_index.llms.xinference.base import DEFAULT_XINFERENCE_TEMP
|
||||
|
||||
from app.xinference.base import XinferenceEmbedding, XinferenceRerank
|
||||
|
||||
|
||||
def get_node_postprocessors():
|
||||
rerank_enabled = os.getenv("RERANK_ENABLED").title()
|
||||
if rerank_enabled is None or rerank_enabled == 'False':
|
||||
return []
|
||||
|
||||
rerank_model = os.getenv("RERANK_MODEL")
|
||||
rerank_url = os.getenv("RERANK_BASE_URL")
|
||||
rerank_top_n = os.getenv("RERANK_TOP_N")
|
||||
rerank_threshold = os.getenv("RERANK_THRESHOLD")
|
||||
postprocess = None
|
||||
if rerank_model is not None:
|
||||
postprocess = [XinferenceRerank(rerank_model, rerank_url, top_n=rerank_top_n, threshold=rerank_threshold)]
|
||||
return postprocess
|
||||
|
||||
def init_settings():
|
||||
model_provider = os.getenv("MODEL_PROVIDER")
|
||||
match model_provider:
|
||||
case "openai":
|
||||
init_openai()
|
||||
case "dashscope":
|
||||
init_dashscope()
|
||||
case "groq":
|
||||
init_groq()
|
||||
case "ollama":
|
||||
init_ollama()
|
||||
case "anthropic":
|
||||
init_anthropic()
|
||||
case "gemini":
|
||||
init_gemini()
|
||||
case "mistral":
|
||||
init_mistral()
|
||||
case "azure-openai":
|
||||
init_azure_openai()
|
||||
case "t-systems":
|
||||
from .llmhub import init_llmhub
|
||||
init_llmhub()
|
||||
case "xinference":
|
||||
init_xinference()
|
||||
case _:
|
||||
raise ValueError(f"Invalid model provider: {model_provider}")
|
||||
|
||||
Settings.chunk_size = int(os.getenv("CHUNK_SIZE", "1024"))
|
||||
Settings.chunk_overlap = int(os.getenv("CHUNK_OVERLAP", "20"))
|
||||
|
||||
|
||||
def init_ollama():
|
||||
# from llama_index.embeddings.ollama import OllamaEmbedding
|
||||
# from llama_index.llms.ollama.base import DEFAULT_REQUEST_TIMEOUT, Ollama
|
||||
#
|
||||
# base_url = os.getenv("OLLAMA_BASE_URL") or "http://127.0.0.1:11434"
|
||||
# request_timeout = float(
|
||||
# os.getenv("OLLAMA_REQUEST_TIMEOUT", DEFAULT_REQUEST_TIMEOUT)
|
||||
# )
|
||||
# Settings.embed_model = OllamaEmbedding(
|
||||
# base_url=base_url,
|
||||
# model_name=os.getenv("EMBEDDING_MODEL"),
|
||||
# )
|
||||
# Settings.llm = Ollama(
|
||||
# base_url=base_url, model=os.getenv("MODEL"), request_timeout=request_timeout
|
||||
# )
|
||||
pass
|
||||
|
||||
def init_xinference():
|
||||
base_url = os.getenv("BASE_URL")
|
||||
model = os.getenv("MODEL")
|
||||
max_tokens = int(os.getenv("LLM_MAX_TOKENS")) if os.getenv("LLM_MAX_TOKENS") is not None else None
|
||||
temperature = float(os.getenv("LLM_TEMPERATURE", DEFAULT_XINFERENCE_TEMP))
|
||||
|
||||
Settings.llm = Xinference(model, base_url, temperature, max_tokens)
|
||||
|
||||
embedding_base_url = os.getenv("EMBEDDING_BASE_URL")
|
||||
embedding_base_url = embedding_base_url if embedding_base_url != None and embedding_base_url != "" else base_url
|
||||
|
||||
embed_model_name = os.getenv("EMBEDDING_MODEL")
|
||||
dimensions = os.getenv("EMBEDDING_DIM")
|
||||
dimensions = int(dimensions) if dimensions is not None else None
|
||||
Settings.embed_model = XinferenceEmbedding(embed_model_name, embedding_base_url, dimensions=dimensions)
|
||||
|
||||
def init_openai():
|
||||
from llama_index.core.constants import DEFAULT_TEMPERATURE
|
||||
from llama_index.embeddings.openai import OpenAIEmbedding
|
||||
from llama_index.llms.openai import OpenAI
|
||||
|
||||
max_tokens = os.getenv("LLM_MAX_TOKENS")
|
||||
config = {
|
||||
"model": os.getenv("MODEL"),
|
||||
"temperature": float(os.getenv("LLM_TEMPERATURE", DEFAULT_TEMPERATURE)),
|
||||
"max_tokens": int(max_tokens) if max_tokens is not None else None,
|
||||
}
|
||||
Settings.llm = OpenAI(**config)
|
||||
|
||||
dimensions = os.getenv("EMBEDDING_DIM")
|
||||
config = {
|
||||
"model": os.getenv("EMBEDDING_MODEL"),
|
||||
"dimensions": int(dimensions) if dimensions is not None else None,
|
||||
}
|
||||
Settings.embed_model = OpenAIEmbedding(**config)
|
||||
|
||||
def init_dashscope():
|
||||
from llama_index.llms.dashscope import DashScope,DashScopeGenerationModels
|
||||
from llama_index.embeddings.dashscope import DashScopeEmbedding,DashScopeBatchTextEmbeddingModels,DashScopeTextEmbeddingType,DashScopeTextEmbeddingModels
|
||||
|
||||
max_tokens = os.getenv("LLM_MAX_TOKENS")
|
||||
config = {
|
||||
"model": os.getenv("MODEL"),
|
||||
"temperature": float(os.getenv("LLM_TEMPERATURE", DEFAULT_TEMPERATURE)),
|
||||
"max_tokens": int(max_tokens) if max_tokens is not None else None,
|
||||
}
|
||||
Settings.llm = llm = DashScope(model_name=DashScopeGenerationModels.QWEN_MAX)
|
||||
|
||||
dimensions = os.getenv("EMBEDDING_DIM")
|
||||
config = {
|
||||
"model": os.getenv("EMBEDDING_MODEL"),
|
||||
"dimensions": int(dimensions) if dimensions is not None else None,
|
||||
}
|
||||
Settings.embed_model = DashScopeEmbedding(model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2,
|
||||
text_type=DashScopeTextEmbeddingType.TEXT_TYPE_QUERY)
|
||||
|
||||
|
||||
def init_azure_openai():
|
||||
# from llama_index.core.constants import DEFAULT_TEMPERATURE
|
||||
# from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding
|
||||
# from llama_index.llms.azure_openai import AzureOpenAI
|
||||
#
|
||||
# llm_deployment = os.environ["AZURE_OPENAI_LLM_DEPLOYMENT"]
|
||||
# embedding_deployment = os.environ["AZURE_OPENAI_EMBEDDING_DEPLOYMENT"]
|
||||
# max_tokens = os.getenv("LLM_MAX_TOKENS")
|
||||
# temperature = os.getenv("LLM_TEMPERATURE", DEFAULT_TEMPERATURE)
|
||||
# dimensions = os.getenv("EMBEDDING_DIM")
|
||||
#
|
||||
# azure_config = {
|
||||
# "api_key": os.environ["AZURE_OPENAI_KEY"],
|
||||
# "azure_endpoint": os.environ["AZURE_OPENAI_ENDPOINT"],
|
||||
# "api_version": os.getenv("AZURE_OPENAI_API_VERSION")
|
||||
# or os.getenv("OPENAI_API_VERSION"),
|
||||
# }
|
||||
#
|
||||
# Settings.llm = AzureOpenAI(
|
||||
# model=os.getenv("MODEL"),
|
||||
# max_tokens=int(max_tokens) if max_tokens is not None else None,
|
||||
# temperature=float(temperature),
|
||||
# deployment_name=llm_deployment,
|
||||
# **azure_config,
|
||||
# )
|
||||
#
|
||||
# Settings.embed_model = AzureOpenAIEmbedding(
|
||||
# model=os.getenv("EMBEDDING_MODEL"),
|
||||
# dimensions=int(dimensions) if dimensions is not None else None,
|
||||
# deployment_name=embedding_deployment,
|
||||
# **azure_config,
|
||||
# )
|
||||
pass
|
||||
|
||||
|
||||
def init_fastembed():
|
||||
"""
|
||||
Use Qdrant Fastembed as the local embedding provider.
|
||||
"""
|
||||
# from llama_index.embeddings.fastembed import FastEmbedEmbedding
|
||||
#
|
||||
# embed_model_map: Dict[str, str] = {
|
||||
# # Small and multilingual
|
||||
# "all-MiniLM-L6-v2": "sentence-transformers/all-MiniLM-L6-v2",
|
||||
# # Large and multilingual
|
||||
# "paraphrase-multilingual-mpnet-base-v2": "sentence-transformers/paraphrase-multilingual-mpnet-base-v2", # noqa: E501
|
||||
# }
|
||||
#
|
||||
# # This will download the model automatically if it is not already downloaded
|
||||
# Settings.embed_model = FastEmbedEmbedding(
|
||||
# model_name=embed_model_map[os.getenv("EMBEDDING_MODEL")]
|
||||
# )
|
||||
pass
|
||||
|
||||
|
||||
def init_groq():
|
||||
# from llama_index.llms.groq import Groq
|
||||
#
|
||||
# model_map: Dict[str, str] = {
|
||||
# "llama3-8b": "llama3-8b-8192",
|
||||
# "llama3-70b": "llama3-70b-8192",
|
||||
# "mixtral-8x7b": "mixtral-8x7b-32768",
|
||||
# }
|
||||
#
|
||||
# Settings.llm = Groq(model=model_map[os.getenv("MODEL")])
|
||||
# # Groq does not provide embeddings, so we use FastEmbed instead
|
||||
# init_fastembed()
|
||||
pass
|
||||
|
||||
|
||||
def init_anthropic():
|
||||
# from llama_index.llms.anthropic import Anthropic
|
||||
#
|
||||
# model_map: Dict[str, str] = {
|
||||
# "claude-3-opus": "claude-3-opus-20240229",
|
||||
# "claude-3-sonnet": "claude-3-sonnet-20240229",
|
||||
# "claude-3-haiku": "claude-3-haiku-20240307",
|
||||
# "claude-2.1": "claude-2.1",
|
||||
# "claude-instant-1.2": "claude-instant-1.2",
|
||||
# }
|
||||
#
|
||||
# Settings.llm = Anthropic(model=model_map[os.getenv("MODEL")])
|
||||
# # Anthropic does not provide embeddings, so we use FastEmbed instead
|
||||
# init_fastembed()
|
||||
pass
|
||||
|
||||
|
||||
def init_gemini():
|
||||
# from llama_index.embeddings.gemini import GeminiEmbedding
|
||||
# from llama_index.llms.gemini import Gemini
|
||||
#
|
||||
# model_name = f"models/{os.getenv('MODEL')}"
|
||||
# embed_model_name = f"models/{os.getenv('EMBEDDING_MODEL')}"
|
||||
#
|
||||
# Settings.llm = Gemini(model=model_name)
|
||||
# Settings.embed_model = GeminiEmbedding(model_name=embed_model_name)
|
||||
pass
|
||||
|
||||
def init_mistral():
|
||||
# from llama_index.embeddings.mistralai import MistralAIEmbedding
|
||||
# from llama_index.llms.mistralai import MistralAI
|
||||
#
|
||||
# Settings.llm = MistralAI(model=os.getenv("MODEL"))
|
||||
# Settings.embed_model = MistralAIEmbedding(model_name=os.getenv("EMBEDDING_MODEL"))
|
||||
pass
|
||||
@@ -1,150 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request, status
|
||||
from llama_index.core.chat_engine.types import BaseChatEngine, NodeWithScore
|
||||
from llama_index.core.llms import MessageRole
|
||||
from llama_index.core.vector_stores.types import MetadataFilter, MetadataFilters
|
||||
|
||||
from app.api.routers.events import EventCallbackHandler
|
||||
from app.api.routers.models import (
|
||||
ChatConfig,
|
||||
ChatData,
|
||||
Message,
|
||||
Result,
|
||||
SourceNodes,
|
||||
)
|
||||
from app.api.routers.vercel_response import VercelStreamResponse
|
||||
from app.api.services.llama_cloud import LLamaCloudFileService
|
||||
from app.engine import get_chat_engine
|
||||
|
||||
chat_router = r = APIRouter()
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
|
||||
def process_response_nodes(
|
||||
nodes: List[NodeWithScore],
|
||||
background_tasks: BackgroundTasks,
|
||||
):
|
||||
"""
|
||||
Start background tasks on the source nodes if needed.
|
||||
"""
|
||||
files_to_download = SourceNodes.get_download_files(nodes)
|
||||
for file in files_to_download:
|
||||
background_tasks.add_task(
|
||||
LLamaCloudFileService.download_llamacloud_pipeline_file, file
|
||||
)
|
||||
|
||||
|
||||
# streaming endpoint - delete if not needed
|
||||
@r.post("")
|
||||
async def chat(
|
||||
request: Request,
|
||||
data: ChatData,
|
||||
background_tasks: BackgroundTasks,
|
||||
chat_engine: BaseChatEngine = Depends(get_chat_engine),
|
||||
):
|
||||
try:
|
||||
last_message_content = data.get_last_message_content()
|
||||
# 由于基于历史消息的提示词没有调整好,所以暂时屏蔽历史消息
|
||||
data.messages.clear()
|
||||
messages = data.get_history_messages()
|
||||
|
||||
doc_ids = data.get_chat_document_ids()
|
||||
filters = generate_filters(doc_ids)
|
||||
params = data.data or {}
|
||||
logger.info("Creating chat engine with filters", filters.dict())
|
||||
chat_engine = get_chat_engine(filters=filters, params=params)
|
||||
|
||||
event_handler = EventCallbackHandler()
|
||||
chat_engine.callback_manager.handlers.append(event_handler) # type: ignore
|
||||
|
||||
response = await chat_engine.astream_chat(last_message_content, messages)
|
||||
process_response_nodes(response.source_nodes, background_tasks)
|
||||
|
||||
return VercelStreamResponse(request, event_handler, response, data)
|
||||
except Exception as e:
|
||||
logger.exception("Error in chat engine", exc_info=True)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Error in chat engine: {e}",
|
||||
) from e
|
||||
|
||||
|
||||
def generate_filters(doc_ids):
|
||||
if len(doc_ids) > 0:
|
||||
filters = MetadataFilters(
|
||||
filters=[
|
||||
MetadataFilter(
|
||||
key="private",
|
||||
value=["true"],
|
||||
operator="nin", # type: ignore
|
||||
),
|
||||
MetadataFilter(
|
||||
key="doc_id",
|
||||
value=doc_ids,
|
||||
operator="in", # type: ignore
|
||||
),
|
||||
],
|
||||
condition="or", # type: ignore
|
||||
)
|
||||
else:
|
||||
filters = MetadataFilters(
|
||||
# Use the "NIN" - "not in" operator to include all public documents (don't have the private key set)
|
||||
filters=[
|
||||
MetadataFilter(
|
||||
key="private",
|
||||
value=["true"],
|
||||
operator="nin", # type: ignore
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
return filters
|
||||
|
||||
|
||||
# non-streaming endpoint - delete if not needed
|
||||
@r.post("/request")
|
||||
async def chat_request(
|
||||
data: ChatData,
|
||||
chat_engine: BaseChatEngine = Depends(get_chat_engine),
|
||||
) -> Result:
|
||||
last_message_content = data.get_last_message_content()
|
||||
messages = data.get_history_messages()
|
||||
|
||||
response = await chat_engine.achat(last_message_content, messages)
|
||||
return Result(
|
||||
result=Message(role=MessageRole.ASSISTANT, content=response.response),
|
||||
nodes=SourceNodes.from_source_nodes(response.source_nodes),
|
||||
)
|
||||
|
||||
|
||||
@r.get("/config")
|
||||
async def chat_config() -> ChatConfig:
|
||||
starter_questions = None
|
||||
conversation_starters = os.getenv("CONVERSATION_STARTERS")
|
||||
if conversation_starters and conversation_starters.strip():
|
||||
starter_questions = conversation_starters.strip().split("\\n")
|
||||
return ChatConfig(starter_questions=starter_questions)
|
||||
|
||||
|
||||
@r.get("/config/llamacloud")
|
||||
async def chat_llama_cloud_config():
|
||||
projects = LLamaCloudFileService.get_all_projects_with_pipelines()
|
||||
pipeline = os.getenv("LLAMA_CLOUD_INDEX_NAME")
|
||||
project = os.getenv("LLAMA_CLOUD_PROJECT_NAME")
|
||||
pipeline_config = (
|
||||
pipeline
|
||||
and project
|
||||
and {
|
||||
"pipeline": pipeline,
|
||||
"project": project,
|
||||
}
|
||||
or None
|
||||
)
|
||||
return {
|
||||
"projects": projects,
|
||||
"pipeline": pipeline_config,
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
import json
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import AsyncGenerator, Dict, Any, List, Optional
|
||||
from llama_index.core.callbacks.base import BaseCallbackHandler
|
||||
from llama_index.core.callbacks.schema import CBEventType
|
||||
from llama_index.core.tools.types import ToolOutput
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CallbackEvent(BaseModel):
|
||||
event_type: CBEventType
|
||||
payload: Optional[Dict[str, Any]] = None
|
||||
event_id: str = ""
|
||||
|
||||
def get_retrieval_message(self) -> dict | None:
|
||||
if self.payload:
|
||||
nodes = self.payload.get("nodes")
|
||||
if nodes:
|
||||
msg = f"根据查询检索到 {len(nodes)} 源文件"
|
||||
else:
|
||||
msg = f"查询检索中: '{self.payload.get('query_str')}'"
|
||||
return {
|
||||
"type": "events",
|
||||
"data": {"title": msg},
|
||||
}
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_tool_message(self) -> dict | None:
|
||||
func_call_args = self.payload.get("function_call")
|
||||
if func_call_args is not None and "tool" in self.payload:
|
||||
tool = self.payload.get("tool")
|
||||
return {
|
||||
"type": "events",
|
||||
"data": {
|
||||
"title": f"调用工具 {tool.name} ,参数: {func_call_args}",
|
||||
},
|
||||
}
|
||||
|
||||
def _is_output_serializable(self, output: Any) -> bool:
|
||||
try:
|
||||
json.dumps(output)
|
||||
return True
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
def get_agent_tool_response(self) -> dict | None:
|
||||
response = self.payload.get("response")
|
||||
if response is not None:
|
||||
sources = response.sources
|
||||
for source in sources:
|
||||
# Return the tool response here to include the toolCall information
|
||||
if isinstance(source, ToolOutput):
|
||||
if self._is_output_serializable(source.raw_output):
|
||||
output = source.raw_output
|
||||
else:
|
||||
output = source.content
|
||||
|
||||
return {
|
||||
"type": "tools",
|
||||
"data": {
|
||||
"toolOutput": {
|
||||
"output": output,
|
||||
"isError": source.is_error,
|
||||
},
|
||||
"toolCall": {
|
||||
"id": None, # There is no tool id in the ToolOutput
|
||||
"name": source.tool_name,
|
||||
"input": source.raw_input,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def to_response(self):
|
||||
try:
|
||||
match self.event_type:
|
||||
case "retrieve":
|
||||
return self.get_retrieval_message()
|
||||
case "function_call":
|
||||
return self.get_tool_message()
|
||||
case "agent_step":
|
||||
return self.get_agent_tool_response()
|
||||
case _:
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error(f"转换回应时间时发生错误,原因: {e}")
|
||||
return None
|
||||
|
||||
|
||||
class EventCallbackHandler(BaseCallbackHandler):
|
||||
_aqueue: asyncio.Queue
|
||||
is_done: bool = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
):
|
||||
"""Initialize the base callback handler."""
|
||||
ignored_events = [
|
||||
CBEventType.CHUNKING,
|
||||
CBEventType.NODE_PARSING,
|
||||
CBEventType.EMBEDDING,
|
||||
CBEventType.LLM,
|
||||
CBEventType.TEMPLATING,
|
||||
]
|
||||
super().__init__(ignored_events, ignored_events)
|
||||
self._aqueue = asyncio.Queue()
|
||||
|
||||
def on_event_start(
|
||||
self,
|
||||
event_type: CBEventType,
|
||||
payload: Optional[Dict[str, Any]] = None,
|
||||
event_id: str = "",
|
||||
**kwargs: Any,
|
||||
) -> str:
|
||||
event = CallbackEvent(event_id=event_id, event_type=event_type, payload=payload)
|
||||
if event.to_response() is not None:
|
||||
self._aqueue.put_nowait(event)
|
||||
|
||||
def on_event_end(
|
||||
self,
|
||||
event_type: CBEventType,
|
||||
payload: Optional[Dict[str, Any]] = None,
|
||||
event_id: str = "",
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
event = CallbackEvent(event_id=event_id, event_type=event_type, payload=payload)
|
||||
if event.to_response() is not None:
|
||||
self._aqueue.put_nowait(event)
|
||||
|
||||
def start_trace(self, trace_id: Optional[str] = None) -> None:
|
||||
"""No-op."""
|
||||
|
||||
def end_trace(
|
||||
self,
|
||||
trace_id: Optional[str] = None,
|
||||
trace_map: Optional[Dict[str, List[str]]] = None,
|
||||
) -> None:
|
||||
"""No-op."""
|
||||
|
||||
async def async_event_gen(self) -> AsyncGenerator[CallbackEvent, None]:
|
||||
while not self._aqueue.empty() or not self.is_done:
|
||||
try:
|
||||
yield await asyncio.wait_for(self._aqueue.get(), timeout=0.1)
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
@@ -1,253 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Dict, List, Literal, Optional, Set
|
||||
|
||||
from llama_index.core.llms import ChatMessage, MessageRole
|
||||
from llama_index.core.schema import NodeWithScore
|
||||
from pydantic import BaseModel, Field, validator, field_validator
|
||||
from pydantic.alias_generators import to_camel
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
|
||||
class FileContent(BaseModel):
|
||||
type: Literal["text", "ref"]
|
||||
# If the file is pure text then the value is be a string
|
||||
# otherwise, it's a list of document IDs
|
||||
value: str | List[str]
|
||||
|
||||
|
||||
class File(BaseModel):
|
||||
id: str
|
||||
content: FileContent
|
||||
filename: str
|
||||
filesize: int
|
||||
filetype: str
|
||||
|
||||
|
||||
class AnnotationFileData(BaseModel):
|
||||
files: List[File] = Field(
|
||||
default=[],
|
||||
description="List of files",
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"csvFiles": [
|
||||
{
|
||||
"content": "Name, Age\nAlice, 25\nBob, 30",
|
||||
"filename": "example.csv",
|
||||
"filesize": 123,
|
||||
"id": "123",
|
||||
"type": "text/csv",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
alias_generator = to_camel
|
||||
|
||||
|
||||
class Annotation(BaseModel):
|
||||
type: str
|
||||
data: AnnotationFileData | List[str]
|
||||
|
||||
def to_content(self) -> str | None:
|
||||
if self.type == "document_file":
|
||||
# We only support generating context content for CSV files for now
|
||||
csv_files = [file for file in self.data.files if file.filetype == "csv"]
|
||||
if len(csv_files) > 0:
|
||||
return "Use data from following CSV raw content\n" + "\n".join(
|
||||
[f"```csv\n{csv_file.content.value}\n```" for csv_file in csv_files]
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
f"The annotation {self.type} is not supported for generating context content"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
class Message(BaseModel):
|
||||
role: MessageRole
|
||||
content: str
|
||||
annotations: List[Annotation] | None = None
|
||||
|
||||
|
||||
class ChatData(BaseModel):
|
||||
messages: List[Message]
|
||||
data: Any = None
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What standards for letters exist?",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@field_validator("messages")
|
||||
def messages_must_not_be_empty(cls, v):
|
||||
if len(v) == 0:
|
||||
raise ValueError("Messages must not be empty")
|
||||
return v
|
||||
|
||||
def get_last_message_content(self) -> str:
|
||||
"""
|
||||
Get the content of the last message along with the data content if available.
|
||||
Fallback to use data content from previous messages
|
||||
"""
|
||||
if len(self.messages) == 0:
|
||||
raise ValueError("There is not any message in the chat")
|
||||
last_message = self.messages[-1]
|
||||
message_content = last_message.content
|
||||
for message in reversed(self.messages):
|
||||
if message.role == MessageRole.USER and message.annotations is not None:
|
||||
annotation_contents = filter(
|
||||
None,
|
||||
[annotation.to_content() for annotation in message.annotations],
|
||||
)
|
||||
if not annotation_contents:
|
||||
continue
|
||||
annotation_text = "\n".join(annotation_contents)
|
||||
message_content = f"{message_content}\n{annotation_text}"
|
||||
break
|
||||
return message_content
|
||||
|
||||
def get_history_messages(self) -> List[ChatMessage]:
|
||||
"""
|
||||
Get the history messages
|
||||
"""
|
||||
return [
|
||||
ChatMessage(role=message.role, content=message.content)
|
||||
for message in self.messages[:-1]
|
||||
]
|
||||
|
||||
def is_last_message_from_user(self) -> bool:
|
||||
return self.messages[-1].role == MessageRole.USER
|
||||
|
||||
def get_chat_document_ids(self) -> List[str]:
|
||||
"""
|
||||
Get the document IDs from the chat messages
|
||||
"""
|
||||
document_ids: List[str] = []
|
||||
for message in self.messages:
|
||||
if message.role == MessageRole.USER and message.annotations is not None:
|
||||
for annotation in message.annotations:
|
||||
if (
|
||||
annotation.type == "document_file"
|
||||
and annotation.data.files is not None
|
||||
):
|
||||
for fi in annotation.data.files:
|
||||
if fi.content.type == "ref":
|
||||
document_ids += fi.content.value
|
||||
return list(set(document_ids))
|
||||
|
||||
|
||||
class LlamaCloudFile(BaseModel):
|
||||
file_name: str
|
||||
pipeline_id: str
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, LlamaCloudFile):
|
||||
return NotImplemented
|
||||
return (
|
||||
self.file_name == other.file_name and self.pipeline_id == other.pipeline_id
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.file_name, self.pipeline_id))
|
||||
|
||||
|
||||
class SourceNodes(BaseModel):
|
||||
id: str
|
||||
metadata: Dict[str, Any]
|
||||
score: Optional[float]
|
||||
text: str
|
||||
url: Optional[str]
|
||||
|
||||
@classmethod
|
||||
def from_source_node(cls, source_node: NodeWithScore):
|
||||
metadata = source_node.node.metadata
|
||||
url = cls.get_url_from_metadata(metadata)
|
||||
#text = 'filename' in metadata and metadata['filename'] or source_node.node.node_id
|
||||
text = source_node.node.text
|
||||
return cls(
|
||||
id=source_node.node.node_id,
|
||||
metadata=metadata,
|
||||
score=source_node.score,
|
||||
text=text, # type: ignore
|
||||
url=url,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_url_from_metadata(cls, metadata: Dict[str, Any]) -> str:
|
||||
url_prefix = os.getenv("FILESERVER_URL_PREFIX")
|
||||
if not url_prefix:
|
||||
logger.warning(
|
||||
"Warning: FILESERVER_URL_PREFIX not set in environment variables. Can't use file server"
|
||||
)
|
||||
file_name = metadata.get("file_name")
|
||||
if file_name and url_prefix:
|
||||
# file_name exists and file server is configured
|
||||
pipeline_id = metadata.get("pipeline_id")
|
||||
if pipeline_id and metadata.get("private") is None:
|
||||
# file is from LlamaCloud and was not ingested locally
|
||||
file_name = f"{pipeline_id}${file_name}"
|
||||
return f"{url_prefix}/output/llamacloud/{file_name}"
|
||||
is_private = metadata.get("private", "false") == "true"
|
||||
if is_private:
|
||||
return f"{url_prefix}/output/uploaded/{file_name}"
|
||||
return f"{url_prefix}/data/{file_name}"
|
||||
else:
|
||||
# fallback to URL in metadata (e.g. for websites)
|
||||
return metadata.get("URL")
|
||||
|
||||
@classmethod
|
||||
def from_source_nodes(cls, source_nodes: List[NodeWithScore]):
|
||||
return [cls.from_source_node(node) for node in source_nodes]
|
||||
|
||||
@staticmethod
|
||||
def get_download_files(nodes: List[NodeWithScore]) -> Set[LlamaCloudFile]:
|
||||
source_nodes = SourceNodes.from_source_nodes(nodes)
|
||||
llama_cloud_files = [
|
||||
LlamaCloudFile(
|
||||
file_name=node.metadata.get("file_name"),
|
||||
pipeline_id=node.metadata.get("pipeline_id"),
|
||||
)
|
||||
for node in source_nodes
|
||||
if (
|
||||
node.metadata.get("private")
|
||||
is None # Only download files are from LlamaCloud and were not ingested locally
|
||||
and node.metadata.get("pipeline_id") is not None
|
||||
and node.metadata.get("file_name") is not None
|
||||
)
|
||||
]
|
||||
# Remove duplicates and return
|
||||
return set(llama_cloud_files)
|
||||
|
||||
|
||||
class Result(BaseModel):
|
||||
result: Message
|
||||
nodes: List[SourceNodes]
|
||||
|
||||
|
||||
class ChatConfig(BaseModel):
|
||||
starter_questions: Optional[List[str]] = Field(
|
||||
default=None,
|
||||
description="List of starter questions",
|
||||
serialization_alias="starterQuestions",
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"starterQuestions": [
|
||||
"What standards for letters exist?",
|
||||
"What are the requirements for a letter to be considered a letter?",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import logging
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.api.services.file import PrivateFileService
|
||||
|
||||
file_upload_router = r = APIRouter()
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
|
||||
class FileUploadRequest(BaseModel):
|
||||
base64: str
|
||||
|
||||
|
||||
@r.post("")
|
||||
def upload_file(request: FileUploadRequest) -> List[str]:
|
||||
try:
|
||||
logger.info("Processing file")
|
||||
return PrivateFileService.process_file(request.base64)
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing file: {e}", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail="Error processing file")
|
||||
@@ -1,109 +0,0 @@
|
||||
import json
|
||||
|
||||
from aiostream import stream
|
||||
from fastapi import Request
|
||||
from fastapi.responses import StreamingResponse
|
||||
from llama_index.core.chat_engine.types import StreamingAgentChatResponse
|
||||
|
||||
from app.api.routers.events import EventCallbackHandler
|
||||
from app.api.routers.models import ChatData, Message, SourceNodes
|
||||
from app.api.services.suggestion import NextQuestionSuggestion
|
||||
|
||||
|
||||
class VercelStreamResponse(StreamingResponse):
|
||||
"""
|
||||
Class to convert the response from the chat engine to the streaming format expected by Vercel
|
||||
"""
|
||||
|
||||
TEXT_PREFIX = "0:"
|
||||
DATA_PREFIX = "8:"
|
||||
|
||||
@classmethod
|
||||
def convert_text(cls, token: str):
|
||||
# Escape newlines and double quotes to avoid breaking the stream
|
||||
token = json.dumps(token)
|
||||
return f"{cls.TEXT_PREFIX}{token}\n"
|
||||
|
||||
@classmethod
|
||||
def convert_data(cls, data: dict):
|
||||
data_str = json.dumps(data)
|
||||
return f"{cls.DATA_PREFIX}[{data_str}]\n"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
request: Request,
|
||||
event_handler: EventCallbackHandler,
|
||||
response: StreamingAgentChatResponse,
|
||||
chat_data: ChatData,
|
||||
):
|
||||
content = VercelStreamResponse.content_generator(
|
||||
request, event_handler, response, chat_data
|
||||
)
|
||||
super().__init__(content=content)
|
||||
|
||||
@classmethod
|
||||
async def content_generator(
|
||||
cls,
|
||||
request: Request,
|
||||
event_handler: EventCallbackHandler,
|
||||
response: StreamingAgentChatResponse,
|
||||
chat_data: ChatData,
|
||||
):
|
||||
# Yield the text response
|
||||
async def _chat_response_generator():
|
||||
final_response = ""
|
||||
async for token in response.async_response_gen():
|
||||
final_response += token
|
||||
yield VercelStreamResponse.convert_text(token)
|
||||
|
||||
# Generate questions that user might interested to
|
||||
conversation = chat_data.messages + [
|
||||
Message(role="assistant", content=final_response)
|
||||
]
|
||||
questions = await NextQuestionSuggestion.suggest_next_questions(
|
||||
conversation
|
||||
)
|
||||
if len(questions) > 0:
|
||||
yield VercelStreamResponse.convert_data(
|
||||
{
|
||||
"type": "suggested_questions",
|
||||
"data": questions,
|
||||
}
|
||||
)
|
||||
|
||||
# the text_generator is the leading stream, once it's finished, also finish the event stream
|
||||
event_handler.is_done = True
|
||||
|
||||
# Yield the source nodes
|
||||
yield cls.convert_data(
|
||||
{
|
||||
"type": "sources",
|
||||
"data": {
|
||||
"nodes": [
|
||||
SourceNodes.from_source_node(node).dict()
|
||||
for node in response.source_nodes
|
||||
]
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Yield the events from the event handler
|
||||
async def _event_generator():
|
||||
async for event in event_handler.async_event_gen():
|
||||
event_response = event.to_response()
|
||||
if event_response is not None:
|
||||
yield VercelStreamResponse.convert_data(event_response)
|
||||
|
||||
combine = stream.merge(_chat_response_generator(), _event_generator())
|
||||
is_stream_started = False
|
||||
async with combine.stream() as streamer:
|
||||
async for output in streamer:
|
||||
if not is_stream_started:
|
||||
is_stream_started = True
|
||||
# Stream a blank message to start the stream
|
||||
yield VercelStreamResponse.convert_text("")
|
||||
|
||||
yield output
|
||||
|
||||
if await request.is_disconnected():
|
||||
break
|
||||
@@ -0,0 +1,616 @@
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from typing import Dict, List, Any, Optional, AsyncGenerator
|
||||
|
||||
from aiostream import stream
|
||||
from fastapi import APIRouter, Request,HTTPException
|
||||
from fastapi.responses import StreamingResponse
|
||||
from llama_index.core import BaseCallbackHandler
|
||||
from llama_index.core.base.llms.types import ChatMessage
|
||||
from llama_index.core.callbacks import CBEventType
|
||||
from llama_index.core.chat_engine.types import StreamingAgentChatResponse
|
||||
from llama_index.core.tools import ToolOutput
|
||||
from llama_index.core.schema import NodeWithScore
|
||||
from pydantic import BaseModel
|
||||
from app.api.routers.request.base import userMng, conversations,message,ProjectInfo,feedback
|
||||
from app.api.routers.request.baseConfig import *
|
||||
from app.api.routers.request.models import ChatRequestData,ChatFileUploadRequest
|
||||
from app.engine import get_chat_engine
|
||||
import uuid
|
||||
from app.api.routers.services.fileServices import PrjFileLoadService,ChatFileService
|
||||
from app.api.routers.services.suggestion import NextQuestionSuggestion
|
||||
import time
|
||||
from llama_index.core.settings import Settings
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
|
||||
v1_router = v = APIRouter()
|
||||
|
||||
|
||||
gEvent_handler = None
|
||||
|
||||
|
||||
CH_Event_map={
|
||||
'CHUNKING':'文本切片',
|
||||
'NODE_PARSING':'节点解析',
|
||||
'EMBEDDING':'生成向量',
|
||||
'LLM':'知识问答',
|
||||
'QUERY':'查询',
|
||||
'RETRIEVE':'检索',
|
||||
'SYNTHESIZE':'答案合成',
|
||||
'TREE':'总结',
|
||||
'SUB_QUESTION':'问题分解',
|
||||
'TEMPLATING':'生成提示词模板',
|
||||
'FUNCTION_CALL':'函数调用',
|
||||
'RERANKING':'节点重排',
|
||||
'EXCEPTION':'执行异常',
|
||||
'AGENT_STEP':'单步执行'
|
||||
}
|
||||
|
||||
|
||||
class ChatCallbackEvent(BaseModel):
|
||||
event_type: ChatEventType
|
||||
payload: Optional[Dict[str, Any]] = None
|
||||
|
||||
def get_common_param(self)-> dict:
|
||||
return {
|
||||
'event': self.event_type.value,
|
||||
'conversation_id':self.payload.get("conversation_id"),
|
||||
'message_id': self.payload.get("message_id"),
|
||||
'created_at': int(time.time()),
|
||||
'task_id': self.payload.get("task_id")
|
||||
}
|
||||
|
||||
def get_WorkflowStart_param(self) -> dict:
|
||||
params = self.get_common_param()
|
||||
params.update({
|
||||
'workflow_run_id':self.payload.get('workflow_run_id'),
|
||||
'data':{
|
||||
"id": self.payload.get('workflow_run_id'),
|
||||
"workflow_id": self.payload.get('workflow_id'),
|
||||
"sequence_number": 1709,
|
||||
"inputs": {
|
||||
"sys.query": f"开始查询 {self.payload.get('query')}",
|
||||
"sys.files": [],
|
||||
"sys.conversation_id": self.payload.get('conversation_id'),
|
||||
"sys.user_id": self.payload.get('use_id')
|
||||
},
|
||||
"created_at": int(time.time())
|
||||
}
|
||||
})
|
||||
return params
|
||||
|
||||
def get_WorkflowFinished_param(self) -> dict:
|
||||
params = self.get_common_param()
|
||||
params.update({
|
||||
'workflow_run_id':self.payload.get('workflow_run_id'),
|
||||
'data':{
|
||||
"id": self.payload.get('workflow_run_id'),
|
||||
"workflow_id": self.payload.get('workflow_id'),
|
||||
"sequence_number": 1709,
|
||||
"status": "succeeded",
|
||||
"outputs": {
|
||||
"answer": self.payload.get('response')
|
||||
},
|
||||
"error": '',
|
||||
"elapsed_time": 36.03764106379822,
|
||||
"total_tokens": 11707,
|
||||
"total_steps": 10,
|
||||
"created_by": {
|
||||
"id": str(uuid.uuid4()),
|
||||
"user": self.payload.get('use_id')
|
||||
},
|
||||
"created_at": int(time.time()),
|
||||
"finished_at": int(time.time()),
|
||||
"files": []
|
||||
}
|
||||
})
|
||||
return params
|
||||
|
||||
def get_NodeStart_param(self) -> dict:
|
||||
params = self.get_common_param()
|
||||
params.update({
|
||||
'workflow_run_id':self.payload.get('workflow_run_id'),
|
||||
'data':{
|
||||
"id": self.payload.get('nodeid'),
|
||||
"node_id": self.payload.get('nodeid'),
|
||||
"node_type": "http-request",
|
||||
"title": CH_Event_map[self.payload.get('title')],
|
||||
"index": self.payload.get('index'),
|
||||
"predecessor_node_id": self.payload.get('predecessor_node_id'),
|
||||
"inputs": '',
|
||||
"created_at": 1724398751,
|
||||
"extras": {}
|
||||
}
|
||||
})
|
||||
return params
|
||||
|
||||
def get_NodeFinished_param(self) -> dict:
|
||||
params = self.get_common_param()
|
||||
params.update({
|
||||
'workflow_run_id':self.payload.get('workflow_run_id'),
|
||||
'data':{
|
||||
"id": self.payload.get('nodeid'),
|
||||
"node_id": self.payload.get('nodeid'),
|
||||
"node_type": "http-request",
|
||||
"title": CH_Event_map[self.payload.get('title')],
|
||||
"index": self.payload.get('index'),
|
||||
"predecessor_node_id": self.payload.get('predecessor_node_id'),
|
||||
"inputs": '',
|
||||
"process_data": '',
|
||||
"outputs": '',
|
||||
"status": "succeeded",
|
||||
"error": '',
|
||||
"elapsed_time": 0.10402441816404462,
|
||||
"execution_metadata": '',
|
||||
"created_at": 1724398751,
|
||||
"finished_at": 1724398751,
|
||||
"files": []
|
||||
}
|
||||
})
|
||||
return params
|
||||
|
||||
def get_Message_param(self) -> dict:
|
||||
params = self.get_common_param()
|
||||
params.update({
|
||||
'id':self.payload.get('message_id'),
|
||||
'answer':self.payload.get('answer')
|
||||
})
|
||||
return params
|
||||
|
||||
def get_MessageEnd_param(self) -> dict:
|
||||
params = self.get_common_param()
|
||||
nodeInfos = []
|
||||
source_nodes = self.payload.get('source_node')
|
||||
if source_nodes is not None:
|
||||
for i in range(len(source_nodes)):
|
||||
source_node:NodeWithScore = source_nodes[i]
|
||||
metadata:dict = source_node.node.metadata
|
||||
nodeInfo = {
|
||||
"position": i,
|
||||
"dataset_id": metadata.get("pipeline_id"),
|
||||
"dataset_name": metadata.get("file_name"),
|
||||
"document_id": source_node.node_id,
|
||||
"document_name": metadata.get("file_name"),
|
||||
"data_source_type": "upload_file",
|
||||
"segment_id": source_node.node_id,
|
||||
"retriever_from": "workflow",
|
||||
"score": source_node.score,
|
||||
"hit_count": 1,
|
||||
"word_count": 632,
|
||||
"segment_position": i,
|
||||
"index_node_hash": "",
|
||||
"content": source_node.text
|
||||
}
|
||||
nodeInfos.append(nodeInfo)
|
||||
params.update({
|
||||
'id':self.payload.get('message_id'),
|
||||
'metadata':{
|
||||
"retriever_resources":nodeInfos,
|
||||
"usage":{
|
||||
"prompt_tokens": 4972,
|
||||
"prompt_unit_price": "0.0",
|
||||
"prompt_price_unit": "0.0",
|
||||
"prompt_price": "0.0",
|
||||
"completion_tokens": 332,
|
||||
"completion_unit_price": "0.0",
|
||||
"completion_price_unit": "0.0",
|
||||
"completion_price": "0.0",
|
||||
"total_tokens": 5304,
|
||||
"total_price": "0.0",
|
||||
"currency": "USD",
|
||||
"latency": 4.897703120019287
|
||||
}
|
||||
}
|
||||
})
|
||||
return params
|
||||
|
||||
def to_response(self)-> dict|None:
|
||||
try:
|
||||
match self.event_type.value:
|
||||
case "workflow_started":
|
||||
return self.get_WorkflowStart_param()
|
||||
case "workflow_finished":
|
||||
return self.get_WorkflowFinished_param()
|
||||
case "node_started":
|
||||
return self.get_NodeStart_param()
|
||||
case 'node_finished':
|
||||
return self.get_NodeFinished_param()
|
||||
case 'message':
|
||||
return self.get_Message_param()
|
||||
case 'message_end':
|
||||
return self.get_MessageEnd_param()
|
||||
case _:
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error(f"转换回应时间时发生错误,原因: {e}")
|
||||
return None
|
||||
|
||||
class ChatEventCallbackHandler(BaseCallbackHandler):
|
||||
_aqueue: asyncio.Queue
|
||||
is_done: bool = False
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the base callback handler."""
|
||||
ignored_events = [
|
||||
# CBEventType.CHUNKING,
|
||||
# CBEventType.NODE_PARSING,
|
||||
# CBEventType.EMBEDDING,
|
||||
# CBEventType.LLM,
|
||||
# CBEventType.TEMPLATING,
|
||||
]
|
||||
super().__init__(ignored_events, ignored_events)
|
||||
self._aqueue = asyncio.Queue()
|
||||
self._response: StreamingAgentChatResponse = None
|
||||
self._ids:Dict[str,Any] = {}
|
||||
self._chatData:ChatRequestData = None
|
||||
self._nodeStack:List[str] = []
|
||||
self._firstEventID:str = None
|
||||
|
||||
def setInitParams(self,ids:dict,data:ChatRequestData):
|
||||
self._ids = ids
|
||||
self._chatData = data
|
||||
self._firstEventID = None
|
||||
|
||||
def setResponse(self,response: StreamingAgentChatResponse):
|
||||
self._response = response
|
||||
|
||||
def on_event_start(
|
||||
self,
|
||||
event_type: CBEventType,
|
||||
payload: Optional[Dict[str, Any]] = None,
|
||||
event_id: str = "",
|
||||
**kwargs: Any,
|
||||
) -> str:
|
||||
if self._firstEventID is None:
|
||||
self._firstEventID = event_id
|
||||
self.start()
|
||||
|
||||
logger.info("event_start:{} type:{} payload:{}\n".format(event_id, event_type, payload))
|
||||
|
||||
self._nodeStack.append(event_id)
|
||||
nindex = len(self._nodeStack) - 1
|
||||
args:Dict[str,Any] = self._ids
|
||||
args.update(
|
||||
{
|
||||
'nodeid':event_id,
|
||||
'title':event_type.name,
|
||||
'index':nindex + 1,
|
||||
'predecessor_node_id': self._nodeStack[nindex - 1] if nindex > 0 else ''
|
||||
}
|
||||
)
|
||||
nd_event = ChatCallbackEvent(event_type = ChatEventType.NODE_START,payload = args)
|
||||
if nd_event.to_response() is not None:
|
||||
self._aqueue.put_nowait(nd_event)
|
||||
|
||||
def on_event_end(
|
||||
self,
|
||||
event_type: CBEventType,
|
||||
payload: Optional[Dict[str, Any]] = None,
|
||||
event_id: str = "",
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
logger.info("event_end:{} type:{} payload:{}\n".format(event_id, event_type, payload))
|
||||
|
||||
#self.response = payload.get("response","")
|
||||
args:Dict[str,Any] = self._ids
|
||||
nodeID = self._nodeStack[-1]
|
||||
if nodeID == event_id:
|
||||
nindex = len(self._nodeStack) - 1
|
||||
args.update(
|
||||
{
|
||||
'nodeid':event_id,
|
||||
'title':event_type.name,
|
||||
'index':nindex + 1,
|
||||
'predecessor_node_id':self._nodeStack[nindex - 1] if nindex > 0 else ''
|
||||
}
|
||||
)
|
||||
nd_event = ChatCallbackEvent(event_type = ChatEventType.NODE_FINISHED,payload = args)
|
||||
if nd_event.to_response() is not None:
|
||||
self._aqueue.put_nowait(nd_event)
|
||||
self._nodeStack.pop()
|
||||
|
||||
if self._firstEventID is not None and self._firstEventID == event_id:
|
||||
self.finished()
|
||||
|
||||
def start_trace(self, trace_id: Optional[str] = None) -> None:
|
||||
"""No-op."""
|
||||
logger.info("trace_start:{}\n".format(trace_id))
|
||||
|
||||
def end_trace(
|
||||
self,
|
||||
trace_id: Optional[str] = None,
|
||||
trace_map: Optional[Dict[str, List[str]]] = None,
|
||||
) -> None:
|
||||
"""No-op."""
|
||||
logger.info("trace_end:{} trace_map:{}\n".format(trace_id, trace_map))
|
||||
|
||||
async def async_event_gen(self) -> AsyncGenerator[ChatCallbackEvent, None]:
|
||||
while not self._aqueue.empty() or not self.is_done:
|
||||
try:
|
||||
yield await asyncio.wait_for(self._aqueue.get(), timeout=0.1)
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
|
||||
def makeWorkflow_startEvent(self)->ChatCallbackEvent:
|
||||
args:Dict[str,Any] = self._ids
|
||||
args.update(
|
||||
{
|
||||
'use_id': self._chatData.user,
|
||||
'query': self._chatData.query,
|
||||
'conversation_id': self._chatData.conversation_id
|
||||
}
|
||||
)
|
||||
return ChatCallbackEvent(event_type = ChatEventType.WORKFLOW_START,payload = args)
|
||||
|
||||
def makeWorkflow_finishedEvent(self)->ChatCallbackEvent:
|
||||
args:Dict[str,Any] = self._ids
|
||||
args.update(
|
||||
{
|
||||
'response': '',
|
||||
'conversation_id': self._chatData.conversation_id
|
||||
}
|
||||
)
|
||||
return ChatCallbackEvent(event_type = ChatEventType.WORKFLOW_FINISHED,payload = args)
|
||||
|
||||
def makeMessage_EndEvent(self)->ChatCallbackEvent:
|
||||
args:Dict[str,Any] = self._ids
|
||||
if self._response is not None:
|
||||
args.update({
|
||||
'source_node': self._response.source_nodes
|
||||
})
|
||||
msgEnt_event = ChatCallbackEvent(event_type = ChatEventType.MESSAGE_END,payload = args)
|
||||
return msgEnt_event
|
||||
|
||||
def start(self):
|
||||
#添加工作流开始事件
|
||||
wf_event = self.makeWorkflow_startEvent()
|
||||
if wf_event.to_response() is not None:
|
||||
self._aqueue.put_nowait(wf_event)
|
||||
|
||||
def finished(self):
|
||||
wf_event = self.makeWorkflow_finishedEvent()
|
||||
if wf_event.to_response() is not None:
|
||||
self._aqueue.put_nowait(wf_event)
|
||||
|
||||
msgEnt_event = self.makeMessage_EndEvent()
|
||||
if msgEnt_event.to_response() is not None:
|
||||
self._aqueue.put_nowait(msgEnt_event)
|
||||
|
||||
class IDManager:
|
||||
def createID(self):
|
||||
return {
|
||||
"message_id" : str(uuid.uuid4()),
|
||||
'task_id':str(uuid.uuid4()),
|
||||
'workflow_run_id': str(uuid.uuid4()),
|
||||
"workflow_id": str(uuid.uuid4())
|
||||
}
|
||||
|
||||
class ChatStreamResponse(StreamingResponse):
|
||||
TEXT_PREFIX = "data: "
|
||||
DATA_PREFIX = "data: "
|
||||
ids:Dict[str,Any] = {}
|
||||
data:ChatRequestData = None
|
||||
|
||||
@classmethod
|
||||
def convert_Message(cls, token: str):
|
||||
params = cls.ids
|
||||
params.update({
|
||||
'answer':token,
|
||||
'conversation_id':cls.data.conversation_id
|
||||
})
|
||||
event = ChatCallbackEvent(event_type = ChatEventType.MESSAGE,payload = params)
|
||||
data_str = json.dumps(event.to_response())
|
||||
return f"{cls.DATA_PREFIX}{data_str}\n\n"
|
||||
|
||||
@classmethod
|
||||
def convert_Event(cls, data: dict):
|
||||
data_str = json.dumps(data)
|
||||
return f"{cls.DATA_PREFIX}{data_str}\n\n"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
request: Request,
|
||||
event_handler: ChatEventCallbackHandler,
|
||||
response: StreamingAgentChatResponse,
|
||||
data: ChatRequestData,
|
||||
ids:Dict[str,Any]
|
||||
):
|
||||
ChatStreamResponse.ids = ids
|
||||
ChatStreamResponse.data = data
|
||||
content = ChatStreamResponse.content_generator(
|
||||
request, event_handler, response, data
|
||||
)
|
||||
super().__init__(content=content)
|
||||
|
||||
@classmethod
|
||||
async def content_generator(
|
||||
cls,
|
||||
request: Request,
|
||||
event_handler: ChatEventCallbackHandler,
|
||||
response: StreamingAgentChatResponse,
|
||||
data: ChatRequestData
|
||||
):
|
||||
|
||||
# Yield the text response
|
||||
async def _chat_response_generator():
|
||||
final_response = ""
|
||||
async for token in response.async_response_gen():
|
||||
final_response += token
|
||||
yield ChatStreamResponse.convert_Message(token)
|
||||
|
||||
# 存储消息历史
|
||||
message().add(user_id=data.user,conversation_id=data.conversation_id,query=data.query,answer=final_response)
|
||||
|
||||
# the text_generator is the leading stream, once it's finished, also finish the event stream
|
||||
event_handler.is_done = True
|
||||
event_handler.setResponse(response)
|
||||
|
||||
# Yield the events from the event handler
|
||||
async def _event_generator():
|
||||
async for event in event_handler.async_event_gen():
|
||||
event_response = event.to_response()
|
||||
if event_response is not None:
|
||||
yield ChatStreamResponse.convert_Event(event_response)
|
||||
|
||||
combine = stream.merge(_chat_response_generator(), _event_generator())
|
||||
is_stream_started = False
|
||||
async with combine.stream() as streamer:
|
||||
async for output in streamer:
|
||||
if not is_stream_started:
|
||||
is_stream_started = True
|
||||
|
||||
yield output
|
||||
|
||||
if await request.is_disconnected():
|
||||
break
|
||||
|
||||
@v.post("/chat-messages")
|
||||
async def post_chatmessages(request: Request, data: ChatRequestData):
|
||||
global gEvent_handler
|
||||
userMng.findNoExistCreate(data.user)
|
||||
data.conversation_id = data.conversation_id if data.conversation_id else str(uuid.uuid4())
|
||||
|
||||
conversaObj = conversations()
|
||||
conversationinfo = conversaObj.get(data.conversation_id)
|
||||
if conversationinfo is None:
|
||||
conversationinfo = conversaObj.add(data.conversation_id, data.user, "新建会话",inputs= data.inputs)
|
||||
|
||||
# 生成聊天参数
|
||||
last_message_content = ChatMessage.from_str(data.query)
|
||||
filters = None
|
||||
params = data.inputs or {}
|
||||
|
||||
# 启动聊天事件监听
|
||||
ids = IDManager().createID()
|
||||
if gEvent_handler is None:
|
||||
gEvent_handler = ChatEventCallbackHandler()
|
||||
Settings.llm.callback_manager.handlers.append(gEvent_handler)
|
||||
|
||||
if gEvent_handler is not None:
|
||||
gEvent_handler.setInitParams(ids = ids,data = data)
|
||||
|
||||
# 获取聊天引擎对象
|
||||
chat_engine = get_chat_engine(filters=filters, params=params)
|
||||
# 执行异步聊天
|
||||
response = await chat_engine.astream_chat(data.query)
|
||||
# 返回异步消息回应
|
||||
return ChatStreamResponse(request, gEvent_handler, response, data,ids)
|
||||
|
||||
@v.get("/messages")
|
||||
async def query_messages(user:str, conversation_id:str):
|
||||
#conversation_id = default_conversation_id if conversation_id is None else conversation_id
|
||||
datas = []
|
||||
records = message().gets(user,conversation_id)
|
||||
if records is None:
|
||||
return {
|
||||
"limit": 20,
|
||||
"has_more": False,
|
||||
"data": []
|
||||
}
|
||||
|
||||
for record in records:
|
||||
res = record.dict()
|
||||
feeds = feedback().query(res['id'])
|
||||
res["message_files"] = []
|
||||
res["feedback"] = {'rating':feeds['rating'] } if feeds != None else ''
|
||||
res["retriever_resources"] = []
|
||||
res["created_at"] = 1723444905
|
||||
res["agent_thoughts"] = []
|
||||
res["status"] = "normal"
|
||||
res["error"] = ''
|
||||
datas.append(res)
|
||||
|
||||
return {
|
||||
"limit": 20,
|
||||
"has_more": False,
|
||||
"data": datas
|
||||
}
|
||||
|
||||
@v.post("/conversations/{itemid}/name")
|
||||
async def post_conversations(request: Request,itemid:str,params:Dict[str,Any]):
|
||||
consaObj = conversations()
|
||||
consaObj.rename(itemid,'知识问答')
|
||||
cond = {
|
||||
'id':itemid,
|
||||
'user_id':params['user']
|
||||
}
|
||||
results = consaObj.query(**cond)
|
||||
if len(results) > 0:
|
||||
res = results[0]
|
||||
return {
|
||||
"id": res['id'],
|
||||
"name": res['name'],
|
||||
"inputs": res['inputs'],
|
||||
"status": res['status'],
|
||||
"introduction": res['introduction'],
|
||||
"created_at": res['created_at'],
|
||||
#"工程位置"
|
||||
}
|
||||
return 'null'
|
||||
|
||||
@v.get("/conversations")
|
||||
async def query_conversations(user:str, first_id:str = None, limit:str = None, pinned:str = None):
|
||||
user_id = '' if user is None else user
|
||||
userMng.findNoExistCreate(user_id)
|
||||
|
||||
return {
|
||||
"limit": 20,
|
||||
"has_more": False,
|
||||
"data": conversations().gets(user_id)
|
||||
}
|
||||
|
||||
@v.get("/parameters")
|
||||
async def query_parameters(user:str):
|
||||
prjObj = ProjectInfo()
|
||||
return BaseConfig().ParamterCfg(projectInfo = prjObj.projectNames())
|
||||
|
||||
@v.post("/messages/{message_id}/feedbacks")
|
||||
async def post_feedbacks(request: Request,message_id:str,params:Dict[str,Any]):
|
||||
if params['rating'] is None:
|
||||
feedback().delete(message_id)
|
||||
else:
|
||||
results = message().query(message_id)
|
||||
if len(results) > 0:
|
||||
result = results[0]
|
||||
feedback().add(message_id=message_id,query=result['query'],
|
||||
answer=result['answer'],rating=params['rating'])
|
||||
|
||||
@v.post("/files/upload")
|
||||
def upload_file(request: ChatFileUploadRequest):
|
||||
try:
|
||||
logger.info("Processing file")
|
||||
resluts = ChatFileService.process_file(request.base64)
|
||||
return {
|
||||
'id':resluts.get('id'),
|
||||
'name': resluts.get('name'),
|
||||
'size': resluts.get('size'),
|
||||
'extension':resluts.get('extension'),
|
||||
'mime_type':resluts.get('mime_type'),
|
||||
'created_by':str(uuid.uuid4()),
|
||||
'created_at':int(time.time())
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing file: {e}", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail="Error processing file")
|
||||
|
||||
@v.post("/project")
|
||||
def upload_file(request: ChatFileUploadRequest):
|
||||
try:
|
||||
logger.info("Processing file")
|
||||
return PrjFileLoadService.process_file(request.base64)
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing file: {e}", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail="Error processing file")
|
||||
|
||||
@v.post("/messages/{message_id}/suggested")
|
||||
async def post_suggested(request: Request,message_id:str,user:str):
|
||||
questions = await NextQuestionSuggestion.suggest_next_questions(message_id)
|
||||
return {
|
||||
"result": "success",
|
||||
"data":questions
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
from datetime import datetime
|
||||
import uuid
|
||||
from app.api.routers.request.baseConfig import BaseConfig
|
||||
from app.api.routers.request.dbOrm import DBManager
|
||||
from typing import List
|
||||
dbManage = DBManager()
|
||||
|
||||
class conversations:
|
||||
def __init__(self) -> None:
|
||||
self._tableName = 'conversations'
|
||||
dbManage.createTable(self._tableName)
|
||||
|
||||
def gets(self,user_id:str):
|
||||
records = dbManage.query(self._tableName,user_id = user_id)
|
||||
datas = []
|
||||
for record in records:
|
||||
datas.append(record)
|
||||
|
||||
return datas
|
||||
|
||||
def get(self, id:str):
|
||||
records = dbManage.query(self._tableName, id=id)
|
||||
if len(records) >0:
|
||||
return records[0]
|
||||
return None
|
||||
|
||||
def add(self,id:str, user_id:str, name:str,inputs:dict):
|
||||
template = BaseConfig().ConversationCfg()
|
||||
template['id'] = id
|
||||
template['user_id'] = user_id
|
||||
template['name'] = name
|
||||
template['created_at'] = 1724399038
|
||||
template['inputs'] = inputs
|
||||
dbManage.addRecord(self._tableName,template)
|
||||
|
||||
def delete(self,id:str):
|
||||
dbManage.delete(self._tableName,id=id)
|
||||
|
||||
def rename(self,id:str,name:str):
|
||||
data = {'name':name}
|
||||
dbManage.update(self._tableName,data,id=id)
|
||||
|
||||
def query(self,**condition):
|
||||
results = []
|
||||
records = dbManage.query(self._tableName,**condition)
|
||||
for record in records:
|
||||
results.append(record.dict())
|
||||
return results
|
||||
|
||||
class user:
|
||||
def __init__(self) -> None:
|
||||
self._tableName = 'user'
|
||||
dbManage.createTable(self._tableName)
|
||||
|
||||
def gets(self):
|
||||
return dbManage.query(self._tableName)
|
||||
|
||||
def get(self,id:str):
|
||||
return dbManage.query(self._tableName,id = id)
|
||||
|
||||
def add(self,id:str):
|
||||
info = {
|
||||
'id':id,
|
||||
'createtime': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
}
|
||||
dbManage.addRecord(self._tableName,info)
|
||||
|
||||
def delete(self,id:str):
|
||||
dbManage.delete(self._tableName,id = id)
|
||||
|
||||
class userMng:
|
||||
userObj = user()
|
||||
@classmethod
|
||||
def findNoExistCreate(cls,user_id:str):
|
||||
userInfo = cls.userObj.get(user_id)
|
||||
if len(userInfo) == 0:
|
||||
cls.userObj.add(user_id)
|
||||
|
||||
def remove(cls,user_id:str):
|
||||
cls.userObj.delete(user_id)
|
||||
|
||||
class parameter:
|
||||
def __init__(self) -> None:
|
||||
self._tableName = 'parameters'
|
||||
dbManage.createTable(self._tableName)
|
||||
|
||||
def get(self,user_id:str):
|
||||
records = dbManage.query(self._tableName,user_id = user_id)
|
||||
data = {}
|
||||
for record in records:
|
||||
key = record['name']
|
||||
value = record['value']
|
||||
data[key] = value
|
||||
return data
|
||||
|
||||
def set(self,user_id:str):
|
||||
dbManage.addRecord(self._tableName,{})
|
||||
|
||||
def delete(self,user_id:str):
|
||||
dbManage.delete(self._tableName,user_id = user_id)
|
||||
|
||||
class message:
|
||||
def __init__(self) -> None:
|
||||
self._tableName = 'messages'
|
||||
dbManage.createTable(self._tableName)
|
||||
|
||||
def gets(self,user_id:str,conversation_id:str):
|
||||
records = dbManage.query(self._tableName,user_id = user_id,conversation_id = conversation_id)
|
||||
datas = []
|
||||
for record in records:
|
||||
datas.append(record)
|
||||
return datas
|
||||
|
||||
def add(self,user_id:str,conversation_id:str,query:str,answer:str):
|
||||
template = BaseConfig.MessageCfg()
|
||||
template['id'] = str(uuid.uuid4())
|
||||
template['user_id'] = user_id
|
||||
template['conversation_id'] = conversation_id
|
||||
template['query'] = query
|
||||
template['answer'] = answer
|
||||
dbManage.addRecord(self._tableName,template)
|
||||
|
||||
def delete(self,user_id:str):
|
||||
dbManage.delete(self._tableName,user_id = user_id)
|
||||
|
||||
def query(self,id:str):
|
||||
results = []
|
||||
condition = {'id':id}
|
||||
records = dbManage.query(self._tableName,**condition)
|
||||
for record in records:
|
||||
results.append(record.dict())
|
||||
return results
|
||||
|
||||
class feedback:
|
||||
def __init__(self) -> None:
|
||||
self._tableName = 'feedbacks'
|
||||
dbManage.createTable(self._tableName)
|
||||
|
||||
def add(self,message_id:str,query:str,answer:str,rating:str):
|
||||
record = {
|
||||
'message_id': message_id,
|
||||
'query': query,
|
||||
'answer': answer,
|
||||
'rating': rating,
|
||||
}
|
||||
dbManage.addRecord(self._tableName,record)
|
||||
|
||||
def delete(self,message_id:str):
|
||||
cond = {'message_id':message_id}
|
||||
dbManage.delete(self._tableName,**cond)
|
||||
|
||||
def query(self,message_id:str):
|
||||
cond = {'message_id':message_id}
|
||||
records = dbManage.query(self._tableName,**cond)
|
||||
if len(records) > 0:
|
||||
return records[0].dict()
|
||||
return None
|
||||
|
||||
class ProjectInfo:
|
||||
def __init__(self) -> None:
|
||||
self._tableName = 'projectInfos'
|
||||
dbManage.createTable(self._tableName)
|
||||
|
||||
def add(self,name:str,flag:str):
|
||||
info = dbManage.query(self._tableName,prjFlag = flag)
|
||||
if len(info) == 0:
|
||||
record = {
|
||||
'prjectName': name,
|
||||
'prjFlag': flag
|
||||
}
|
||||
dbManage.addRecord(self._tableName,record)
|
||||
|
||||
def projectNames(self)->List[str]:
|
||||
records = dbManage.query(self._tableName)
|
||||
names = []
|
||||
for record in records:
|
||||
data:dict = record.dict()
|
||||
name = data.get('prjectName')
|
||||
if name !='':
|
||||
names.append(name)
|
||||
return names
|
||||
|
||||
def prjFalg(self,name:str):
|
||||
records = dbManage.query(self._tableName)
|
||||
for record in records:
|
||||
data:dict = record.dict()
|
||||
if data.get('prjectName') == name:
|
||||
return data['prjFlag']
|
||||
return ''
|
||||
@@ -0,0 +1,103 @@
|
||||
from pydantic import BaseModel
|
||||
import os
|
||||
from enum import Enum
|
||||
|
||||
class BaseConfig(BaseModel):
|
||||
projectInfo:str = os.getenv("PROJECT_TITLE","会话提示消息")
|
||||
|
||||
def ParamterCfg(self,**args):
|
||||
prjItems = args.get('projectInfo')
|
||||
questions = os.getenv("CONVERSATION_STARTERS", "dev")
|
||||
return{
|
||||
"opening_statement": self.projectInfo,
|
||||
"suggested_questions": questions.split('\n'),
|
||||
"suggested_questions_after_answer": {
|
||||
"enabled": False
|
||||
},
|
||||
"speech_to_text": {
|
||||
"enabled": False
|
||||
},
|
||||
"text_to_speech": {
|
||||
"enabled": False,
|
||||
"language": "",
|
||||
"voice": ""
|
||||
},
|
||||
"retriever_resource": {
|
||||
"enabled": True
|
||||
},
|
||||
"annotation_reply": {
|
||||
"enabled": False
|
||||
},
|
||||
"more_like_this": {
|
||||
"enabled": False
|
||||
},
|
||||
"user_input_form": [
|
||||
{
|
||||
"select": {
|
||||
"variable": "projectname",
|
||||
"label": "\u5de5\u7a0b\u540d\u79f0",
|
||||
"type": "select",
|
||||
"max_length": 48,
|
||||
"required": True,
|
||||
"options": prjItems
|
||||
}
|
||||
}
|
||||
],
|
||||
"sensitive_word_avoidance": {
|
||||
"enabled": False
|
||||
},
|
||||
"file_upload": {
|
||||
"image": {
|
||||
"enabled": False,
|
||||
"number_limits": 3,
|
||||
"transfer_methods": [
|
||||
"remote_url"
|
||||
]
|
||||
}
|
||||
},
|
||||
"system_parameters": {
|
||||
"image_file_size_limit": "10",
|
||||
"language": "",
|
||||
"voice": "",
|
||||
},
|
||||
"retriever_resource": {
|
||||
"enabled": True
|
||||
},
|
||||
"annotation_reply": {
|
||||
"enabled": False
|
||||
},
|
||||
"more_like_this": {
|
||||
"enabled": False
|
||||
},
|
||||
}
|
||||
|
||||
def ConversationCfg(self):
|
||||
return{
|
||||
"id": "",
|
||||
'user_id':'',
|
||||
"name": "",
|
||||
"inputs": {},
|
||||
"status": "normal",
|
||||
"introduction": self.projectInfo,
|
||||
"created_at":''
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def MessageCfg(cls):
|
||||
return {
|
||||
"id": "",
|
||||
'user_id':'',
|
||||
"conversation_id": "",
|
||||
"inputs": {},
|
||||
"query": "",
|
||||
"answer": ""
|
||||
}
|
||||
|
||||
|
||||
class ChatEventType(str, Enum):
|
||||
WORKFLOW_START = "workflow_started"
|
||||
WORKFLOW_FINISHED = "workflow_finished"
|
||||
NODE_START = "node_started"
|
||||
NODE_FINISHED = "node_finished"
|
||||
MESSAGE = "message"
|
||||
MESSAGE_END = "message_end"
|
||||
@@ -0,0 +1,239 @@
|
||||
import os
|
||||
from typing import Dict, List, Any
|
||||
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import create_engine, Column, String, Integer, JSON,Float
|
||||
from sqlalchemy.engine.reflection import Inspector
|
||||
from sqlalchemy.orm import sessionmaker, declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
#orm类
|
||||
class ConversationOrm(Base):
|
||||
__tablename__ = "conversations"
|
||||
|
||||
id = Column(String, primary_key=True)
|
||||
user_id = Column(String)
|
||||
name = Column(String)
|
||||
inputs = Column(JSON)
|
||||
status = Column(String)
|
||||
introduction = Column(String)
|
||||
created_at = Column(Integer)
|
||||
|
||||
def update(self,data:Dict[str,Any]):
|
||||
if 'name' in data:
|
||||
self.name = data['name']
|
||||
|
||||
class UserOrm(Base):
|
||||
__tablename__ = "user"
|
||||
|
||||
id = Column(String, primary_key=True)
|
||||
createtime = Column(String)
|
||||
|
||||
class ParametersOrm(Base):
|
||||
__tablename__ = "parameters"
|
||||
|
||||
user_id = Column(String,primary_key=True)
|
||||
name = Column(String)
|
||||
value = Column(JSON)
|
||||
|
||||
class MessagesOrm(Base):
|
||||
__tablename__ = "messages"
|
||||
|
||||
id = Column(String,primary_key=True)
|
||||
user_id = Column(String)
|
||||
conversation_id = Column(String)
|
||||
inputs = Column(JSON)
|
||||
query = Column(String)
|
||||
answer = Column(String)
|
||||
|
||||
class FeedBackOrm(Base):
|
||||
__tablename__ = "feedbacks"
|
||||
|
||||
message_id = Column(String,primary_key=True)
|
||||
query = Column(String)
|
||||
answer = Column(String)
|
||||
rating = Column(String)
|
||||
|
||||
class ProjectInfoOrm(Base):
|
||||
__tablename__ = "projectInfos"
|
||||
|
||||
prjFlag = Column(String,primary_key=True)
|
||||
prjectName = Column(String)
|
||||
|
||||
|
||||
#数据结构
|
||||
class ConversationModel(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
inputs: Dict[str, Any]
|
||||
status: str
|
||||
introduction: str
|
||||
created_at: int
|
||||
|
||||
class Config:
|
||||
from_attributes=True
|
||||
|
||||
@classmethod
|
||||
def orm(cls):
|
||||
return ConversationOrm
|
||||
|
||||
class UserModel(BaseModel):
|
||||
id: str
|
||||
createtime: str
|
||||
|
||||
class Config:
|
||||
from_attributes=True
|
||||
|
||||
@classmethod
|
||||
def orm(cls):
|
||||
return UserOrm
|
||||
|
||||
class ParametersModel(BaseModel):
|
||||
user_id : str
|
||||
name : str
|
||||
value : Dict[str, Any]
|
||||
|
||||
class Config:
|
||||
from_attributes=True
|
||||
|
||||
@classmethod
|
||||
def orm(cls):
|
||||
return ParametersOrm
|
||||
|
||||
class MessagesModel(BaseModel):
|
||||
id :str
|
||||
conversation_id :str
|
||||
inputs : Dict[str, Any]
|
||||
query : str
|
||||
answer : str
|
||||
|
||||
class Config:
|
||||
from_attributes=True
|
||||
|
||||
@classmethod
|
||||
def orm(cls):
|
||||
return MessagesOrm
|
||||
|
||||
class FeedBackModel(BaseModel):
|
||||
message_id :str
|
||||
query :str
|
||||
answer :str
|
||||
rating :str
|
||||
|
||||
class Config:
|
||||
from_attributes=True
|
||||
|
||||
@classmethod
|
||||
def orm(cls):
|
||||
return FeedBackOrm
|
||||
|
||||
class ProjectInfoModel(BaseModel):
|
||||
prjectName:str
|
||||
prjFlag:str
|
||||
|
||||
class Config:
|
||||
from_attributes=True
|
||||
|
||||
@classmethod
|
||||
def orm(cls):
|
||||
return ProjectInfoOrm
|
||||
|
||||
class DBManager:
|
||||
def __init__(self) -> None:
|
||||
DATABASE_URL = os.getenv("SQLITE_DATABASE_URL")
|
||||
self._engine = create_engine(DATABASE_URL)
|
||||
self.SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=self._engine)
|
||||
|
||||
def createTable(self,tableName:str):
|
||||
if self._engine is None:
|
||||
return
|
||||
if not self.exist(tableName):
|
||||
Base.metadata.tables[tableName].create(self._engine)
|
||||
|
||||
def addRecord(self,tableName:str,record:Dict[str,Any]):
|
||||
ormCls = self._get_orm(tableName)
|
||||
if ormCls is None:
|
||||
return
|
||||
session = self.SessionLocal()
|
||||
data = ormCls(**record)
|
||||
session.add(data)
|
||||
session.commit()
|
||||
|
||||
def addRecords(self,tableName:str,records:List[Dict[str,Any]]):
|
||||
ormCls = self._get_orm(tableName)
|
||||
if ormCls is None:
|
||||
return
|
||||
datas = []
|
||||
session = self.SessionLocal()
|
||||
for record in records:
|
||||
datas.append(ormCls(**record))
|
||||
session.add(datas)
|
||||
session.commit()
|
||||
|
||||
def delete(self,tableName:str,**filter):
|
||||
session = self.SessionLocal()
|
||||
ormCls = self._get_orm(tableName)
|
||||
if ormCls is None:
|
||||
return
|
||||
records = session.query(ormCls).filter_by(**filter).all()
|
||||
if records is not None:
|
||||
for record in records:
|
||||
session.delete(record)
|
||||
session.commit()
|
||||
|
||||
def update(self,tableName:str,data:Dict[str,Any],**filter):
|
||||
if not self.exist(tableName):
|
||||
return
|
||||
session = self.SessionLocal()
|
||||
ormCls = self._get_orm(tableName)
|
||||
if ormCls is None:
|
||||
return
|
||||
if len(filter) > 0:
|
||||
records = session.query(ormCls).filter_by(**filter).all()
|
||||
else:
|
||||
records = session.query(ormCls).all()
|
||||
for record in records:
|
||||
if record is not None:
|
||||
record.update(data)
|
||||
session.commit()
|
||||
|
||||
def query(self,tableName:str,**filter):
|
||||
session = self.SessionLocal()
|
||||
ormCls = self._get_orm(tableName)
|
||||
if ormCls is None:
|
||||
return
|
||||
modelCls = self._get_model(ormCls)
|
||||
if modelCls is None:
|
||||
return
|
||||
|
||||
if filter is not None:
|
||||
records = session.query(ormCls).filter_by(**filter).all()
|
||||
else:
|
||||
records = session.query(ormCls).all()
|
||||
|
||||
datas = []
|
||||
for record in records:
|
||||
datas.append(modelCls.from_orm(record))
|
||||
return datas
|
||||
|
||||
def exist(self,tableName:str)->bool:
|
||||
if self._engine is None:
|
||||
return
|
||||
inspector = Inspector.from_engine(self._engine)
|
||||
return inspector.has_table(tableName)
|
||||
|
||||
def _get_orm(self,tableName:str):
|
||||
subClss = Base.__subclasses__()
|
||||
for sunCls in subClss:
|
||||
if sunCls.__tablename__ == tableName:
|
||||
return sunCls
|
||||
return None
|
||||
|
||||
def _get_model(self,orm:Any):
|
||||
subClss = BaseModel.__subclasses__()
|
||||
for sunCls in subClss:
|
||||
if 'orm' in sunCls.__dict__ and sunCls.orm() == orm:
|
||||
return sunCls
|
||||
return None
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
from typing import Dict, Any
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
class ChatRequestData(BaseModel):
|
||||
inputs: Dict[str,Any]
|
||||
query: str
|
||||
user: str
|
||||
response_mode: str
|
||||
files: Any
|
||||
conversation_id: str = None
|
||||
|
||||
class ChatFileUploadRequest(BaseModel):
|
||||
base64: str
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
import base64,os,mimetypes,requests,tempfile
|
||||
from typing import List,Dict,Any
|
||||
from uuid import uuid4
|
||||
from app.settings import init_settings
|
||||
from app.engine.loaders import get_document_Types, get_documents,getFileCacahePath
|
||||
from app.engine.vectordb import get_vector_store
|
||||
from app.engine.generate import get_doc_store,run_pipeline,persist_storage
|
||||
from llama_index.core.schema import Document
|
||||
from pathlib import Path
|
||||
from llama_index.core.readers.file.base import (
|
||||
_try_loading_included_file_formats as get_file_loaders_map,
|
||||
)
|
||||
from llama_index.readers.file import FlatReader
|
||||
from llama_index.core.ingestion import IngestionPipeline
|
||||
from llama_index.core import VectorStoreIndex
|
||||
from app.engine.index import get_index
|
||||
|
||||
STORAGE_DIR = os.getenv("STORAGE_DIR", "storage")
|
||||
|
||||
class PrjFileLoadService:
|
||||
@staticmethod
|
||||
def store_and_parse_file(file_data):
|
||||
prjtoJson_url = os.getenv('PRJTOJSON_URL')
|
||||
convert_url = prjtoJson_url +'/prj_convert_clt2json'
|
||||
files ={'file':file_data}
|
||||
response1 = requests.post(
|
||||
url = convert_url,
|
||||
files=files
|
||||
)
|
||||
if response1.text is None or response1.text=='':
|
||||
return None
|
||||
|
||||
load_url = prjtoJson_url +'/file_download'
|
||||
response2 = requests.post(
|
||||
url = load_url,
|
||||
data=response1.text
|
||||
)
|
||||
if response2.text is None or response2.content=='':
|
||||
return None
|
||||
|
||||
try:
|
||||
tempFilePath:str = tempfile.gettempdir() + f"\\{uuid4().hex}.zip"
|
||||
with open(tempFilePath,'wb') as file:
|
||||
file.write(response2.content)
|
||||
|
||||
prjID = str(uuid4())
|
||||
filePath = getFileCacahePath() + f'/Projects/{prjID}'
|
||||
os.makedirs(filePath)
|
||||
import zipfile
|
||||
with zipfile.ZipFile(tempFilePath,'r') as zip_File:
|
||||
for zip_info in zip_File.infolist():
|
||||
zip_info.filename = zip_info.filename.encode('cp437').decode('gbk')
|
||||
zip_File.extract(zip_info,filePath)
|
||||
os.remove(tempFilePath)
|
||||
return f'Projects_{prjID}'
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def process_file(base64_content: str) -> str:
|
||||
prjFlag = PrjFileLoadService.store_and_parse_file(base64_content)
|
||||
if prjFlag is None:
|
||||
return None
|
||||
#生成向量并持久化至本地
|
||||
documents = get_documents(prjFlag)
|
||||
for doc in documents:
|
||||
doc.metadata["private"] = "false"
|
||||
docstore = get_doc_store(prjFlag)
|
||||
vector_store = get_vector_store(prjFlag)
|
||||
_ = run_pipeline(docstore, vector_store, documents)
|
||||
persist_storage(docstore, vector_store)
|
||||
return prjFlag
|
||||
|
||||
class ChatFileService:
|
||||
PRIVATE_STORE_PATH = os.getenv('CHAT_UPLOAD_FILECACHE','output/uploaded')
|
||||
resluts:Dict[str,Any] = {}
|
||||
|
||||
@staticmethod
|
||||
def process_file(base64_content: str) -> dict:
|
||||
file_data, extension = ChatFileService.preprocess_base64_file(base64_content)
|
||||
documents = ChatFileService.store_and_parse_file(file_data, extension)
|
||||
|
||||
pipeline = IngestionPipeline()
|
||||
nodes = pipeline.run(documents=documents)
|
||||
current_index = get_index()
|
||||
pipeline = IngestionPipeline()
|
||||
nodes = pipeline.run(documents=documents)
|
||||
if current_index is None:
|
||||
current_index = VectorStoreIndex(nodes=nodes)
|
||||
else:
|
||||
current_index.insert_nodes(nodes=nodes)
|
||||
current_index.storage_context.persist(
|
||||
persist_dir=os.environ.get("STORAGE_DIR", "storage")
|
||||
)
|
||||
|
||||
return ChatFileService.resluts
|
||||
|
||||
@staticmethod
|
||||
def preprocess_base64_file(base64_content: str) -> tuple:
|
||||
header, data = base64_content.split(",", 1)
|
||||
mime_type = header.split(";")[0].split(":", 1)[1]
|
||||
extension = mimetypes.guess_extension(mime_type)
|
||||
ChatFileService.resluts['mime_type'] = mime_type
|
||||
ChatFileService.resluts['extension'] = extension
|
||||
return base64.b64decode(data), extension
|
||||
|
||||
@staticmethod
|
||||
def store_and_parse_file(file_data, extension) -> List[Document]:
|
||||
os.makedirs(ChatFileService.PRIVATE_STORE_PATH, exist_ok=True)
|
||||
fileID = uuid4().hex
|
||||
file_name = f"{fileID}{extension}"
|
||||
file_path = Path(os.path.join(ChatFileService.PRIVATE_STORE_PATH, file_name))
|
||||
ChatFileService.resluts['id'] = fileID
|
||||
ChatFileService.resluts['file_name'] = file_name
|
||||
|
||||
with open(file_path, "wb") as f:
|
||||
f.write(file_data)
|
||||
|
||||
ChatFileService.resluts['size'] = os.path.getsize(file_path)
|
||||
reader_cls = ChatFileService.default_file_loaders_map().get(extension)
|
||||
if reader_cls is None:
|
||||
raise ValueError(f"File extension {extension} is not supported")
|
||||
reader = reader_cls()
|
||||
documents = reader.load_data(file_path)
|
||||
for doc in documents:
|
||||
doc.metadata["file_name"] = file_name
|
||||
doc.metadata["private"] = "true"
|
||||
return documents
|
||||
|
||||
@staticmethod
|
||||
def default_file_loaders_map():
|
||||
default_loaders = get_file_loaders_map()
|
||||
default_loaders[".txt"] = FlatReader
|
||||
return default_loaders
|
||||
+7
-12
@@ -1,6 +1,6 @@
|
||||
from typing import List
|
||||
|
||||
from app.api.routers.models import Message
|
||||
from app.api.routers.request.base import message
|
||||
from llama_index.core.prompts import PromptTemplate
|
||||
from llama_index.core.settings import Settings
|
||||
from pydantic import BaseModel
|
||||
@@ -23,26 +23,21 @@ class NextQuestions(BaseModel):
|
||||
class NextQuestionSuggestion:
|
||||
@staticmethod
|
||||
async def suggest_next_questions(
|
||||
messages: List[Message],
|
||||
message_id: str,
|
||||
number_of_questions: int = N_QUESTION_TO_GENERATE,
|
||||
) -> List[str]:
|
||||
# Reduce the cost by only using the last two messages
|
||||
last_user_message = None
|
||||
last_assistant_message = None
|
||||
for message in reversed(messages):
|
||||
if message.role == "user":
|
||||
last_user_message = f"User: {message.content}"
|
||||
elif message.role == "assistant":
|
||||
last_assistant_message = f"Assistant: {message.content}"
|
||||
if last_user_message and last_assistant_message:
|
||||
break
|
||||
results = message().query(message_id)
|
||||
if len(results) > 0:
|
||||
last_user_message = results[0]['query']
|
||||
last_assistant_message = results[0]['answer']
|
||||
conversation: str = f"{last_user_message}\n{last_assistant_message}"
|
||||
|
||||
output: NextQuestions = await Settings.llm.astructured_predict(
|
||||
NextQuestions,
|
||||
prompt=NEXT_QUESTIONS_SUGGESTION_PROMPT,
|
||||
conversation=conversation,
|
||||
nun_questions=number_of_questions,
|
||||
)
|
||||
|
||||
return output.questions
|
||||
return []
|
||||
@@ -1,113 +0,0 @@
|
||||
import base64
|
||||
import mimetypes
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
from uuid import uuid4
|
||||
|
||||
from app.engine.index import get_index
|
||||
from llama_index.core import VectorStoreIndex
|
||||
from llama_index.core.ingestion import IngestionPipeline
|
||||
from llama_index.core.readers.file.base import (
|
||||
_try_loading_included_file_formats as get_file_loaders_map,
|
||||
)
|
||||
from llama_index.core.readers.file.base import (
|
||||
default_file_metadata_func,
|
||||
)
|
||||
from llama_index.core.schema import Document
|
||||
from llama_index.indices.managed.llama_cloud.base import LlamaCloudIndex
|
||||
from llama_index.readers.file import FlatReader
|
||||
|
||||
|
||||
def get_llamaparse_parser():
|
||||
from app.engine.loaders import load_configs
|
||||
from app.engine.loaders.file import FileLoaderConfig, llama_parse_parser
|
||||
|
||||
config = load_configs()
|
||||
file_loader_config = FileLoaderConfig(**config["file"])
|
||||
if file_loader_config.use_llama_parse:
|
||||
return llama_parse_parser()
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def default_file_loaders_map():
|
||||
default_loaders = get_file_loaders_map()
|
||||
default_loaders[".txt"] = FlatReader
|
||||
return default_loaders
|
||||
|
||||
|
||||
class PrivateFileService:
|
||||
PRIVATE_STORE_PATH = "output/uploaded"
|
||||
|
||||
@staticmethod
|
||||
def preprocess_base64_file(base64_content: str) -> tuple:
|
||||
header, data = base64_content.split(",", 1)
|
||||
mime_type = header.split(";")[0].split(":", 1)[1]
|
||||
extension = mimetypes.guess_extension(mime_type)
|
||||
# File data as bytes
|
||||
return base64.b64decode(data), extension
|
||||
|
||||
@staticmethod
|
||||
def store_and_parse_file(file_data, extension) -> List[Document]:
|
||||
# Store file to the private directory
|
||||
os.makedirs(PrivateFileService.PRIVATE_STORE_PATH, exist_ok=True)
|
||||
|
||||
# random file name
|
||||
file_name = f"{uuid4().hex}{extension}"
|
||||
file_path = Path(os.path.join(PrivateFileService.PRIVATE_STORE_PATH, file_name))
|
||||
|
||||
# write file
|
||||
with open(file_path, "wb") as f:
|
||||
f.write(file_data)
|
||||
|
||||
# Load file to documents
|
||||
# If LlamaParse is enabled, use it to parse the file
|
||||
# Otherwise, use the default file loaders
|
||||
reader = get_llamaparse_parser()
|
||||
if reader is None:
|
||||
reader_cls = default_file_loaders_map().get(extension)
|
||||
if reader_cls is None:
|
||||
raise ValueError(f"File extension {extension} is not supported")
|
||||
reader = reader_cls()
|
||||
documents = reader.load_data(file_path)
|
||||
# Add custom metadata
|
||||
for doc in documents:
|
||||
doc.metadata["file_name"] = file_name
|
||||
doc.metadata["private"] = "true"
|
||||
return documents
|
||||
|
||||
@staticmethod
|
||||
def process_file(base64_content: str) -> List[str]:
|
||||
file_data, extension = PrivateFileService.preprocess_base64_file(base64_content)
|
||||
documents = PrivateFileService.store_and_parse_file(file_data, extension)
|
||||
|
||||
# Only process nodes, no store the index
|
||||
pipeline = IngestionPipeline()
|
||||
nodes = pipeline.run(documents=documents)
|
||||
|
||||
# Add the nodes to the index and persist it
|
||||
current_index = get_index()
|
||||
|
||||
# Insert the documents into the index
|
||||
if isinstance(current_index, LlamaCloudIndex):
|
||||
# LlamaCloudIndex is a managed index so we don't need to process the nodes
|
||||
# just insert the documents
|
||||
for doc in documents:
|
||||
current_index.insert(doc)
|
||||
else:
|
||||
# Only process nodes, no store the index
|
||||
pipeline = IngestionPipeline()
|
||||
nodes = pipeline.run(documents=documents)
|
||||
|
||||
# Add the nodes to the index and persist it
|
||||
if current_index is None:
|
||||
current_index = VectorStoreIndex(nodes=nodes)
|
||||
else:
|
||||
current_index.insert_nodes(nodes=nodes)
|
||||
current_index.storage_context.persist(
|
||||
persist_dir=os.environ.get("STORAGE_DIR", "storage")
|
||||
)
|
||||
|
||||
# Return the document ids
|
||||
return [doc.doc_id for doc in documents]
|
||||
@@ -1,114 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import requests
|
||||
from app.api.routers.models import LlamaCloudFile
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
|
||||
class LLamaCloudFileService:
|
||||
LLAMA_CLOUD_URL = "https://cloud.llamaindex.ai/api/v1"
|
||||
LOCAL_STORE_PATH = "output/llamacloud"
|
||||
|
||||
DOWNLOAD_FILE_NAME_TPL = "{pipeline_id}${filename}"
|
||||
|
||||
@classmethod
|
||||
def get_all_projects(cls) -> List[Dict[str, Any]]:
|
||||
url = f"{cls.LLAMA_CLOUD_URL}/projects"
|
||||
return cls._make_request(url)
|
||||
|
||||
@classmethod
|
||||
def get_all_pipelines(cls) -> List[Dict[str, Any]]:
|
||||
url = f"{cls.LLAMA_CLOUD_URL}/pipelines"
|
||||
return cls._make_request(url)
|
||||
|
||||
@classmethod
|
||||
def get_all_projects_with_pipelines(cls) -> List[Dict[str, Any]]:
|
||||
try:
|
||||
projects = cls.get_all_projects()
|
||||
pipelines = cls.get_all_pipelines()
|
||||
return [
|
||||
{
|
||||
**project,
|
||||
"pipelines": [p for p in pipelines if p["project_id"] == project["id"]],
|
||||
}
|
||||
for project in projects
|
||||
]
|
||||
except Exception as error:
|
||||
logger.error(f"Error listing projects and pipelines: {error}")
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def _get_files(cls, pipeline_id: str) -> List[Dict[str, Any]]:
|
||||
url = f"{cls.LLAMA_CLOUD_URL}/pipelines/{pipeline_id}/files"
|
||||
return cls._make_request(url)
|
||||
|
||||
@classmethod
|
||||
def _get_file_detail(cls, project_id: str, file_id: str) -> Dict[str, Any]:
|
||||
url = f"{cls.LLAMA_CLOUD_URL}/files/{file_id}/content?project_id={project_id}"
|
||||
return cls._make_request(url)
|
||||
|
||||
@classmethod
|
||||
def _download_file(cls, url: str, local_file_path: str):
|
||||
logger.info(f"Downloading file to {local_file_path}")
|
||||
# Create directory if it doesn't exist
|
||||
os.makedirs(cls.LOCAL_STORE_PATH, exist_ok=True)
|
||||
# Download the file
|
||||
with requests.get(url, stream=True) as r:
|
||||
r.raise_for_status()
|
||||
with open(local_file_path, "wb") as f:
|
||||
for chunk in r.iter_content(chunk_size=8192):
|
||||
f.write(chunk)
|
||||
logger.info("File downloaded successfully")
|
||||
|
||||
@classmethod
|
||||
def download_llamacloud_pipeline_file(
|
||||
cls,
|
||||
file: LlamaCloudFile,
|
||||
force_download: bool = False,
|
||||
):
|
||||
file_name = file.file_name
|
||||
pipeline_id = file.pipeline_id
|
||||
|
||||
# Check is the file already exists
|
||||
downloaded_file_path = cls.get_file_path(file_name, pipeline_id)
|
||||
if os.path.exists(downloaded_file_path) and not force_download:
|
||||
logger.debug(f"File {file_name} already exists in local storage")
|
||||
return
|
||||
try:
|
||||
logger.info(f"Downloading file {file_name} for pipeline {pipeline_id}")
|
||||
files = cls._get_files(pipeline_id)
|
||||
if not files or not isinstance(files, list):
|
||||
raise Exception("No files found in LlamaCloud")
|
||||
for file_entry in files:
|
||||
if file_entry["name"] == file_name:
|
||||
file_id = file_entry["file_id"]
|
||||
project_id = file_entry["project_id"]
|
||||
file_detail = cls._get_file_detail(project_id, file_id)
|
||||
cls._download_file(file_detail["url"], downloaded_file_path)
|
||||
break
|
||||
except Exception as error:
|
||||
logger.info(f"Error fetching file from LlamaCloud: {error}")
|
||||
|
||||
@classmethod
|
||||
def get_file_name(cls, name: str, pipeline_id: str) -> str:
|
||||
return cls.DOWNLOAD_FILE_NAME_TPL.format(pipeline_id=pipeline_id, filename=name)
|
||||
|
||||
@classmethod
|
||||
def get_file_path(cls, name: str, pipeline_id: str) -> str:
|
||||
return os.path.join(cls.LOCAL_STORE_PATH, cls.get_file_name(name, pipeline_id))
|
||||
|
||||
@staticmethod
|
||||
def _make_request(
|
||||
url: str, data=None, headers: Optional[Dict] = None, method: str = "get"
|
||||
):
|
||||
if headers is None:
|
||||
headers = {
|
||||
"Accept": "application/json",
|
||||
"Authorization": f'Bearer {os.getenv("LLAMA_CLOUD_API_KEY")}',
|
||||
}
|
||||
response = requests.request(method, url, headers=headers, data=data)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
@@ -1,22 +0,0 @@
|
||||
import logging
|
||||
from llama_index.core.indices import VectorStoreIndex
|
||||
from app.engine.vectordb import get_vector_store
|
||||
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
index = None
|
||||
|
||||
def get_index(params=None):
|
||||
global index
|
||||
if index is None:
|
||||
logger.info("Connecting vector store...")
|
||||
|
||||
store = get_vector_store()
|
||||
# Load the index from the vector store
|
||||
# If you are using a vector store that doesn't store text,
|
||||
# you must load the index from both the vector store and the document store
|
||||
index = VectorStoreIndex.from_vector_store(store)
|
||||
logger.info("Finished load index from vector store.")
|
||||
|
||||
return index
|
||||
@@ -1,61 +0,0 @@
|
||||
import os
|
||||
|
||||
from llama_index.core.agent import AgentRunner, ReActChatFormatter
|
||||
from llama_index.core.settings import Settings
|
||||
from llama_index.core.tools.query_engine import QueryEngineTool
|
||||
|
||||
from app.engine.engine import create_query_engine, create_summary_query_engine
|
||||
from app.engine.index import get_index
|
||||
#from app.engine.loaders.db import makeDescriptionByEngine
|
||||
from app.engine.tools import ToolFactory
|
||||
|
||||
|
||||
def get_chat_engine(filters=None, params=None):
|
||||
system_prompt = os.getenv("SYSTEM_PROMPT")
|
||||
top_k = int(os.getenv("TOP_K", "3"))
|
||||
use_reranker = os.getenv("RERANK_ENABLED")
|
||||
tools = []
|
||||
|
||||
# 创建SQL查询工具
|
||||
# sql_query_engine = create_summary_query_engine(index)
|
||||
# sql_query_tool = QueryEngineTool.from_defaults(query_engine=sql_query_engine,
|
||||
# name="zjdata_query_tool",
|
||||
# description="来源于一个由博微公司电力造价软件编制的造价工程文件。该文件以多张表格的形式存储存储了整个工程的全部数据内容。适用于以详细的自然语言查询表格数据方式查询造价工程各项具体属性、费用的数值。请先使用“zj_query_tool”无法解决才使用本工具"
|
||||
# )
|
||||
#tools.append(sql_query_tool)
|
||||
|
||||
# Add query tool if index exists
|
||||
index = get_index()
|
||||
if index is not None:
|
||||
summary_query_engine = create_summary_query_engine(index,top_k,use_reranker,filters)
|
||||
summary_query_tool = QueryEngineTool.from_defaults( query_engine=summary_query_engine, name="summary_query_tool",
|
||||
description="适用于任何需要进行全面总结、概括的要求。",
|
||||
)
|
||||
query_engine = create_query_engine(index,top_k,use_reranker,filters)
|
||||
query_engine_tool = QueryEngineTool.from_defaults(query_engine=query_engine, name="zj_query_tool",
|
||||
description="由博微公司编制的关于电力造价知识、电力造价编制软件知识和造价工程文件结构的知识库。适用于查询电力领域、电力造价领域、博微、博微电力、博微造价等业务等内容。如果本知识库没有直接答案但有解决思路的可以返回解决办法后建议使用“zjdata_query_tool”工具。",
|
||||
)
|
||||
|
||||
tools.append(summary_query_tool)
|
||||
tools.append(query_engine_tool)
|
||||
|
||||
# Add additional tools
|
||||
tools += ToolFactory.from_env()
|
||||
|
||||
prefix_messages = ("""您的设计旨在帮助完成各种任务,从回答问题到提供其他类型分析的摘要。\n\n##工具\n\n你可以访问各种工具。你有责任按照你认为合适的顺序使用这些工具来完成当前的任务。\n这可能需要将任务分解为子任务,并使用不同的工具来完成每个子任务。\n\n你可以访问以下工具:\n{tool_desc}\n\n\n##输出格式\n\n请用与问题相同的语言回答,并使用以下格式:\n\n \nThought: 用户当前的语言是:(user's language)。我需要使用工具来帮助我回答问题。\nAction: 如果使用工具,则为工具名称(one of {tool_names})。\nAction Input: 输入给工具的内容,使用JSON格式表示kwargs(例如{{\"input\": \"hello world\", \"num_beams\": 5}})\n \n\n请始终以Thought开始。\n\n请始终以Thought开始。\n\n请始终以Thought开始。\n\n请始终以Thought开始。\n\n切勿用Markdown代码标记包围你的响应。如果需要,可以在响应中使用代码标记。\n\n请为Action Input使用有效的JSON格式。不要这样做{{\'input\': \'hello world\', \'num_beams\': 5}}。\n\n如果使用此格式,用户将以下面的格式进行回应:\n\n \nObservation: 工具响应\n \n\n你应该继续重复上述格式,直到你有足够的信息来回答问题而无需使用更多工具。此时,你必须使用以下两种格式之一进行回答:\n\n \nThought: 我可以不用任何工具来回答。我将使用用户的语言来回答。\nAnswer: [你的答案(与用户问题相同的语言)]\n \n\n \nThought: 我无法使用提供的工具回答问题。\nAnswer: [你的答案(与用户问题相同的语言)]\n \n\n##如果从工具中得到的回应是Empty Response,那么只需要回答“我不知道”,不需要额外回答别的内容。## 当前对话\n\n以下是当前对话,由人类和助手的消息交替组成。\n""")
|
||||
react_chat_formatter = ReActChatFormatter.from_defaults(prefix_messages)
|
||||
agentrunner = AgentRunner.from_llm(
|
||||
llm=Settings.llm,
|
||||
tools=tools,
|
||||
react_chat_formatter=react_chat_formatter,
|
||||
system_prompt=system_prompt,
|
||||
verbose=True,
|
||||
)
|
||||
return agentrunner
|
||||
# create the function calling worker for reasoning
|
||||
# worker = FunctionCallingAgentWorker.from_tools(
|
||||
# tools, verbose=True
|
||||
# )
|
||||
#
|
||||
# # wrap the worker in the top-level planner
|
||||
# return StructuredPlannerAgent(worker, tools)
|
||||
@@ -1 +0,0 @@
|
||||
STORAGE_DIR = "storage" # directory to cache the generated index
|
||||
@@ -1,108 +0,0 @@
|
||||
import os
|
||||
|
||||
from llama_index.core import SummaryIndex, SQLDatabase, VectorStoreIndex
|
||||
from llama_index.core.indices.struct_store import SQLTableRetrieverQueryEngine
|
||||
from llama_index.core.objects import SQLTableNodeMapping, ObjectIndex, SQLTableSchema
|
||||
from llama_index.core.query_engine import RetrieverQueryEngine
|
||||
from llama_index.core.response_synthesizers import ResponseMode
|
||||
from llama_index.readers.database import DatabaseReader
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
from app.engine.prompt import text_qa_template, refine_template, summary_template, simple_template
|
||||
from app.engine.retriever.HybridRetriever import HybridRetriever
|
||||
from app.settings import get_node_postprocessors
|
||||
|
||||
def makeDescriptionByEngine(sql_database:SQLDatabase):
|
||||
reader = DatabaseReader(sql_database)
|
||||
|
||||
table_names = sql_database.get_usable_table_names()
|
||||
table_schema_objs = []
|
||||
for table_name in table_names:
|
||||
columns = sql_database.get_table_columns(table_name)
|
||||
if len(columns) > 150:
|
||||
continue
|
||||
stats_txt = ""
|
||||
|
||||
if table_name == 'gongchengshuxing':
|
||||
stats_txt = '该表中有以下属性:'
|
||||
documents = reader.load_data(query='select name from gongchengshuxing')
|
||||
for index in range(len(documents) if len(documents) < 30 else 30):
|
||||
if index == 0:
|
||||
continue
|
||||
elif index > 1:
|
||||
stats_txt += ','
|
||||
stats_txt += documents[index].text.split(':')[1]
|
||||
|
||||
tbSchema = (SQLTableSchema(table_name=table_name, context_str=stats_txt))
|
||||
table_schema_objs.append(tbSchema)
|
||||
|
||||
return table_schema_objs
|
||||
|
||||
def get_Retriever(index,**kwargs):
|
||||
strEnableHybrid = os.getenv("HYBRID_ENABLED",'False')
|
||||
bEnableHybrid = True if strEnableHybrid is not None and strEnableHybrid.title() == 'True' else False
|
||||
if bEnableHybrid:
|
||||
alpha = float(os.getenv("HYBRID_ALPHA", "0.5"))
|
||||
retriever = HybridRetriever(index,alpha = alpha,**kwargs)
|
||||
else:
|
||||
retriever = index.as_retriever(**kwargs)
|
||||
return retriever
|
||||
|
||||
|
||||
sql_database = None
|
||||
sql_obj_index = None
|
||||
|
||||
# Create a summary query engine
|
||||
def create_summary_query_engine(top_k=3, use_reranker=False, filters=None):
|
||||
global sql_obj_index
|
||||
global sql_database
|
||||
if sql_obj_index is None or sql_database is None:
|
||||
sqlengine = create_engine(os.getenv("SQL_DATABASE_URL", ""))
|
||||
sql_database = SQLDatabase(sqlengine)
|
||||
table_schema_objs = makeDescriptionByEngine(sql_database)
|
||||
table_node_mapping = SQLTableNodeMapping(sql_database)
|
||||
|
||||
sql_obj_index = ObjectIndex.from_objects(
|
||||
table_schema_objs,
|
||||
table_node_mapping,
|
||||
index_cls=VectorStoreIndex,
|
||||
)
|
||||
|
||||
# 创建SQL查询工具
|
||||
sql_query_engine = SQLTableRetrieverQueryEngine(sql_database,
|
||||
sql_obj_index.as_retriever(similarity_top_k=top_k),
|
||||
verbose=True,
|
||||
)
|
||||
return sql_query_engine
|
||||
|
||||
# Create a summary query engine
|
||||
def create_summary_query_engine(index, top_k=3, use_reranker=False, filters=None):
|
||||
summary_index = SummaryIndex(index.vector_store.get_nodes(node_ids=None))
|
||||
summary_query_engine = summary_index.as_query_engine(
|
||||
response_mode=ResponseMode.TREE_SUMMARIZE,
|
||||
use_async=True,
|
||||
streaming=True,
|
||||
)
|
||||
return summary_query_engine
|
||||
|
||||
# Create a query engine
|
||||
def create_query_engine(index, top_k=3, use_reranker=False, filters=None):
|
||||
# 创建向量检索查询工具
|
||||
postprocess = None
|
||||
if use_reranker:
|
||||
postprocess = get_node_postprocessors()
|
||||
|
||||
query_engine = RetrieverQueryEngine.from_args(
|
||||
get_Retriever(index,
|
||||
similarity_top_k=top_k,
|
||||
filters=filters),
|
||||
text_qa_template=text_qa_template,
|
||||
refine_template=refine_template,
|
||||
summary_template = summary_template,
|
||||
simple_template = simple_template,
|
||||
node_postprocessors=postprocess,
|
||||
use_async=True,
|
||||
streaming=True,
|
||||
)
|
||||
|
||||
return query_engine
|
||||
@@ -1,94 +0,0 @@
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from app.engine.loaders import get_documents
|
||||
from app.engine.vectordb import get_vector_store
|
||||
from app.settings import init_settings
|
||||
from app.engine.retriever.CHBM25Retriever import CHBM25Retriever
|
||||
from llama_index.core.ingestion import IngestionPipeline
|
||||
from llama_index.core.node_parser import SentenceSplitter
|
||||
from llama_index.core.settings import Settings
|
||||
from llama_index.core.storage import StorageContext
|
||||
from llama_index.core.storage.docstore import SimpleDocumentStore
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger()
|
||||
|
||||
STORAGE_DIR = os.getenv("STORAGE_DIR", "storage")
|
||||
|
||||
|
||||
def get_doc_store():
|
||||
|
||||
# If the storage directory is there, load the document store from it.
|
||||
# If not, set up an in-memory document store since we can't load from a directory that doesn't exist.
|
||||
if os.path.exists(STORAGE_DIR):
|
||||
return SimpleDocumentStore.from_persist_dir(STORAGE_DIR)
|
||||
else:
|
||||
return SimpleDocumentStore()
|
||||
|
||||
|
||||
def run_pipeline(docstore, vector_store, documents):
|
||||
pipeline = IngestionPipeline(
|
||||
transformations=[
|
||||
SentenceSplitter(
|
||||
chunk_size=Settings.chunk_size,
|
||||
chunk_overlap=Settings.chunk_overlap,
|
||||
),
|
||||
Settings.embed_model,
|
||||
],
|
||||
docstore=docstore,
|
||||
docstore_strategy="upserts_and_delete",
|
||||
vector_store=vector_store,
|
||||
)
|
||||
|
||||
# Run the ingestion pipeline and store the results
|
||||
nodes = pipeline.run(show_progress=True, documents=documents)
|
||||
|
||||
return nodes
|
||||
|
||||
|
||||
def persist_storage(docstore, vector_store):
|
||||
storage_context = StorageContext.from_defaults(
|
||||
docstore=docstore,
|
||||
vector_store=vector_store,
|
||||
)
|
||||
storage_context.persist(STORAGE_DIR)
|
||||
|
||||
|
||||
def persist_BMRetriever(vector_store):
|
||||
STORAGE_DIR = os.getenv("BM_RETRIEVER_PATH", "storage_bm")
|
||||
top_k = int(os.getenv("TOP_K", "3"))
|
||||
bmRetriver = CHBM25Retriever.from_defaults(similarity_top_k=top_k,nodes=vector_store.get_nodes([]))
|
||||
bmRetriver.persist(STORAGE_DIR)
|
||||
|
||||
|
||||
def generate_datasource():
|
||||
init_settings()
|
||||
logger.info("Generate index for the provided data")
|
||||
|
||||
# Get the stores and documents or create new ones
|
||||
documents = get_documents()
|
||||
# Set private=false to mark the document as public (required for filtering)
|
||||
for doc in documents:
|
||||
doc.metadata["private"] = "false"
|
||||
docstore = get_doc_store()
|
||||
vector_store = get_vector_store()
|
||||
|
||||
# Run the ingestion pipeline
|
||||
_ = run_pipeline(docstore, vector_store, documents)
|
||||
|
||||
# Build the index and persist storage
|
||||
persist_storage(docstore, vector_store)
|
||||
persist_BMRetriever(vector_store)
|
||||
|
||||
logger.info("Finished generating the index")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from phoenix.trace import using_project
|
||||
with using_project(os.getenv("PHOENIX_PROJECT_NAME") + "_generate") as obj:
|
||||
generate_datasource()
|
||||
@@ -1,93 +0,0 @@
|
||||
from llama_index.core import PromptTemplate
|
||||
|
||||
text_qa_template_str = (
|
||||
"# 角色\n"
|
||||
"你是一名博微造价工程数据查询助手,专精于电力工程文件中的信息。"
|
||||
"你的职责是提供有关电力造价、造价编制软件、文件结构及相关数据的精准、客观的回答,"
|
||||
"如同直接从文件中提取的内容。\n"
|
||||
"知识库中已经导入一个工程的全部数据,请你站在当前工程的角度回答用户关于工程文件的问题。\n"
|
||||
"例如:询问“此工程”指当前导入的工程。询问“此工程名称”指当前导入的工程的工程名称。\n"
|
||||
|
||||
"## 技能\n"
|
||||
"### 技能 1: 数据查询与提供\n"
|
||||
"- 准确回答所有关于电力工程造价的相关问题。\n"
|
||||
"- 提供具体数据,如成本估算、材料清单、劳动力需求等。\n"
|
||||
"- 确保提供的信息严格基于工程文档中的记录。\n"
|
||||
|
||||
"### 技能 2: 技术性解释\n"
|
||||
"- 解释造价工程中的技术术语和概念。\n"
|
||||
"- 为复杂的工程细节提供清晰易懂的说明。\n"
|
||||
|
||||
"## 约束\n"
|
||||
"- 仅回答与电力工程造价文件相关的具体问题。\n"
|
||||
"- 不进行任何超出文件内容的猜测或假设。\n"
|
||||
"- 所有回答均基于文件内容,采用客观和技术性的语言。\n"
|
||||
"- 请基于这些信息回答问题。如果无法找到相关信息,请不要额外发散回答,不要回答多余的信息,只需要回答“我不知道这个问题的答案”。\n"
|
||||
"以下为上下文信息\n"
|
||||
"---------------------\n"
|
||||
"{context_str}\n"
|
||||
"---------------------\n"
|
||||
"请根据上下文信息而非先前知识回答我的问题或回复我的指令。前面的上下文信息可能有用,也可能没用,你需要从我给出的上下文信息中选出与我的问题最相关的那些,来为你的回答提供依据。回答一定要忠于原文,简洁但不丢信息,不要胡乱编造。如果无法找到相关信息,请不要额外发散回答,不要回答多余的信息,只需要回答“我不知道这个问题的答案”。我的问题或指令是什么语种,你就用什么语种回复。\n"
|
||||
"如果是表结构或者是数据库的相关内容,只用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n"
|
||||
|
||||
"问题:{query_str}\n"
|
||||
"你的回复: "
|
||||
)
|
||||
|
||||
|
||||
text_qa_template = PromptTemplate(text_qa_template_str)
|
||||
|
||||
refine_template_str = (
|
||||
"这是原本的问题: {query_str}\n"
|
||||
"我们已经提供了回答: {existing_answer}\n"
|
||||
"现在我们有机会改进这个回答 "
|
||||
"使用以下更多上下文(仅当有助于改进回答时使用)\n"
|
||||
"如果新的上下文对回答没有影响,或者原来的回答已经正确,不要在上次回答的后边再加上多余的补充信息,直接返回原本的回答。\n"
|
||||
"如果新的上下文对回答没有影响,或者原来的回答已经正确,不要在上次回答的后边再加上多余的补充信息,直接返回原本的回答。\n"
|
||||
"------------\n"
|
||||
"{context_msg}\n"
|
||||
"------------\n"
|
||||
"如果回答中已经包含有正确答案,不要返回多余的解释等信息,只返回正确答案\n"
|
||||
"如果是表结构或者是数据库的相关内容,仅用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n"
|
||||
"改进的回答: "
|
||||
)
|
||||
|
||||
refine_template = PromptTemplate(refine_template_str)
|
||||
|
||||
summary_template_str = (
|
||||
"# 角色\n"
|
||||
"你是一名博微造价工程数据查询助手,专精于电力工程文件中的信息。"
|
||||
"你的职责是提供有关电力造价、造价编制软件、文件结构及相关数据的精准、客观的回答,"
|
||||
"如同直接从文件中提取的内容。\n"
|
||||
|
||||
"## 技能\n"
|
||||
"### 技能 1: 数据查询与提供\n"
|
||||
"- 准确回答所有关于电力工程造价的相关问题。\n"
|
||||
"- 提供具体数据,如成本估算、材料清单、劳动力需求等。\n"
|
||||
"- 确保提供的信息严格基于工程文档中的记录。\n"
|
||||
|
||||
"### 技能 2: 技术性解释\n"
|
||||
"- 解释造价工程中的技术术语和概念。\n"
|
||||
"- 为复杂的工程细节提供清晰易懂的说明。\n"
|
||||
|
||||
"## 约束\n"
|
||||
"- 仅回答与电力工程造价文件相关的具体问题。\n"
|
||||
"- 不进行任何超出文件内容的猜测或假设。\n"
|
||||
"- 所有回答均基于文件内容,采用客观和技术性的语言。\n"
|
||||
"- 请基于这些信息回答问题。如果无法找到相关信息,请不要额外发散回答,不要回答多余的信息,只需要回答“我不知道这个问题的答案”。\n"
|
||||
"来自多个来源的上下文信息如下。\n"
|
||||
"---------------------\n"
|
||||
"{context_str}\n"
|
||||
"---------------------\n"
|
||||
"鉴于来自多个来源的信息而非先验知识, "
|
||||
"回答查询。\n"
|
||||
"如果是表结构或者是数据库的相关内容,只用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n"
|
||||
"Query: {query_str}\n"
|
||||
"Answer: "
|
||||
)
|
||||
summary_template = PromptTemplate(summary_template_str)
|
||||
|
||||
simple_template_str = (
|
||||
"{query_str}"
|
||||
)
|
||||
simple_template = PromptTemplate(simple_template_str)
|
||||
@@ -1,71 +0,0 @@
|
||||
import os
|
||||
from llama_index.vector_stores.chroma import ChromaVectorStore
|
||||
from llama_index.vector_stores.qdrant import QdrantVectorStore
|
||||
from qdrant_client import qdrant_client
|
||||
|
||||
qclient = None
|
||||
|
||||
def get_qdrant_vector_store():
|
||||
collection_name = os.getenv("VECTOR_STORE_COLLECTION", "default")
|
||||
vector_store_path = os.getenv("VECTOR_STORE_PATH")
|
||||
host=os.getenv("VECTOR_STORE_HOST", "127.0.0.1"),
|
||||
port=int(os.getenv("VECTOR_STORE_PORT", "6333")),
|
||||
|
||||
if not vector_store_path or not host:
|
||||
raise ValueError(
|
||||
"Please provide either VECTOR_STORE_PATH or VECTOR_STORE_HOST and VECTOR_STORE_PORT"
|
||||
)
|
||||
# if VECTOR_STORE_PATH is set, use a local QdrantVectorStore from the path
|
||||
# otherwise, use a remote QdrantVectorStore
|
||||
global qclient
|
||||
if qclient == None:
|
||||
if vector_store_path:
|
||||
qclient = qdrant_client.QdrantClient(
|
||||
path=vector_store_path,
|
||||
)
|
||||
else:
|
||||
qclient = qdrant_client.QdrantClient(
|
||||
host=host,
|
||||
port=port,
|
||||
)
|
||||
|
||||
vector_store = QdrantVectorStore(client=qclient, collection_name=collection_name)
|
||||
return vector_store
|
||||
|
||||
def get_chroma_vector_store():
|
||||
collection_name = os.getenv("VECTOR_STORE_COLLECTION", "default")
|
||||
vector_store_path = os.getenv("VECTOR_STORE_PATH")
|
||||
# if VECTOR_STORE_PATH is set, use a local ChromaVectorStore from the path
|
||||
# otherwise, use a remote ChromaVectorStore (ChromaDB Cloud is not supported yet)
|
||||
if vector_store_path:
|
||||
store = ChromaVectorStore.from_params(
|
||||
persist_dir=vector_store_path, collection_name=collection_name,
|
||||
collection_kwargs={"metadata":{"hnsw:space":"cosine"}},
|
||||
)
|
||||
else:
|
||||
if not os.getenv("VECTOR_STORE_HOST") or not os.getenv("VECTOR_STORE_PORT"):
|
||||
raise ValueError(
|
||||
"Please provide either VECTOR_STORE_PATH or VECTOR_STORE_HOST and VECTOR_STORE_PORT"
|
||||
)
|
||||
store = ChromaVectorStore.from_params(
|
||||
host=os.getenv("VECTOR_STORE_HOST"),
|
||||
port=int(os.getenv("VECTOR_STORE_PORT")),
|
||||
collection_name=collection_name,
|
||||
collection_kwargs={"metadata":{"hnsw:space":"cosine"}},
|
||||
)
|
||||
return store
|
||||
|
||||
def get_vector_store():
|
||||
store_type=os.getenv("VECTOR_STORE_TYPE")
|
||||
|
||||
store = None
|
||||
|
||||
match store_type:
|
||||
case "chroma":
|
||||
store = get_chroma_vector_store()
|
||||
case "qdrant":
|
||||
store = get_qdrant_vector_store()
|
||||
case _:
|
||||
raise ValueError(f"Invalid vector store type: {store_type}")
|
||||
|
||||
return store
|
||||
@@ -6,16 +6,28 @@ from llama_index.core.tools.query_engine import QueryEngineTool
|
||||
|
||||
from app.engine.engine import create_query_engine, create_summary_query_engine
|
||||
from app.engine.index import get_index
|
||||
from app.engine.prompt import ReActChatFormatter_messages, tree_summary_query_engine_tool_messages, \
|
||||
query_engine_tool_messages, summary_query_tool_messages
|
||||
#from app.engine.loaders.db import makeDescriptionByEngine
|
||||
from app.engine.tools import ToolFactory
|
||||
from app.api.routers.request.base import ProjectInfo
|
||||
from llama_index.core.response_synthesizers import ResponseMode
|
||||
|
||||
def getPrjFalg(params:dict=None)->str:
|
||||
if 'prjFalg' in params:
|
||||
return params.get('prjFalg')
|
||||
else:
|
||||
prjFlag = ''
|
||||
if params is not None:
|
||||
prjFlag = ProjectInfo().prjFalg(params.get('projectname'))
|
||||
return prjFlag
|
||||
|
||||
|
||||
def get_chat_engine(filters=None, params=None):
|
||||
def get_chat_engine(filters=None, params:dict=None):
|
||||
system_prompt = os.getenv("SYSTEM_PROMPT")
|
||||
top_k = int(os.getenv("TOP_K", "3"))
|
||||
use_reranker = os.getenv("RERANK_ENABLED")
|
||||
tools = []
|
||||
|
||||
# 创建SQL查询工具
|
||||
# sql_query_engine = create_summary_query_engine(index)
|
||||
# sql_query_tool = QueryEngineTool.from_defaults(query_engine=sql_query_engine,
|
||||
@@ -25,33 +37,40 @@ def get_chat_engine(filters=None, params=None):
|
||||
#tools.append(sql_query_tool)
|
||||
|
||||
# Add query tool if index exists
|
||||
index = get_index()
|
||||
index = get_index(getPrjFalg(params))
|
||||
if index is not None:
|
||||
|
||||
|
||||
summary_query_engine = create_summary_query_engine(index,top_k,use_reranker,filters)
|
||||
summary_query_tool = QueryEngineTool.from_defaults( query_engine=summary_query_engine, name="summary_query_tool",
|
||||
description="适用于任何需要进行全面总结、概括的要求。",
|
||||
)
|
||||
query_engine = create_query_engine(index,top_k,use_reranker,filters)
|
||||
query_engine_tool = QueryEngineTool.from_defaults(query_engine=query_engine, name="zj_query_tool",
|
||||
description="由博微公司编制的关于电力造价知识、电力造价编制软件知识和造价工程文件结构的知识库。适用于查询电力领域、电力造价领域、博微、博微电力、博微造价等业务等内容。如果本知识库没有直接答案但有解决思路的可以返回解决办法后建议使用“zjdata_query_tool”工具。",
|
||||
description=summary_query_tool_messages,
|
||||
)
|
||||
|
||||
tools.append(summary_query_tool)
|
||||
query_engine = create_query_engine(index,top_k,use_reranker,filters,response_mode = ResponseMode.TREE_SUMMARIZE)
|
||||
query_engine_tool = QueryEngineTool.from_defaults(query_engine=query_engine, name="zj_query_tool",
|
||||
description=query_engine_tool_messages)
|
||||
|
||||
query_engine = create_query_engine(index,top_k,use_reranker,filters,response_mode = ResponseMode.TREE_SUMMARIZE)
|
||||
query_engine_tool_1 = QueryEngineTool.from_defaults(query_engine=query_engine, name="zj_query_tool_1",
|
||||
description=tree_summary_query_engine_tool_messages)
|
||||
|
||||
tools.append(query_engine_tool)
|
||||
#tools.append(query_engine_tool_1)
|
||||
#tools.append(summary_query_tool)
|
||||
|
||||
# Add additional tools
|
||||
tools += ToolFactory.from_env()
|
||||
|
||||
prefix_messages = ("""您的设计旨在帮助完成各种任务,从回答问题到提供其他类型分析的摘要。\n\n##工具\n\n你可以访问各种工具。你有责任按照你认为合适的顺序使用这些工具来完成当前的任务。\n这可能需要将任务分解为子任务,并使用不同的工具来完成每个子任务。\n\n你可以访问以下工具:\n{tool_desc}\n\n\n##输出格式\n\n请用与问题相同的语言回答,并使用以下格式:\n\n \nThought: 用户当前的语言是:(user's language)。我需要使用工具来帮助我回答问题。\nAction: 如果使用工具,则为工具名称(one of {tool_names})。\nAction Input: 输入给工具的内容,使用JSON格式表示kwargs(例如{{\"input\": \"hello world\", \"num_beams\": 5}})\n \n\n请始终以Thought开始。\n\n请始终以Thought开始。\n\n请始终以Thought开始。\n\n请始终以Thought开始。\n\n切勿用Markdown代码标记包围你的响应。如果需要,可以在响应中使用代码标记。\n\n请为Action Input使用有效的JSON格式。不要这样做{{\'input\': \'hello world\', \'num_beams\': 5}}。\n\n如果使用此格式,用户将以下面的格式进行回应:\n\n \nObservation: 工具响应\n \n\n你应该继续重复上述格式,直到你有足够的信息来回答问题而无需使用更多工具。此时,你必须使用以下两种格式之一进行回答:\n\n \nThought: 我可以不用任何工具来回答。我将使用用户的语言来回答。\nAnswer: [你的答案(与用户问题相同的语言)]\n \n\n \nThought: 我无法使用提供的工具回答问题。\nAnswer: [你的答案(与用户问题相同的语言)]\n \n\n##如果从工具中得到的回应是Empty Response,那么只需要回答“我不知道”,不需要额外回答别的内容。## 当前对话\n\n以下是当前对话,由人类和助手的消息交替组成。\n""")
|
||||
react_chat_formatter = ReActChatFormatter.from_defaults(prefix_messages)
|
||||
react_chat_formatter = ReActChatFormatter.from_defaults(ReActChatFormatter_messages)
|
||||
agentrunner = AgentRunner.from_llm(
|
||||
llm=Settings.llm,
|
||||
tools=tools,
|
||||
react_chat_formatter=react_chat_formatter,
|
||||
#react_chat_formatter=react_chat_formatter,
|
||||
system_prompt=system_prompt,
|
||||
verbose=True,
|
||||
)
|
||||
return agentrunner
|
||||
|
||||
# create the function calling worker for reasoning
|
||||
# worker = FunctionCallingAgentWorker.from_tools(
|
||||
# tools, verbose=True
|
||||
|
||||
@@ -7,10 +7,31 @@ from llama_index.core.query_engine import RetrieverQueryEngine
|
||||
from llama_index.core.response_synthesizers import ResponseMode
|
||||
from llama_index.readers.database import DatabaseReader
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
from util.register import *
|
||||
from app.engine.prompt import text_qa_template, refine_template, summary_template, simple_template
|
||||
from app.engine.retriever.HybridRetriever import HybridRetriever
|
||||
from app.settings import get_node_postprocessors
|
||||
from app.engine.response.treeSummResponse import CustomTreeResponse
|
||||
from llama_index.core.settings import Settings
|
||||
from llama_index.core.indices.property_graph import LLMSynonymRetriever,VectorContextRetriever
|
||||
from llama_index.core import PropertyGraphIndex
|
||||
from app.engine.retriever.graphKeyWordRetriever import GraphKeyWordRetriever
|
||||
|
||||
ModelPlateCategory = '模型平台'
|
||||
|
||||
def get_node_postprocessors():
|
||||
rerank_enabled = os.getenv("RERANK_ENABLED").title()
|
||||
if rerank_enabled is None or rerank_enabled == 'False':
|
||||
return []
|
||||
|
||||
Rerank_provider = os.getenv("RERANK_PROVIDER")
|
||||
modelPaltCls = ClsRegister.get(ModelPlateCategory,Rerank_provider)
|
||||
postprocess = None
|
||||
if modelPaltCls is not None:
|
||||
modelPalt = modelPaltCls()
|
||||
postprocess = modelPalt.rerank()
|
||||
else:
|
||||
raise ValueError(f"Invalid rerank provider: {Rerank_provider}")
|
||||
return postprocess
|
||||
|
||||
def makeDescriptionByEngine(sql_database:SQLDatabase):
|
||||
reader = DatabaseReader(sql_database)
|
||||
@@ -48,6 +69,13 @@ def get_Retriever(index,**kwargs):
|
||||
retriever = index.as_retriever(**kwargs)
|
||||
return retriever
|
||||
|
||||
def get_synthesizer():
|
||||
return CustomTreeResponse(
|
||||
llm=Settings.llm,
|
||||
summary_template=summary_template,
|
||||
use_async=True,
|
||||
streaming=False,
|
||||
)
|
||||
|
||||
sql_database = None
|
||||
sql_obj_index = None
|
||||
@@ -81,28 +109,50 @@ def create_summary_query_engine(index, top_k=3, use_reranker=False, filters=None
|
||||
summary_query_engine = summary_index.as_query_engine(
|
||||
response_mode=ResponseMode.TREE_SUMMARIZE,
|
||||
use_async=True,
|
||||
streaming=True,
|
||||
streaming=False,
|
||||
)
|
||||
return summary_query_engine
|
||||
|
||||
# Create a query engine
|
||||
def create_query_engine(index, top_k=3, use_reranker=False, filters=None):
|
||||
def create_query_engine(index,top_k=3, use_reranker=False, filters=None, response_mode=None):
|
||||
# 创建向量检索查询工具
|
||||
postprocess = None
|
||||
if use_reranker:
|
||||
postprocess = get_node_postprocessors()
|
||||
|
||||
query_engine = RetrieverQueryEngine.from_args(
|
||||
get_Retriever(index,
|
||||
llm_query = os.getenv('LLM_QUERY_WAY','rag')
|
||||
if llm_query == 'graph':
|
||||
graphIndex:PropertyGraphIndex = index
|
||||
keyWord_retriver = GraphKeyWordRetriever(graphIndex.property_graph_store,
|
||||
include_text=False
|
||||
)
|
||||
if graphIndex.property_graph_store.supports_vector_queries:
|
||||
vector_store = None
|
||||
else:
|
||||
vector_store = graphIndex.vector_store
|
||||
vector_retriver = VectorContextRetriever(graphIndex.property_graph_store,
|
||||
vector_store = vector_store,
|
||||
embed_model=Settings.embed_model,
|
||||
similarity_top_k=top_k,
|
||||
filters=filters),
|
||||
include_text=False
|
||||
)
|
||||
|
||||
retriever = graphIndex.as_retriever(sub_retrievers=[keyWord_retriver,vector_retriver])
|
||||
|
||||
else:
|
||||
retriever = get_Retriever(index,
|
||||
similarity_top_k=top_k,
|
||||
filters=filters)
|
||||
query_engine = RetrieverQueryEngine.from_args(
|
||||
retriever = retriever,
|
||||
text_qa_template=text_qa_template,
|
||||
refine_template=refine_template,
|
||||
summary_template = summary_template,
|
||||
simple_template = simple_template,
|
||||
node_postprocessors=postprocess,
|
||||
use_async=True,
|
||||
streaming=True,
|
||||
streaming=False,
|
||||
response_mode = response_mode
|
||||
)
|
||||
|
||||
return query_engine
|
||||
@@ -5,39 +5,41 @@ load_dotenv()
|
||||
import logging
|
||||
import os
|
||||
|
||||
from app.engine.loaders import get_documents
|
||||
from app.engine.vectordb import get_vector_store
|
||||
from app.engine.loaders import get_document_Types, get_documents,getProjectInfos
|
||||
from app.engine.vectordb import get_vector_store,get_Neo4j_Graph_Store
|
||||
from app.settings import init_settings
|
||||
from app.engine.retriever.CHBM25Retriever import CHBM25Retriever
|
||||
from llama_index.core.ingestion import IngestionPipeline
|
||||
from llama_index.core.node_parser import SentenceSplitter
|
||||
from llama_index.core.node_parser import SentenceSplitter,MarkdownNodeParser
|
||||
from llama_index.core.settings import Settings
|
||||
from llama_index.core.storage import StorageContext
|
||||
from llama_index.core.storage.docstore import SimpleDocumentStore
|
||||
from llama_index.core import PropertyGraphIndex
|
||||
from app.engine.graph.extractor import PrjGraphExtractor
|
||||
from app.engine.graph.graphStore import RAGPropertyGraphStore
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger()
|
||||
|
||||
STORAGE_DIR = os.getenv("STORAGE_DIR", "storage")
|
||||
|
||||
|
||||
def get_doc_store():
|
||||
|
||||
def get_doc_store(docType:str):
|
||||
# If the storage directory is there, load the document store from it.
|
||||
# If not, set up an in-memory document store since we can't load from a directory that doesn't exist.
|
||||
if os.path.exists(STORAGE_DIR):
|
||||
return SimpleDocumentStore.from_persist_dir(STORAGE_DIR)
|
||||
storeDir = os.path.join(STORAGE_DIR,docType)
|
||||
if os.path.exists(storeDir):
|
||||
return SimpleDocumentStore.from_persist_dir(storeDir)
|
||||
else:
|
||||
return SimpleDocumentStore()
|
||||
|
||||
|
||||
def run_pipeline(docstore, vector_store, documents):
|
||||
pipeline = IngestionPipeline(
|
||||
transformations=[
|
||||
SentenceSplitter(
|
||||
chunk_size=Settings.chunk_size,
|
||||
chunk_overlap=Settings.chunk_overlap,
|
||||
),
|
||||
#SentenceSplitter(
|
||||
#chunk_size=Settings.chunk_size,
|
||||
#chunk_overlap=Settings.chunk_overlap,
|
||||
#),
|
||||
#MarkdownNodeParser(),
|
||||
Settings.embed_model,
|
||||
],
|
||||
docstore=docstore,
|
||||
@@ -47,10 +49,8 @@ def run_pipeline(docstore, vector_store, documents):
|
||||
|
||||
# Run the ingestion pipeline and store the results
|
||||
nodes = pipeline.run(show_progress=True, documents=documents)
|
||||
|
||||
return nodes
|
||||
|
||||
|
||||
def persist_storage(docstore, vector_store):
|
||||
storage_context = StorageContext.from_defaults(
|
||||
docstore=docstore,
|
||||
@@ -58,25 +58,25 @@ def persist_storage(docstore, vector_store):
|
||||
)
|
||||
storage_context.persist(STORAGE_DIR)
|
||||
|
||||
|
||||
def persist_BMRetriever(vector_store):
|
||||
STORAGE_DIR = os.getenv("BM_RETRIEVER_PATH", "storage_bm")
|
||||
top_k = int(os.getenv("TOP_K", "3"))
|
||||
bmRetriver = CHBM25Retriever.from_defaults(similarity_top_k=top_k,nodes=vector_store.get_nodes([]))
|
||||
nodes = vector_store.get_nodes([])
|
||||
top_k = min(int(os.getenv("TOP_K", "3")),len(nodes))
|
||||
bmRetriver = CHBM25Retriever.from_defaults(similarity_top_k=top_k,nodes = nodes)
|
||||
bmRetriver.persist(STORAGE_DIR)
|
||||
|
||||
|
||||
def generate_datasource():
|
||||
init_settings()
|
||||
logger.info("Generate index for the provided data")
|
||||
|
||||
# Get the stores and documents or create new ones
|
||||
documents = get_documents()
|
||||
docTypes = get_document_Types()
|
||||
for docType in docTypes:
|
||||
documents = get_documents(docType)
|
||||
# Set private=false to mark the document as public (required for filtering)
|
||||
for doc in documents:
|
||||
doc.metadata["private"] = "false"
|
||||
docstore = get_doc_store()
|
||||
vector_store = get_vector_store()
|
||||
docstore = get_doc_store(docType)
|
||||
vector_store = get_vector_store(docType)
|
||||
|
||||
# Run the ingestion pipeline
|
||||
_ = run_pipeline(docstore, vector_store, documents)
|
||||
@@ -87,8 +87,54 @@ def generate_datasource():
|
||||
|
||||
logger.info("Finished generating the index")
|
||||
|
||||
class PropertyGraphChache:
|
||||
def generate(self):
|
||||
GRAPH_STORE_TYPE = os.getenv("GRAPH_STORE_TYPE", "")
|
||||
GRAPH_STORAGE_DIR = os.getenv("GRAPH_STORAGE_PATH", "storage_graph")
|
||||
prjInfos = getProjectInfos()
|
||||
for prjInfo in prjInfos:
|
||||
prjFlag = prjInfo['flag']
|
||||
prjName = prjInfo['name']
|
||||
chche_Path = GRAPH_STORAGE_DIR + f'/{prjFlag}'
|
||||
|
||||
if GRAPH_STORE_TYPE == 'neo4j':
|
||||
self.neo4jProertyGraph(prjName,prjFlag,chche_Path)
|
||||
else:
|
||||
self.simplePropertyGraph(prjName,prjFlag,chche_Path)
|
||||
|
||||
def simplePropertyGraph(self,prjName:str,prjFlag:str,filePath:str):
|
||||
documents = get_documents(prjFlag)
|
||||
storeContext = StorageContext.from_defaults(vector_store=get_vector_store(prjFlag),
|
||||
property_graph_store = RAGPropertyGraphStore())
|
||||
index = PropertyGraphIndex(
|
||||
nodes =documents,
|
||||
kg_extractors = [PrjGraphExtractor(prjName)],
|
||||
embed_model = Settings.embed_model,
|
||||
storage_context = storeContext,
|
||||
show_progress= True
|
||||
)
|
||||
os.makedirs(filePath,exist_ok = True)
|
||||
index.storage_context.persist(persist_dir = filePath)
|
||||
|
||||
def neo4jProertyGraph(self,prjName:str,prjFlag:str,filePath:str):
|
||||
neo4jStore =get_Neo4j_Graph_Store(prjFlag)
|
||||
documents = get_documents(prjFlag)
|
||||
PropertyGraphIndex(
|
||||
nodes =documents,
|
||||
property_graph_store = neo4jStore,
|
||||
kg_extractors = [PrjGraphExtractor(prjName)],
|
||||
embed_model = Settings.embed_model,
|
||||
show_progress= True
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
init_settings()
|
||||
llm_query = os.getenv('LLM_QUERY_WAY','rag')
|
||||
from phoenix.trace import using_project
|
||||
with using_project(os.getenv("PHOENIX_PROJECT_NAME") + "_generate") as obj:
|
||||
if llm_query == 'graph':
|
||||
PropertyGraphChache().generate()
|
||||
else:
|
||||
generate_datasource()
|
||||
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
import os
|
||||
from llama_index.core.schema import TransformComponent, BaseNode
|
||||
from llama_index.core.graph_stores.types import (
|
||||
KG_NODES_KEY,
|
||||
KG_RELATIONS_KEY,
|
||||
)
|
||||
from app.engine.loaders.markdownReader import ChunkMarkdownReader
|
||||
from app.engine.graph.graphTypes import *
|
||||
import uuid
|
||||
|
||||
IdField = '_id'
|
||||
nodeTypeField = 'nodeType'
|
||||
parentIDField = 'parentId'
|
||||
|
||||
class Record:
|
||||
def __init__(self,id:str,tableName:str,property:dict) -> None:
|
||||
self._childs = []
|
||||
self._id = id
|
||||
self._property:dict = property
|
||||
self._tableName = tableName
|
||||
|
||||
def add(self,rcd:'Record'):
|
||||
self._childs.append(rcd)
|
||||
|
||||
@property
|
||||
def Property(self):
|
||||
return self._property
|
||||
|
||||
@property
|
||||
def Id(self):
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def Name(self):
|
||||
for name,value in self._property.items():
|
||||
if '名称' in name:
|
||||
return value
|
||||
raise ValueError('记录名称为空')
|
||||
|
||||
@property
|
||||
def Label(self):
|
||||
if '工程属性' in self._tableName:
|
||||
label = '属性项'
|
||||
else:
|
||||
label = self.Property[nodeTypeField] if nodeTypeField in self.Property else self.Name
|
||||
label = label + '项'
|
||||
return label
|
||||
|
||||
@property
|
||||
def HasChild(self):
|
||||
return len(self._childs) > 0
|
||||
|
||||
def childCount(self):
|
||||
return len(self._childs)
|
||||
|
||||
def child(self,index:int):
|
||||
return self._childs[index]
|
||||
|
||||
class RecordTreeMake:
|
||||
def __init__(self,tableName:str,records:list) -> None:
|
||||
self._records = records
|
||||
self._tableName = tableName
|
||||
|
||||
def make(self)->list[Record]:
|
||||
rcdMaps:dict[str,Record] = {}
|
||||
for record in self._records:
|
||||
parid= ''
|
||||
if parentIDField in record:
|
||||
parid = record[parentIDField]
|
||||
id = record[IdField] if IdField in record else str(uuid.uuid1())
|
||||
if parid in rcdMaps:
|
||||
parRcd = rcdMaps[parid]
|
||||
parRcd.add(Record(id,self._tableName,record))
|
||||
else:
|
||||
rcdMaps[id] = Record(id,self._tableName,record)
|
||||
return list(rcdMaps.values())
|
||||
|
||||
class PrjGraphExtractor(TransformComponent):
|
||||
ProjectName:str
|
||||
_nodeMaps = {}
|
||||
_prjID = ''
|
||||
def __init__(self,PrjName:str):
|
||||
super().__init__(ProjectName = PrjName)
|
||||
|
||||
def __call__(
|
||||
self, llama_nodes: list[BaseNode], **kwargs
|
||||
) -> list[BaseNode]:
|
||||
if len(llama_nodes) > 0:
|
||||
self._addPrjNode(llama_nodes[0])
|
||||
|
||||
for llama_node in llama_nodes:
|
||||
fileName = self._getFileName(llama_node)
|
||||
if fileName == '工程属性':
|
||||
self._dealAttributeNode(llama_node)
|
||||
else:
|
||||
self._dealCommonNode(llama_node)
|
||||
return llama_nodes
|
||||
|
||||
def _dealCommonNode(self,llama_node:BaseNode):
|
||||
fileName = self._getFileName(llama_node)
|
||||
existing_nodes:list = llama_node.metadata.pop(KG_NODES_KEY, [])
|
||||
existing_relations:list = llama_node.metadata.pop(KG_RELATIONS_KEY, [])
|
||||
|
||||
records:dict[str,list] = self._getRecordNode(llama_node)
|
||||
fInfos = fileName.split('_')
|
||||
if len(fInfos) == 1:
|
||||
fileID = self._addTableNode(existing_nodes = existing_nodes,name=fInfos[0], label=fInfos[0])
|
||||
elif len(fInfos) == 2:
|
||||
fileID = self._addTableNode(existing_nodes = existing_nodes,name=fInfos[1], label=fInfos[0])
|
||||
else:
|
||||
raise ValueError("文件名存在多个下划线")
|
||||
|
||||
rdMake = RecordTreeMake(fileName,records)
|
||||
rcds:list[Record] = rdMake.make()
|
||||
|
||||
for record in rcds:
|
||||
self._make_RecordEdge(existing_nodes = existing_nodes,
|
||||
existing_relations = existing_relations,
|
||||
fileID = fileID,
|
||||
rcd = record)
|
||||
|
||||
existing_relations.append(
|
||||
RagRelation(
|
||||
label="包含",
|
||||
source_id= self._prjID,
|
||||
target_id= fileID
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
llama_node.metadata[KG_NODES_KEY] = existing_nodes
|
||||
llama_node.metadata[KG_RELATIONS_KEY] = existing_relations
|
||||
|
||||
def _dealAttributeNode(self,llama_node:BaseNode):
|
||||
fileName = self._getFileName(llama_node)
|
||||
existing_nodes:list = llama_node.metadata.pop(KG_NODES_KEY, [])
|
||||
existing_relations:list = llama_node.metadata.pop(KG_RELATIONS_KEY, [])
|
||||
records:dict[str,list] = self._getRecordNode(llama_node)
|
||||
fileID = self._addTableNode(existing_nodes = existing_nodes,name=fileName, label=fileName)
|
||||
|
||||
rdMake = RecordTreeMake(fileName,records)
|
||||
rcds:list[Record] = rdMake.make()
|
||||
|
||||
for record in rcds:
|
||||
attID = self._add_RecorNode(existing_nodes = existing_nodes,rcd = record)
|
||||
existing_relations.append(
|
||||
RagRelation(
|
||||
label="聚合",
|
||||
source_id= fileID,
|
||||
target_id= attID
|
||||
)
|
||||
)
|
||||
|
||||
existing_relations.append(
|
||||
RagRelation(
|
||||
label="包含",
|
||||
source_id= self._prjID,
|
||||
target_id= fileID
|
||||
)
|
||||
)
|
||||
|
||||
llama_node.metadata[KG_NODES_KEY] = existing_nodes
|
||||
llama_node.metadata[KG_RELATIONS_KEY] = existing_relations
|
||||
|
||||
def _getRecordNode(self,llama_node:BaseNode):
|
||||
content = llama_node.get_content()
|
||||
rd = ChunkMarkdownReader()
|
||||
rd.markdown_to_tups(content)
|
||||
records = rd.records()
|
||||
return records
|
||||
|
||||
def _getFileName(self,llama_node:BaseNode):
|
||||
meta = llama_node.metadata
|
||||
fileName:str = os.path.splitext(meta['file_name'])[0]
|
||||
return fileName
|
||||
|
||||
def _addPrjNode(self,llama_node:BaseNode):
|
||||
existing_nodes:list = llama_node.metadata.pop(KG_NODES_KEY, [])
|
||||
self._prjID = self._addTableNode(existing_nodes = existing_nodes,name=self.ProjectName,label=self.ProjectName)
|
||||
llama_node.metadata[KG_NODES_KEY] = existing_nodes
|
||||
|
||||
def _addTableNode(self,existing_nodes:list,name:str,label:str):
|
||||
return self._add_Node(existing_nodes,name,label,str(uuid.uuid1()))
|
||||
|
||||
def _add_RecorNode(self,existing_nodes:list,rcd:Record):
|
||||
return self._add_Node(existing_nodes,rcd.Name,rcd.Label,rcd.Id,rcd.Property)
|
||||
|
||||
def _add_Node(self,existing_nodes:list,name:str,label:str,defaultid:str,property:dict= {}):
|
||||
id:str = ''
|
||||
if name in self._nodeMaps:
|
||||
nodes:list[RagEntityNode] = self._nodeMaps[name]
|
||||
for node in nodes:
|
||||
if node.properties == property and node.name == name and node.label == label:
|
||||
id = node.id
|
||||
break
|
||||
|
||||
if id =='':
|
||||
id = defaultid
|
||||
newNode = RagEntityNode(name = name,label=label,properties = property,uid = id)
|
||||
existing_nodes.append(newNode)
|
||||
if name in self._nodeMaps:
|
||||
nodes:list[RagEntityNode] = self._nodeMaps[name]
|
||||
nodes.append(newNode)
|
||||
else:
|
||||
self._nodeMaps[name] = [newNode]
|
||||
return id
|
||||
|
||||
def _make_RecordEdge(self,existing_nodes:list,existing_relations:list,fileID:str,rcd:Record,parID:str = ''):
|
||||
rcdID = self._add_RecorNode(existing_nodes = existing_nodes,rcd = rcd)
|
||||
if fileID!='':
|
||||
existing_relations.append(
|
||||
RagRelation(
|
||||
label="子级",
|
||||
source_id= fileID,
|
||||
target_id= rcdID
|
||||
)
|
||||
)
|
||||
|
||||
if parID!='':
|
||||
existing_relations.append(
|
||||
RagRelation(
|
||||
label="子级",
|
||||
source_id= parID,
|
||||
target_id= rcdID
|
||||
)
|
||||
)
|
||||
|
||||
if rcd.HasChild:
|
||||
for i in range(rcd.childCount()):
|
||||
child = rcd.child(i)
|
||||
self._make_RecordEdge(existing_nodes,existing_relations,'',child,rcdID)
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
from typing import Any, List, Dict, Sequence, Tuple, Optional
|
||||
from llama_index.core.graph_stores.simple_labelled import SimplePropertyGraphStore
|
||||
from llama_index.core.graph_stores.types import LabelledNode,ChunkNode,LabelledPropertyGraph
|
||||
from app.engine.graph.graphTypes import *
|
||||
|
||||
class RAGPropertyGraphStore(SimplePropertyGraphStore):
|
||||
@classmethod
|
||||
def from_dict(
|
||||
cls,
|
||||
data: dict,
|
||||
) -> "SimplePropertyGraphStore":
|
||||
"""Load from dict."""
|
||||
# need to load nodes manually
|
||||
node_dicts = data["nodes"]
|
||||
relation_dicts = data["relations"]
|
||||
|
||||
kg_nodes: Dict[str, LabelledNode] = {}
|
||||
kg_relations: Dict[str, LabelledNode] = {}
|
||||
for id, node_dict in node_dicts.items():
|
||||
if "name" in node_dict:
|
||||
kg_nodes[id] = RagEntityNode.model_validate(node_dict)
|
||||
elif "text" in node_dict:
|
||||
kg_nodes[id] = ChunkNode.model_validate(node_dict)
|
||||
else:
|
||||
raise ValueError(f"Could not infer node type for data: {node_dict!s}")
|
||||
|
||||
for id, node_dict in relation_dicts.items():
|
||||
kg_relations[id] = RagRelation.model_validate(node_dict)
|
||||
|
||||
# clear the nodes, to load later
|
||||
data["nodes"] = {}
|
||||
data["relations"] = {}
|
||||
|
||||
# load the graph
|
||||
graph = LabelledPropertyGraph.model_validate(data)
|
||||
|
||||
# add the node back
|
||||
graph.nodes = kg_nodes
|
||||
graph.relations = kg_relations
|
||||
|
||||
return cls(graph)
|
||||
|
||||
def save_networkx_graph(self, name: str = "kg.html") -> None:
|
||||
"""Display the graph store, useful for debugging."""
|
||||
import networkx as nx
|
||||
|
||||
G = nx.DiGraph()
|
||||
for node in self.graph.nodes.values():
|
||||
if isinstance(node,EntityNode):
|
||||
G.add_node(node.id, label=node.name)
|
||||
for triplet in self.graph.triplets:
|
||||
G.add_edge(triplet[0], triplet[2], label=triplet[1])
|
||||
|
||||
# save to html file
|
||||
from pyvis.network import Network
|
||||
|
||||
net = Network(notebook=False, directed=True)
|
||||
net.from_nx(G)
|
||||
net.write_html(name)
|
||||
@@ -0,0 +1,38 @@
|
||||
from llama_index.core.graph_stores.types import (
|
||||
EntityNode,
|
||||
Relation
|
||||
)
|
||||
|
||||
class RagEntityNode(EntityNode):
|
||||
uid : str
|
||||
def __str__(self) -> str:
|
||||
"""Return the string representation of the node."""
|
||||
if self.properties:
|
||||
prop = self.properties
|
||||
if 'triplet_source_id' in prop:
|
||||
prop.pop('triplet_source_id')
|
||||
if len(prop) > 0:
|
||||
return f"{self.name} ({prop})"
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
"""Get the node id."""
|
||||
#return self.name.replace('"', " ")
|
||||
return self.uid
|
||||
|
||||
class RagRelation(Relation):
|
||||
def __str__(self) -> str:
|
||||
"""Return the string representation of the relation."""
|
||||
if self.properties:
|
||||
prop = self.properties
|
||||
if 'triplet_source_id' in prop:
|
||||
prop.pop('triplet_source_id')
|
||||
if len(prop) > 0:
|
||||
return f"{self.label} ({prop})"
|
||||
return self.label
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
"""Get the relation id."""
|
||||
return self.label
|
||||
@@ -0,0 +1,88 @@
|
||||
from llama_index.core.indices.property_graph import LLMSynonymRetriever,VectorContextRetriever,PGRetriever
|
||||
from llama_index.core.indices.property_graph.transformations.schema_llm import *
|
||||
from llama_index.core import SimpleDirectoryReader
|
||||
from llama_index.core import settings
|
||||
from llama_index.core import PropertyGraphIndex,KnowledgeGraphIndex
|
||||
from typing import List,Tuple,Literal
|
||||
from app.settings import init_settings
|
||||
import os
|
||||
from llama_index.core.storage.storage_context import StorageContext
|
||||
from llama_index.core import load_index_from_storage
|
||||
from app.observability import init_observability
|
||||
from app.engine.vectordb import get_Neo4j_Graph_Store,get_vector_store
|
||||
from llama_index.core.response_synthesizers import ResponseMode
|
||||
from util.register import *
|
||||
from llama_index.core.query_engine import RetrieverQueryEngine
|
||||
from app.engine.prompt import text_qa_template, refine_template, summary_template, simple_template
|
||||
from app.engine.engine import get_node_postprocessors
|
||||
from app.engine.graph.graphStore import RAGPropertyGraphStore
|
||||
|
||||
from app.engine.retriever.graphKeyWordRetriever import GraphKeyWordRetriever
|
||||
class PropertyGraph:
|
||||
def __init__(self,prjFlag:str) -> None:
|
||||
self._prjFlag = prjFlag
|
||||
|
||||
def create_query_engine(self,retriever):
|
||||
postprocess = get_node_postprocessors()
|
||||
query_engine = RetrieverQueryEngine.from_args(
|
||||
retriever = retriever,
|
||||
text_qa_template=text_qa_template,
|
||||
refine_template=refine_template,
|
||||
summary_template = summary_template,
|
||||
simple_template = simple_template,
|
||||
node_postprocessors=postprocess,
|
||||
use_async=True,
|
||||
streaming=False,
|
||||
response_mode = ResponseMode.TREE_SUMMARIZE
|
||||
)
|
||||
return query_engine
|
||||
|
||||
def getPropertyGraphIndex(self):
|
||||
GRAPH_STORE_TYPE = os.getenv("GRAPH_STORE_TYPE", "")
|
||||
if GRAPH_STORE_TYPE == 'neo4j':
|
||||
index = PropertyGraphIndex.from_existing(property_graph_store= get_Neo4j_Graph_Store(self._prjFlag))
|
||||
else:
|
||||
GRAPH_STORAGE_DIR = os.getenv("GRAPH_STORAGE_PATH", "storage_graph")
|
||||
prjCachePath = GRAPH_STORAGE_DIR + f"/{self._prjFlag}"
|
||||
if not os.path.exists(prjCachePath):
|
||||
return None
|
||||
storeContext = StorageContext.from_defaults(persist_dir = prjCachePath,vector_store = get_vector_store(self._prjFlag),
|
||||
property_graph_store = RAGPropertyGraphStore.from_persist_dir(prjCachePath))
|
||||
index = load_index_from_storage(storeContext)
|
||||
return index
|
||||
|
||||
def query(self,query_str:str):
|
||||
index = self.getPropertyGraphIndex()
|
||||
synonym_retriver = GraphKeyWordRetriever(index.property_graph_store,
|
||||
include_text=False
|
||||
)
|
||||
if index.property_graph_store.supports_vector_queries:
|
||||
vector_store = None
|
||||
else:
|
||||
vector_store = index.vector_store
|
||||
vector_retriver = VectorContextRetriever(index.property_graph_store,
|
||||
vector_store = vector_store,
|
||||
embed_model=settings.Settings.embed_model,
|
||||
similarity_top_k=10,
|
||||
include_text=False
|
||||
)
|
||||
|
||||
retriever = index.as_retriever(sub_retrievers=[synonym_retriver,vector_retriver])
|
||||
query_engine = self.create_query_engine(retriever)
|
||||
|
||||
response = query_engine.query(query_str)
|
||||
print(response)
|
||||
return str(response)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
init_settings()
|
||||
init_observability()
|
||||
graph = PropertyGraph('projects_0ffaf7fb-8a61-46e2-97a2-8f924e9560a7')
|
||||
graph.query('工程属性表有哪些字段')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+31
-13
@@ -1,22 +1,40 @@
|
||||
import logging
|
||||
import logging,os
|
||||
from llama_index.core.indices import VectorStoreIndex
|
||||
from app.engine.vectordb import get_vector_store
|
||||
|
||||
from app.engine.vectordb import get_vector_store,get_Neo4j_Graph_Store
|
||||
from typing import Dict,Any
|
||||
from llama_index.core import PropertyGraphIndex
|
||||
from llama_index.core.storage.storage_context import StorageContext
|
||||
from llama_index.core import load_index_from_storage
|
||||
from app.engine.graph.graphStore import RAGPropertyGraphStore
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
index = None
|
||||
|
||||
def get_index(params=None):
|
||||
global index
|
||||
if index is None:
|
||||
def get_index(prjFlag:str):
|
||||
if prjFlag is None or prjFlag == '':
|
||||
raise ValueError('无效的工程标识')
|
||||
logger.info("Connecting vector store...")
|
||||
|
||||
store = get_vector_store()
|
||||
# Load the index from the vector store
|
||||
# If you are using a vector store that doesn't store text,
|
||||
# you must load the index from both the vector store and the document store
|
||||
index = None
|
||||
llm_query = os.getenv('LLM_QUERY_WAY')
|
||||
if llm_query == 'graph':
|
||||
index = getPropertyGraphIndex(prjFlag)
|
||||
else:
|
||||
store = get_vector_store(prjFlag)
|
||||
index = VectorStoreIndex.from_vector_store(store)
|
||||
logger.info("Finished load index from vector store.")
|
||||
|
||||
return index
|
||||
|
||||
|
||||
def getPropertyGraphIndex(prjFlag:str):
|
||||
GRAPH_STORE_TYPE = os.getenv("GRAPH_STORE_TYPE", "")
|
||||
if GRAPH_STORE_TYPE == 'neo4j':
|
||||
index = PropertyGraphIndex.from_existing(property_graph_store= get_Neo4j_Graph_Store(prjFlag))
|
||||
else:
|
||||
GRAPH_STORAGE_DIR = os.getenv("GRAPH_STORAGE_PATH", "storage_graph")
|
||||
prjCachePath = GRAPH_STORAGE_DIR + f"/{prjFlag}"
|
||||
if not os.path.exists(prjCachePath):
|
||||
return None
|
||||
storeContext = StorageContext.from_defaults(persist_dir = prjCachePath,vector_store = get_vector_store(prjFlag),
|
||||
property_graph_store = RAGPropertyGraphStore.from_persist_dir(prjCachePath))
|
||||
index = load_index_from_storage(storeContext)
|
||||
return index
|
||||
@@ -1,40 +0,0 @@
|
||||
import logging
|
||||
|
||||
import yaml
|
||||
from app.engine.loaders.db import DBLoaderConfig, get_db_documents
|
||||
from app.engine.loaders.file import FileLoaderConfig, get_file_documents
|
||||
from app.engine.loaders.web import WebLoaderConfig, get_web_documents
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def load_configs():
|
||||
with open("config/loaders.yaml") as f:
|
||||
configs = yaml.safe_load(f)
|
||||
return configs
|
||||
|
||||
|
||||
def get_documents():
|
||||
documents = []
|
||||
config = load_configs()
|
||||
if config is None or len(config.items()) == 0:
|
||||
return documents
|
||||
|
||||
for loader_type, loader_config in config.items():
|
||||
logger.info(
|
||||
f"Loading documents from loader: {loader_type}, config: {loader_config}"
|
||||
)
|
||||
|
||||
loader_config = loader_config or []
|
||||
match loader_type:
|
||||
case "file":
|
||||
document = get_file_documents(FileLoaderConfig(**loader_config))
|
||||
case "web":
|
||||
document = get_web_documents(WebLoaderConfig(**loader_config))
|
||||
case "db":
|
||||
document = get_db_documents(configs=[DBLoaderConfig(**cfg) for cfg in loader_config])
|
||||
case _:
|
||||
raise ValueError(f"Invalid loader type: {loader_type}")
|
||||
documents.extend(document)
|
||||
|
||||
return documents
|
||||
@@ -1,140 +0,0 @@
|
||||
import logging
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from llama_index.core import SQLDatabase, Document
|
||||
from llama_index.readers.database import DatabaseReader
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.engine import Engine
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class CustomDatabaseReader(DatabaseReader):
|
||||
"""Simple Database reader.
|
||||
|
||||
Concatenates each row into Document used by LlamaIndex.
|
||||
|
||||
Args:
|
||||
sql_database (Optional[SQLDatabase]): SQL database to use,
|
||||
including table names to specify.
|
||||
See :ref:`Ref-Struct-Store` for more details.
|
||||
|
||||
OR
|
||||
|
||||
engine (Optional[Engine]): SQLAlchemy Engine object of the database connection.
|
||||
|
||||
OR
|
||||
|
||||
uri (Optional[str]): uri of the database connection.
|
||||
|
||||
OR
|
||||
|
||||
scheme (Optional[str]): scheme of the database connection.
|
||||
host (Optional[str]): host of the database connection.
|
||||
port (Optional[int]): port of the database connection.
|
||||
user (Optional[str]): user of the database connection.
|
||||
password (Optional[str]): password of the database connection.
|
||||
dbname (Optional[str]): dbname of the database connection.
|
||||
|
||||
Returns:
|
||||
DatabaseReader: A DatabaseReader object.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
sql_database: Optional[SQLDatabase] = None,
|
||||
engine: Optional[Engine] = None,
|
||||
uri: Optional[str] = None,
|
||||
scheme: Optional[str] = None,
|
||||
host: Optional[str] = None,
|
||||
port: Optional[str] = None,
|
||||
user: Optional[str] = None,
|
||||
password: Optional[str] = None,
|
||||
dbname: Optional[str] = None,
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
"""Initialize with parameters."""
|
||||
if sql_database:
|
||||
self.sql_database = sql_database
|
||||
elif engine:
|
||||
self.sql_database = SQLDatabase(engine, *args, **kwargs)
|
||||
elif uri:
|
||||
self.uri = uri
|
||||
self.sql_database = SQLDatabase.from_uri(uri, *args, **kwargs)
|
||||
elif scheme and host and port and user and password and dbname:
|
||||
uri = f"{scheme}://{user}:{password}@{host}:{port}/{dbname}"
|
||||
self.uri = uri
|
||||
self.sql_database = SQLDatabase.from_uri(uri, *args, **kwargs)
|
||||
else:
|
||||
raise ValueError(
|
||||
"You must provide either a SQLDatabase, "
|
||||
"a SQL Alchemy Engine, a valid connection URI, or a valid "
|
||||
"set of credentials."
|
||||
)
|
||||
|
||||
def load_data(self, query: str, explanation: str) -> List[Document]:
|
||||
"""Query and load data from the Database, returning a list of Documents.
|
||||
|
||||
Args:
|
||||
query (str): Query parameter to filter tables and rows.
|
||||
explanation (str): Explanation for the query to be included in the document.
|
||||
|
||||
Returns:
|
||||
List[Document]: A list of Document objects.
|
||||
"""
|
||||
dco_str = explanation + "\n"
|
||||
|
||||
with self.sql_database.engine.connect() as connection:
|
||||
if query is None:
|
||||
raise ValueError("A query parameter is necessary to filter the data")
|
||||
else:
|
||||
result = connection.execute(text(query))
|
||||
|
||||
dco_str += ", ".join(
|
||||
[f"{entry}" for entry in result.keys()]
|
||||
) + "\n"
|
||||
|
||||
for item in result.fetchall():
|
||||
# Fetch each item
|
||||
record_str = ", ".join(
|
||||
[f"{entry}" for col, entry in zip(result.keys(), item)]
|
||||
)
|
||||
dco_str += record_str + "\n"
|
||||
|
||||
doc = Document(text=dco_str)
|
||||
doc.metadata["name"] = query
|
||||
doc.metadata["context"] = query
|
||||
doc.metadata["file_type"] = "application/vnd.ms-excel"
|
||||
return [doc]
|
||||
|
||||
class DBLoaderConfig(BaseModel):
|
||||
uri: str
|
||||
queries: List[dict]
|
||||
|
||||
def get_db_documents(configs: list[DBLoaderConfig]):
|
||||
docs = []
|
||||
|
||||
if len(configs) == 0 or configs[0].uri == "":
|
||||
logger.warning(
|
||||
f"Failed to load database, error message: uri is empty. Return as empty document list."
|
||||
)
|
||||
return docs
|
||||
|
||||
metadata = {
|
||||
'file_type': 'application/booway.document.zj',
|
||||
}
|
||||
|
||||
for entry in configs:
|
||||
engine = create_engine(entry.uri)
|
||||
sql_database = SQLDatabase(engine)
|
||||
|
||||
loader = CustomDatabaseReader(sql_database)
|
||||
for query_dict in entry.queries:
|
||||
query = query_dict.get("sql", "")
|
||||
explanation = query_dict.get("explanation", "")
|
||||
logger.info(f"Loading data from database with query: {query}")
|
||||
documents = loader.load_data(query=query, explanation=explanation)
|
||||
|
||||
docs.extend(documents)
|
||||
return docs
|
||||
@@ -1,88 +0,0 @@
|
||||
import os
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from llama_index.core.readers.base import BaseReader
|
||||
from llama_index.core.readers.json import JSONReader
|
||||
from llama_parse import LlamaParse
|
||||
from pydantic import BaseModel, validator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FileLoaderConfig(BaseModel):
|
||||
data_dir: str = "data"
|
||||
use_llama_parse: bool = False
|
||||
|
||||
@validator("data_dir")
|
||||
def data_dir_must_exist(cls, v):
|
||||
if not os.path.isdir(v):
|
||||
raise ValueError(f"Directory '{v}' does not exist")
|
||||
return v
|
||||
|
||||
|
||||
def llama_parse_parser():
|
||||
if os.getenv("LLAMA_CLOUD_API_KEY") is None:
|
||||
raise ValueError(
|
||||
"LLAMA_CLOUD_API_KEY environment variable is not set. "
|
||||
"Please set it in .env file or in your shell environment then run again!"
|
||||
)
|
||||
parser = LlamaParse(
|
||||
result_type="markdown",
|
||||
verbose=True,
|
||||
language="en",
|
||||
ignore_errors=False,
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def llama_parse_extractor() -> Dict[str, LlamaParse]:
|
||||
from llama_parse.utils import SUPPORTED_FILE_TYPES
|
||||
|
||||
parser = llama_parse_parser()
|
||||
return {file_type: parser for file_type in SUPPORTED_FILE_TYPES}
|
||||
|
||||
def llama_local_extractor() -> Dict[str, BaseReader]:
|
||||
return {".json" : JSONReader(clean_json=False,levels_back=0)}
|
||||
|
||||
|
||||
def get_file_documents(config: FileLoaderConfig):
|
||||
from llama_index.core.readers import SimpleDirectoryReader
|
||||
|
||||
try:
|
||||
file_extractor = None
|
||||
if config.use_llama_parse:
|
||||
# LlamaParse is async first,
|
||||
# so we need to use nest_asyncio to run it in sync mode
|
||||
import nest_asyncio
|
||||
|
||||
nest_asyncio.apply()
|
||||
|
||||
file_extractor = llama_parse_extractor()
|
||||
else:
|
||||
file_extractor = llama_local_extractor()
|
||||
|
||||
reader = SimpleDirectoryReader(
|
||||
config.data_dir,
|
||||
recursive=True,
|
||||
filename_as_id=True,
|
||||
raise_on_error=True,
|
||||
file_extractor=file_extractor,
|
||||
)
|
||||
return reader.load_data()
|
||||
except Exception as e:
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
# Catch the error if the data dir is empty
|
||||
# and return as empty document list
|
||||
_, _, exc_traceback = sys.exc_info()
|
||||
function_name = traceback.extract_tb(exc_traceback)[-1].name
|
||||
if function_name == "_add_files":
|
||||
logger.warning(
|
||||
f"Failed to load file documents, error message: {e} . Return as empty document list."
|
||||
)
|
||||
return []
|
||||
else:
|
||||
# Raise the error if it is not the case of empty data dir
|
||||
raise e
|
||||
@@ -1,37 +0,0 @@
|
||||
import os
|
||||
import json
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class CrawlUrl(BaseModel):
|
||||
base_url: str
|
||||
prefix: str
|
||||
max_depth: int = Field(default=1, ge=0)
|
||||
|
||||
|
||||
class WebLoaderConfig(BaseModel):
|
||||
driver_arguments: list[str] = Field(default=None)
|
||||
urls: list[CrawlUrl] = []
|
||||
|
||||
|
||||
def get_web_documents(config: WebLoaderConfig):
|
||||
from llama_index.readers.web import WholeSiteReader
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
|
||||
options = Options()
|
||||
driver_arguments = config.driver_arguments or []
|
||||
for arg in driver_arguments:
|
||||
options.add_argument(arg)
|
||||
|
||||
docs = []
|
||||
urls = config.urls or []
|
||||
for url in config.urls:
|
||||
scraper = WholeSiteReader(
|
||||
prefix=url.prefix,
|
||||
max_depth=url.max_depth,
|
||||
driver=webdriver.Chrome(options=options),
|
||||
)
|
||||
docs.extend(scraper.load_data(url.base_url))
|
||||
|
||||
return docs
|
||||
@@ -1,26 +1,96 @@
|
||||
import logging
|
||||
|
||||
import yaml
|
||||
from app.engine.loaders.db import DBLoaderConfig, get_db_documents
|
||||
from app.engine.loaders.file import FileLoaderConfig, get_file_documents
|
||||
from app.engine.loaders.web import WebLoaderConfig, get_web_documents
|
||||
from app.engine.loaders.file import getProjectName
|
||||
import os
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def load_configs():
|
||||
with open("config/loaders.yaml") as f:
|
||||
with open("config/loaders.yaml",encoding='utf-8') as f:
|
||||
configs = yaml.safe_load(f)
|
||||
return configs
|
||||
|
||||
def path_difference(path1:str, path2:str):
|
||||
import os
|
||||
path1 = os.path.abspath(path1)
|
||||
path2 = os.path.abspath(path2)
|
||||
|
||||
def get_documents():
|
||||
path1_parts = path1.split(os.path.sep)
|
||||
path2_parts = path2.split(os.path.sep)
|
||||
|
||||
for i, part in enumerate(path1_parts):
|
||||
if part != path2_parts[i]:
|
||||
break
|
||||
else:
|
||||
i += 1
|
||||
|
||||
pathKey = ''
|
||||
for j in range(i,len(path2_parts)):
|
||||
pathKey+=path2_parts[j] + '_'
|
||||
return pathKey[0:-1]
|
||||
|
||||
def getFileCacahePath():
|
||||
rootPath = 'data'
|
||||
configs = load_configs()
|
||||
if configs is not None and len(configs.items()) > 0:
|
||||
for loader_type, loader_config in configs.items():
|
||||
if loader_type == "file":
|
||||
rootPath = FileLoaderConfig(**loader_config).data_dir
|
||||
break
|
||||
return rootPath
|
||||
|
||||
def get_document_Types():
|
||||
rootPath = getFileCacahePath()
|
||||
types = []
|
||||
dirStack = [rootPath]
|
||||
while len(dirStack) > 0:
|
||||
curDir = dirStack.pop()
|
||||
dirs = [os.path.join(curDir, d) for d in os.listdir(curDir) if os.path.isdir(os.path.join(curDir, d))]
|
||||
if len(dirs) > 0:
|
||||
for dir in dirs:
|
||||
dirStack.append(dir)
|
||||
else:
|
||||
types.append(path_difference(rootPath,curDir))
|
||||
return types
|
||||
|
||||
def getProjectInfos():
|
||||
config = load_configs()
|
||||
if config is None or len(config.items()) == 0:
|
||||
return None
|
||||
|
||||
prjDir = None
|
||||
for loader_type, loader_config in config.items():
|
||||
if loader_config.get('enable', True):
|
||||
loader_config = loader_config or []
|
||||
config = FileLoaderConfig(**loader_config)
|
||||
prjDir = config.data_dir
|
||||
break
|
||||
if prjDir is None:
|
||||
return None
|
||||
|
||||
prjInfos = []
|
||||
prjFlags = get_document_Types()
|
||||
for prjFlag in prjFlags:
|
||||
fileDir = os.path.join(config.data_dir,prjFlag.replace('_','\\'))
|
||||
prjInfo = {}
|
||||
prjInfo['flag'] = prjFlag
|
||||
prjInfo['name'] = getProjectName(fileDir)
|
||||
prjInfos.append(prjInfo)
|
||||
return prjInfos
|
||||
|
||||
def get_documents(docType:str):
|
||||
documents = []
|
||||
config = load_configs()
|
||||
|
||||
if config is None or len(config.items()) == 0:
|
||||
return documents
|
||||
|
||||
for loader_type, loader_config in config.items():
|
||||
if loader_config.get('enable', True): # 检查 enable 字段
|
||||
logger.info(
|
||||
f"Loading documents from loader: {loader_type}, config: {loader_config}"
|
||||
)
|
||||
@@ -28,7 +98,7 @@ def get_documents():
|
||||
loader_config = loader_config or []
|
||||
match loader_type:
|
||||
case "file":
|
||||
document = get_file_documents(FileLoaderConfig(**loader_config))
|
||||
document = get_file_documents(FileLoaderConfig(**loader_config),docType)
|
||||
case "web":
|
||||
document = get_web_documents(WebLoaderConfig(**loader_config))
|
||||
case "db":
|
||||
|
||||
@@ -2,17 +2,14 @@ import logging
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from llama_index.core import SQLDatabase, Document
|
||||
from llama_index.core.objects import SQLTableSchema
|
||||
from llama_index.core.readers.base import BaseReader
|
||||
from llama_index.readers.database import DatabaseReader
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.engine import Engine
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class CustomDatabaseReader(BaseReader):
|
||||
class CustomDatabaseReader(DatabaseReader):
|
||||
"""Simple Database reader.
|
||||
|
||||
Concatenates each row into Document used by LlamaIndex.
|
||||
@@ -86,18 +83,19 @@ class CustomDatabaseReader(BaseReader):
|
||||
List[Document]: A list of Document objects.
|
||||
"""
|
||||
dco_str = ""
|
||||
|
||||
with self.sql_database.engine.connect() as connection:
|
||||
if query is None:
|
||||
raise ValueError("A query parameter is necessary to filter the data")
|
||||
else:
|
||||
result = connection.execute(text(query))
|
||||
|
||||
dco_str = ", ".join(
|
||||
dco_str += ", ".join(
|
||||
[f"{entry}" for entry in result.keys()]
|
||||
)
|
||||
) + "\n"
|
||||
|
||||
for item in result.fetchall():
|
||||
# fetch each item
|
||||
# Fetch each item
|
||||
record_str = ", ".join(
|
||||
[f"{entry}" for col, entry in zip(result.keys(), item)]
|
||||
)
|
||||
@@ -111,45 +109,36 @@ class CustomDatabaseReader(BaseReader):
|
||||
|
||||
class DBLoaderConfig(BaseModel):
|
||||
uri: str
|
||||
queries: List[str]
|
||||
queries: List[dict]
|
||||
|
||||
def get_db_documents(configs: list[DBLoaderConfig]):
|
||||
def get_db_documents(configs: List[DBLoaderConfig]) -> List[Document]:
|
||||
docs = []
|
||||
|
||||
if len(configs) == 0 or configs[0].uri == "":
|
||||
if not configs or not configs[0].uri:
|
||||
logger.warning(
|
||||
f"Failed to load database, error message: uri is empty. Return as empty document list."
|
||||
)
|
||||
return docs
|
||||
|
||||
metadata = {
|
||||
#'file_name':'',
|
||||
'file_type':'application/booway.document.zj',
|
||||
#'file_path':'',
|
||||
#'file_size':'',
|
||||
#'creation_date':'',
|
||||
#'last_modified_date':'',
|
||||
'file_type': 'application/booway.document.zj',
|
||||
}
|
||||
|
||||
#from llama_index.readers.database import DatabaseReader
|
||||
for entry in configs:
|
||||
engine = create_engine(entry.uri)
|
||||
sql_database = SQLDatabase(engine)
|
||||
|
||||
# table_schema_objs = makeDescriptionByEngine(sql_database)
|
||||
# table_node_mapping = SQLTableNodeMapping(sql_database)
|
||||
#
|
||||
# nodes = table_node_mapping.to_nodes(table_schema_objs)
|
||||
# for node in nodes:
|
||||
# node.metadata.update(metadata)
|
||||
#
|
||||
# docs.extend(nodes)
|
||||
|
||||
queries = entry.queries or []
|
||||
loader = CustomDatabaseReader(sql_database)
|
||||
for query in queries:
|
||||
for query_dict in entry.queries:
|
||||
query = query_dict.get("sql", "")
|
||||
explanation = query_dict.get("explanation", "")
|
||||
logger.info(f"Loading data from database with query: {query}")
|
||||
documents = loader.load_data(query=query)
|
||||
|
||||
docs.extend(documents)
|
||||
# 添加解释到元数据中
|
||||
for doc in documents:
|
||||
doc.metadata["explanation"] = explanation
|
||||
doc.metadata.update(metadata) # 更新或添加额外的元数据
|
||||
docs.append(doc)
|
||||
|
||||
return docs
|
||||
@@ -6,6 +6,12 @@ from llama_index.core.readers.base import BaseReader
|
||||
from llama_index.core.readers.json import JSONReader
|
||||
from llama_parse import LlamaParse
|
||||
from pydantic import BaseModel, validator
|
||||
from app.engine.loaders.markdownReader import ChunkMarkdownReader
|
||||
from app.engine.loaders.projectJson import ProjectJson
|
||||
from typing import Any, Callable, Dict, Generator, List, Optional, Type, Set
|
||||
import fsspec,mimetypes
|
||||
from fsspec.implementations.local import LocalFileSystem
|
||||
from datetime import datetime
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -20,6 +26,80 @@ class FileLoaderConfig(BaseModel):
|
||||
raise ValueError(f"Directory '{v}' does not exist")
|
||||
return v
|
||||
|
||||
class CustomFileMetadataFunc:
|
||||
"""
|
||||
Default file metadata function wrapper which stores the fs.
|
||||
Allows for pickling of the function.
|
||||
"""
|
||||
|
||||
def __init__(self, fs: Optional[fsspec.AbstractFileSystem] = None):
|
||||
self.fs = fs or self._get_default_fs()
|
||||
|
||||
def __call__(self, file_path: str) -> Dict:
|
||||
return self._default_file_metadata_func(file_path, self.fs)
|
||||
|
||||
def _default_file_metadata_func(self,
|
||||
file_path: str, fs: Optional[fsspec.AbstractFileSystem] = None
|
||||
) -> Dict:
|
||||
"""
|
||||
Get some handy metadata from filesystem.
|
||||
|
||||
Args:
|
||||
file_path: str: file path in str
|
||||
"""
|
||||
fs = fs or self._get_default_fs()
|
||||
stat_result = fs.stat(file_path)
|
||||
|
||||
try:
|
||||
file_name = os.path.basename(str(stat_result["name"]))
|
||||
except Exception as e:
|
||||
file_name = os.path.basename(file_path)
|
||||
|
||||
creation_date = self._format_file_timestamp(stat_result.get("created"))
|
||||
last_modified_date = self._format_file_timestamp(stat_result.get("mtime"))
|
||||
last_accessed_date = self._format_file_timestamp(stat_result.get("atime"))
|
||||
default_meta = {
|
||||
"file_name": file_name,
|
||||
"file_type": mimetypes.guess_type(file_path)[0],
|
||||
"file_size": stat_result.get("size"),
|
||||
"creation_date": creation_date,
|
||||
"last_modified_date": last_modified_date,
|
||||
"last_accessed_date": last_accessed_date,
|
||||
}
|
||||
|
||||
# Return not null value
|
||||
return {
|
||||
meta_key: meta_value
|
||||
for meta_key, meta_value in default_meta.items()
|
||||
if meta_value is not None
|
||||
}
|
||||
|
||||
def _format_file_timestamp(
|
||||
timestamp: float, include_time: bool = False
|
||||
) -> Optional[str]:
|
||||
"""
|
||||
Format file timestamp to a %Y-%m-%d string.
|
||||
|
||||
Args:
|
||||
timestamp (float): timestamp in float
|
||||
include_time (bool): whether to include time in the formatted string
|
||||
|
||||
Returns:
|
||||
str: formatted timestamp
|
||||
"""
|
||||
try:
|
||||
if include_time:
|
||||
return datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d")
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _get_default_fs(self) -> fsspec.AbstractFileSystem:
|
||||
return LocalFileSystem()
|
||||
|
||||
def _is_default_fs(self,fs: fsspec.AbstractFileSystem) -> bool:
|
||||
return isinstance(fs, LocalFileSystem) and not fs.auto_mkdir
|
||||
|
||||
|
||||
def llama_parse_parser():
|
||||
if os.getenv("LLAMA_CLOUD_API_KEY") is None:
|
||||
@@ -35,7 +115,6 @@ def llama_parse_parser():
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def llama_parse_extractor() -> Dict[str, LlamaParse]:
|
||||
from llama_parse.utils import SUPPORTED_FILE_TYPES
|
||||
|
||||
@@ -43,10 +122,13 @@ def llama_parse_extractor() -> Dict[str, LlamaParse]:
|
||||
return {file_type: parser for file_type in SUPPORTED_FILE_TYPES}
|
||||
|
||||
def llama_local_extractor() -> Dict[str, BaseReader]:
|
||||
return {".json" : JSONReader(clean_json=False,levels_back=0)}
|
||||
parser = {
|
||||
".json" : JSONReader(clean_json=False,levels_back=0),
|
||||
".md" : ChunkMarkdownReader(),
|
||||
}
|
||||
return parser
|
||||
|
||||
|
||||
def get_file_documents(config: FileLoaderConfig):
|
||||
def get_file_documents(config: FileLoaderConfig,childPath: str):
|
||||
from llama_index.core.readers import SimpleDirectoryReader
|
||||
|
||||
try:
|
||||
@@ -63,11 +145,12 @@ def get_file_documents(config: FileLoaderConfig):
|
||||
file_extractor = llama_local_extractor()
|
||||
|
||||
reader = SimpleDirectoryReader(
|
||||
config.data_dir,
|
||||
os.path.join(config.data_dir,childPath.replace('_','\\')),
|
||||
recursive=True,
|
||||
filename_as_id=True,
|
||||
raise_on_error=True,
|
||||
file_extractor=file_extractor,
|
||||
file_metadata = CustomFileMetadataFunc()
|
||||
)
|
||||
return reader.load_data()
|
||||
except Exception as e:
|
||||
@@ -86,3 +169,32 @@ def get_file_documents(config: FileLoaderConfig):
|
||||
else:
|
||||
# Raise the error if it is not the case of empty data dir
|
||||
raise e
|
||||
|
||||
def prjFileSuffix(dir:str):
|
||||
entries = os.listdir(dir)
|
||||
file_names = [entry for entry in entries if os.path.isfile(os.path.join(dir, entry))]
|
||||
if len(file_names) > 0:
|
||||
return os.path.splitext(file_names[0])[1]
|
||||
return ''
|
||||
|
||||
def getProjectName(dir:str):
|
||||
suffix = prjFileSuffix(dir)
|
||||
if suffix== '.json':
|
||||
prjJson = ProjectJson(dir)
|
||||
prjJson.parse()
|
||||
tb = prjJson.table('工程属性')
|
||||
records = tb.records()
|
||||
for record in records:
|
||||
name = record.value('名称')
|
||||
if name == '工程名称':
|
||||
return record.value('值')
|
||||
elif suffix == '.md':
|
||||
md_files = [f for f in os.listdir(dir) if f.endswith('.md')]
|
||||
for md_file in md_files:
|
||||
prjPath = os.path.join(dir, md_file)
|
||||
basename = os.path.splitext(md_file)[0]
|
||||
if basename =='工程属性':
|
||||
rd = ChunkMarkdownReader()
|
||||
rd.load_data(prjPath)
|
||||
return rd.findValue("名称=='工程名称'",'值')
|
||||
return ''
|
||||
@@ -0,0 +1,80 @@
|
||||
from app.engine.loaders.projectJson import *
|
||||
|
||||
class MarkDown:
|
||||
def __init__(self,table:JsonTable,path:str) -> None:
|
||||
self._table = table
|
||||
self._path = path
|
||||
|
||||
def build(self):
|
||||
flds:Dict[str,Field] = self._table.fields()
|
||||
records:List[Record] = self._table.records()
|
||||
columns:list = []
|
||||
colComments:list = []
|
||||
ignores:List[str] = []
|
||||
for name,fld in flds.items():
|
||||
if self._table.name() == '工程属性' and (name =='_id' or name =='nodeType' or name =='relTbId'):
|
||||
ignores.append(name)
|
||||
continue
|
||||
|
||||
columns.append(fld.value('name'))
|
||||
colComments.append(fld.value('alias'))
|
||||
|
||||
rowdatas = []
|
||||
for record in records:
|
||||
datas = []
|
||||
for col in columns:
|
||||
if col in ignores:
|
||||
continue
|
||||
txt:str = record.value(col)
|
||||
content = txt.replace('\n',"")
|
||||
content = content.replace('\r',"")
|
||||
datas.append(content)
|
||||
rowdatas.append(datas)
|
||||
|
||||
content = self.convert(self._table.name(),self._table.comment(),columns,colComments,rowdatas)
|
||||
with open(self._path, 'w',encoding='utf-8') as file:
|
||||
file.write(content)
|
||||
|
||||
def convert(self,tableName:str,tableComment:str,columns:list,colComments:list,rowdatas:list):
|
||||
strTitle = "# " + tableName + '\n'
|
||||
if tableName!='':
|
||||
strTitle+= f"备注:{tableComment}" + '\n'
|
||||
|
||||
for i in range(len(columns)):
|
||||
strTitle+= f"- 字段名称:{columns[i]}" + '\n'
|
||||
comment = colComments[i]
|
||||
if comment!='':
|
||||
strTitle+= f" - 备注:{comment}" + '\n'
|
||||
|
||||
markdown_table = "|"
|
||||
# 添加列标题
|
||||
markdown_table += "|".join(columns) + "|\n"
|
||||
# 添加分隔行
|
||||
markdown_table += "|" + "|".join(['---' for _ in columns]) + "|\n"
|
||||
# 遍历每个数据行
|
||||
for row in rowdatas:
|
||||
# 添加数据行
|
||||
markdown_table += "|" + "|".join(row) + "|\n"
|
||||
return strTitle + "\n" + markdown_table
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
intputDir = 'C:\\Users\\wanyaokun\\Desktop\\markdown\\Project'
|
||||
outputDir = 'C:\\Users\\wanyaokun\\Desktop\\markdown\\data'
|
||||
|
||||
subdirectories = {}
|
||||
for dp, dn, fn in os.walk(intputDir):
|
||||
for d in dn:
|
||||
subdirectories[d] = os.path.join(dp, d)
|
||||
for dirName,dirPath in subdirectories.items():
|
||||
prjSon = ProjectJson(dirPath)
|
||||
prjSon.parse()
|
||||
tables = prjSon.tables()
|
||||
outPut = os.path.join(outputDir,dirName)
|
||||
os.makedirs(outPut,exist_ok=True)
|
||||
for name,table in tables.items():
|
||||
outputPath = os.path.join(outPut,f'{table.name()}.md')
|
||||
mdObj = MarkDown(table,outputPath)
|
||||
mdObj.build()
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
from llama_index.readers.file.markdown import MarkdownReader
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
import re
|
||||
from llama_index.core.utils import get_tokenizer
|
||||
|
||||
|
||||
class ChunkMarkdownReader(MarkdownReader):
|
||||
def __init__(
|
||||
self,
|
||||
*args: Any,
|
||||
chunkSize:int = 2048,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
self._chunkSize = chunkSize
|
||||
self._tokenizer = get_tokenizer()
|
||||
self._colheader = ''
|
||||
self._rows = []
|
||||
super().__init__(*args,**kwargs)
|
||||
|
||||
def markdown_to_tups(self, markdown_text: str) -> List[Tuple[Optional[str], str]]:
|
||||
markdown_tups: List[Tuple[Optional[str], str]] = []
|
||||
lines = self._multi_char_split(markdown_text,'\r\n')
|
||||
lines = [line for line in lines if line!='']
|
||||
|
||||
strTitle = ''
|
||||
tokensNum:int = 0
|
||||
current_lines = []
|
||||
strheader:str = ''
|
||||
headerSize:int = 0
|
||||
bAreadyJudgeTitle = False
|
||||
for line in lines:
|
||||
tokensNum += self._token_size(line)
|
||||
if tokensNum > self._chunkSize and len(current_lines) > 0:
|
||||
if len(markdown_tups) == 0:
|
||||
titleHead = strTitle + '\n' + strheader if strTitle!= '' else strheader
|
||||
markdown_tups.append((titleHead, "\n".join(current_lines)))
|
||||
else:
|
||||
markdown_tups.append((strheader , "\n".join(current_lines)))
|
||||
tokensNum = headerSize
|
||||
current_lines.clear()
|
||||
|
||||
if strheader!='':
|
||||
self._rows.append(line)
|
||||
|
||||
if line.startswith('|') and strTitle == '' and not bAreadyJudgeTitle:
|
||||
if len(current_lines) > 0:
|
||||
if tokensNum > self._chunkSize:
|
||||
raise ValueError('标题Token数大于chunkSize大小')
|
||||
strTitle = "\n".join(current_lines)
|
||||
current_lines.clear()
|
||||
bAreadyJudgeTitle = True
|
||||
|
||||
current_lines.append(line)
|
||||
|
||||
if line.startswith("|---"):
|
||||
self._colheader = current_lines[0]
|
||||
strheader = "\n".join(current_lines)
|
||||
headerSize= headerSize + self._token_size(strheader)
|
||||
current_lines.clear()
|
||||
|
||||
|
||||
if len(current_lines) > 0:
|
||||
if len(markdown_tups) == 0:
|
||||
titleHead = strTitle + '\n' + strheader if strTitle!= '' else strheader
|
||||
markdown_tups.append((titleHead, "\n".join(current_lines)))
|
||||
else:
|
||||
markdown_tups.append((strheader , "\n".join(current_lines)))
|
||||
|
||||
return [
|
||||
(
|
||||
key if key is None else re.sub(r"#", "", key).strip(),
|
||||
re.sub(r"<.*?>", "", value),
|
||||
)
|
||||
for key, value in markdown_tups
|
||||
]
|
||||
|
||||
def _token_size(self, text: str) -> int:
|
||||
return len(self._tokenizer(text))
|
||||
|
||||
def findValue(self,expression:str,Field:str):
|
||||
cols = self._colheader.split('|')
|
||||
cols = [item for item in cols if item]
|
||||
|
||||
for row in self._rows:
|
||||
rowtrs = row.split('|')
|
||||
rowdatas = [item for item in rowtrs if item and (item!='\r' or item!='\n')]
|
||||
if len(rowdatas) == 0:
|
||||
continue
|
||||
gData = {}
|
||||
for cName,rValue in zip(cols,rowdatas):
|
||||
gData[cName] = rValue
|
||||
if eval(expression,gData):
|
||||
return gData[Field]
|
||||
return ''
|
||||
|
||||
def records(self):
|
||||
cols = self._colheader.split('|')
|
||||
cols = cols[1:-1]
|
||||
records = []
|
||||
for row in self._rows:
|
||||
rowtrs = row.split('|')
|
||||
rowdatas = [item for item in rowtrs if (item!='\r' or item!='\n')]
|
||||
rowdatas = rowdatas[1:-1]
|
||||
if len(rowdatas) == 0:
|
||||
continue
|
||||
record = {}
|
||||
for cName,rValue in zip(cols,rowdatas):
|
||||
record[cName] = rValue
|
||||
records.append(record)
|
||||
return records
|
||||
|
||||
def _multi_char_split(self,string, separators):
|
||||
# 将多个分隔符连成一个正则表达式
|
||||
pattern = '[' + re.escape(separators) + ']'
|
||||
# 使用正则表达式进行分割
|
||||
return re.split(pattern, string)
|
||||
@@ -0,0 +1,79 @@
|
||||
from typing import Dict,List,Any
|
||||
import json,os
|
||||
|
||||
class Record:
|
||||
def __init__(self,datas:Dict[str,Any]) -> None:
|
||||
self._datas:Dict[str,Any] = datas
|
||||
|
||||
def value(self,key:str):
|
||||
if key in self._datas:
|
||||
return self._datas.get(key)
|
||||
return ''
|
||||
|
||||
class Field:
|
||||
def __init__(self,datas:Dict[str,Any]) -> None:
|
||||
self._datas:Dict[str,Any] = datas
|
||||
|
||||
def value(self,key:str):
|
||||
if key in self._datas:
|
||||
return self._datas.get(key)
|
||||
return ''
|
||||
|
||||
class JsonTable:
|
||||
def __init__(self,filePth:str) -> None:
|
||||
self._filePth = filePth
|
||||
self._fields:Dict[str,Field] = {}
|
||||
self._records:List[Record] = []
|
||||
self._fileName = os.path.splitext(os.path.basename(filePth))[0]
|
||||
self._name = ''
|
||||
self._comment = ''
|
||||
|
||||
def parse(self):
|
||||
with open(self._filePth, 'r',encoding='utf-8') as file:
|
||||
jsObj = json.load(file)
|
||||
data:dict = jsObj.get('table')
|
||||
self._name = data.get('name')
|
||||
self._comment = data.get('comment')
|
||||
Jsfields = data.get('fields')
|
||||
for jsfiled in Jsfields:
|
||||
field = Field(jsfiled)
|
||||
self._fields[field.value('name')] =field
|
||||
|
||||
JsRecords = data.get('records')
|
||||
for jsRecord in JsRecords:
|
||||
self._records.append(Record(jsRecord))
|
||||
|
||||
def records(self):
|
||||
return self._records
|
||||
|
||||
def fields(self):
|
||||
return self._fields
|
||||
|
||||
def name(self):
|
||||
return self._fileName
|
||||
|
||||
def comment(self):
|
||||
return self._comment
|
||||
|
||||
|
||||
class ProjectJson:
|
||||
def __init__(self,dir:str) -> None:
|
||||
self._dir = dir
|
||||
self._tables:Dict[str,JsonTable] = {}
|
||||
|
||||
def parse(self):
|
||||
json_files = [f for f in os.listdir(self._dir) if f.endswith('.json')]
|
||||
for json_file in json_files:
|
||||
prjPath = os.path.join(self._dir, json_file)
|
||||
tb = JsonTable(prjPath)
|
||||
tb.parse()
|
||||
basename = os.path.splitext(json_file)[0]
|
||||
self._tables[basename] = tb
|
||||
|
||||
def table(self,tableName:str):
|
||||
return self._tables[tableName]
|
||||
|
||||
def tables(self):
|
||||
return self._tables
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from llama_index.core.base.llms.types import LLMMetadata
|
||||
import os
|
||||
|
||||
class SiliconCloudOpenAI(OpenAI):
|
||||
@property
|
||||
def metadata(self) -> LLMMetadata:
|
||||
bIsChat = os.getenv('IS_CHAT_MODEL')
|
||||
bIsFuncall = os.getenv('IS_FUN_CALL_MODEL')
|
||||
bIsChat = True if bIsChat.lower() in ['true','1'] else False
|
||||
bIsFuncall = True if bIsFuncall.lower() in ['true','1'] else False
|
||||
|
||||
return LLMMetadata(
|
||||
context_window= int(os.getenv('CONTEXT_WINDOW')),
|
||||
num_output=self.max_tokens or -1,
|
||||
is_chat_model=bIsChat,
|
||||
is_function_calling_model=bIsFuncall,
|
||||
model_name=self.model,
|
||||
)
|
||||
@@ -0,0 +1,123 @@
|
||||
|
||||
from llama_index.llms.xinference import Xinference
|
||||
from typing import Any, Callable, Dict, Optional, Sequence, Tuple
|
||||
from llama_index.core.llms.callbacks import (
|
||||
llm_chat_callback,
|
||||
llm_completion_callback,
|
||||
)
|
||||
from llama_index.core.base.llms.types import (
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
ChatResponseGen,
|
||||
CompletionResponse,
|
||||
CompletionResponseGen,
|
||||
LLMMetadata,
|
||||
MessageRole,
|
||||
)
|
||||
from llama_index.llms.xinference.utils import (
|
||||
xinference_message_to_history,
|
||||
xinference_modelname_to_contextsize,
|
||||
)
|
||||
|
||||
class XinferenceModel(Xinference):
|
||||
@llm_chat_callback()
|
||||
def chat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:
|
||||
msgs = []
|
||||
assert self._generator is not None
|
||||
for message in messages:
|
||||
msgs.append(message.dict())
|
||||
response_text = self._generator.chat(
|
||||
messages=msgs,
|
||||
generate_config={
|
||||
"stream": False,
|
||||
"temperature": self.temperature,
|
||||
"max_tokens": self.max_tokens,
|
||||
},
|
||||
)["choices"][0]["message"]["content"]
|
||||
return ChatResponse(
|
||||
message=ChatMessage(
|
||||
role=MessageRole.ASSISTANT,
|
||||
content=response_text,
|
||||
),
|
||||
delta=None,
|
||||
)
|
||||
|
||||
@llm_chat_callback()
|
||||
def stream_chat(
|
||||
self, messages: Sequence[ChatMessage], **kwargs: Any
|
||||
) -> ChatResponseGen:
|
||||
msgs = []
|
||||
for message in messages:
|
||||
msgs.append(message.dict())
|
||||
assert self._generator is not None
|
||||
response_iter = self._generator.chat(
|
||||
messages=msgs,
|
||||
generate_config={
|
||||
"stream": True,
|
||||
"temperature": self.temperature,
|
||||
"max_tokens": self.max_tokens,
|
||||
},
|
||||
)
|
||||
|
||||
def gen() -> ChatResponseGen:
|
||||
text = ""
|
||||
for c in response_iter:
|
||||
delta = c["choices"][0]["delta"].get("content", "")
|
||||
text += delta
|
||||
yield ChatResponse(
|
||||
message=ChatMessage(
|
||||
role=MessageRole.ASSISTANT,
|
||||
content=text,
|
||||
),
|
||||
delta=delta,
|
||||
)
|
||||
|
||||
return gen()
|
||||
|
||||
@llm_completion_callback()
|
||||
def complete(
|
||||
self, prompt: str, formatted: bool = False, **kwargs: Any
|
||||
) -> CompletionResponse:
|
||||
assert self._generator is not None
|
||||
message = ChatMessage.from_str(prompt,MessageRole.SYSTEM)
|
||||
msgs = [message.dict()]
|
||||
response_text = self._generator.chat(
|
||||
messages=msgs,
|
||||
generate_config={
|
||||
"stream": False,
|
||||
"temperature": self.temperature,
|
||||
"max_tokens": self.max_tokens,
|
||||
},
|
||||
)["choices"][0]["message"]["content"]
|
||||
return CompletionResponse(
|
||||
delta=None,
|
||||
text=response_text,
|
||||
)
|
||||
|
||||
@llm_completion_callback()
|
||||
def stream_complete(
|
||||
self, prompt: str, formatted: bool = False, **kwargs: Any
|
||||
) -> CompletionResponseGen:
|
||||
assert self._generator is not None
|
||||
message = ChatMessage.from_str(prompt,MessageRole.SYSTEM)
|
||||
msgs = [message.dict()]
|
||||
response_iter = self._generator.chat(
|
||||
messages=msgs,
|
||||
generate_config={
|
||||
"stream": True,
|
||||
"temperature": self.temperature,
|
||||
"max_tokens": self.max_tokens,
|
||||
},
|
||||
)
|
||||
|
||||
def gen() -> CompletionResponseGen:
|
||||
text = ""
|
||||
for c in response_iter:
|
||||
delta = c["choices"][0]["delta"].get("content", "")
|
||||
text += delta
|
||||
yield CompletionResponse(
|
||||
delta=delta,
|
||||
text=text,
|
||||
)
|
||||
|
||||
return gen()
|
||||
+101
-57
@@ -2,88 +2,132 @@ from llama_index.core import PromptTemplate
|
||||
|
||||
text_qa_template_str = (
|
||||
"# 角色\n"
|
||||
"你是一名博微造价工程数据查询助手,专精于电力工程文件中的信息。"
|
||||
"你的职责是提供有关电力造价、造价编制软件、文件结构及相关数据的精准、客观的回答,"
|
||||
"如同直接从文件中提取的内容。\n"
|
||||
|
||||
"## 技能\n"
|
||||
"### 技能 1: 数据查询与提供\n"
|
||||
"- 准确回答所有关于电力工程造价的相关问题。\n"
|
||||
"- 提供具体数据,如成本估算、材料清单、劳动力需求等。\n"
|
||||
"- 确保提供的信息严格基于工程文档中的记录。\n"
|
||||
|
||||
"### 技能 2: 技术性解释\n"
|
||||
"- 解释造价工程中的技术术语和概念。\n"
|
||||
"- 为复杂的工程细节提供清晰易懂的说明。\n"
|
||||
|
||||
"## 约束\n"
|
||||
"- 仅回答与电力工程造价文件相关的具体问题。\n"
|
||||
"- 不进行任何超出文件内容的猜测或假设。\n"
|
||||
"- 所有回答均基于文件内容,采用客观和技术性的语言。\n"
|
||||
"- 请基于这些信息回答问题。如果无法找到相关信息,请不要额外发散回答,不要回答多余的信息,只需要回答“我不知道这个问题的答案”。\n"
|
||||
"以下为上下文信息\n"
|
||||
"你是一名擅长博微造价工程数据问答的专家,可以根据电力工程文件中的内容回答用户问题。\n"
|
||||
"\n"
|
||||
"# 任务描述:\n"
|
||||
"请仔细阅读所给的文档片段,并根据其内容回答问题。\n"
|
||||
"您需要判断文档的内容是否可以回答问题,不要强行回答。如果可以回答,答案必须严格遵循文档内容,即使与事实不符。\n"
|
||||
"如果答案与事实不符,直接给出答案,不要做解释。\n"
|
||||
"\n"
|
||||
"# 回答规则:\n"
|
||||
"- 请使用与文档材料相同的语言回答问题。\n"
|
||||
"- 评估文档是否含有足够信息回答问题。无关时不要回答。\n"
|
||||
"- 如果问题能被回答,你的回答必须严格遵循文档内容,即使与事实不符。一定不要做多余解释。\n"
|
||||
"- 如果问题能被回答,直接引用文档的相关信息保证答案准确、完整,并追求简洁。\n"
|
||||
"- 当文档中只有少量信息与问题相关时,重点关注这部分信息,这种情况下一定回答。\n"
|
||||
"- 当文档中信息与问题无关时,请不要额外发散回答,只需要回答“我不知道这个问题的答案”。\n"
|
||||
"\n"
|
||||
"来自多个来源的文档片段如下,请充分理解以下参考资料内容,组织出满足用户提问的条理清晰的回复。\n"
|
||||
"---------------------\n"
|
||||
"{context_str}\n"
|
||||
"---------------------\n"
|
||||
"请根据上下文信息而非先前知识回答我的问题或回复我的指令。前面的上下文信息可能有用,也可能没用,你需要从我给出的上下文信息中选出与我的问题最相关的那些,来为你的回答提供依据。回答一定要忠于原文,简洁但不丢信息,不要胡乱编造。如果无法找到相关信息,请不要额外发散回答,不要回答多余的信息,只需要回答“我不知道这个问题的答案”。我的问题或指令是什么语种,你就用什么语种回复。\n"
|
||||
"鉴于来自多个来源的文档片段而非先验知识,回答查询。\n"
|
||||
"如果是表结构或者是数据库的相关内容,只用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n"
|
||||
|
||||
"问题:{query_str}\n"
|
||||
"你的回复: "
|
||||
"Query: {query_str}\n"
|
||||
"Answer: "
|
||||
)
|
||||
|
||||
|
||||
text_qa_template = PromptTemplate(text_qa_template_str)
|
||||
|
||||
refine_template_str = (
|
||||
"这是原本的问题: {query_str}\n"
|
||||
"我们已经提供了回答: {existing_answer}\n"
|
||||
"现在我们有机会改进这个回答 "
|
||||
"使用以下更多上下文(仅当需要用时)\n"
|
||||
"使用以下更多上下文(仅当有助于改进回答时使用)\n"
|
||||
"你需要仔细的判断新的上下文的信息与原本问题必须一个字都不差,如果有一点差别,那就不能改变我现有的回答。\n"
|
||||
"在判断回答是否正确的时候,你应该仔细对比新的上下文中包含的信息是否与原本的问题一字不差,如果一字不差,才能当作新的正确回答。\n"
|
||||
"如果新的上下文对回答没有影响,或者原来的回答已经正确,不要在上次回答的后边再加上多余的补充信息,直接返回原本的回答。\n"
|
||||
"判断一下如果原回答正确,且在新的上下文仍然包含正确的回答,请将新的回答与原回答一起返回。\n"
|
||||
"------------\n"
|
||||
"{context_msg}\n"
|
||||
"------------\n"
|
||||
"根据新的上下文, 请改进原来的回答。"
|
||||
"如果新的上下文没有用, 直接返回原本的回答。\n"
|
||||
"如果是表结构或者是数据库的相关内容,只用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n"
|
||||
"如果回答中已经包含有正确答案,不要返回多余的解释等信息,只返回正确答案\n"
|
||||
"如果是表结构或者是数据库的相关内容,仅用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n"
|
||||
"改进的回答: "
|
||||
)
|
||||
|
||||
refine_template = PromptTemplate(refine_template_str)
|
||||
|
||||
summary_template_str = (
|
||||
"# 角色\n"
|
||||
"你是一名博微造价工程数据查询助手,专精于电力工程文件中的信息。"
|
||||
"你的职责是提供有关电力造价、造价编制软件、文件结构及相关数据的精准、客观的回答,"
|
||||
"如同直接从文件中提取的内容。\n"
|
||||
# summary_template_str = (
|
||||
# "# 角色\n"
|
||||
# "你是一名擅长博微造价工程数据问答的专家,可以根据电力工程文件中的内容回答用户问题。\n"
|
||||
# "\n"
|
||||
# "# 任务描述:\n"
|
||||
# "请仔细阅读所给的文档片段,并根据其内容回答问题。\n"
|
||||
# "您需要判断文档的内容是否可以回答问题,不要强行回答。如果可以回答,答案必须严格遵循文档内容,即使与事实不符。\n"
|
||||
# "如果答案与事实不符,直接给出答案,不要做解释。\n"
|
||||
# "\n"
|
||||
# "# 回答规则:\n"
|
||||
# "- 请使用与文档材料相同的语言回答问题。\n"
|
||||
# "- 评估文档是否含有足够信息回答问题。无关时不要回答。\n"
|
||||
# "- 如果问题能被回答,你的回答必须严格遵循文档内容,即使与事实不符。一定不要做多余解释。\n"
|
||||
# "- 如果问题能被回答,直接引用文档的相关信息保证答案准确、完整,并追求简洁。\n"
|
||||
# "- 当文档中只有少量信息与问题相关时,重点关注这部分信息,这种情况下一定回答。\n"
|
||||
# "- 当文档中信息与问题无关时,请不要额外发散回答,只需要回答为' '。\n"
|
||||
# "\n"
|
||||
# "来自多个来源的文档片段如下,请充分理解以下参考资料内容,组织出满足用户提问的条理清晰的回复。\n"
|
||||
# "---------------------\n"
|
||||
# "{context_str}\n"
|
||||
# "---------------------\n"
|
||||
# "鉴于来自多个来源的文档片段而非先验知识,回答查询。\n"
|
||||
# "如果是表结构或者是数据库的相关内容,只用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n"
|
||||
# "Query: {query_str}\n"
|
||||
# "Answer: "
|
||||
# )
|
||||
|
||||
"## 技能\n"
|
||||
"### 技能 1: 数据查询与提供\n"
|
||||
"- 准确回答所有关于电力工程造价的相关问题。\n"
|
||||
"- 提供具体数据,如成本估算、材料清单、劳动力需求等。\n"
|
||||
"- 确保提供的信息严格基于工程文档中的记录。\n"
|
||||
|
||||
"### 技能 2: 技术性解释\n"
|
||||
"- 解释造价工程中的技术术语和概念。\n"
|
||||
"- 为复杂的工程细节提供清晰易懂的说明。\n"
|
||||
summary_template_str = """
|
||||
你是一名擅长博微造价工程数据问答的专家,可以根据电力工程文件中的内容回答用户问题。
|
||||
来自多个来源的文档片段如下,请充分理解以下参考资料内容,回答问题。
|
||||
---------------------
|
||||
{context_str}
|
||||
---------------------
|
||||
当你不知道答案的时候,不要编造答案,直接回答不知道,不需要解释为什么不知道。
|
||||
问题: {query_str}
|
||||
回答:
|
||||
"""
|
||||
|
||||
|
||||
"## 约束\n"
|
||||
"- 仅回答与电力工程造价文件相关的具体问题。\n"
|
||||
"- 不进行任何超出文件内容的猜测或假设。\n"
|
||||
"- 所有回答均基于文件内容,采用客观和技术性的语言。\n"
|
||||
"- 请基于这些信息回答问题。如果无法找到相关信息,请不要额外发散回答,不要回答多余的信息,只需要回答“我不知道这个问题的答案”。\n"
|
||||
"来自多个来源的上下文信息如下。\n"
|
||||
"---------------------\n"
|
||||
"{context_str}\n"
|
||||
"---------------------\n"
|
||||
"鉴于来自多个来源的信息而非先验知识, "
|
||||
"回答查询。\n"
|
||||
"如果是表结构或者是数据库的相关内容,只用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n"
|
||||
"Query: {query_str}\n"
|
||||
"Answer: "
|
||||
)
|
||||
summary_template = PromptTemplate(summary_template_str)
|
||||
|
||||
simple_template_str = (
|
||||
"{query_str}"
|
||||
)
|
||||
simple_template = PromptTemplate(simple_template_str)
|
||||
|
||||
ReActChatFormatter_messages = (
|
||||
"您的设计旨在帮助完成各种任务,从回答问题到提供其他类型分析的摘要。\n\n"
|
||||
"##工具\n\n"
|
||||
"你可以访问各种工具。你有责任按照你认为合适的顺序使用这些工具来完成当前的任务。\n"
|
||||
"这可能需要将任务分解为子任务,并使用不同的工具来完成每个子任务。\n\n"
|
||||
"你可以访问以下工具:\n"
|
||||
"{tool_desc}\n\n\n"
|
||||
"##输出格式\n\n"
|
||||
"请用与问题相同的语言回答,并使用以下格式:\n\n"
|
||||
"'''\n"
|
||||
"Thought: 用户当前的语言是:(user's language)。我需要使用工具来帮助我回答问题。\n"
|
||||
"Action: 如果使用工具,则为工具名称(one of {tool_names})。\n"
|
||||
"Action Input: 输入给工具的内容,使用JSON格式表示kwargs(例如{{\"input\": \"hello world\", \"num_beams\": 5}})\n"
|
||||
"'''\n\n"
|
||||
"请始终以Thought开始。\n\n"
|
||||
"切勿用Markdown代码标记包围你的响应。如果需要,可以在响应中使用代码标记。\n\n"
|
||||
"请为Action Input使用有效的JSON格式。不要这样做{{\'input\': \'hello world\', \'num_beams\': 5}}。\n\n"
|
||||
"如果使用此格式,用户将以下面的格式进行回应:\n\n"
|
||||
"'''\n"
|
||||
"Observation: 工具响应\n"
|
||||
"'''\n\n"
|
||||
"你应该继续重复上述格式,直到你有足够的信息来回答问题而无需使用更多工具。此时,你必须使用以下两种格式之一进行回答:\n\n"
|
||||
"'''\nThought: 我可以不用任何工具来回答。我将使用用户的语言来回答。\n"
|
||||
"Answer: [你的答案(与用户问题相同的语言)]\n"
|
||||
"'''\n\n"
|
||||
"'''\n"
|
||||
"Thought: 我无法使用提供的工具回答问题。\n"
|
||||
"Answer: [你的答案(与用户问题相同的语言)]\n"
|
||||
"'''\n\n##如果从工具中得到的回应是Empty Response,那么只需要回答“我不知道”,不需要额外回答别的内容。## 当前对话\n\n"
|
||||
"以下是当前对话,由人类和助手的消息交替组成。\n"
|
||||
)
|
||||
|
||||
|
||||
summary_query_tool_messages = "适用于任何需要进行全面总结、概括的要求。"
|
||||
query_engine_tool_messages = "适用于回答任何问题。"
|
||||
tree_summary_query_engine_tool_messages = "在询问工程中单位的具体数值,例如用量,费率,合计,金额等的时候建议使用本工具。"
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
from typing import Any, List, Optional
|
||||
from llama_index.core.postprocessor import SentenceTransformerRerank
|
||||
from llama_index.core.schema import MetadataMode, NodeWithScore, QueryBundle
|
||||
from llama_index.core.callbacks import CBEventType, EventPayload
|
||||
from llama_index.core.bridge.pydantic import PrivateAttr
|
||||
|
||||
class OllamaRerank(SentenceTransformerRerank):
|
||||
_score_threshold: float = PrivateAttr()
|
||||
def __init__(
|
||||
self,
|
||||
top_n: int = 2,
|
||||
model: str = "cross-encoder/stsb-distilroberta-base",
|
||||
device: Optional[str] = None,
|
||||
keep_retrieval_score: Optional[bool] = False,
|
||||
score_threshold:float = 0.3
|
||||
):
|
||||
self._score_threshold = score_threshold
|
||||
super().__init__(top_n,model,device,keep_retrieval_score)
|
||||
|
||||
@classmethod
|
||||
def class_name(cls) -> str:
|
||||
return "OllamaRerank"
|
||||
|
||||
def _postprocess_nodes(
|
||||
self,
|
||||
nodes: List[NodeWithScore],
|
||||
query_bundle: Optional[QueryBundle] = None,
|
||||
) -> List[NodeWithScore]:
|
||||
if query_bundle is None:
|
||||
raise ValueError("Missing query bundle in extra info.")
|
||||
if len(nodes) == 0:
|
||||
return []
|
||||
|
||||
query_and_nodes = [
|
||||
(
|
||||
query_bundle.query_str,
|
||||
node.node.get_content(metadata_mode=MetadataMode.EMBED),
|
||||
)
|
||||
for node in nodes
|
||||
]
|
||||
|
||||
with self.callback_manager.event(
|
||||
CBEventType.RERANKING,
|
||||
payload={
|
||||
EventPayload.NODES: nodes,
|
||||
EventPayload.MODEL_NAME: self.model,
|
||||
EventPayload.QUERY_STR: query_bundle.query_str,
|
||||
EventPayload.TOP_K: self.top_n,
|
||||
},
|
||||
) as event:
|
||||
scores = self._model.predict(query_and_nodes)
|
||||
|
||||
assert len(scores) == len(nodes)
|
||||
|
||||
for node, score in zip(nodes, scores):
|
||||
if self.keep_retrieval_score:
|
||||
node.node.metadata["retrieval_score"] = node.score
|
||||
node.score = score
|
||||
|
||||
for i in range(len(nodes)-1,-1,-1):
|
||||
node = nodes[i]
|
||||
if node.score < self._score_threshold:
|
||||
nodes.remove(node)
|
||||
|
||||
new_nodes = sorted(nodes, key=lambda x: -x.score if x.score else 0)[
|
||||
: self.top_n
|
||||
]
|
||||
event.on_end(payload={EventPayload.NODES: new_nodes})
|
||||
|
||||
return new_nodes
|
||||
@@ -0,0 +1,97 @@
|
||||
import requests
|
||||
from typing import List, Optional
|
||||
from llama_index.core.bridge.pydantic import Field
|
||||
from llama_index.core.callbacks import CBEventType, EventPayload
|
||||
from llama_index.core.instrumentation import get_dispatcher
|
||||
from llama_index.core.instrumentation.events.rerank import (
|
||||
ReRankEndEvent,
|
||||
ReRankStartEvent,
|
||||
)
|
||||
from llama_index.core.postprocessor.types import BaseNodePostprocessor
|
||||
from llama_index.core.schema import NodeWithScore, QueryBundle, MetadataMode
|
||||
|
||||
dispatcher = get_dispatcher(__name__)
|
||||
|
||||
|
||||
class SiliconCloudRerank(BaseNodePostprocessor):
|
||||
top_n: int = Field(
|
||||
default=5,
|
||||
description="The number of nodes to return.",
|
||||
)
|
||||
model: str = Field(
|
||||
default="bge-reranker-base",
|
||||
description="The SiliconCloud model uid to use.",
|
||||
)
|
||||
base_url: str = Field(
|
||||
default="https://api.siliconflow.cn/v1",
|
||||
description="The SiliconCloud base url to use.",
|
||||
)
|
||||
api_key:str = Field(
|
||||
default="",
|
||||
description="The SiliconCloud Api key to use.",
|
||||
)
|
||||
score_threshold: float = Field(default=0.3,description="分数阈值")
|
||||
|
||||
@classmethod
|
||||
def class_name(cls) -> str:
|
||||
return "SiliconCloudRerank"
|
||||
|
||||
def get_query_str(self, query):
|
||||
return query.query_str if isinstance(query, QueryBundle) else query
|
||||
|
||||
def _postprocess_nodes(
|
||||
self,
|
||||
nodes: List[NodeWithScore],
|
||||
query_bundle: Optional[QueryBundle] = None,
|
||||
) -> List[NodeWithScore]:
|
||||
dispatcher.event(
|
||||
ReRankStartEvent(
|
||||
query=query_bundle,
|
||||
nodes=nodes,
|
||||
top_n=self.top_n,
|
||||
model_name=self.model,
|
||||
)
|
||||
)
|
||||
if query_bundle is None:
|
||||
raise ValueError("Missing query bundle.")
|
||||
if len(nodes) == 0:
|
||||
return []
|
||||
with self.callback_manager.event(
|
||||
CBEventType.RERANKING,
|
||||
payload={
|
||||
EventPayload.NODES: nodes,
|
||||
EventPayload.MODEL_NAME: self.model,
|
||||
EventPayload.QUERY_STR: self.get_query_str(query_bundle),
|
||||
EventPayload.TOP_K: self.top_n,
|
||||
},
|
||||
) as event:
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
'Authorization': f'Bearer {self.api_key}'
|
||||
}
|
||||
json_data = {
|
||||
"model": self.model,
|
||||
"query": self.get_query_str(query_bundle),
|
||||
"documents": [
|
||||
node.node.get_content(metadata_mode=MetadataMode.EMBED)
|
||||
for node in nodes
|
||||
],
|
||||
}
|
||||
response = requests.post(
|
||||
url=f"{self.base_url}/rerank", headers=headers, json=json_data
|
||||
)
|
||||
response.encoding = "utf-8"
|
||||
if response.status_code != 200:
|
||||
raise Exception(
|
||||
f"SiliconCloud call failed with status code {response.status_code}."
|
||||
f"Details: {response.text}"
|
||||
)
|
||||
rerank_nodes = [
|
||||
NodeWithScore(
|
||||
node=nodes[result["index"]].node, score=result["relevance_score"]
|
||||
)
|
||||
for result in response.json()["results"][: self.top_n]
|
||||
]
|
||||
event.on_end(payload={EventPayload.NODES: rerank_nodes})
|
||||
dispatcher.event(ReRankEndEvent(nodes=rerank_nodes))
|
||||
return rerank_nodes
|
||||
@@ -0,0 +1,75 @@
|
||||
import requests
|
||||
from llama_index.postprocessor.xinference_rerank import XinferenceRerank
|
||||
from llama_index.core.bridge.pydantic import Field
|
||||
from typing import List, Optional
|
||||
from llama_index.core.bridge.pydantic import Field
|
||||
from llama_index.core.callbacks import CBEventType, EventPayload
|
||||
from llama_index.core.instrumentation import get_dispatcher
|
||||
from llama_index.core.instrumentation.events.rerank import (
|
||||
ReRankEndEvent,
|
||||
ReRankStartEvent,
|
||||
)
|
||||
from llama_index.core.schema import NodeWithScore, QueryBundle, MetadataMode
|
||||
dispatcher = get_dispatcher(__name__)
|
||||
|
||||
class CustomXinFerenceRerank(XinferenceRerank):
|
||||
score_threshold: float = Field(default=0.3,description="分数阈值")
|
||||
|
||||
def _postprocess_nodes(
|
||||
self,
|
||||
nodes: List[NodeWithScore],
|
||||
query_bundle: Optional[QueryBundle] = None,
|
||||
) -> List[NodeWithScore]:
|
||||
dispatcher.event(
|
||||
ReRankStartEvent(
|
||||
query=query_bundle,
|
||||
nodes=nodes,
|
||||
top_n=self.top_n,
|
||||
model_name=self.model,
|
||||
)
|
||||
)
|
||||
if query_bundle is None:
|
||||
raise ValueError("Missing query bundle.")
|
||||
if len(nodes) == 0:
|
||||
return []
|
||||
with self.callback_manager.event(
|
||||
CBEventType.RERANKING,
|
||||
payload={
|
||||
EventPayload.NODES: nodes,
|
||||
EventPayload.MODEL_NAME: self.model,
|
||||
EventPayload.QUERY_STR: self.get_query_str(query_bundle),
|
||||
EventPayload.TOP_K: self.top_n,
|
||||
},
|
||||
) as event:
|
||||
headers = {"Content-Type": "application/json"}
|
||||
json_data = {
|
||||
"model": self.model,
|
||||
"query": self.get_query_str(query_bundle),
|
||||
"documents": [
|
||||
node.node.get_content(metadata_mode=MetadataMode.EMBED)
|
||||
for node in nodes
|
||||
],
|
||||
}
|
||||
response = requests.post(
|
||||
url=f"{self.base_url}/v1/rerank", headers=headers, json=json_data
|
||||
)
|
||||
response.encoding = "utf-8"
|
||||
if response.status_code != 200:
|
||||
raise Exception(
|
||||
f"Xinference call failed with status code {response.status_code}."
|
||||
f"Details: {response.text}"
|
||||
)
|
||||
|
||||
rerank_nodes = []
|
||||
for result in response.json()["results"]:
|
||||
node = NodeWithScore(
|
||||
node=nodes[result["index"]].node, score=result["relevance_score"]
|
||||
)
|
||||
if node.score > self.score_threshold:
|
||||
rerank_nodes.append(node)
|
||||
|
||||
if len(rerank_nodes) > self.top_n:
|
||||
rerank_nodes = sorted(rerank_nodes,key=lambda x:x.score,reverse = True)[:self.top_n]
|
||||
event.on_end(payload={EventPayload.NODES: rerank_nodes})
|
||||
dispatcher.event(ReRankEndEvent(nodes=rerank_nodes))
|
||||
return rerank_nodes
|
||||
@@ -0,0 +1,234 @@
|
||||
from llama_index.core.response_synthesizers.tree_summarize import TreeSummarize
|
||||
from typing import Any, Optional, Sequence,List
|
||||
import asyncio
|
||||
from llama_index.core.callbacks.base import CallbackManager
|
||||
from llama_index.core.indices.prompt_helper import PromptHelper
|
||||
from llama_index.core.prompts import BasePromptTemplate
|
||||
from llama_index.core.service_context import ServiceContext
|
||||
from llama_index.core.llms import LLM
|
||||
from llama_index.core.types import BaseModel,RESPONSE_TEXT_TYPE
|
||||
from llama_index.core.async_utils import run_async_tasks
|
||||
from llama_index.core.utils import get_tokenizer
|
||||
from llama_index.core.prompts.prompt_utils import get_empty_prompt_txt
|
||||
|
||||
class CustomTreeResponse(TreeSummarize):
|
||||
def __init__(
|
||||
self,
|
||||
llm: Optional[LLM] = None,
|
||||
callback_manager: Optional[CallbackManager] = None,
|
||||
prompt_helper: Optional[PromptHelper] = None,
|
||||
summary_template: Optional[BasePromptTemplate] = None,
|
||||
output_cls: Optional[BaseModel] = None,
|
||||
streaming: bool = False,
|
||||
use_async: bool = False,
|
||||
verbose: bool = False,
|
||||
service_context: Optional[ServiceContext] = None,
|
||||
) -> None:
|
||||
self._tokenizer = get_tokenizer()
|
||||
super().__init__(llm,callback_manager,prompt_helper,summary_template,output_cls
|
||||
,streaming,use_async,verbose,service_context)
|
||||
|
||||
async def aget_response(
|
||||
self,
|
||||
query_str: str,
|
||||
text_chunks: Sequence[str],
|
||||
**response_kwargs: Any,
|
||||
) -> RESPONSE_TEXT_TYPE:
|
||||
"""Get tree summarize response."""
|
||||
summary_template = self._summary_template.partial_format(query_str=query_str)
|
||||
|
||||
text_chunks = self.repack(text_chunks=text_chunks)
|
||||
|
||||
if self._verbose:
|
||||
print(f"{len(text_chunks)} text chunks after repacking")
|
||||
|
||||
|
||||
# give final response if there is only one chunk
|
||||
if len(text_chunks) == 1:
|
||||
response: RESPONSE_TEXT_TYPE
|
||||
if self._streaming:
|
||||
response = await self._llm.astream(
|
||||
summary_template, context_str=text_chunks[0], **response_kwargs
|
||||
)
|
||||
else:
|
||||
if self._output_cls is None:
|
||||
response = await self._llm.apredict(
|
||||
summary_template,
|
||||
context_str=text_chunks[0],
|
||||
**response_kwargs,
|
||||
)
|
||||
else:
|
||||
response = await self._llm.astructured_predict(
|
||||
self._output_cls,
|
||||
summary_template,
|
||||
context_str=text_chunks[0],
|
||||
**response_kwargs,
|
||||
)
|
||||
|
||||
# return pydantic object if output_cls is specified
|
||||
return response
|
||||
|
||||
else:
|
||||
# summarize each chunk
|
||||
if self._output_cls is None:
|
||||
tasks = [
|
||||
self._llm.apredict(
|
||||
summary_template,
|
||||
context_str=text_chunk,
|
||||
**response_kwargs,
|
||||
)
|
||||
for text_chunk in text_chunks
|
||||
]
|
||||
else:
|
||||
tasks = [
|
||||
self._llm.astructured_predict(
|
||||
self._output_cls,
|
||||
summary_template,
|
||||
context_str=text_chunk,
|
||||
**response_kwargs,
|
||||
)
|
||||
for text_chunk in text_chunks
|
||||
]
|
||||
|
||||
summary_responses = await asyncio.gather(*tasks)
|
||||
if self._output_cls is not None:
|
||||
summaries = [summary.json() for summary in summary_responses]
|
||||
else:
|
||||
summaries = summary_responses
|
||||
|
||||
# recursively summarize the summaries
|
||||
return await self.aget_response(
|
||||
query_str=query_str,
|
||||
text_chunks=summaries,
|
||||
**response_kwargs,
|
||||
)
|
||||
|
||||
def get_response(
|
||||
self,
|
||||
query_str: str,
|
||||
text_chunks: Sequence[str],
|
||||
**response_kwargs: Any,
|
||||
) -> RESPONSE_TEXT_TYPE:
|
||||
"""Get tree summarize response."""
|
||||
summary_template = self._summary_template.partial_format(query_str=query_str)
|
||||
text_chunks = self.repack(text_chunks=text_chunks)
|
||||
|
||||
if self._verbose:
|
||||
print(f"{len(text_chunks)} text chunks after repacking")
|
||||
|
||||
# give final response if there is only one chunk
|
||||
if len(text_chunks) == 1:
|
||||
response: RESPONSE_TEXT_TYPE
|
||||
if self._streaming:
|
||||
response = self._llm.stream(
|
||||
summary_template, context_str=text_chunks[0], **response_kwargs
|
||||
)
|
||||
else:
|
||||
if self._output_cls is None:
|
||||
response = self._llm.predict(
|
||||
summary_template,
|
||||
context_str=text_chunks[0],
|
||||
**response_kwargs,
|
||||
)
|
||||
else:
|
||||
response = self._llm.structured_predict(
|
||||
self._output_cls,
|
||||
summary_template,
|
||||
context_str=text_chunks[0],
|
||||
**response_kwargs,
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
else:
|
||||
# summarize each chunk
|
||||
if self._use_async:
|
||||
if self._output_cls is None:
|
||||
tasks = [
|
||||
self._llm.apredict(
|
||||
summary_template,
|
||||
context_str=text_chunk,
|
||||
**response_kwargs,
|
||||
)
|
||||
for text_chunk in text_chunks
|
||||
]
|
||||
else:
|
||||
tasks = [
|
||||
self._llm.astructured_predict(
|
||||
self._output_cls,
|
||||
summary_template,
|
||||
context_str=text_chunk,
|
||||
**response_kwargs,
|
||||
)
|
||||
for text_chunk in text_chunks
|
||||
]
|
||||
|
||||
summary_responses = run_async_tasks(tasks)
|
||||
|
||||
if self._output_cls is not None:
|
||||
summaries = [summary.json() for summary in summary_responses]
|
||||
else:
|
||||
summaries = summary_responses
|
||||
else:
|
||||
if self._output_cls is None:
|
||||
summaries = [
|
||||
self._llm.predict(
|
||||
summary_template,
|
||||
context_str=text_chunk,
|
||||
**response_kwargs,
|
||||
)
|
||||
for text_chunk in text_chunks
|
||||
]
|
||||
else:
|
||||
summaries = [
|
||||
self._llm.structured_predict(
|
||||
self._output_cls,
|
||||
summary_template,
|
||||
context_str=text_chunk,
|
||||
**response_kwargs,
|
||||
)
|
||||
for text_chunk in text_chunks
|
||||
]
|
||||
summaries = [summary.json() for summary in summaries]
|
||||
|
||||
# recursively summarize the summaries
|
||||
return self.get_response(
|
||||
query_str=query_str, text_chunks=summaries, **response_kwargs
|
||||
)
|
||||
|
||||
def repack( self,text_chunks: Sequence[str],) ->List[str]:
|
||||
prompt_str = get_empty_prompt_txt(self._summary_template)
|
||||
num_prompt_tokens = self._token_size(prompt_str)
|
||||
avaliableSize = self._get_available_context_size(num_prompt_tokens)
|
||||
ava_chunks = []
|
||||
sumSize = 0
|
||||
results = []
|
||||
for text_chunk in text_chunks:
|
||||
one_chunk_size = self._token_size(text_chunk)
|
||||
if one_chunk_size > avaliableSize:
|
||||
raise ValueError("文本块大小大于可用上下文大小")
|
||||
sumSize = sumSize + one_chunk_size
|
||||
if sumSize > avaliableSize:
|
||||
results.append(self._merge_chunks(ava_chunks))
|
||||
ava_chunks.clear()
|
||||
sumSize = 0
|
||||
ava_chunks.append(text_chunk)
|
||||
if len(ava_chunks) > 0:
|
||||
results.append(self._merge_chunks(ava_chunks))
|
||||
return results
|
||||
|
||||
def _get_available_context_size(self, num_prompt_tokens: int) -> int:
|
||||
llm_metadata = self._llm.metadata
|
||||
context_size_tokens = llm_metadata.context_window - num_prompt_tokens - llm_metadata.num_output
|
||||
if context_size_tokens < 0:
|
||||
raise ValueError(
|
||||
f"Calculated available context size {context_size_tokens} was"
|
||||
" not non-negative."
|
||||
)
|
||||
return context_size_tokens
|
||||
|
||||
def _token_size(self, text: str) -> int:
|
||||
return len(self._tokenizer(text))
|
||||
|
||||
def _merge_chunks(self,ava_chunks:list):
|
||||
return "\n\n".join([c.strip() for c in ava_chunks if c.strip()])
|
||||
@@ -1,133 +0,0 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from typing import Any, Callable, Dict, List, Optional, cast
|
||||
|
||||
from llama_index.core.base.base_retriever import BaseRetriever
|
||||
from llama_index.core.callbacks.base import CallbackManager
|
||||
from llama_index.core.constants import DEFAULT_SIMILARITY_TOP_K
|
||||
from llama_index.core.indices.vector_store.base import VectorStoreIndex
|
||||
from llama_index.core.schema import BaseNode, IndexNode, NodeWithScore, QueryBundle
|
||||
from llama_index.core.storage.docstore.types import BaseDocumentStore
|
||||
from llama_index.core.vector_stores.utils import (
|
||||
node_to_metadata_dict,
|
||||
metadata_dict_to_node,
|
||||
)
|
||||
|
||||
import bm25s
|
||||
from app.engine.retriever.CHTokener import chTokenize
|
||||
|
||||
CHDEFAULT_PERSIST_ARGS = {"similarity_top_k": "similarity_top_k", "_verbose": "verbose"}
|
||||
|
||||
CHDEFAULT_PERSIST_FILENAME = "retriever.json"
|
||||
|
||||
class CHBM25Retriever(BaseRetriever):
|
||||
def __init__(
|
||||
self,
|
||||
nodes: Optional[List[BaseNode]] = None,
|
||||
existing_bm25: Optional[bm25s.BM25] = None,
|
||||
similarity_top_k: int = DEFAULT_SIMILARITY_TOP_K,
|
||||
callback_manager: Optional[CallbackManager] = None,
|
||||
objects: Optional[List[IndexNode]] = None,
|
||||
object_map: Optional[dict] = None,
|
||||
verbose: bool = False,
|
||||
) -> None:
|
||||
self.similarity_top_k = similarity_top_k
|
||||
if existing_bm25 is not None:
|
||||
self.bm25 = existing_bm25
|
||||
self.corpus = existing_bm25.corpus
|
||||
else:
|
||||
from nltk.corpus import stopwords
|
||||
if nodes is None:
|
||||
raise ValueError("Please pass nodes or an existing BM25 object.")
|
||||
|
||||
self.corpus = [node_to_metadata_dict(node) for node in nodes]
|
||||
|
||||
corpus_tokens = chTokenize(
|
||||
[node.get_content() for node in nodes],
|
||||
show_progress=verbose,
|
||||
)
|
||||
self.bm25 = bm25s.BM25()
|
||||
self.bm25.index(corpus_tokens, show_progress=verbose)
|
||||
super().__init__(
|
||||
callback_manager=callback_manager,
|
||||
object_map=object_map,
|
||||
objects=objects,
|
||||
verbose=verbose,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_defaults(
|
||||
cls,
|
||||
index: Optional[VectorStoreIndex] = None,
|
||||
nodes: Optional[List[BaseNode]] = None,
|
||||
docstore: Optional[BaseDocumentStore] = None,
|
||||
similarity_top_k: int = DEFAULT_SIMILARITY_TOP_K,
|
||||
verbose: bool = False,
|
||||
) -> "CHBM25Retriever":
|
||||
if sum(bool(val) for val in [index, nodes, docstore]) != 1:
|
||||
raise ValueError("Please pass exactly one of index, nodes, or docstore.")
|
||||
|
||||
if index is not None:
|
||||
docstore = index.docstore
|
||||
|
||||
if docstore is not None:
|
||||
nodes = cast(List[BaseNode], list(docstore.docs.values()))
|
||||
|
||||
assert (
|
||||
nodes is not None
|
||||
), "Please pass exactly one of index, nodes, or docstore."
|
||||
|
||||
return cls(
|
||||
nodes=nodes,
|
||||
similarity_top_k=similarity_top_k,
|
||||
verbose=verbose,
|
||||
)
|
||||
|
||||
def get_persist_args(self) -> Dict[str, Any]:
|
||||
"""Get Persist Args Dict to Save."""
|
||||
return {
|
||||
CHDEFAULT_PERSIST_ARGS[key]: getattr(self, key)
|
||||
for key in CHDEFAULT_PERSIST_ARGS
|
||||
if hasattr(self, key)
|
||||
}
|
||||
|
||||
def persist(self, path: str, **kwargs: Any) -> None:
|
||||
"""Persist the retriever to a directory."""
|
||||
self.bm25.save(path, corpus=self.corpus, **kwargs)
|
||||
with open(os.path.join(path, CHDEFAULT_PERSIST_FILENAME), "w") as f:
|
||||
json.dump(self.get_persist_args(), f, indent=2)
|
||||
|
||||
@classmethod
|
||||
def from_persist_dir(cls, path: str, **kwargs: Any) -> "CHBM25Retriever":
|
||||
"""Load the retriever from a directory."""
|
||||
bm25 = bm25s.BM25.load(path, load_corpus=True, **kwargs)
|
||||
with open(os.path.join(path, CHDEFAULT_PERSIST_FILENAME)) as f:
|
||||
retriever_data = json.load(f)
|
||||
return cls(existing_bm25=bm25, **retriever_data)
|
||||
|
||||
def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]:
|
||||
query = query_bundle.query_str
|
||||
tokenized_query = chTokenize(
|
||||
query,show_progress=self._verbose
|
||||
)
|
||||
indexes, scores = self.bm25.retrieve(
|
||||
tokenized_query, k=self.similarity_top_k, show_progress=self._verbose
|
||||
)
|
||||
|
||||
# batched, but only one query
|
||||
indexes = indexes[0]
|
||||
scores = scores[0]
|
||||
|
||||
nodes: List[NodeWithScore] = []
|
||||
for idx, score in zip(indexes, scores):
|
||||
# idx can be an int or a dict of the node
|
||||
if isinstance(idx, dict):
|
||||
node = metadata_dict_to_node(idx)
|
||||
else:
|
||||
node_dict = self.corpus[int(idx)]
|
||||
node = metadata_dict_to_node(node_dict)
|
||||
nodes.append(NodeWithScore(node=node, score=float(score)))
|
||||
|
||||
return nodes
|
||||
@@ -1,46 +0,0 @@
|
||||
from typing import Any, Dict, List, Union, Callable, NamedTuple
|
||||
from bm25s.tokenization import *
|
||||
|
||||
try:
|
||||
from tqdm.auto import tqdm
|
||||
except ImportError:
|
||||
|
||||
def tqdm(iterable, *args, **kwargs):
|
||||
return iterable
|
||||
|
||||
|
||||
def chinese_tokenizer(text: str) -> List[str]:
|
||||
import jieba
|
||||
from nltk.corpus import stopwords
|
||||
tokens = jieba.lcut(text)
|
||||
return [token for token in tokens if token not in stopwords.words('chinese')]
|
||||
|
||||
def chTokenize(
|
||||
texts,
|
||||
show_progress: bool = True,
|
||||
leave: bool = False,
|
||||
) -> Union[List[List[str]], Tokenized]:
|
||||
if isinstance(texts, str):
|
||||
texts = [texts]
|
||||
|
||||
corpus_ids = []
|
||||
token_to_index = {}
|
||||
|
||||
for text in tqdm(
|
||||
texts, desc="Split strings", leave=leave, disable=not show_progress
|
||||
):
|
||||
|
||||
splitted = chinese_tokenizer(text)
|
||||
doc_ids = []
|
||||
|
||||
for token in splitted:
|
||||
if token not in token_to_index:
|
||||
token_to_index[token] = len(token_to_index)
|
||||
|
||||
token_id = token_to_index[token]
|
||||
doc_ids.append(token_id)
|
||||
|
||||
corpus_ids.append(doc_ids)
|
||||
|
||||
return Tokenized(ids=corpus_ids, vocab=token_to_index)
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import os
|
||||
from typing import Optional, Any, Dict, List
|
||||
|
||||
from llama_index.core.base.base_retriever import BaseRetriever
|
||||
from llama_index.core.schema import NodeWithScore, QueryBundle
|
||||
|
||||
from app.engine.retriever.CHBM25Retriever import CHBM25Retriever
|
||||
|
||||
|
||||
class HybridRetriever(BaseRetriever):
|
||||
def __init__(
|
||||
self,
|
||||
vector_index,
|
||||
similarity_top_k: int = 2,
|
||||
out_top_k: Optional[int] = None,
|
||||
alpha: float = 0.5,
|
||||
filters = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self._vector_index = vector_index
|
||||
self._embed_model = vector_index._embed_model
|
||||
self._out_top_k = out_top_k or similarity_top_k
|
||||
self._vecRetriever = vector_index.as_retriever(
|
||||
similarity_top_k=similarity_top_k,filters = filters
|
||||
)
|
||||
|
||||
STORAGE_DIR = os.getenv("BM_RETRIEVER_PATH", "storage_bm")
|
||||
if os.path.exists(STORAGE_DIR) and len(os.listdir(STORAGE_DIR)) > 0:
|
||||
self._bm25Retriever = CHBM25Retriever.from_persist_dir(STORAGE_DIR)
|
||||
else:
|
||||
bmRetriver = CHBM25Retriever.from_defaults(similarity_top_k=similarity_top_k,nodes=self._vector_index.vector_store.get_nodes(None))
|
||||
bmRetriver.persist(STORAGE_DIR)
|
||||
self._alpha = alpha
|
||||
|
||||
|
||||
|
||||
def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]:
|
||||
vecNodes:List[NodeWithScore] = self._vecRetriever.retrieve(query_bundle.query_str)
|
||||
bmNodes:List[NodeWithScore] = self._bm25Retriever.retrieve(query_bundle.query_str)
|
||||
|
||||
bmDic:Dict[str,NodeWithScore] = {}
|
||||
for node in bmNodes:
|
||||
bmDic[node.node_id] = node
|
||||
|
||||
result_tups = []
|
||||
for i in range(len(vecNodes)):
|
||||
node = vecNodes[i]
|
||||
bmScore = 0.0
|
||||
if node.node_id in bmDic:
|
||||
bmScore = bmDic[node.node_id].score
|
||||
bmDic.pop(node.node_id)
|
||||
else:
|
||||
bmScore = 0.0
|
||||
full_similarity = (self._alpha * node.score) + (
|
||||
(1 - self._alpha) * bmScore
|
||||
)
|
||||
result_tups.append((full_similarity, node))
|
||||
|
||||
for _,node in bmDic.items():
|
||||
full_similarity = (1 - self._alpha) * node.score
|
||||
result_tups.append((full_similarity, node))
|
||||
|
||||
result_tups = sorted(result_tups, key=lambda x: x[0], reverse=True)
|
||||
for full_score, node in result_tups:
|
||||
node.score = full_score
|
||||
return [n for _, n in result_tups][:self._out_top_k]
|
||||
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
from typing import Any, Dict, List, Union, Callable, NamedTuple
|
||||
from bm25s.tokenization import *
|
||||
|
||||
@@ -8,9 +9,12 @@ except ImportError:
|
||||
def tqdm(iterable, *args, **kwargs):
|
||||
return iterable
|
||||
|
||||
import jieba
|
||||
jiebapath = os.environ.get("JIEBA_DATA", "")
|
||||
jieba.set_dictionary(os.path.join(jiebapath, 'dict.txt')) #设置字典
|
||||
jieba.initialize() #初始化jeiba
|
||||
|
||||
def chinese_tokenizer(text: str) -> List[str]:
|
||||
import jieba
|
||||
from nltk.corpus import stopwords
|
||||
tokens = jieba.lcut(text)
|
||||
return [token for token in tokens if token not in stopwords.words('chinese')]
|
||||
|
||||
@@ -24,13 +24,15 @@ class HybridRetriever(BaseRetriever):
|
||||
self._vecRetriever = vector_index.as_retriever(
|
||||
similarity_top_k=similarity_top_k,filters = filters
|
||||
)
|
||||
|
||||
self._bm25Retriever = None
|
||||
STORAGE_DIR = os.getenv("BM_RETRIEVER_PATH", "storage_bm")
|
||||
if os.path.exists(STORAGE_DIR) and len(os.listdir(STORAGE_DIR)) > 0:
|
||||
self._bm25Retriever = CHBM25Retriever.from_persist_dir(STORAGE_DIR)
|
||||
else:
|
||||
bmRetriver = CHBM25Retriever.from_defaults(similarity_top_k=similarity_top_k,nodes=self._vector_index.vector_store.get_nodes(None))
|
||||
bmRetriver.persist(STORAGE_DIR)
|
||||
nodes = self._vector_index.vector_store.get_nodes(None)
|
||||
similarity_top_k = min(len(nodes),similarity_top_k)
|
||||
self._bm25Retriever = CHBM25Retriever.from_defaults(similarity_top_k=similarity_top_k,nodes=nodes)
|
||||
self._bm25Retriever.persist(STORAGE_DIR)
|
||||
self._alpha = alpha
|
||||
|
||||
|
||||
@@ -43,6 +45,16 @@ class HybridRetriever(BaseRetriever):
|
||||
for node in bmNodes:
|
||||
bmDic[node.node_id] = node
|
||||
|
||||
vecScores = [node_with_score.score for node_with_score in vecNodes]
|
||||
bmSores = [node_with_score.score for node_with_score in bmNodes]
|
||||
|
||||
vec_min_score = min(vecScores) if len(vecScores) > 0 else 0
|
||||
vec_max_score = max(vecScores) if len(vecScores) > 0 else 0
|
||||
|
||||
bm_min_score = min(bmSores) if len(bmSores) > 0 else 0
|
||||
bm_max_score = max(bmSores) if len(bmSores) > 0 else 0
|
||||
|
||||
|
||||
result_tups = []
|
||||
for i in range(len(vecNodes)):
|
||||
node = vecNodes[i]
|
||||
@@ -52,7 +64,11 @@ class HybridRetriever(BaseRetriever):
|
||||
bmDic.pop(node.node_id)
|
||||
else:
|
||||
bmScore = 0.0
|
||||
full_similarity = (self._alpha * node.score) + (
|
||||
|
||||
bmScore = self.normal_score(bmScore,bm_min_score,bm_max_score)
|
||||
vecScore = self.normal_score(node.score,vec_min_score,vec_max_score)
|
||||
|
||||
full_similarity = (self._alpha * vecScore) + (
|
||||
(1 - self._alpha) * bmScore
|
||||
)
|
||||
result_tups.append((full_similarity, node))
|
||||
@@ -65,3 +81,9 @@ class HybridRetriever(BaseRetriever):
|
||||
for full_score, node in result_tups:
|
||||
node.score = full_score
|
||||
return [n for _, n in result_tups][:self._out_top_k]
|
||||
|
||||
def normal_score(self,score,min,max):
|
||||
if min == max:
|
||||
return 1.0 if score > 0 else 0.0
|
||||
else:
|
||||
return (score - min) / (max - min)
|
||||
@@ -0,0 +1,73 @@
|
||||
import os
|
||||
from typing import Any, List, Sequence, Optional
|
||||
from llama_index.core.schema import BaseNode, NodeWithScore, QueryBundle
|
||||
from llama_index.core.graph_stores.types import (
|
||||
PropertyGraphStore,
|
||||
KG_SOURCE_REL,
|
||||
VECTOR_SOURCE_KEY,
|
||||
)
|
||||
from llama_index.core.indices.property_graph.sub_retrievers.base import BasePGRetriever
|
||||
from llama_index.core.graph_stores.types import (
|
||||
PropertyGraphStore,
|
||||
KG_SOURCE_REL
|
||||
)
|
||||
from app.engine.retriever.CHBM25Retriever import CHBM25Retriever
|
||||
|
||||
class GraphBM25Retriever(BasePGRetriever):
|
||||
def __init__(
|
||||
self,
|
||||
graph_store: PropertyGraphStore,
|
||||
include_text: bool = True,
|
||||
path_depth: int = 1,
|
||||
similarity_score: Optional[float] = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
self._path_depth = path_depth
|
||||
self._similarity_score = similarity_score
|
||||
STORAGE_DIR = os.getenv("BM_RETRIEVER_PATH", "storage_bm")
|
||||
if os.path.exists(STORAGE_DIR) and len(os.listdir(STORAGE_DIR)) > 0:
|
||||
self._bm25Retriever = CHBM25Retriever.from_persist_dir(STORAGE_DIR)
|
||||
super().__init__(graph_store=graph_store, include_text=include_text, **kwargs)
|
||||
|
||||
async def aretrieve_from_graph(
|
||||
self, query_bundle: QueryBundle
|
||||
) -> List[NodeWithScore]:
|
||||
query_result:List[NodeWithScore] = self._bm25Retriever._retrieve(query_bundle.query_str)
|
||||
nodes,scores = [],[]
|
||||
for scoreNode in query_result:
|
||||
nodes.append(scoreNode.node)
|
||||
scores.append(scoreNode.score)
|
||||
|
||||
kg_ids = self._get_kg_ids(nodes)
|
||||
kg_nodes = await self._graph_store.aget(ids=kg_ids)
|
||||
triplets = await self._graph_store.aget_rel_map(
|
||||
kg_nodes, depth=self._path_depth, ignore_rels=[KG_SOURCE_REL]
|
||||
)
|
||||
new_scores = []
|
||||
for triplet in triplets:
|
||||
score1 = (
|
||||
scores[kg_ids.index(triplet[0].id)] if triplet[0].id in kg_ids else 0.0
|
||||
)
|
||||
score2 = (
|
||||
scores[kg_ids.index(triplet[2].id)] if triplet[2].id in kg_ids else 0.0
|
||||
)
|
||||
new_scores.append(max(score1, score2))
|
||||
|
||||
assert len(triplets) == len(new_scores)
|
||||
|
||||
if self._similarity_score:
|
||||
filtered_data = [
|
||||
(triplet, score)
|
||||
for triplet, score in zip(triplets, new_scores)
|
||||
if score >= self._similarity_score
|
||||
]
|
||||
|
||||
top_k = sorted(filtered_data, key=lambda x: x[1], reverse=True)
|
||||
else:
|
||||
top_k = sorted(zip(triplets, new_scores), key=lambda x: x[1], reverse=True)
|
||||
|
||||
return self._get_nodes_with_score([x[0] for x in top_k], [x[1] for x in top_k])
|
||||
|
||||
def _get_kg_ids(self, kg_nodes: Sequence[BaseNode]) -> List[str]:
|
||||
"""Backward compatibility method to get kg_ids from kg_nodes."""
|
||||
return [node.metadata.get(VECTOR_SOURCE_KEY, node.id_) for node in kg_nodes]
|
||||
@@ -0,0 +1,63 @@
|
||||
from typing import Any, Callable, List, Optional, Union
|
||||
from llama_index.core.llms.llm import LLM
|
||||
from llama_index.core.indices.property_graph.sub_retrievers.base import (
|
||||
BasePGRetriever,
|
||||
)
|
||||
from llama_index.core.graph_stores.types import (
|
||||
PropertyGraphStore,
|
||||
KG_SOURCE_REL,
|
||||
)
|
||||
from llama_index.core.settings import Settings
|
||||
from llama_index.core.schema import (
|
||||
NodeWithScore,
|
||||
QueryBundle,
|
||||
)
|
||||
from llama_index.core.graph_stores.types import EntityNode
|
||||
|
||||
|
||||
class GraphKeyWordRetriever(BasePGRetriever):
|
||||
def __init__(
|
||||
self,
|
||||
graph_store: PropertyGraphStore,
|
||||
include_text: bool = True,
|
||||
path_depth: int = 1,
|
||||
llm: Optional[LLM] = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
self._llm = llm or Settings.llm
|
||||
self._path_depth = path_depth
|
||||
super().__init__(graph_store=graph_store, include_text=include_text, **kwargs)
|
||||
|
||||
def _prepare_matches(self,query_bundle: QueryBundle) -> List[NodeWithScore]:
|
||||
kg_nodes = []
|
||||
labelNodes = self._graph_store.get()
|
||||
for labelNode in labelNodes:
|
||||
if isinstance(labelNode,EntityNode) and labelNode.name in query_bundle.query_str:
|
||||
kg_nodes.append(labelNode)
|
||||
triplets = self._graph_store.get_rel_map(
|
||||
kg_nodes,
|
||||
depth=self._path_depth,
|
||||
ignore_rels=[KG_SOURCE_REL],
|
||||
)
|
||||
return self._get_nodes_with_score(triplets)
|
||||
|
||||
async def _aprepare_matches(self,query_bundle: QueryBundle) -> List[NodeWithScore]:
|
||||
kg_nodes = []
|
||||
labelNodes = await self._graph_store.aget()
|
||||
for labelNode in labelNodes:
|
||||
if isinstance(labelNode,EntityNode) and labelNode.name in query_bundle.query_str:
|
||||
kg_nodes.append(labelNode)
|
||||
triplets = await self._graph_store.aget_rel_map(
|
||||
kg_nodes,
|
||||
depth=self._path_depth,
|
||||
ignore_rels=[KG_SOURCE_REL],
|
||||
)
|
||||
return self._get_nodes_with_score(triplets)
|
||||
|
||||
def retrieve_from_graph(self, query_bundle: QueryBundle) -> List[NodeWithScore]:
|
||||
return self._prepare_matches(query_bundle)
|
||||
|
||||
async def aretrieve_from_graph(
|
||||
self, query_bundle: QueryBundle
|
||||
) -> List[NodeWithScore]:
|
||||
return await self._aprepare_matches(query_bundle)
|
||||
@@ -1,36 +0,0 @@
|
||||
from llama_index.core.tools.function_tool import FunctionTool
|
||||
|
||||
|
||||
def duckduckgo_search(
|
||||
query: str,
|
||||
region: str = "wt-wt",
|
||||
max_results: int = 10,
|
||||
):
|
||||
"""
|
||||
Use this function to search for any query in DuckDuckGo.
|
||||
Args:
|
||||
query (str): The query to search in DuckDuckGo.
|
||||
region Optional(str): The region to be used for the search in [country-language] convention, ex us-en, uk-en, ru-ru, etc...
|
||||
max_results Optional(int): The maximum number of results to be returned. Default is 10.
|
||||
"""
|
||||
try:
|
||||
from duckduckgo_search import DDGS
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"duckduckgo_search package is required to use this function."
|
||||
"Please install it by running: `poetry add duckduckgo_search` or `pip install duckduckgo_search`"
|
||||
)
|
||||
|
||||
params = {
|
||||
"keywords": query,
|
||||
"region": region,
|
||||
"max_results": max_results,
|
||||
}
|
||||
results = []
|
||||
with DDGS() as ddg:
|
||||
results = list(ddg.text(**params))
|
||||
return results
|
||||
|
||||
|
||||
def get_tools(**kwargs):
|
||||
return [FunctionTool.from_defaults(duckduckgo_search)]
|
||||
@@ -1,60 +0,0 @@
|
||||
import os
|
||||
import yaml
|
||||
import json
|
||||
import importlib
|
||||
from cachetools import cached, LRUCache
|
||||
from llama_index.core.tools.tool_spec.base import BaseToolSpec
|
||||
from llama_index.core.tools.function_tool import FunctionTool
|
||||
|
||||
|
||||
class ToolType:
|
||||
LLAMAHUB = "llamahub"
|
||||
LOCAL = "local"
|
||||
|
||||
|
||||
class ToolFactory:
|
||||
|
||||
TOOL_SOURCE_PACKAGE_MAP = {
|
||||
ToolType.LLAMAHUB: "llama_index.tools",
|
||||
ToolType.LOCAL: "app.engine.tools",
|
||||
}
|
||||
|
||||
def load_tools(tool_type: str, tool_name: str, config: dict) -> list[FunctionTool]:
|
||||
source_package = ToolFactory.TOOL_SOURCE_PACKAGE_MAP[tool_type]
|
||||
try:
|
||||
if "ToolSpec" in tool_name:
|
||||
tool_package, tool_cls_name = tool_name.split(".")
|
||||
module_name = f"{source_package}.{tool_package}"
|
||||
module = importlib.import_module(module_name)
|
||||
tool_class = getattr(module, tool_cls_name)
|
||||
tool_spec: BaseToolSpec = tool_class(**config)
|
||||
return tool_spec.to_tool_list()
|
||||
else:
|
||||
module = importlib.import_module(f"{source_package}.{tool_name}")
|
||||
tools = module.get_tools(**config)
|
||||
if not all(isinstance(tool, FunctionTool) for tool in tools):
|
||||
raise ValueError(
|
||||
f"The module {module} does not contain valid tools"
|
||||
)
|
||||
return tools
|
||||
except ImportError as e:
|
||||
raise ValueError(f"Failed to import tool {tool_name}: {e}")
|
||||
except AttributeError as e:
|
||||
raise ValueError(f"Failed to load tool {tool_name}: {e}")
|
||||
|
||||
@staticmethod
|
||||
def from_env() -> list[FunctionTool]:
|
||||
tools = []
|
||||
if os.path.exists("config/tools.yaml"):
|
||||
with open("config/tools.yaml", "r") as f:
|
||||
tool_configs = yaml.safe_load(f)
|
||||
if tool_configs != None and len(tool_configs.items()) != 0:
|
||||
for tool_type, config_entries in tool_configs.items():
|
||||
if config_entries == None or len(config_entries.items()) == 0:
|
||||
continue
|
||||
|
||||
for tool_name, config in config_entries.items():
|
||||
tools.extend(
|
||||
ToolFactory.load_tools(tool_type, tool_name, config)
|
||||
)
|
||||
return tools
|
||||
@@ -1,108 +0,0 @@
|
||||
import os
|
||||
import uuid
|
||||
import logging
|
||||
import requests
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel, Field
|
||||
from llama_index.core.tools import FunctionTool
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ImageGeneratorToolOutput(BaseModel):
|
||||
is_success: bool = Field(
|
||||
...,
|
||||
description="Whether the image generation was successful.",
|
||||
)
|
||||
image_url: Optional[str] = Field(
|
||||
None,
|
||||
description="The URL of the generated image.",
|
||||
)
|
||||
error_message: Optional[str] = Field(
|
||||
None,
|
||||
description="The error message if the image generation failed.",
|
||||
)
|
||||
|
||||
|
||||
class ImageGeneratorTool:
|
||||
_IMG_OUTPUT_FORMAT = "webp"
|
||||
_IMG_OUTPUT_DIR = "output/tool"
|
||||
_IMG_GEN_API = "https://api.stability.ai/v2beta/stable-image/generate/core"
|
||||
|
||||
def __init__(self, api_key: str = None):
|
||||
if not api_key:
|
||||
api_key = os.getenv("STABILITY_API_KEY")
|
||||
self._api_key = api_key
|
||||
self.fileserver_url_prefix = os.getenv("FILESERVER_URL_PREFIX")
|
||||
if self._api_key is None:
|
||||
raise ValueError(
|
||||
"STABILITY_API_KEY key is required to run image generator. Get it here: https://platform.stability.ai/account/keys"
|
||||
)
|
||||
if self.fileserver_url_prefix is None:
|
||||
raise ValueError("FILESERVER_URL_PREFIX is required.")
|
||||
|
||||
def _prepare_output_dir(self):
|
||||
"""
|
||||
Create the output directory if it doesn't exist
|
||||
"""
|
||||
if not os.path.exists(self._IMG_OUTPUT_DIR):
|
||||
os.makedirs(self._IMG_OUTPUT_DIR, exist_ok=True)
|
||||
|
||||
def _save_image(self, image_data: bytes):
|
||||
self._prepare_output_dir()
|
||||
filename = f"{uuid.uuid4()}.{self._IMG_OUTPUT_FORMAT}"
|
||||
output_path = os.path.join(self._IMG_OUTPUT_DIR, filename)
|
||||
with open(output_path, "wb") as f:
|
||||
f.write(image_data)
|
||||
url = f"{os.getenv('FILESERVER_URL_PREFIX')}/{self._IMG_OUTPUT_DIR}/{filename}"
|
||||
logger.info(f"Saved image to {output_path}.\nURL: {url}")
|
||||
return url
|
||||
|
||||
def _call_stability_api(self, prompt: str):
|
||||
headers = {
|
||||
"authorization": f"Bearer {self._api_key}",
|
||||
"accept": "image/*",
|
||||
}
|
||||
data = {
|
||||
"prompt": prompt,
|
||||
"output_format": self._IMG_OUTPUT_FORMAT,
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
self._IMG_GEN_API,
|
||||
headers=headers,
|
||||
files={"none": ""},
|
||||
data=data,
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
return response
|
||||
|
||||
def generate_image(self, prompt: str) -> ImageGeneratorToolOutput:
|
||||
"""
|
||||
Use this tool to generate an image based on the prompt.
|
||||
Args:
|
||||
prompt (str): The prompt to generate the image from.
|
||||
"""
|
||||
|
||||
try:
|
||||
# Call the Stability API
|
||||
response = self._call_stability_api(prompt)
|
||||
|
||||
# Save the image and get the URL
|
||||
image_url = self._save_image(response.content)
|
||||
|
||||
return ImageGeneratorToolOutput(
|
||||
is_success=True,
|
||||
image_url=image_url,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception(e, exc_info=True)
|
||||
return ImageGeneratorToolOutput(
|
||||
is_success=False,
|
||||
error_message=str(e),
|
||||
)
|
||||
|
||||
|
||||
def get_tools(**kwargs):
|
||||
return [FunctionTool.from_defaults(ImageGeneratorTool(**kwargs).generate_image)]
|
||||
@@ -1,143 +0,0 @@
|
||||
import os
|
||||
import logging
|
||||
import base64
|
||||
import uuid
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Tuple, Dict, Optional
|
||||
from llama_index.core.tools import FunctionTool
|
||||
from e2b_code_interpreter import CodeInterpreter
|
||||
from e2b_code_interpreter.models import Logs
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InterpreterExtraResult(BaseModel):
|
||||
type: str
|
||||
content: Optional[str] = None
|
||||
filename: Optional[str] = None
|
||||
url: Optional[str] = None
|
||||
|
||||
|
||||
class E2BToolOutput(BaseModel):
|
||||
is_error: bool
|
||||
logs: Logs
|
||||
results: List[InterpreterExtraResult] = []
|
||||
|
||||
|
||||
class E2BCodeInterpreter:
|
||||
|
||||
output_dir = "output/tool"
|
||||
|
||||
def __init__(self, api_key: str = None):
|
||||
if api_key is None:
|
||||
api_key = os.getenv("E2B_API_KEY")
|
||||
filesever_url_prefix = os.getenv("FILESERVER_URL_PREFIX")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"E2B_API_KEY key is required to run code interpreter. Get it here: https://e2b.dev/docs/getting-started/api-key"
|
||||
)
|
||||
if not filesever_url_prefix:
|
||||
raise ValueError(
|
||||
"FILESERVER_URL_PREFIX is required to display file output from sandbox"
|
||||
)
|
||||
|
||||
self.filesever_url_prefix = filesever_url_prefix
|
||||
self.interpreter = CodeInterpreter(api_key=api_key)
|
||||
|
||||
def __del__(self):
|
||||
self.interpreter.close()
|
||||
|
||||
def get_output_path(self, filename: str) -> str:
|
||||
# if output directory doesn't exist, create it
|
||||
if not os.path.exists(self.output_dir):
|
||||
os.makedirs(self.output_dir, exist_ok=True)
|
||||
return os.path.join(self.output_dir, filename)
|
||||
|
||||
def save_to_disk(self, base64_data: str, ext: str) -> Dict:
|
||||
filename = f"{uuid.uuid4()}.{ext}" # generate a unique filename
|
||||
buffer = base64.b64decode(base64_data)
|
||||
output_path = self.get_output_path(filename)
|
||||
|
||||
try:
|
||||
with open(output_path, "wb") as file:
|
||||
file.write(buffer)
|
||||
except IOError as e:
|
||||
logger.error(f"Failed to write to file {output_path}: {str(e)}")
|
||||
raise e
|
||||
|
||||
logger.info(f"Saved file to {output_path}")
|
||||
|
||||
return {
|
||||
"outputPath": output_path,
|
||||
"filename": filename,
|
||||
}
|
||||
|
||||
def get_file_url(self, filename: str) -> str:
|
||||
return f"{self.filesever_url_prefix}/{self.output_dir}/{filename}"
|
||||
|
||||
def parse_result(self, result) -> List[InterpreterExtraResult]:
|
||||
"""
|
||||
The result could include multiple formats (e.g. png, svg, etc.) but encoded in base64
|
||||
We save each result to disk and return saved file metadata (extension, filename, url)
|
||||
"""
|
||||
if not result:
|
||||
return []
|
||||
|
||||
output = []
|
||||
|
||||
try:
|
||||
formats = result.formats()
|
||||
results = [result[format] for format in formats]
|
||||
|
||||
for ext, data in zip(formats, results):
|
||||
match ext:
|
||||
case "png" | "svg" | "jpeg" | "pdf":
|
||||
result = self.save_to_disk(data, ext)
|
||||
filename = result["filename"]
|
||||
output.append(
|
||||
InterpreterExtraResult(
|
||||
type=ext,
|
||||
filename=filename,
|
||||
url=self.get_file_url(filename),
|
||||
)
|
||||
)
|
||||
case _:
|
||||
output.append(
|
||||
InterpreterExtraResult(
|
||||
type=ext,
|
||||
content=data,
|
||||
)
|
||||
)
|
||||
except Exception as error:
|
||||
logger.exception(error, exc_info=True)
|
||||
logger.error("Error when parsing output from E2b interpreter tool", error)
|
||||
|
||||
return output
|
||||
|
||||
def interpret(self, code: str) -> E2BToolOutput:
|
||||
"""
|
||||
Execute python code in a Jupyter notebook cell, the toll will return result, stdout, stderr, display_data, and error.
|
||||
|
||||
Parameters:
|
||||
code (str): The python code to be executed in a single cell.
|
||||
"""
|
||||
logger.info(
|
||||
f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}"
|
||||
)
|
||||
exec = self.interpreter.notebook.exec_cell(code)
|
||||
|
||||
if exec.error:
|
||||
logger.error("Error when executing code", exec.error)
|
||||
output = E2BToolOutput(is_error=True, logs=exec.logs, results=[])
|
||||
else:
|
||||
if len(exec.results) == 0:
|
||||
output = E2BToolOutput(is_error=False, logs=exec.logs, results=[])
|
||||
else:
|
||||
results = self.parse_result(exec.results[0])
|
||||
output = E2BToolOutput(is_error=False, logs=exec.logs, results=results)
|
||||
return output
|
||||
|
||||
|
||||
def get_tools(**kwargs):
|
||||
return [FunctionTool.from_defaults(E2BCodeInterpreter(**kwargs).interpret)]
|
||||
@@ -1,78 +0,0 @@
|
||||
from typing import Dict, List, Tuple
|
||||
from llama_index.tools.openapi import OpenAPIToolSpec
|
||||
from llama_index.tools.requests import RequestsToolSpec
|
||||
|
||||
|
||||
class OpenAPIActionToolSpec(OpenAPIToolSpec, RequestsToolSpec):
|
||||
"""
|
||||
A combination of OpenAPI and Requests tool specs that can parse OpenAPI specs and make requests.
|
||||
|
||||
openapi_uri: str: The file path or URL to the OpenAPI spec.
|
||||
domain_headers: dict: Whitelist domains and the headers to use.
|
||||
"""
|
||||
|
||||
spec_functions = OpenAPIToolSpec.spec_functions + RequestsToolSpec.spec_functions
|
||||
# Cached parsed specs by URI
|
||||
_specs: Dict[str, Tuple[Dict, List[str]]] = {}
|
||||
|
||||
def __init__(self, openapi_uri: str, domain_headers: dict = None, **kwargs):
|
||||
if domain_headers is None:
|
||||
domain_headers = {}
|
||||
if openapi_uri not in self._specs:
|
||||
openapi_spec, servers = self._load_openapi_spec(openapi_uri)
|
||||
self._specs[openapi_uri] = (openapi_spec, servers)
|
||||
else:
|
||||
openapi_spec, servers = self._specs[openapi_uri]
|
||||
|
||||
# Add the servers to the domain headers if they are not already present
|
||||
for server in servers:
|
||||
if server not in domain_headers:
|
||||
domain_headers[server] = {}
|
||||
|
||||
OpenAPIToolSpec.__init__(self, spec=openapi_spec)
|
||||
RequestsToolSpec.__init__(self, domain_headers)
|
||||
|
||||
@staticmethod
|
||||
def _load_openapi_spec(uri: str) -> Tuple[Dict, List[str]]:
|
||||
"""
|
||||
Load an OpenAPI spec from a URI.
|
||||
|
||||
Args:
|
||||
uri (str): A file path or URL to the OpenAPI spec.
|
||||
|
||||
Returns:
|
||||
List[Document]: A list of Document objects.
|
||||
"""
|
||||
import yaml
|
||||
from urllib.parse import urlparse
|
||||
|
||||
if uri.startswith("http"):
|
||||
import requests
|
||||
|
||||
response = requests.get(uri)
|
||||
if response.status_code != 200:
|
||||
raise ValueError(
|
||||
"Could not initialize OpenAPIActionToolSpec: "
|
||||
f"Failed to load OpenAPI spec from {uri}, status code: {response.status_code}"
|
||||
)
|
||||
spec = yaml.safe_load(response.text)
|
||||
elif uri.startswith("file"):
|
||||
filepath = urlparse(uri).path
|
||||
with open(filepath, "r") as file:
|
||||
spec = yaml.safe_load(file)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Could not initialize OpenAPIActionToolSpec: Invalid OpenAPI URI provided. "
|
||||
"Only HTTP and file path are supported."
|
||||
)
|
||||
# Add the servers to the whitelist
|
||||
try:
|
||||
servers = [
|
||||
urlparse(server["url"]).netloc for server in spec.get("servers", [])
|
||||
]
|
||||
except KeyError as e:
|
||||
raise ValueError(
|
||||
"Could not initialize OpenAPIActionToolSpec: Invalid OpenAPI spec provided. "
|
||||
"Could not get `servers` from the spec."
|
||||
) from e
|
||||
return spec, servers
|
||||
@@ -1,73 +0,0 @@
|
||||
"""Open Meteo weather map tool spec."""
|
||||
|
||||
import logging
|
||||
import requests
|
||||
import pytz
|
||||
from llama_index.core.tools import FunctionTool
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OpenMeteoWeather:
|
||||
geo_api = "https://geocoding-api.open-meteo.com/v1"
|
||||
weather_api = "https://api.open-meteo.com/v1"
|
||||
|
||||
@classmethod
|
||||
def _get_geo_location(cls, location: str) -> dict:
|
||||
"""Get geo location from location name."""
|
||||
params = {"name": location, "count": 10, "language": "en", "format": "json"}
|
||||
response = requests.get(f"{cls.geo_api}/search", params=params)
|
||||
if response.status_code != 200:
|
||||
raise Exception(f"Failed to fetch geo location: {response.status_code}")
|
||||
else:
|
||||
data = response.json()
|
||||
result = data["results"][0]
|
||||
geo_location = {
|
||||
"id": result["id"],
|
||||
"name": result["name"],
|
||||
"latitude": result["latitude"],
|
||||
"longitude": result["longitude"],
|
||||
}
|
||||
return geo_location
|
||||
|
||||
@classmethod
|
||||
def get_weather_information(cls, location: str) -> dict:
|
||||
"""Use this function to get the weather of any given location.
|
||||
Note that the weather code should follow WMO Weather interpretation codes (WW):
|
||||
0: Clear sky
|
||||
1, 2, 3: Mainly clear, partly cloudy, and overcast
|
||||
45, 48: Fog and depositing rime fog
|
||||
51, 53, 55: Drizzle: Light, moderate, and dense intensity
|
||||
56, 57: Freezing Drizzle: Light and dense intensity
|
||||
61, 63, 65: Rain: Slight, moderate and heavy intensity
|
||||
66, 67: Freezing Rain: Light and heavy intensity
|
||||
71, 73, 75: Snow fall: Slight, moderate, and heavy intensity
|
||||
77: Snow grains
|
||||
80, 81, 82: Rain showers: Slight, moderate, and violent
|
||||
85, 86: Snow showers slight and heavy
|
||||
95: Thunderstorm: Slight or moderate
|
||||
96, 99: Thunderstorm with slight and heavy hail
|
||||
"""
|
||||
logger.info(
|
||||
f"Calling open-meteo api to get weather information of location: {location}"
|
||||
)
|
||||
geo_location = cls._get_geo_location(location)
|
||||
timezone = pytz.timezone("UTC").zone
|
||||
params = {
|
||||
"latitude": geo_location["latitude"],
|
||||
"longitude": geo_location["longitude"],
|
||||
"current": "temperature_2m,weather_code",
|
||||
"hourly": "temperature_2m,weather_code",
|
||||
"daily": "weather_code",
|
||||
"timezone": timezone,
|
||||
}
|
||||
response = requests.get(f"{cls.weather_api}/forecast", params=params)
|
||||
if response.status_code != 200:
|
||||
raise Exception(
|
||||
f"Failed to fetch weather information: {response.status_code}"
|
||||
)
|
||||
return response.json()
|
||||
|
||||
|
||||
def get_tools(**kwargs):
|
||||
return [FunctionTool.from_defaults(OpenMeteoWeather.get_weather_information)]
|
||||
@@ -1,10 +1,9 @@
|
||||
import os
|
||||
import yaml
|
||||
import json
|
||||
import importlib
|
||||
from cachetools import cached, LRUCache
|
||||
from llama_index.core.tools.tool_spec.base import BaseToolSpec
|
||||
import os
|
||||
|
||||
import yaml
|
||||
from llama_index.core.tools.function_tool import FunctionTool
|
||||
from llama_index.core.tools.tool_spec.base import BaseToolSpec
|
||||
|
||||
|
||||
class ToolType:
|
||||
@@ -46,7 +45,7 @@ class ToolFactory:
|
||||
def from_env() -> list[FunctionTool]:
|
||||
tools = []
|
||||
if os.path.exists("config/tools.yaml"):
|
||||
with open("config/tools.yaml", "r") as f:
|
||||
with open("config/tools.yaml", "r", encoding='UTF-8') as f:
|
||||
tool_configs = yaml.safe_load(f)
|
||||
if tool_configs != None and len(tool_configs.items()) != 0:
|
||||
for tool_type, config_entries in tool_configs.items():
|
||||
|
||||
@@ -2,15 +2,17 @@ import os
|
||||
from llama_index.vector_stores.chroma import ChromaVectorStore
|
||||
from llama_index.vector_stores.qdrant import QdrantVectorStore
|
||||
from qdrant_client import qdrant_client
|
||||
|
||||
from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore
|
||||
qclient = None
|
||||
|
||||
def get_qdrant_vector_store():
|
||||
collection_name = os.getenv("VECTOR_STORE_COLLECTION", "default")
|
||||
def get_qdrant_vector_store(docType:str):
|
||||
collection_name = docType
|
||||
llm_query = os.getenv('LLM_QUERY_WAY','rag')
|
||||
vector_store_path = os.getenv("VECTOR_STORE_PATH")
|
||||
host=os.getenv("VECTOR_STORE_HOST", "127.0.0.1"),
|
||||
port=int(os.getenv("VECTOR_STORE_PORT", "6333")),
|
||||
|
||||
vector_store_path =os.path.join(vector_store_path,llm_query,docType)
|
||||
if not vector_store_path or not host:
|
||||
raise ValueError(
|
||||
"Please provide either VECTOR_STORE_PATH or VECTOR_STORE_HOST and VECTOR_STORE_PORT"
|
||||
@@ -32,9 +34,10 @@ def get_qdrant_vector_store():
|
||||
vector_store = QdrantVectorStore(client=qclient, collection_name=collection_name)
|
||||
return vector_store
|
||||
|
||||
def get_chroma_vector_store():
|
||||
collection_name = os.getenv("VECTOR_STORE_COLLECTION", "default")
|
||||
vector_store_path = os.getenv("VECTOR_STORE_PATH")
|
||||
def get_chroma_vector_store(docType:str):
|
||||
collection_name = docType
|
||||
llm_query = os.getenv('LLM_QUERY_WAY','rag')
|
||||
vector_store_path =os.path.join(os.getenv("VECTOR_STORE_PATH"),llm_query,docType)
|
||||
# if VECTOR_STORE_PATH is set, use a local ChromaVectorStore from the path
|
||||
# otherwise, use a remote ChromaVectorStore (ChromaDB Cloud is not supported yet)
|
||||
if vector_store_path:
|
||||
@@ -55,17 +58,31 @@ def get_chroma_vector_store():
|
||||
)
|
||||
return store
|
||||
|
||||
def get_vector_store():
|
||||
def get_vector_store(docType:str):
|
||||
store_type=os.getenv("VECTOR_STORE_TYPE")
|
||||
|
||||
store = None
|
||||
|
||||
match store_type:
|
||||
case "chroma":
|
||||
store = get_chroma_vector_store()
|
||||
store = get_chroma_vector_store(docType)
|
||||
case "qdrant":
|
||||
store = get_qdrant_vector_store()
|
||||
store = get_qdrant_vector_store(docType)
|
||||
case _:
|
||||
raise ValueError(f"Invalid vector store type: {store_type}")
|
||||
|
||||
return store
|
||||
|
||||
def get_Neo4j_Graph_Store(docType:str):
|
||||
from neo4j import GraphDatabase
|
||||
driver = GraphDatabase.driver(os.getenv('NEO4J_URL'), auth=(os.getenv('NEO4J_USERNAME'), os.getenv('NEO4J_PASSWORD')))
|
||||
with driver.session() as session:
|
||||
session.run("MATCH (n) DETACH DELETE n")
|
||||
driver.close()
|
||||
|
||||
neo4jStore = Neo4jPropertyGraphStore(
|
||||
username= os.getenv('NEO4J_USERNAME'),
|
||||
password= os.getenv('NEO4J_PASSWORD'),
|
||||
url=os.getenv('NEO4J_URL'),
|
||||
database= docType
|
||||
)
|
||||
return neo4jStore
|
||||
+209
-110
@@ -1,136 +1,169 @@
|
||||
import os
|
||||
from typing import Dict
|
||||
|
||||
from abc import abstractmethod
|
||||
from llama_index.core.constants import DEFAULT_TEMPERATURE
|
||||
from llama_index.core.settings import Settings
|
||||
from llama_index.llms.xinference import Xinference
|
||||
from llama_index.embeddings.xinference import XinferenceEmbedding
|
||||
#from llama_index.llms.xinference import Xinference
|
||||
from app.engine.model.xinference import XinferenceModel
|
||||
from app.engine.rerank.xinferenceRerank import CustomXinFerenceRerank
|
||||
from llama_index.llms.xinference.base import DEFAULT_XINFERENCE_TEMP
|
||||
|
||||
from app.xinference.base import XinferenceEmbedding, XinferenceRerank
|
||||
|
||||
from app.engine.loaders import getProjectInfos
|
||||
from app.api.routers.request.base import ProjectInfo
|
||||
from modelProvide.customDashScope import CustomDashScope
|
||||
from util.register import *
|
||||
from llama_index.core.callbacks import CallbackManager
|
||||
|
||||
def get_node_postprocessors():
|
||||
rerank_enabled = os.getenv("RERANK_ENABLED").title()
|
||||
if rerank_enabled is None or rerank_enabled == 'False':
|
||||
return []
|
||||
|
||||
rerank_model = os.getenv("RERANK_MODEL")
|
||||
rerank_url = os.getenv("RERANK_BASE_URL")
|
||||
rerank_top_n = os.getenv("RERANK_TOP_N")
|
||||
rerank_threshold = os.getenv("RERANK_THRESHOLD")
|
||||
postprocess = None
|
||||
if rerank_model is not None:
|
||||
postprocess = [XinferenceRerank(rerank_model, rerank_url, top_n=rerank_top_n, threshold=rerank_threshold)]
|
||||
return postprocess
|
||||
ModelPlateCategory = '模型平台'
|
||||
|
||||
def init_settings():
|
||||
model_provider = os.getenv("MODEL_PROVIDER")
|
||||
match model_provider:
|
||||
case "openai":
|
||||
init_openai()
|
||||
case "dashscope":
|
||||
init_dashscope()
|
||||
case "groq":
|
||||
init_groq()
|
||||
case "ollama":
|
||||
init_ollama()
|
||||
case "anthropic":
|
||||
init_anthropic()
|
||||
case "gemini":
|
||||
init_gemini()
|
||||
case "mistral":
|
||||
init_mistral()
|
||||
case "azure-openai":
|
||||
init_azure_openai()
|
||||
case "t-systems":
|
||||
from .llmhub import init_llmhub
|
||||
init_llmhub()
|
||||
case "xinference":
|
||||
init_xinference()
|
||||
case _:
|
||||
modelPaltCls:ModelPlatform = ClsRegister.get(ModelPlateCategory,model_provider)
|
||||
if modelPaltCls is not None:
|
||||
modelPalt:ModelPlatform = modelPaltCls()
|
||||
Settings.llm = modelPalt.model()
|
||||
else:
|
||||
raise ValueError(f"Invalid model provider: {model_provider}")
|
||||
|
||||
embedding_provider = os.getenv("EMBEDDING_PROVIDER")
|
||||
modelPaltCls:ModelPlatform = ClsRegister.get(ModelPlateCategory,embedding_provider)
|
||||
if modelPalt is not None:
|
||||
modelPalt:ModelPlatform = modelPaltCls()
|
||||
Settings.embed_model = modelPalt.embedding()
|
||||
else:
|
||||
raise ValueError(f"Invalid embedding provider: {embedding_provider}")
|
||||
|
||||
Settings.llm.callback_manager = CallbackManager()
|
||||
Settings.chunk_size = int(os.getenv("CHUNK_SIZE", "1024"))
|
||||
Settings.chunk_overlap = int(os.getenv("CHUNK_OVERLAP", "20"))
|
||||
|
||||
class ModelPlatform:
|
||||
@abstractmethod
|
||||
def model(self):
|
||||
pass
|
||||
|
||||
def init_ollama():
|
||||
# from llama_index.embeddings.ollama import OllamaEmbedding
|
||||
# from llama_index.llms.ollama.base import DEFAULT_REQUEST_TIMEOUT, Ollama
|
||||
#
|
||||
@abstractmethod
|
||||
def embedding(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def rerank(self):
|
||||
pass
|
||||
|
||||
@register(ModelPlateCategory,'ollama')
|
||||
class OllamaPlatform(ModelPlatform):
|
||||
def model(self):
|
||||
from llama_index.llms.ollama.base import DEFAULT_REQUEST_TIMEOUT, Ollama
|
||||
|
||||
base_url = os.getenv("OLLAMA_BASE_URL") or "http://127.0.0.1:11434"
|
||||
request_timeout = float(
|
||||
os.getenv("OLLAMA_REQUEST_TIMEOUT", DEFAULT_REQUEST_TIMEOUT)
|
||||
)
|
||||
Settings.llm = Ollama(
|
||||
base_url=base_url, model=os.getenv("MODEL"), request_timeout=request_timeout
|
||||
)
|
||||
pass
|
||||
|
||||
def embedding(self):
|
||||
#from llama_index.embeddings.ollama import OllamaEmbedding
|
||||
# base_url = os.getenv("OLLAMA_BASE_URL") or "http://127.0.0.1:11434"
|
||||
# request_timeout = float(
|
||||
# os.getenv("OLLAMA_REQUEST_TIMEOUT", DEFAULT_REQUEST_TIMEOUT)
|
||||
# )
|
||||
# Settings.embed_model = OllamaEmbedding(
|
||||
# base_url=base_url,
|
||||
# model_name=os.getenv("EMBEDDING_MODEL"),
|
||||
# )
|
||||
# Settings.llm = Ollama(
|
||||
# base_url=base_url, model=os.getenv("MODEL"), request_timeout=request_timeout
|
||||
# )
|
||||
pass
|
||||
|
||||
def init_xinference():
|
||||
def rerank(self):
|
||||
from app.engine.rerank.ollamRerank import OllamaRerank
|
||||
modelpath = os.getcwd() + os.getenv('RERANK_MODEL')
|
||||
top_n = os.getenv('RERANK_TOP_N',5)
|
||||
threshold = float(os.getenv('RERANK_THRESHOLD',0.3))
|
||||
rerank = OllamaRerank(
|
||||
model=modelpath,
|
||||
top_n=top_n,
|
||||
device="cpu",
|
||||
score_threshold= threshold
|
||||
)
|
||||
return [rerank]
|
||||
|
||||
@register(ModelPlateCategory,'xinference')
|
||||
class XinferencePlatform(ModelPlatform):
|
||||
def model(self):
|
||||
base_url = os.getenv("BASE_URL")
|
||||
model = os.getenv("MODEL")
|
||||
max_tokens = int(os.getenv("LLM_MAX_TOKENS")) if os.getenv("LLM_MAX_TOKENS") is not None else None
|
||||
temperature = float(os.getenv("LLM_TEMPERATURE", DEFAULT_XINFERENCE_TEMP))
|
||||
return XinferenceModel(model_uid = model,endpoint = base_url,temperature = temperature,max_tokens = max_tokens)
|
||||
|
||||
Settings.llm = Xinference(model, base_url, temperature, max_tokens)
|
||||
|
||||
def embedding(self):
|
||||
base_url = os.getenv("BASE_URL")
|
||||
embedding_base_url = os.getenv("EMBEDDING_BASE_URL")
|
||||
embedding_base_url = embedding_base_url if embedding_base_url != None and embedding_base_url != "" else base_url
|
||||
|
||||
embed_model_name = os.getenv("EMBEDDING_MODEL")
|
||||
dimensions = os.getenv("EMBEDDING_DIM")
|
||||
dimensions = int(dimensions) if dimensions is not None else None
|
||||
Settings.embed_model = XinferenceEmbedding(embed_model_name, embedding_base_url, dimensions=dimensions)
|
||||
return XinferenceEmbedding(embed_model_name, embedding_base_url)
|
||||
|
||||
def init_openai():
|
||||
def rerank(self):
|
||||
rerank_model = os.getenv("RERANK_MODEL")
|
||||
rerank_url = os.getenv("RERANK_BASE_URL")
|
||||
rerank_top_n = os.getenv("RERANK_TOP_N")
|
||||
rerank_threshold = os.getenv("RERANK_THRESHOLD")
|
||||
postprocess = None
|
||||
if rerank_model is not None:
|
||||
postprocess = [CustomXinFerenceRerank(model = rerank_model, base_url = rerank_url, top_n=rerank_top_n,score_threshold=rerank_threshold)]
|
||||
return postprocess
|
||||
|
||||
@register(ModelPlateCategory,'openai')
|
||||
class OpenAIPlatform(ModelPlatform):
|
||||
def model(self):
|
||||
from llama_index.core.constants import DEFAULT_TEMPERATURE
|
||||
from app.engine.model.siliconCloudOpenAI import SiliconCloudOpenAI
|
||||
return SiliconCloudOpenAI(api_key= os.getenv('OPENAI_API_KEY'),
|
||||
api_base= os.getenv('BASE_URL'),
|
||||
model= os.getenv('MODEL'),
|
||||
temperature = float(os.getenv("LLM_TEMPERATURE", DEFAULT_TEMPERATURE)))
|
||||
|
||||
def embedding(self):
|
||||
from llama_index.embeddings.openai import OpenAIEmbedding
|
||||
from llama_index.llms.openai import OpenAI
|
||||
return OpenAIEmbedding(api_key=os.getenv('OPENAI_API_KEY'),
|
||||
api_base= os.getenv('EMBEDDING_BASE_URL'),
|
||||
model_name = os.getenv('EMBEDDING_MODEL'),
|
||||
dimensions= int(os.getenv("EMBEDDING_DIM")))
|
||||
|
||||
max_tokens = os.getenv("LLM_MAX_TOKENS")
|
||||
config = {
|
||||
"model": os.getenv("MODEL"),
|
||||
"temperature": float(os.getenv("LLM_TEMPERATURE", DEFAULT_TEMPERATURE)),
|
||||
"max_tokens": int(max_tokens) if max_tokens is not None else None,
|
||||
}
|
||||
Settings.llm = OpenAI(**config)
|
||||
def rerank(self):
|
||||
from app.engine.rerank.siliconCloudRerank import SiliconCloudRerank
|
||||
postprocess = [SiliconCloudRerank(top_n = int(os.getenv('RERANK_TOP_N',5)),
|
||||
model = os.getenv('RERANK_MODEL'),
|
||||
base_url = os.getenv('RERANK_BASE_URL'),
|
||||
api_key = os.getenv('OPENAI_API_KEY')
|
||||
)]
|
||||
return postprocess
|
||||
|
||||
dimensions = os.getenv("EMBEDDING_DIM")
|
||||
config = {
|
||||
"model": os.getenv("EMBEDDING_MODEL"),
|
||||
"dimensions": int(dimensions) if dimensions is not None else None,
|
||||
}
|
||||
Settings.embed_model = OpenAIEmbedding(**config)
|
||||
@register(ModelPlateCategory,'dashscope')
|
||||
class DashscopePlatform(ModelPlatform):
|
||||
def model(self):
|
||||
apikey = os.getenv('DASHSCOPE_API_KEY')
|
||||
modelName = os.getenv('MODEL')
|
||||
return CustomDashScope(model_name=modelName,api_key = apikey)
|
||||
|
||||
def init_dashscope():
|
||||
from llama_index.llms.dashscope import DashScope,DashScopeGenerationModels
|
||||
from llama_index.embeddings.dashscope import DashScopeEmbedding,DashScopeBatchTextEmbeddingModels,DashScopeTextEmbeddingType,DashScopeTextEmbeddingModels
|
||||
def embedding(self):
|
||||
from llama_index.embeddings.dashscope import DashScopeEmbedding,DashScopeTextEmbeddingType,DashScopeTextEmbeddingModels
|
||||
api_key = os.getenv('DASHSCOPE_API_KEY')
|
||||
modelName = os.getenv('EMBEDDING_MODEL')
|
||||
return DashScopeEmbedding(model_name=modelName,
|
||||
text_type=DashScopeTextEmbeddingType.TEXT_TYPE_QUERY,api_key = api_key)
|
||||
|
||||
max_tokens = os.getenv("LLM_MAX_TOKENS")
|
||||
config = {
|
||||
"model": os.getenv("MODEL"),
|
||||
"temperature": float(os.getenv("LLM_TEMPERATURE", DEFAULT_TEMPERATURE)),
|
||||
"max_tokens": int(max_tokens) if max_tokens is not None else None,
|
||||
}
|
||||
Settings.llm = llm = DashScope(model_name=DashScopeGenerationModels.QWEN_MAX)
|
||||
def rerank(self):
|
||||
pass
|
||||
|
||||
dimensions = os.getenv("EMBEDDING_DIM")
|
||||
config = {
|
||||
"model": os.getenv("EMBEDDING_MODEL"),
|
||||
"dimensions": int(dimensions) if dimensions is not None else None,
|
||||
}
|
||||
Settings.embed_model = DashScopeEmbedding(model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2,
|
||||
text_type=DashScopeTextEmbeddingType.TEXT_TYPE_QUERY)
|
||||
|
||||
|
||||
def init_azure_openai():
|
||||
@register(ModelPlateCategory,'azure-openai')
|
||||
class AzureOpenaiPlatform(ModelPlatform):
|
||||
def model(self):
|
||||
# from llama_index.core.constants import DEFAULT_TEMPERATURE
|
||||
# from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding
|
||||
# from llama_index.llms.azure_openai import AzureOpenAI
|
||||
#
|
||||
# llm_deployment = os.environ["AZURE_OPENAI_LLM_DEPLOYMENT"]
|
||||
@@ -146,15 +179,32 @@ def init_azure_openai():
|
||||
# or os.getenv("OPENAI_API_VERSION"),
|
||||
# }
|
||||
#
|
||||
# Settings.llm = AzureOpenAI(
|
||||
# return AzureOpenAI(
|
||||
# model=os.getenv("MODEL"),
|
||||
# max_tokens=int(max_tokens) if max_tokens is not None else None,
|
||||
# temperature=float(temperature),
|
||||
# deployment_name=llm_deployment,
|
||||
# **azure_config,
|
||||
# )
|
||||
pass
|
||||
|
||||
def embedding(self):
|
||||
# from llama_index.core.constants import DEFAULT_TEMPERATURE
|
||||
# from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding
|
||||
#
|
||||
# Settings.embed_model = AzureOpenAIEmbedding(
|
||||
# llm_deployment = os.environ["AZURE_OPENAI_LLM_DEPLOYMENT"]
|
||||
# embedding_deployment = os.environ["AZURE_OPENAI_EMBEDDING_DEPLOYMENT"]
|
||||
# max_tokens = os.getenv("LLM_MAX_TOKENS")
|
||||
# temperature = os.getenv("LLM_TEMPERATURE", DEFAULT_TEMPERATURE)
|
||||
# dimensions = os.getenv("EMBEDDING_DIM")
|
||||
#
|
||||
# azure_config = {
|
||||
# "api_key": os.environ["AZURE_OPENAI_KEY"],
|
||||
# "azure_endpoint": os.environ["AZURE_OPENAI_ENDPOINT"],
|
||||
# "api_version": os.getenv("AZURE_OPENAI_API_VERSION")
|
||||
# or os.getenv("OPENAI_API_VERSION"),
|
||||
# }
|
||||
# return AzureOpenAIEmbedding(
|
||||
# model=os.getenv("EMBEDDING_MODEL"),
|
||||
# dimensions=int(dimensions) if dimensions is not None else None,
|
||||
# deployment_name=embedding_deployment,
|
||||
@@ -162,11 +212,17 @@ def init_azure_openai():
|
||||
# )
|
||||
pass
|
||||
|
||||
def rerank(self):
|
||||
pass
|
||||
|
||||
def init_fastembed():
|
||||
"""
|
||||
Use Qdrant Fastembed as the local embedding provider.
|
||||
"""
|
||||
@register(ModelPlateCategory,'fastembed')
|
||||
class FastembedPlatform(ModelPlatform):
|
||||
@abstractmethod
|
||||
def model(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def embedding(self):
|
||||
# from llama_index.embeddings.fastembed import FastEmbedEmbedding
|
||||
#
|
||||
# embed_model_map: Dict[str, str] = {
|
||||
@@ -182,8 +238,14 @@ def init_fastembed():
|
||||
# )
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def rerank(self):
|
||||
pass
|
||||
|
||||
def init_groq():
|
||||
@register(ModelPlateCategory,'groq')
|
||||
class GroqPlatform(ModelPlatform):
|
||||
@abstractmethod
|
||||
def model(self):
|
||||
# from llama_index.llms.groq import Groq
|
||||
#
|
||||
# model_map: Dict[str, str] = {
|
||||
@@ -197,8 +259,17 @@ def init_groq():
|
||||
# init_fastembed()
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def embedding(self):
|
||||
pass
|
||||
|
||||
def init_anthropic():
|
||||
@abstractmethod
|
||||
def rerank(self):
|
||||
pass
|
||||
|
||||
@register(ModelPlateCategory,'anthropic')
|
||||
class AnthropicPlatform(ModelPlatform):
|
||||
def model(self):
|
||||
# from llama_index.llms.anthropic import Anthropic
|
||||
#
|
||||
# model_map: Dict[str, str] = {
|
||||
@@ -214,22 +285,50 @@ def init_anthropic():
|
||||
# init_fastembed()
|
||||
pass
|
||||
|
||||
def embedding(self):
|
||||
pass
|
||||
|
||||
def init_gemini():
|
||||
# from llama_index.embeddings.gemini import GeminiEmbedding
|
||||
def rerank(self):
|
||||
pass
|
||||
|
||||
@register(ModelPlateCategory,'gemini')
|
||||
class GeminiPlatform(ModelPlatform):
|
||||
def model(self):
|
||||
# from llama_index.llms.gemini import Gemini
|
||||
#
|
||||
# model_name = f"models/{os.getenv('MODEL')}"
|
||||
# embed_model_name = f"models/{os.getenv('EMBEDDING_MODEL')}"
|
||||
#
|
||||
# Settings.llm = Gemini(model=model_name)
|
||||
# Settings.embed_model = GeminiEmbedding(model_name=embed_model_name)
|
||||
# return Gemini(model=model_name)
|
||||
pass
|
||||
|
||||
def init_mistral():
|
||||
# from llama_index.embeddings.mistralai import MistralAIEmbedding
|
||||
# from llama_index.llms.mistralai import MistralAI
|
||||
#
|
||||
# Settings.llm = MistralAI(model=os.getenv("MODEL"))
|
||||
# Settings.embed_model = MistralAIEmbedding(model_name=os.getenv("EMBEDDING_MODEL"))
|
||||
def embedding(self):
|
||||
# from llama_index.embeddings.gemini import GeminiEmbedding
|
||||
# embed_model_name = f"models/{os.getenv('EMBEDDING_MODEL')}"
|
||||
# return GeminiEmbedding(model_name=embed_model_name)
|
||||
pass
|
||||
|
||||
def rerank(self):
|
||||
pass
|
||||
|
||||
@register(ModelPlateCategory,'mistral')
|
||||
class MistralPlatform(ModelPlatform):
|
||||
def model(self):
|
||||
# from llama_index.llms.mistralai import MistralAI
|
||||
# return MistralAI(model=os.getenv("MODEL"))
|
||||
pass
|
||||
|
||||
def embedding(self):
|
||||
# from llama_index.embeddings.mistralai import MistralAIEmbedding
|
||||
# return MistralAIEmbedding(model_name=os.getenv("EMBEDDING_MODEL"))
|
||||
pass
|
||||
|
||||
def rerank(self):
|
||||
pass
|
||||
|
||||
def init_ProjectInfo():
|
||||
prjObj = ProjectInfo()
|
||||
prjInfos:list[tuple] = getProjectInfos()
|
||||
for prjInfo in prjInfos:
|
||||
prjObj.add(prjInfo['name'],prjInfo['flag'])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,272 +0,0 @@
|
||||
"""Xinference embeddings file."""
|
||||
|
||||
import logging
|
||||
from enum import Enum
|
||||
from http import HTTPStatus
|
||||
from typing import Any, Dict, List, Optional, Union, Tuple
|
||||
|
||||
from llama_index.core.base.embeddings.base import BaseEmbedding, Embedding, dispatcher
|
||||
from llama_index.core.bridge.pydantic import PrivateAttr
|
||||
from llama_index.core.callbacks import CBEventType, EventPayload
|
||||
from llama_index.core.embeddings.multi_modal_base import MultiModalEmbedding
|
||||
from llama_index.core.instrumentation.events.rerank import ReRankStartEvent, ReRankEndEvent
|
||||
from llama_index.core.postprocessor.types import BaseNodePostprocessor
|
||||
from llama_index.core.schema import ImageType, NodeWithScore, QueryBundle
|
||||
from pydantic import Field
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
EMBED_MAX_INPUT_LENGTH = 2048
|
||||
EMBED_MAX_BATCH_SIZE = 1
|
||||
|
||||
|
||||
class XinferenceEmbedding(BaseEmbedding):
|
||||
"""Xinference class for text embedding.
|
||||
|
||||
"""
|
||||
model_description: Dict[str, Any] = Field(
|
||||
description="The model description from Xinference."
|
||||
)
|
||||
_generator: Any = PrivateAttr()
|
||||
_model_uid: str = Field(description="The Xinference model to use.")
|
||||
_endpoint: str = Field(description="The Xinference endpoint URL to use.")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model_uid: str,
|
||||
endpoint: str,
|
||||
embed_batch_size: int = EMBED_MAX_BATCH_SIZE,
|
||||
dimensions: Optional[int] = None,
|
||||
additional_kwargs: Optional[Dict[str, Any]] = None,
|
||||
api_key: Optional[str] = None,
|
||||
api_base: Optional[str] = None,
|
||||
api_version: Optional[str] = None,
|
||||
max_retries: int = 10,
|
||||
# timeout: float = 60.0,
|
||||
# reuse_client: bool = True,
|
||||
# callback_manager: Optional[CallbackManager] = None,
|
||||
# default_headers: Optional[Dict[str, str]] = None,
|
||||
# http_client: Optional[httpx.Client] = None,
|
||||
# async_http_client: Optional[httpx.AsyncClient] = None,
|
||||
# num_workers: Optional[int] = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
generator, model_description, embed_batch_size, dimensions = self.load_model(
|
||||
model_uid, endpoint
|
||||
)
|
||||
self._generator = generator
|
||||
#self._model_uid = model_uid
|
||||
#self._endpoint = endpoint
|
||||
super().__init__(
|
||||
embed_batch_size=embed_batch_size,
|
||||
dimensions=dimensions,
|
||||
#callback_manager=callback_manager,
|
||||
model_name=model_uid,
|
||||
additional_kwargs=additional_kwargs,
|
||||
api_key=api_key,
|
||||
api_base=api_base,
|
||||
api_version=api_version,
|
||||
max_retries=max_retries,
|
||||
# reuse_client=reuse_client,
|
||||
# timeout=timeout,
|
||||
# default_headers=default_headers,
|
||||
# num_workers=num_workers,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def load_model(self, model_uid: str, endpoint: str) -> Tuple[Any, int, dict]:
|
||||
try:
|
||||
from xinference.client import RESTfulClient
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Could not import Xinference library."
|
||||
'Please install Xinference with `pip install "xinference[all]"`'
|
||||
)
|
||||
|
||||
client = RESTfulClient(endpoint)
|
||||
|
||||
try:
|
||||
assert isinstance(client, RESTfulClient)
|
||||
except AssertionError:
|
||||
raise RuntimeError(
|
||||
"Could not create RESTfulClient instance."
|
||||
"Please make sure Xinference endpoint is running at the correct port."
|
||||
)
|
||||
|
||||
generator = client.get_model(model_uid)
|
||||
model_description = client.list_models()[model_uid]
|
||||
|
||||
try:
|
||||
assert generator is not None
|
||||
assert model_description is not None
|
||||
except AssertionError:
|
||||
raise RuntimeError(
|
||||
"Could not get model from endpoint."
|
||||
"Please make sure Xinference endpoint is running at the correct port."
|
||||
)
|
||||
|
||||
model = model_description["model_name"]
|
||||
replica = model_description['replica']
|
||||
dimensions = model_description['dimensions']
|
||||
max_tokens = model_description['max_tokens']
|
||||
|
||||
return generator, model_description, replica, dimensions
|
||||
|
||||
@classmethod
|
||||
def class_name(cls) -> str:
|
||||
return "XinferenceEmbedding"
|
||||
|
||||
def _get_text_embedding(self, text: str) -> Embedding:
|
||||
"""
|
||||
Embed the input text synchronously.
|
||||
|
||||
Subclasses should implement this method. Reference get_text_embedding's
|
||||
docstring for more information.
|
||||
"""
|
||||
assert self._generator is not None
|
||||
|
||||
response = self._generator.create_embedding(input=text)
|
||||
return response['data'][0]['embedding']
|
||||
|
||||
def _get_query_embedding(self, query: str) -> Embedding:
|
||||
"""
|
||||
Embed the input query synchronously.
|
||||
|
||||
Subclasses should implement this method. Reference get_query_embedding's
|
||||
docstring for more information.
|
||||
"""
|
||||
return self._get_text_embedding(query)
|
||||
|
||||
async def _aget_query_embedding(self, query: str) -> Embedding:
|
||||
"""
|
||||
Embed the input query asynchronously.
|
||||
|
||||
Subclasses should implement this method. Reference get_query_embedding's
|
||||
docstring for more information.
|
||||
"""
|
||||
return self._get_query_embedding(query)
|
||||
|
||||
class XinferenceRerank(BaseNodePostprocessor):
|
||||
"""Xinference class for rerank.
|
||||
|
||||
"""
|
||||
model_description: Dict[str, Any] = Field(
|
||||
description="The model description from Xinference."
|
||||
)
|
||||
_generator: Any = PrivateAttr()
|
||||
_model_uid: str = Field(description="The Xinference model to use.")
|
||||
_endpoint: str = Field(description="The Xinference endpoint URL to use.")
|
||||
model: str = Field(description="Dashscope rerank model name.")
|
||||
top_n: int = Field(description="Top N nodes to return.")
|
||||
threshold: float = Field(description="threshold nodes to return.")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model_uid: str,
|
||||
endpoint: str,
|
||||
top_n: int = None,
|
||||
threshold: float = None,
|
||||
return_documents: bool = False
|
||||
):
|
||||
_model_uid = model_uid
|
||||
_endpoint = endpoint
|
||||
_op_n = top_n
|
||||
threshold = threshold
|
||||
generator, model_description = self.load_model(
|
||||
model_uid, endpoint
|
||||
)
|
||||
self._generator = generator
|
||||
super().__init__(top_n=top_n, model=model_uid, model_uid=model_uid, threshold = threshold, return_documents=return_documents)
|
||||
|
||||
@classmethod
|
||||
def class_name(cls) -> str:
|
||||
return "XinferenceRerank"
|
||||
|
||||
def _postprocess_nodes(
|
||||
self,
|
||||
nodes: List[NodeWithScore],
|
||||
query_bundle: Optional[QueryBundle] = None,
|
||||
) -> List[NodeWithScore]:
|
||||
if query_bundle is None:
|
||||
raise ValueError("Missing query bundle in extra info.")
|
||||
if len(nodes) == 0:
|
||||
return []
|
||||
|
||||
dispatcher.event(
|
||||
ReRankStartEvent(
|
||||
nodes = nodes,
|
||||
top_n = self.top_n,
|
||||
query = query_bundle,
|
||||
model_name = self.model
|
||||
)
|
||||
)
|
||||
|
||||
with self.callback_manager.event(
|
||||
CBEventType.RERANKING,
|
||||
payload={
|
||||
EventPayload.NODES: nodes,
|
||||
EventPayload.MODEL_NAME: self._model_uid,
|
||||
EventPayload.QUERY_STR: query_bundle.query_str,
|
||||
EventPayload.TOP_K: self.top_n,
|
||||
},
|
||||
) as event:
|
||||
texts = [node.node.get_content() for node in nodes]
|
||||
response = self._generator.rerank(texts,query_bundle.query_str)
|
||||
new_nodes = []
|
||||
for result in response['results']:
|
||||
new_node_with_score = NodeWithScore(
|
||||
node=nodes[result['index']].node, score=result['relevance_score']
|
||||
)
|
||||
if self.threshold is not None:
|
||||
if new_node_with_score.score >=self.threshold:
|
||||
new_nodes.append(new_node_with_score)
|
||||
|
||||
if self.top_n is not None:
|
||||
if len(new_nodes) > self.top_n:
|
||||
for index in new_nodes[self.top_n:-1]:
|
||||
new_nodes.remove(index)
|
||||
|
||||
event.on_end(payload={EventPayload.NODES: new_nodes})
|
||||
|
||||
dispatcher.event(
|
||||
ReRankEndEvent(
|
||||
nodes= new_nodes
|
||||
)
|
||||
)
|
||||
return new_nodes
|
||||
|
||||
def load_model(self, model_uid: str, endpoint: str) -> Tuple[Any, int, dict]:
|
||||
try:
|
||||
from xinference.client import RESTfulClient
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Could not import Xinference library."
|
||||
'Please install Xinference with `pip install "xinference[all]"`'
|
||||
)
|
||||
|
||||
client = RESTfulClient(endpoint)
|
||||
|
||||
try:
|
||||
assert isinstance(client, RESTfulClient)
|
||||
except AssertionError:
|
||||
raise RuntimeError(
|
||||
"Could not create RESTfulClient instance."
|
||||
"Please make sure Xinference endpoint is running at the correct port."
|
||||
)
|
||||
|
||||
generator = client.get_model(model_uid)
|
||||
model_description = client.list_models()[model_uid]
|
||||
|
||||
try:
|
||||
assert generator is not None
|
||||
assert model_description is not None
|
||||
except AssertionError:
|
||||
raise RuntimeError(
|
||||
"Could not get model from endpoint."
|
||||
"Please make sure Xinference endpoint is running at the correct port."
|
||||
)
|
||||
|
||||
model = model_description["model_name"]
|
||||
|
||||
return generator, model_description
|
||||
@@ -1,272 +0,0 @@
|
||||
"""Xinference embeddings file."""
|
||||
|
||||
import logging
|
||||
from enum import Enum
|
||||
from http import HTTPStatus
|
||||
from typing import Any, Dict, List, Optional, Union, Tuple
|
||||
|
||||
from llama_index.core.base.embeddings.base import BaseEmbedding, Embedding, dispatcher
|
||||
from llama_index.core.bridge.pydantic import PrivateAttr
|
||||
from llama_index.core.callbacks import CBEventType, EventPayload
|
||||
from llama_index.core.embeddings.multi_modal_base import MultiModalEmbedding
|
||||
from llama_index.core.instrumentation.events.rerank import ReRankStartEvent, ReRankEndEvent
|
||||
from llama_index.core.postprocessor.types import BaseNodePostprocessor
|
||||
from llama_index.core.schema import ImageType, NodeWithScore, QueryBundle
|
||||
from pydantic import Field
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
EMBED_MAX_INPUT_LENGTH = 2048
|
||||
EMBED_MAX_BATCH_SIZE = 1
|
||||
|
||||
|
||||
class XinferenceEmbedding(BaseEmbedding):
|
||||
"""Xinference class for text embedding.
|
||||
|
||||
"""
|
||||
model_description: Dict[str, Any] = Field(
|
||||
description="The model description from Xinference."
|
||||
)
|
||||
_generator: Any = PrivateAttr()
|
||||
_model_uid: str = Field(description="The Xinference model to use.")
|
||||
_endpoint: str = Field(description="The Xinference endpoint URL to use.")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model_uid: str,
|
||||
endpoint: str,
|
||||
embed_batch_size: int = EMBED_MAX_BATCH_SIZE,
|
||||
dimensions: Optional[int] = None,
|
||||
additional_kwargs: Optional[Dict[str, Any]] = None,
|
||||
api_key: Optional[str] = None,
|
||||
api_base: Optional[str] = None,
|
||||
api_version: Optional[str] = None,
|
||||
max_retries: int = 10,
|
||||
# timeout: float = 60.0,
|
||||
# reuse_client: bool = True,
|
||||
# callback_manager: Optional[CallbackManager] = None,
|
||||
# default_headers: Optional[Dict[str, str]] = None,
|
||||
# http_client: Optional[httpx.Client] = None,
|
||||
# async_http_client: Optional[httpx.AsyncClient] = None,
|
||||
# num_workers: Optional[int] = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
generator, model_description, embed_batch_size, dimensions = self.load_model(
|
||||
model_uid, endpoint
|
||||
)
|
||||
self._generator = generator
|
||||
#self._model_uid = model_uid
|
||||
#self._endpoint = endpoint
|
||||
super().__init__(
|
||||
embed_batch_size=embed_batch_size,
|
||||
dimensions=dimensions,
|
||||
#callback_manager=callback_manager,
|
||||
model_name=model_uid,
|
||||
additional_kwargs=additional_kwargs,
|
||||
api_key=api_key,
|
||||
api_base=api_base,
|
||||
api_version=api_version,
|
||||
max_retries=max_retries,
|
||||
# reuse_client=reuse_client,
|
||||
# timeout=timeout,
|
||||
# default_headers=default_headers,
|
||||
# num_workers=num_workers,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def load_model(self, model_uid: str, endpoint: str) -> Tuple[Any, int, dict]:
|
||||
try:
|
||||
from xinference.client import RESTfulClient
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Could not import Xinference library."
|
||||
'Please install Xinference with `pip install "xinference[all]"`'
|
||||
)
|
||||
|
||||
client = RESTfulClient(endpoint)
|
||||
|
||||
try:
|
||||
assert isinstance(client, RESTfulClient)
|
||||
except AssertionError:
|
||||
raise RuntimeError(
|
||||
"Could not create RESTfulClient instance."
|
||||
"Please make sure Xinference endpoint is running at the correct port."
|
||||
)
|
||||
|
||||
generator = client.get_model(model_uid)
|
||||
model_description = client.list_models()[model_uid]
|
||||
|
||||
try:
|
||||
assert generator is not None
|
||||
assert model_description is not None
|
||||
except AssertionError:
|
||||
raise RuntimeError(
|
||||
"Could not get model from endpoint."
|
||||
"Please make sure Xinference endpoint is running at the correct port."
|
||||
)
|
||||
|
||||
model = model_description["model_name"]
|
||||
replica = model_description['replica']
|
||||
dimensions = model_description['dimensions']
|
||||
max_tokens = model_description['max_tokens']
|
||||
|
||||
return generator, model_description, replica, dimensions
|
||||
|
||||
@classmethod
|
||||
def class_name(cls) -> str:
|
||||
return "XinferenceEmbedding"
|
||||
|
||||
def _get_text_embedding(self, text: str) -> Embedding:
|
||||
"""
|
||||
Embed the input text synchronously.
|
||||
|
||||
Subclasses should implement this method. Reference get_text_embedding's
|
||||
docstring for more information.
|
||||
"""
|
||||
assert self._generator is not None
|
||||
|
||||
response = self._generator.create_embedding(input=text)
|
||||
return response['data'][0]['embedding']
|
||||
|
||||
def _get_query_embedding(self, query: str) -> Embedding:
|
||||
"""
|
||||
Embed the input query synchronously.
|
||||
|
||||
Subclasses should implement this method. Reference get_query_embedding's
|
||||
docstring for more information.
|
||||
"""
|
||||
return self._get_text_embedding(query)
|
||||
|
||||
async def _aget_query_embedding(self, query: str) -> Embedding:
|
||||
"""
|
||||
Embed the input query asynchronously.
|
||||
|
||||
Subclasses should implement this method. Reference get_query_embedding's
|
||||
docstring for more information.
|
||||
"""
|
||||
return self._get_query_embedding(query)
|
||||
|
||||
class XinferenceRerank(BaseNodePostprocessor):
|
||||
"""Xinference class for rerank.
|
||||
|
||||
"""
|
||||
model_description: Dict[str, Any] = Field(
|
||||
description="The model description from Xinference."
|
||||
)
|
||||
_generator: Any = PrivateAttr()
|
||||
_model_uid: str = Field(description="The Xinference model to use.")
|
||||
_endpoint: str = Field(description="The Xinference endpoint URL to use.")
|
||||
model: str = Field(description="Dashscope rerank model name.")
|
||||
top_n: int = Field(description="Top N nodes to return.")
|
||||
threshold: float = Field(description="threshold nodes to return.")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model_uid: str,
|
||||
endpoint: str,
|
||||
top_n: int = None,
|
||||
threshold: float = None,
|
||||
return_documents: bool = False
|
||||
):
|
||||
_model_uid = model_uid
|
||||
_endpoint = endpoint
|
||||
_op_n = top_n
|
||||
threshold = threshold
|
||||
generator, model_description = self.load_model(
|
||||
model_uid, endpoint
|
||||
)
|
||||
self._generator = generator
|
||||
super().__init__(top_n=top_n, model=model_uid, model_uid=model_uid, threshold = threshold, return_documents=return_documents)
|
||||
|
||||
@classmethod
|
||||
def class_name(cls) -> str:
|
||||
return "XinferenceRerank"
|
||||
|
||||
def _postprocess_nodes(
|
||||
self,
|
||||
nodes: List[NodeWithScore],
|
||||
query_bundle: Optional[QueryBundle] = None,
|
||||
) -> List[NodeWithScore]:
|
||||
if query_bundle is None:
|
||||
raise ValueError("Missing query bundle in extra info.")
|
||||
if len(nodes) == 0:
|
||||
return []
|
||||
|
||||
dispatcher.event(
|
||||
ReRankStartEvent(
|
||||
nodes = nodes,
|
||||
top_n = self.top_n,
|
||||
query = query_bundle,
|
||||
model_name = self.model
|
||||
)
|
||||
)
|
||||
|
||||
with self.callback_manager.event(
|
||||
CBEventType.RERANKING,
|
||||
payload={
|
||||
EventPayload.NODES: nodes,
|
||||
EventPayload.MODEL_NAME: self._model_uid,
|
||||
EventPayload.QUERY_STR: query_bundle.query_str,
|
||||
EventPayload.TOP_K: self.top_n,
|
||||
},
|
||||
) as event:
|
||||
texts = [node.node.get_content() for node in nodes]
|
||||
response = self._generator.rerank(texts,query_bundle.query_str)
|
||||
new_nodes = []
|
||||
for result in response['results']:
|
||||
new_node_with_score = NodeWithScore(
|
||||
node=nodes[result['index']].node, score=result['relevance_score']
|
||||
)
|
||||
if self.threshold is not None:
|
||||
if new_node_with_score.score >=self.threshold:
|
||||
new_nodes.append(new_node_with_score)
|
||||
|
||||
if self.top_n is not None:
|
||||
if len(new_nodes) > self.top_n:
|
||||
for index in new_nodes[self.top_n:-1]:
|
||||
new_nodes.remove(index)
|
||||
|
||||
event.on_end(payload={EventPayload.NODES: new_nodes})
|
||||
|
||||
dispatcher.event(
|
||||
ReRankEndEvent(
|
||||
nodes= new_nodes
|
||||
)
|
||||
)
|
||||
return new_nodes
|
||||
|
||||
def load_model(self, model_uid: str, endpoint: str) -> Tuple[Any, int, dict]:
|
||||
try:
|
||||
from xinference.client import RESTfulClient
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Could not import Xinference library."
|
||||
'Please install Xinference with `pip install "xinference[all]"`'
|
||||
)
|
||||
|
||||
client = RESTfulClient(endpoint)
|
||||
|
||||
try:
|
||||
assert isinstance(client, RESTfulClient)
|
||||
except AssertionError:
|
||||
raise RuntimeError(
|
||||
"Could not create RESTfulClient instance."
|
||||
"Please make sure Xinference endpoint is running at the correct port."
|
||||
)
|
||||
|
||||
generator = client.get_model(model_uid)
|
||||
model_description = client.list_models()[model_uid]
|
||||
|
||||
try:
|
||||
assert generator is not None
|
||||
assert model_description is not None
|
||||
except AssertionError:
|
||||
raise RuntimeError(
|
||||
"Could not get model from endpoint."
|
||||
"Please make sure Xinference endpoint is running at the correct port."
|
||||
)
|
||||
|
||||
model = model_description["model_name"]
|
||||
|
||||
return generator, model_description
|
||||
+33
-18
@@ -1,33 +1,48 @@
|
||||
file:
|
||||
enable: true # 添加 enable 字段
|
||||
# use_llama_parse: Use LlamaParse if `true`. Needs a `LLAMA_CLOUD_API_KEY` from https://cloud.llamaindex.ai set as environment variable
|
||||
use_llama_parse: false
|
||||
|
||||
db:
|
||||
#db:
|
||||
# The configuration for the database loader, only supports MySQL and PostgreSQL databases for now.
|
||||
# uri: The URI for the database. E.g.: mysql+pymysql://user:password@localhost:3306/db or postgresql+psycopg2://user:password@localhost:5432/db
|
||||
# query: The query to fetch data from the database. E.g.: SELECT * FROM table
|
||||
- uri: mysql+pymysql://zjinfo1:Dy2Bcr53Hm5xRkba@110.42.234.166:3306/zjinfo1
|
||||
#- uri: mysql+pymysql://zjinfo:Y6EAjEEdSYmskA8B@110.42.234.166:3306/zjinfo
|
||||
# - uri: mysql+pymysql://zjinfo2:GSKcziSdBixDXwcd@110.42.234.166:3306/zjinfo2
|
||||
queries:
|
||||
- sql: select * from ProjectProperties limit 30;
|
||||
explanation: "工程属性表数据,层级关系包含在博微电力造价工程文件格式_ProjectProperties.json文件中。"
|
||||
#- uri: mysql+pymysql://zjinfo1:Dy2Bcr53Hm5xRkba@110.42.234.166:3306/zjinfo1
|
||||
#enable: false # 添加 enable 字段
|
||||
#queries:
|
||||
#- sql: select * from ProjectProperties;
|
||||
#explanation: "工程属性表数据,层级关系包含在博微电力造价工程文件格式_ProjectProperties.json文件中。"
|
||||
|
||||
- sql: select Id, ParentId, Level, Name, Code, Amount, Amount_Total from TotalCalculateTable;
|
||||
explanation: "总算表数据,层级关系包含在博微电力造价工程文件格式_TotalCalculateTable.json文件中。"
|
||||
#- sql: select Id, ParentId, Level, Name, Code, Amount, Amount_Total from TotalCalculateTable;
|
||||
#explanation: "总算表数据,层级关系包含在博微电力造价工程文件格式_TotalCalculateTable.json文件中。"
|
||||
|
||||
- sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where Level = 3 and ProfessionalType = '线路' limit 50;
|
||||
explanation: "专业类型为线路的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。"
|
||||
#- sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '线路';
|
||||
#explanation: "专业类型为线路的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。"
|
||||
#- sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '余物清理';
|
||||
#explanation: "专业类型为余物清理的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。"
|
||||
#- sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '拆除线路';
|
||||
#explanation: "专业类型为拆除线路的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。"
|
||||
|
||||
- sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where Level = 3 and ProfessionalType = '余物清理' limit 50;
|
||||
explanation: "专业类型为余物清理的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。"
|
||||
#- sql: select Id, ParentId, Level, Name, Code, Rate, Amount from OtherFee;
|
||||
#explanation: "其他费用表数据,层级关系包含在博微电力造价工程文件格式_OtherFee.json文件中"
|
||||
|
||||
- sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where Level = 3 and ProfessionalType = '拆除线路' limit 50;
|
||||
explanation: "专业类型为拆除线路的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。"
|
||||
|
||||
- sql: select Id, ParentId, Level, Name, Code, Rate, Amount from OtherFee;
|
||||
explanation: "其他费用表数据,层级关系包含在博微电力造价工程文件格式_OtherFee.json文件中"
|
||||
#- sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表'
|
||||
#explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中"
|
||||
#- sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表(调试工程)aa'
|
||||
#explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中"
|
||||
#- sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '大型土石方取费表'
|
||||
#explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中"
|
||||
#- sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表(余物清理)'
|
||||
#explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中"
|
||||
#- sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表(余物清理)(1)'
|
||||
#explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中"
|
||||
#- sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表(拆除)'
|
||||
#explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中"
|
||||
|
||||
#- sql: select Name, Code, Calculation_Formula, Rate, from ProjectQuantities where Professional_Type = '线路'
|
||||
#explanation: "专业类型为线路的工程量表数据,层级关系包含在博微电力造价工程文件格式_ProjectQuantities.json文件中"
|
||||
#- sql: select Name, Code, Calculation_Formula, Rate, from ProjectQuantities where Professional_Type = '余物清理'
|
||||
#explanation: "专业类型为余物清理的工程量表数据,层级关系包含在博微电力造价工程文件格式_ProjectQuantities.json文件中"
|
||||
#web:
|
||||
# driver_arguments:
|
||||
# # The arguments to pass to the webdriver. E.g.: add --headless to run in headless mode
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# 其他费用
|
||||
备注:其他费用表被称为“工程费用中其他费用明细”。其他费用是指为完成工程项目建设所必需的,但不属于建筑工程费、安装工程费、设备购置费、基本预备费的其他相关费用。包括建设场地征用及清理费、项目建设管理费、项目建设技术服务费、生产准备费、大件运输措施费、专业爆破服务费等。查询示例: SELECT Rate FROM OtherFee WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:relTbId
|
||||
- 字段名称:parentId
|
||||
- 字段名称:序号
|
||||
- 备注:序号,序列号
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:金额,价格
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:金额
|
||||
- 备注:金额,价格
|
||||
- 字段名称:编码
|
||||
- 备注:WBS编号,WBS编码
|
||||
- 字段名称:服务内容
|
||||
- 字段名称:费用归属
|
||||
- 字段名称:输出
|
||||
- 字段名称:不可竞争费用
|
||||
- 字段名称:编制依据
|
||||
- 备注:编制依据,编制来源
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:表一显示
|
||||
- 字段名称:税率
|
||||
|
||||
|_id|nodeType|relTbId|parentId|序号|名称|代码|单位|取费基数|费率|金额|编码|服务内容|费用归属|输出|不可竞争费用|编制依据|备注|表一显示|税率|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|31ywrqmravb4|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}||1|建设场地征用及清理费|A||建设场地征用及清理费|100|16831284.228711|31831000000|||否|否|23eds股份认同||是|0|
|
||||
|31ywrqmravb5|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}||2|项目建设管理费|B|||100|1619697876.652205|31832000000|||否|否|||否|0|
|
||||
|31ywrqmtsrnk|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmravb5|2.1|项目法人管理费|B1||本体工程费+编制基准期价差|1.17|986923559.414937|31832100000|||否|否|||否|0|
|
||||
|31ywrqmtsrnl|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmravb5|2.2|招标费|B2||本体工程费+编制基准期价差|0.28|236186834.73178|31832200000|||否|否||线路长度超过500km时,超过部分每增加100km,费率乘以0.92系数 |否|6|
|
||||
|31ywrqmtsrnm|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmravb5|2.3|工程监理费|B3||工程监理费|100|131009.92|31832300000|||否|否|23eds股份认同|说明:162号文指导费率区间:单回路0.64-0.65(万元/km);同杆(塔)双回0.77-0.78(万元/km)。|否|6|
|
||||
|31ywrqmtsrnn|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmravb5|2.4|设备材料监造费|B4||监造材料费|0|0|31832400000|||否|否|||否|6|
|
||||
|31ywrqmwao00|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmravb5|2.5|施工过程造价咨询及竣工结算审核费|B5||本体工程费+编制基准期价差|0.47|396456472.585488|31832500000|||否|否|12|费用计算低于3000元时,按3000元计列。|否|6|
|
||||
|31ywrqmwao01|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmravb5|2.6|工程保险费|B6|||100|0|31832600000|||否|否|||否|6|
|
||||
|31ywrqmwao02|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}||3|项目建设技术服务费|C|||100|16855957065.430212|31833000000|||否|否|沃尔沃12||否|6|
|
||||
|31ywrqmwao03|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao02|3.1|项目前期工作费|C1|||100|0|31833100000|||否|否|地方||否|6|
|
||||
|31ywrqmyskcg|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.1|可行性研究费用|C11|||100|0|31833110000|||否|否||说明:162号文指导费用区间:5万元-10万元;10km以上,增加0.2万元/km;多回路、高海拔等可调整。|否|6|
|
||||
|31ywrqmyskch|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.2|环境影响评价费用|C12|||100|0|31833120000|||否|否||说明:162号文指导费用区间:5万元-8万元;20km以上,增加0.25万元/km;穿越环境敏感区、平行走廊等可调整。|否|6|
|
||||
|31ywrqmyskci|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.3|建设项目规划选址费|C13|||100|0|31833130000|||否|否||说明:162号文指导费用区间:3万元-10万元;10km以上,增加0.05万元/km;平行走廊等可调整。|否|6|
|
||||
|31ywrqn1agow|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.4|水土保持方案编审费用|C14|||100|0|31833140000|||否|否|二|说明:162号文指导费用区间:2万元-3万元;10km以上,增加0.1万元/km;平行走廊等可调整。|否|6|
|
||||
|31ywrqn1agox|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.5|地质灾害危险性评估费用|C15|||100|0|31833150000|||否|否||说明:162号文指导费用区间:1万元-2万元;10km以上,增加0.15万元/km;平行走廊等可调整。|否|6|
|
||||
|31ywrqn1agoy|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.6|地震安全性评价费用|C16|||100|0|31833160000|||否|否||说明:线路工程原则上不计此费用|否|6|
|
||||
|31ywrqn3sd1c|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.7|文物调查费用|C17|||100|0|31833170000|||否|否||说明:162号文指导费用区间:2万元-3万元;10km以上,增加0.05-0.15万元/km;平行走廊等可调整。|否|6|
|
||||
|31ywrqn3sd1d|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.8|矿产压覆评估费用|C18|||100|0|31833180000|||否|否||说明:162号文指导费用区间:3万元-8万元;10km以上,增加0.1-0.3万元/km;平行走廊等可调整。|否|6|
|
||||
|31ywrqn3sd1e|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.9|用地预审费用|C19|||100|0|31833190000|||否|否||说明:162号文指导费用区间:3万元-5万元;10km以上,增加0.1-0.3万元/km;平行走廊等可调整。|否|6|
|
||||
|31ywrqn3sd1f|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.10|节能评估费用|C1A|||100|0|318331A0000|||否|否||说明:162号文指导费用区间:2万元-5万元;20km以上,增加0.01-0.05万元/km;平行走廊等可调整。|否|6|
|
||||
|31ywrqn6a9ds|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.11|社会稳定风险评估费用|C1B|||100|0|318331B0000|||否|否||说明:162号文指导费用区间:5万元-10万元;20km以上,增加0.01-0.05万元/km;平行走廊等可调整。|否|6|
|
||||
|31ywrqn6a9dt|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.12|使用林地可行性研究费用|C1C|||100|0|318331C0000|||否|否||说明:162号文指导费用区间:2万元-3万元;10km以上,增加0.05万元/km。|否|6|
|
||||
|31ywrqn8s5q8|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao03|3.1.13|前期工作管理费用|C1D|||100|0|318331D0000|||否|否||说明:162号文指导费用:5万元;单独的变电站、换流站、输电线路工程按40%-60%调整|否|6|
|
||||
|31ywrqn8s5q9|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao02|3.2|知识产权转让与研究试验费|C2|||100|0|31833200000|||否|否||根据建设项目法人提出的项目和费用计列。|否|6|
|
||||
|31ywrqn8s5qa|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao02|3.3|勘察设计费|C3|||100|16164210209.43|31833300000|||否|否|qwe||否|6|
|
||||
|31ywrqn8s5qb|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqn8s5qa|3.3.1|勘察费|C31||勘察费|100|12122154260|31833310000|||否|否|zx||否|6|
|
||||
|31ywrqn8s5qc|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqn8s5qa|3.3.2|设计费|C32||设计费|100|4042055949.43|31833320000|||否|否|asd||否|6|
|
||||
|31ywrqnba22o|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao02|3.4|设计文件评审费|C4|||100|56840|31833400000|||否|否|drf||否|6|
|
||||
|31ywrqnba22p|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnba22o|3.4.1|可行性研究文件评审费|C41||可行性研究评审费|100|13340|31833410000|||否|否|hf||否|6|
|
||||
|31ywrqndryf4|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnba22o|3.4.2|初步设计文件评审费|C42||初步设计评审费|100|18560|31833420000|||否|否|vb||否|6|
|
||||
|31ywrqndryf5|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnba22o|3.4.3|施工图文件评审费|C43||施工图评审费|100|24940|31833430000|||否|否|asdf||否|6|
|
||||
|31ywrqndryf6|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao02|3.5|项目后评价费|C5||本体工程费+编制基准期价差|0.5|421762204.878178|31833500000|||否|否|asd|1.架空交流输电线路长度超过300km时,超过部分乘以0.8系数;架空直流输电线路长度超过1500km时,超过部分乘以0.8系数。 2.单项输变电工程,建筑工程费+安装工程费低于2000万元,取费基数取2000万元。|否|6|
|
||||
|31ywrqng9urk|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao02|3.6|工程建设检测费|C6|||100|185575370.146398|31833600000|||否|否|sd||是|6|
|
||||
|31ywrqng9url|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqng9urk|3.6.1|电力工程质量检测费|C61||本体工程费+编制基准期价差|0.22|185575370.146398|31833610000|||是|否|e||否|6|
|
||||
|31ywrqng9urm|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqng9urk|3.6.2|特种设备安全监测费|C62|||100|0|31833620000|||否|否|||是|6|
|
||||
|31ywrqng9urn|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqng9urk|3.6.3|环境监测及环境保护验收费|C63|||100|0|31833630000|||否|否|||否|6|
|
||||
|31ywrqng9uro|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqng9urk|3.6.4|水土保持监测及验收费|C64|||100|0|31833640000|||是|否|||是|6|
|
||||
|31ywrqnirr40|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqng9urk|3.6.5|桩基检测费|C65|||100|0|31833650000|||否|否|||否|6|
|
||||
|31ywrqnirr41|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqmwao02|3.7|电力工程技术经济标准编制费|C7||本体工程费+编制基准期价差|0.1|84352440.975636|31833700000|||否|否|||否|6|
|
||||
|31ywrqnirr42|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}||4|生产准备费|D|||100|472373669.46356|31834000000|||是|否|||否|0|
|
||||
|31ywrqnirr43|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnirr42|4.1|管理车辆购置费|D1||本体工程费+编制基准期价差|0.25|210881102.439089|31834100000|||否|否||注:如果管理车辆由项目法人单位统一配置,并且不在工程项目中分摊相关费用时,本项费用不计。|否|13|
|
||||
|31ywrqnl9ngg|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnirr42|4.2|工器具及办公家具购置费|D2||本体工程费+编制基准期价差|0.21|177140126.048835|31834200000|||否|否|||否|13|
|
||||
|31ywrqnl9ngh|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnirr42|4.3|生产职工培训及提前进场费|D3||本体工程费+编制基准期价差|0.1|84352440.975636|31834300000|||否|否|||否|0|
|
||||
|31ywrqnnrjsw|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}||5|专业爆破服务费|E|||100|0|31835000000|||否|否|||否|0|
|
||||
|31ywrqnnrjsx|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}||6|其他|F|||100|0|31836000000|||否|否|||否|0|
|
||||
|31ywrqnnrjsy|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}||7|新费用|SD3||本体工程费+编制基准期价差|100|84352440975.635651||||否|否|||否|0|
|
||||
|31ywrqnq9g5c|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}||8|新费用1||||100|107625611701.459076||||否|否|||否|0|
|
||||
|31ywrqnq9g5d|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.1|新费用15|||本体工程费|100|55105688268.517624||||否|否|||否|0|
|
||||
|31ywrqnq9g5e|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.2|新费用2|||设备购置费|100|2567934636.357451||||否|否|||否|0|
|
||||
|31ywrqnq9g5f|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.3|新费用3|||监造材料费|100|24036.0696||||否|否|||否|0|
|
||||
|31ywrqnsrchs|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.4|新费用4|||监造设备费|100|15924502.368||||否|否|||否|0|
|
||||
|31ywrqnsrcht|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.5|新费用5|||甲供主材费含税|100|2220128892.505839||||否|否|||否|0|
|
||||
|31ywrqnsrchu|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.6|新费用6|||乙供主材费不含税|100|2802065.505122||||否|否|||否|0|
|
||||
|31ywrqnsrchv|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.7|新费用7|||勘察费|100|12122154260||||否|否|||否|0|
|
||||
|31ywrqnsrchw|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.8|新费用8|||设计费|100|4042055949.43||||否|否|||否|0|
|
||||
|31ywrqnv98u8|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.9|新费用9|||基本设计费|100|2285224349.13||||否|否|||否|0|
|
||||
|31ywrqnv98u9|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.10|新费用10|||建设场地征用及清理费|100|16831284.228711||||否|否|||否|0|
|
||||
|31ywrqnv98ua|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.11|新费用11|||编制基准期价差|100|29246752707.118019||||否|否|||否|0|
|
||||
|31ywrqnv98ub|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.12|新费用12|||余物清理费|100|90736.228711||||否|否|||否|0|
|
||||
|31ywrqnxr56o|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.13|新费用13|||工程税率|100|9||||否|否|||否|0|
|
||||
|31ywrqnxr56p|其他费用|{0086C94C-6041-44CB-B021-E696A825DF9A}|31ywrqnq9g5c|8.14|新费用14|||线路亘长|100|5||||否|否|||否|0|
|
||||
@@ -0,0 +1,29 @@
|
||||
# 大型土石方取费表_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{EA4C703B-0027-4884-9820-9BD4EE91A66B}|FFZ1|||一|否|100|直接工程费|取费表||{7422B3F1-AD7B-4B33-BC19-098E6419DDC2}|
|
||||
|{6DA65B76-41D3-40C8-A9D7-867D0997FFC7}|RGF|取费定额人工费||1|否|100|人工费|取费表|{EA4C703B-0027-4884-9820-9BD4EE91A66B}|{7422B3F1-AD7B-4B33-BC19-098E6419DDC2}|
|
||||
|{AC5B806B-A8C9-46C1-B30B-3A6048389B98}|CLF|取费定额乙供材料费不含税+乙供取费主材费不含税+甲供取费主材费含税||2|否|100|材料费|取费表|{EA4C703B-0027-4884-9820-9BD4EE91A66B}|{7422B3F1-AD7B-4B33-BC19-098E6419DDC2}|
|
||||
|{FE6C418F-D50F-43F0-939E-6E786619FEF0}|JXF|取费定额机械费||3|否|100|施工机械使用费|取费表|{EA4C703B-0027-4884-9820-9BD4EE91A66B}|{7422B3F1-AD7B-4B33-BC19-098E6419DDC2}|
|
||||
|{CC66691E-2C2B-4D5A-8592-F32DF6AF0C32}|TZHQF|FFZ1-甲供主材进项税额|综合取费费用额(包含措施费、间接费、利润)|二|否|17.79|综合取费费用额|取费表||{7422B3F1-AD7B-4B33-BC19-098E6419DDC2}|
|
||||
|{5FA19404-F27F-42C7-AA88-657810C04FBD}|TFFS|FFZ1+TZHQF-甲供取费主材费含税+不取费定额费不含税+不取费乙供主材费不含税||三|否|9|税金|取费表||{7422B3F1-AD7B-4B33-BC19-098E6419DDC2}|
|
||||
|{19644FFF-4F8E-4905-9680-FC634E1976FD}|THJ|FFZ1+TZHQF+TFFS+一笔性费用+不取费定额费不含税+不取费乙供主材费不含税+不取费甲供主材费含税||四|否|100|合计|取费表||{7422B3F1-AD7B-4B33-BC19-098E6419DDC2}|
|
||||
@@ -0,0 +1,47 @@
|
||||
# 线路取费表(调试工程)aa_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{89584688-CE5E-459B-91CB-7EE6A67B3F69}|FFZ||撒大声地|一|否|100|直接费|取费表||{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{562076A7-DD26-454C-9551-0D4378F004E1}|FFZ1||水电费asf|1|否|100|直接工程费|取费表|{89584688-CE5E-459B-91CB-7EE6A67B3F69}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{C1F7FABF-3DD4-4143-9B50-8F77AF8CC714}|DZF||adsf|1.1|否|100|定额直接费|取费表|{562076A7-DD26-454C-9551-0D4378F004E1}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{8FFEB7C5-4BC3-4BCD-8867-3AE8D0B4AF1F}|RGF|取费定额人工费||1.1.1|否|100|人工费|取费表|{C1F7FABF-3DD4-4143-9B50-8F77AF8CC714}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{1CE55F21-2825-495D-962F-358874DF5098}|CLF|取费定额乙供材料费不含税|sdf|1.1.2|否|100|材料费|取费表|{C1F7FABF-3DD4-4143-9B50-8F77AF8CC714}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{47CCA71B-DEFA-471D-B5A9-CC572DF00E72}|JXF|取费定额机械费|dsf|1.1.3|否|100|施工机械使用费|取费表|{C1F7FABF-3DD4-4143-9B50-8F77AF8CC714}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{E4D27C6B-1830-4648-B658-3EB73FB9F68C}|ZZCF||fds|1.2|否|100|装置性材料费|取费表|{562076A7-DD26-454C-9551-0D4378F004E1}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{9C2930D6-714A-466C-B9DC-DAA94D27D6C7}|JZZCF|甲供取费主材费含税||1.2.1|否|100|甲供装置性材料费|取费表|{E4D27C6B-1830-4648-B658-3EB73FB9F68C}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{82F14392-48E0-4FF7-8F2B-656A7CFA00E7}|YZZCF|乙供取费主材费不含税|dsf|1.2.2|否|100|乙供装置性材料费|取费表|{E4D27C6B-1830-4648-B658-3EB73FB9F68C}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{8FA168BD-6916-49B8-A456-E8CC2A53045E}|FFZ2|||2|否|100|措施费|取费表|{89584688-CE5E-459B-91CB-7EE6A67B3F69}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{2E0E2997-9AB8-448D-B225-739D600B75A7}|DYF|取费定额人工费||2.1|否|3.57|冬雨季施工增加费|取费表|{8FA168BD-6916-49B8-A456-E8CC2A53045E}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{C29B035D-5F92-4075-9BF1-6CA59BCE213B}|YSF|取费定额人工费|sd|2.2|否|0|夜间施工增加费|取费表|{8FA168BD-6916-49B8-A456-E8CC2A53045E}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{252CA171-CC5D-4935-B1DD-DC56D611874D}|SYF|取费定额人工费|f|2.3|否|3.82|施工工具用具使用费|取费表|{8FA168BD-6916-49B8-A456-E8CC2A53045E}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{9C145731-E29B-452D-B456-245B4852346B}|TDF|取费定额人工费||2.4|否|0|特殊地区施工增加费|取费表|{8FA168BD-6916-49B8-A456-E8CC2A53045E}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{E52BA944-762A-4A20-964E-CB3632D72879}|LSF|DZF||2.5|否|6.35|临时设施费|取费表|{8FA168BD-6916-49B8-A456-E8CC2A53045E}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{428548D1-9A8B-4278-9DDA-D393760B603D}|ZYF|取费定额人工费|dsdsf|2.6|否|2.36|施工机构迁移费|取费表|{8FA168BD-6916-49B8-A456-E8CC2A53045E}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{FA0FA01C-D535-47D9-ADEE-D8FE85E9BCEE}|BZF|FFZ1-甲供主材进项税额||2.7|否|3.55|安全文明施工费|取费表|{8FA168BD-6916-49B8-A456-E8CC2A53045E}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{03647B7A-CB22-4C9D-9EC6-D31B78FE78C8}|FFJ|||二|否|100|间接费|取费表||{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{82339946-C479-4DDF-A90F-46A7E4B59B40}|GF|||1|否|100|规费|取费表|{03647B7A-CB22-4C9D-9EC6-D31B78FE78C8}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{837BB29C-A795-4761-B5CD-6D47A1222E5B}|BZHF|取费定额人工费*1.05|sdf|1.1|否|2|社会保险费|取费表|{82339946-C479-4DDF-A90F-46A7E4B59B40}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{D8947795-59A2-4B0B-81E3-1D77B5B5DACA}|GJJ|取费定额人工费*1.05||1.2|否|2|住房公积金|取费表|{82339946-C479-4DDF-A90F-46A7E4B59B40}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{DB95097F-9AAF-4B15-9A91-A60FCD5A8F8A}|GLF|取费定额人工费||2|否|35.76|企业管理费|取费表|{03647B7A-CB22-4C9D-9EC6-D31B78FE78C8}|{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{846F0E21-9BC9-4188-A699-1CF4E84D54BF}|FFR|FFZ+FFJ-甲供主材进项税额|f|三|否|5|利润|取费表||{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{F240BBFC-34FA-440E-9B9E-0185114F0668}|FFS|FFZ+FFJ+FFR-甲供取费主材费含税+不取费定额费不含税+不取费乙供主材费不含税|fsd|四|否|9|税金|取费表||{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
|{CF5E9612-3C9D-46B0-BA8F-93762C0F8131}|HJ|FFZ+FFJ+FFR+FFS+一笔性费用+不取费定额费不含税+不取费乙供主材费不含税+不取费甲供主材费含税|df|五|否|100|合计|取费表||{56791DC7-0475-4DA9-ABE6-60E32D70BAD0}|
|
||||
@@ -0,0 +1,132 @@
|
||||
# 线路取费表_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{70406D96-B3AE-49BA-B01B-770DE3B90099}|FFZ||dsf|一|否|100|直接费|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{580EEFEB-BD7D-4E9E-AB6F-06112640566E}|FFZ1||dsf|1|否|100|直接工程费|取费表|{70406D96-B3AE-49BA-B01B-770DE3B90099}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{EC40FC4E-6922-49D5-A6D4-6D4DAC5D4F5D}|DZF|||1.1|否|100|定额直接费|取费表|{580EEFEB-BD7D-4E9E-AB6F-06112640566E}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{8D96B01B-FA07-478A-808B-C7F7173DC3E2}|RGF|取费定额人工费|sdf|1.1.1|否|100|人工费|取费表|{EC40FC4E-6922-49D5-A6D4-6D4DAC5D4F5D}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{DB5F8BD1-B3E5-492D-960B-EA429CC75B8F}|CLF|取费定额乙供材料费不含税|f|1.1.2|否|100|材料费|取费表|{EC40FC4E-6922-49D5-A6D4-6D4DAC5D4F5D}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{80157259-369F-4A43-BE1A-BAEFAA3DF543}|JXF|取费定额机械费||1.1.3|否|100|施工机械使用费|取费表|{EC40FC4E-6922-49D5-A6D4-6D4DAC5D4F5D}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{EC524B6C-D8E9-4B96-9F45-979A328CA242}|ZZCF||sdf|1.2|否|100|装置性材料费|取费表|{580EEFEB-BD7D-4E9E-AB6F-06112640566E}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{FC50C3AD-D531-47EF-B1CC-DDC6D58B5C80}|JZZCF|甲供取费主材费含税||1.2.1|否|100|甲供装置性材料费|取费表|{EC524B6C-D8E9-4B96-9F45-979A328CA242}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{49A170B8-7B38-40F2-9392-0B79DFEFBBE2}|YZZCF|乙供取费主材费不含税|sdf|1.2.2|否|100|乙供装置性材料费|取费表|{EC524B6C-D8E9-4B96-9F45-979A328CA242}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{D69561EB-7F49-42B9-90D4-0B8F0C9F522F}|FFZ2||dsfs|2|否|100|措施费|取费表|{70406D96-B3AE-49BA-B01B-770DE3B90099}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{1BC0B3CD-F3DC-4501-9BBA-517247CBA843}|DYF|取费定额人工费||2.1|否|3.57|冬雨季施工增加费|取费表|{D69561EB-7F49-42B9-90D4-0B8F0C9F522F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{B51D7BD8-E114-495A-A331-76A9DD21310F}|YSF|取费定额人工费||2.2|否|0|夜间施工增加费|取费表|{D69561EB-7F49-42B9-90D4-0B8F0C9F522F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{EC9ED826-4477-4BF9-97FF-E3C7339C7345}|SYF|取费定额人工费|sdf|2.3|否|3.82|施工工具用具使用费|取费表|{D69561EB-7F49-42B9-90D4-0B8F0C9F522F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{0A9E4A3E-49ED-4BE1-97EC-4AD16315737C}|TDF|取费定额人工费||2.4|否|0|特殊地区施工增加费|取费表|{D69561EB-7F49-42B9-90D4-0B8F0C9F522F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{4A33D32F-0460-4A7E-B949-798F49318FE7}|LSF|DZF||2.5|否|6.35|临时设施费|取费表|{D69561EB-7F49-42B9-90D4-0B8F0C9F522F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{C19DFCF6-3036-45C3-9575-1636F532BE7D}|ZYF|取费定额人工费|sdf|2.6|否|2.36|施工机构迁移费|取费表|{D69561EB-7F49-42B9-90D4-0B8F0C9F522F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{5FD896CC-F364-416C-8D60-A94301EDAFA4}|BZF|FFZ1-甲供主材进项税额||2.7|否|3.55|安全文明施工费|取费表|{D69561EB-7F49-42B9-90D4-0B8F0C9F522F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{8AF614D8-993D-4199-A360-8F6328D06A75}|FFJ||df|二|否|100|间接费|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{61EA8A77-BD86-41F3-8AF5-1A584B60D1DF}|GF||dsf|1|否|100|规费|取费表|{8AF614D8-993D-4199-A360-8F6328D06A75}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{7175C4E2-EEDA-428F-BA0E-8187CB6C761A}|BZHF|取费定额人工费*1.05|sd|1.1|否|2|社会保险费|取费表|{61EA8A77-BD86-41F3-8AF5-1A584B60D1DF}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{7838D12C-9489-40B1-91CE-CDE82BE01E43}|GJJ|取费定额人工费*1.05|fsdf|1.2|否|2|住房公积金|取费表|{61EA8A77-BD86-41F3-8AF5-1A584B60D1DF}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{E2D542B4-0B36-4D4F-B766-829AE372D61B}|GLF|取费定额人工费||2|否|35.76|企业管理费|取费表|{8AF614D8-993D-4199-A360-8F6328D06A75}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{265EF8F8-25C1-40D5-9541-6C983203E2A4}|TSF|DZF|sdf|3|否|0|施工企业配合调试费|取费表|{8AF614D8-993D-4199-A360-8F6328D06A75}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{A771C271-1AE0-4C69-A713-9A2258763A94}|FFR|FFZ+FFJ-甲供主材进项税额||三|否|5|利润|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{6D7F08B2-E8F9-46E5-AC9E-936CE7342F08}|FFS|FFZ+FFJ+FFR-甲供取费主材费含税+不取费定额费不含税+不取费乙供主材费不含税|ffsd|四|否|9|税金|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{A2CB4552-ADFC-41C5-AFF3-BE3C796CAEEE}|SBF||sd|五|否|100|设备费|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{F137DC37-302F-434D-9A46-118F9B14802C}|SBY|乙供设备费不含税+乙供设备税金|fdf|1|否|100|乙供设备不含税价|取费表|{A2CB4552-ADFC-41C5-AFF3-BE3C796CAEEE}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{879B6551-1BDF-442D-B6B5-CAFF38E0CD7D}|SBJ|甲供设备费含税|sdfsd|2|否|100|甲供设备含税价|取费表|{A2CB4552-ADFC-41C5-AFF3-BE3C796CAEEE}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{078B3961-C38B-410D-A810-2AEF3E9F26FB}|AZF|DZF+FFZ2+FFJ+FFR+FFS+不取费定额费不含税+一笔性费用||六|否|100|安装费|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{329944F5-E6C9-494E-9AA8-BB59D88A3F2B}|ZCF|ZZCF+不取费乙供主材费不含税+不取费甲供主材费含税|dsf|七|否|100|主材费|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{A20AEF8B-EE68-4B47-B9AA-72D30F8275A4}|ZJ|AZF+ZCF+SBF||八|否|100|总计|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{9EBA5169-2402-4BEC-8D50-AFB98EB8B3F7}|E|取费定额人工费+231|我加的|a|否|100|新费用|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{B57AEA48-C1DE-425D-A053-A585148A04B9}|HJ|ZJ-SBF+E|dsf|九|否|100|合计|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{E1038F7A-CF74-40D5-90EA-586E8102768B}|||||否|100|常用变量|取费表||{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{CE1D4531-4DAB-43F0-B19C-F1B2C44B803E}||取费定额人工费||1|否|100|新费用69|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{BEC5078F-57FE-43C9-A068-FB4866499DD9}||取费定额乙供材料费不含税||2|否|100|新费用1|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{B899075D-CF02-48B5-A2A9-C82655846164}||取费定额机械费||3|否|100|新费用2|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{D63B6670-B748-4563-9C17-02E21F68BAF3}||甲供取费主材费含税||4|否|100|新费用3|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{43189C40-AA16-487F-8FC0-3B5AE33C32F8}||乙供取费主材费不含税||5|否|100|新费用4|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{20AD5254-D7E4-465A-A6B4-0EFF6741D6C2}||甲供设备费含税||6|否|100|甲供设备费含税|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{59B2E543-174A-41A2-A989-53D8C2361EEC}||乙供设备费不含税||7|否|100|乙供设备费不含税|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{0DBD69A2-F553-4289-B64F-08AAD5661492}||乙供设备税金||8|否|100|乙供设备税金|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{E8A4D69C-DD16-4A5C-B249-267DA144062D}||甲供主材进项税额||9|否|100|甲供主材进项税额|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{907DCC9F-1E9D-4005-AA41-311C07D26B65}||人工价差||10|否|100|新费用5|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{67FEA6C5-9CFD-425B-A2B3-739F44BF102B}||乙供材料价差不含税||11|否|100|新费用6|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{63A8F2C0-3E19-4215-8FC1-B2C1E2EEAD8B}||机械价差||12|否|100|新费用7|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{02746A4C-4393-4FC1-BAAA-8C184695AA9F}||甲供主材价差含税||13|否|100|新费用8|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{A38F7EC6-01AB-4A3E-90A7-98E49C6DBDAB}||乙供主材价差不含税||14|否|100|新费用9|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{A51F720F-02CD-4B15-A688-169ABF5A973B}||不取费定额费不含税||15|否|100|新费用10|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{A58A1C6B-6800-44B8-9E76-1C7C8204173D}||不取费甲供主材费含税||16|否|100|新费用11|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{72D23F7A-69FD-4B8D-B44B-974662E25BC0}||不取费乙供主材费不含税||17|否|100|新费用12|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{F0DCFFCF-7A5A-432C-832C-EA1DDDCAD41A}||工程税率||18|否|100|工程税率|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{AA4C2BC3-6749-4E19-AA38-C65A3E13FB62}||一笔性费用||19|否|100|一笔性费用|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{7476AD1B-7270-4F63-96A8-2589CF06D1B3}||线路亘长||20|否|100|线路亘长|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{38FC8F6A-AA41-433E-B20E-3A4C35F0097A}||||21|否|100|新费用13|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{2F021F6F-E56D-4211-A298-9CBBBC0E0D7F}||定额_取费_人工费||21.1|否|100|新费用14|取费表|{38FC8F6A-AA41-433E-B20E-3A4C35F0097A}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{6CBA8586-9F1B-42A1-AADA-32CC6ED651BF}||定额_取费_乙供材料费不含税||21.2|否|100|新费用15|取费表|{38FC8F6A-AA41-433E-B20E-3A4C35F0097A}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{817A70A0-E8DA-44F3-8F4E-FB7E948A6FD1}||定额_取费_机械费||21.3|否|100|新费用16|取费表|{38FC8F6A-AA41-433E-B20E-3A4C35F0097A}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{91127133-F48B-4063-912B-BCDB7878B10E}||定额_取费_人工价差||21.4|否|100|新费用17|取费表|{38FC8F6A-AA41-433E-B20E-3A4C35F0097A}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{9BBC63D2-7B4D-4D48-8EB6-5A2B9BCDB3FD}||定额_取费_乙供材料价差不含税||21.5|否|100|新费用18|取费表|{38FC8F6A-AA41-433E-B20E-3A4C35F0097A}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{22E4FFC6-E81F-4857-9783-2FC95E1A639A}||定额_取费_机械价差||21.6|否|100|新费用19|取费表|{38FC8F6A-AA41-433E-B20E-3A4C35F0097A}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{9F894ADA-2261-4302-8BFA-386AEDF4A926}||||22|否|100|新费用20|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{927CED17-7151-4418-8FC9-B63206E283E1}||定额_不取费_人工费||22.1|否|100|新费用21|取费表|{9F894ADA-2261-4302-8BFA-386AEDF4A926}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{A75FD504-21F8-4BE6-8138-9F7FF0BD0594}||定额_不取费_乙供材料费不含税||22.2|否|100|新费用22|取费表|{9F894ADA-2261-4302-8BFA-386AEDF4A926}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{03049308-7B53-4A57-8526-AC97ADBBAF47}||定额_不取费_机械费||22.3|否|100|新费用23|取费表|{9F894ADA-2261-4302-8BFA-386AEDF4A926}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{6543B15A-BF08-4045-A4B6-840BE8BB6E47}||定额_不取费_人工价差||22.4|否|100|新费用24|取费表|{9F894ADA-2261-4302-8BFA-386AEDF4A926}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{6E3F1BF6-0853-4E45-BAB4-386D524C599C}||定额_不取费_乙供材料价差不含税||22.5|否|100|新费用25|取费表|{9F894ADA-2261-4302-8BFA-386AEDF4A926}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{D59699DA-05E5-4650-88C9-8EA21BD00EFF}||定额_不取费_机械价差||22.6|否|100|新费用26|取费表|{9F894ADA-2261-4302-8BFA-386AEDF4A926}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}||||23|否|100|新费用27|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{474E7BF3-3988-44B9-AC5F-4053C3D408F0}||主材_取费_甲供主材费不含税||23.1|否|100|新费用28|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{84DB0E83-6C43-46A6-80FA-B08E8EE36E68}||主材_取费_甲供主材费含税||23.2|否|100|新费用29|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{697F88B9-9E58-49B8-AC5E-0758DEE7DFCE}||主材_取费_甲供主材损耗费不含税||23.3|否|100|新费用30|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{8470F441-CAB5-4A49-B3B0-891F582ED1A9}||主材_取费_甲供主材损耗费含税||23.4|否|100|新费用31|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{B83443A8-2E42-49D9-8B73-F1FC22B7041B}||主材_取费_甲供主材价差不含税||23.5|否|100|新费用32|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{D3CCC6FE-F841-426B-A356-6BFC22D13967}||主材_取费_甲供主材价差含税||23.6|否|100|新费用33|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{15C154B4-EE35-4882-8733-C4F40E52BA95}||主材_取费_甲供主材损耗价差不含税||23.7|否|100|新费用34|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{BA607DED-D353-44EF-93AC-BAADDD1A0AB3}||主材_取费_甲供主材损耗价差含税||23.8|否|100|新费用35|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{66C0E832-4E6F-4844-9F1D-8E0A16EEDE14}||主材_取费_乙供主材费不含税||23.9|否|100|新费用36|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{9439D197-6506-4471-B3A8-1B471CFD694E}||主材_取费_乙供主材损耗费不含税||23.10|否|100|新费用37|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{8F7DB6EA-CB2F-4425-8F05-0099C550EEDA}||主材_取费_乙供主材价差不含税||23.11|否|100|新费用38|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{4CDF8FA3-BED1-4556-BFBA-33F9855844DA}||主材_取费_乙供主材损耗价差不含税||23.12|否|100|新费用39|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{374EC738-5796-4708-A142-C2239C72F81C}||主材_取费_运输重量||23.13|否|100|新费用40|取费表|{D0CF04E5-2B54-4BC0-A43A-A5FEAC1F4628}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{29B550FC-E48E-4D28-A177-E4F8E484209F}||||24|否|100|新费用41|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{8D0D0A30-1188-4012-B0E9-0405DE56A8B7}||主材_不取费_甲供主材费不含税||24.1|否|100|新费用42|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{EDE14BEF-1E81-4881-A214-F13026973492}||主材_不取费_甲供主材费含税||24.2|否|100|新费用43|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{4C09CF4E-81C8-4560-ABA8-FB97465FC7E9}||主材_不取费_甲供主材损耗费不含税||24.3|否|100|新费用44|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{C28704AF-43E9-4CD6-BBA0-BCF05AAEE5EA}||主材_不取费_甲供主材损耗费含税||24.4|否|100|新费用45|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{3936A573-8B9D-4CD5-8D65-BDAE63BB0D71}||主材_不取费_甲供主材价差不含税||24.5|否|100|新费用46|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{0FD66B7E-CDBC-49AF-B836-19BA85CEB858}||主材_不取费_甲供主材价差含税||24.6|否|100|新费用47|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{34514126-514F-4DF8-97E3-49C904673865}||主材_不取费_甲供主材损耗价差不含税||24.7|否|100|新费用48|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{E8233277-0395-451E-AAAD-28FD938A3D6C}||主材_不取费_甲供主材损耗价差含税||24.8|否|100|新费用49|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{9AA5F7F4-4CE5-429E-8EE1-99AD32BD9677}||主材_不取费_乙供主材费不含税||24.9|否|100|新费用50|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{C154129C-4002-44C9-B994-BEB0CAA73B48}||主材_不取费_乙供主材损耗费不含税||24.10|否|100|新费用51|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{0D0C2193-1379-496D-AAC9-50754767BBEE}||主材_不取费_乙供主材价差不含税||24.11|否|100|新费用52|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{8C0E8186-18E0-4AFC-B802-916495002B61}||主材_不取费_乙供主材损耗价差不含税||24.12|否|100|新费用53|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{FC1DA50B-6D72-45B4-8996-DF9E05002A64}||主材_不取费_运输重量||24.13|否|100|新费用54|取费表|{29B550FC-E48E-4D28-A177-E4F8E484209F}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{4377CDFD-A4BC-4999-9453-70E80B093C5E}||||25|否|100|新费用55|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{174A8B58-F00B-4821-8389-0847465C5EA2}||设备_普通设备_甲供设备费不含税||25.1|否|100|新费用56|取费表|{4377CDFD-A4BC-4999-9453-70E80B093C5E}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{E0225E32-6C03-41F4-B99F-DF95A6CC5FD6}||设备_普通设备_甲供设备费含税||25.2|否|100|新费用57|取费表|{4377CDFD-A4BC-4999-9453-70E80B093C5E}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{E8401E26-9357-4001-8096-CE060AF515BF}||设备_普通设备_甲供设备运杂费||25.3|否|100|新费用58|取费表|{4377CDFD-A4BC-4999-9453-70E80B093C5E}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{009925CC-BD88-4C73-A775-44FF9F5E535B}||设备_普通设备_乙供设备费不含税||25.4|否|100|新费用59|取费表|{4377CDFD-A4BC-4999-9453-70E80B093C5E}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{8C8D8D6A-7739-4C25-9FF7-8B5F642D8088}||设备_普通设备_乙供设备运杂费||25.5|否|100|新费用60|取费表|{4377CDFD-A4BC-4999-9453-70E80B093C5E}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{6A78CFF1-7C26-40EF-A3AD-0269B341D86E}||设备_普通设备_乙供设备税金||25.6|否|100|新费用61|取费表|{4377CDFD-A4BC-4999-9453-70E80B093C5E}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{8294A47B-1FDF-4AAF-AAB6-CB8326F40A1C}||||26|否|100|新费用62|取费表|{E1038F7A-CF74-40D5-90EA-586E8102768B}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{41AEEC6D-CD38-486E-A240-05E21324A4E6}||设备_主要设备_甲供设备费不含税||26.1|否|100|新费用63|取费表|{8294A47B-1FDF-4AAF-AAB6-CB8326F40A1C}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{14561281-0438-4E0E-9AF9-978970E8430C}||设备_主要设备_甲供设备费含税||26.2|否|100|新费用64|取费表|{8294A47B-1FDF-4AAF-AAB6-CB8326F40A1C}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{A3EA36EA-1E6E-4E98-AE0E-C41AC66ED23D}||设备_主要设备_甲供设备运杂费||26.3|否|100|新费用65|取费表|{8294A47B-1FDF-4AAF-AAB6-CB8326F40A1C}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{DC4C6DB0-C8D7-41F8-90B4-A86C51FC5BD0}||设备_主要设备_乙供设备费不含税||26.4|否|100|新费用66|取费表|{8294A47B-1FDF-4AAF-AAB6-CB8326F40A1C}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{B26F93F7-4E62-419B-B7B9-B5A928C9B987}||设备_主要设备_乙供设备运杂费||26.5|否|100|新费用67|取费表|{8294A47B-1FDF-4AAF-AAB6-CB8326F40A1C}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
|{4BD38BC2-C975-4F2D-A2F9-4132E04AD281}||设备_主要设备_乙供设备税金||26.6|否|100|新费用68|取费表|{8294A47B-1FDF-4AAF-AAB6-CB8326F40A1C}|{0607D565-D3F4-4D42-9AB8-39C7E397C325}|
|
||||
@@ -0,0 +1,32 @@
|
||||
# 线路取费表(余物清理)(1)_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{2EF96B62-7EFA-4E78-B2D4-EEF578970753}|FFZ||ds|一|否|100|直接费|取费表||{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{B27E7DBB-D33E-4E0C-811A-46F473455D7B}|FFZ1||sdf|1|否|100|直接工程费|取费表|{2EF96B62-7EFA-4E78-B2D4-EEF578970753}|{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{8E8CBA5E-E555-4DCE-830B-AE86D20BA946}|DZF|||1.1|否|100|定额直接费|取费表|{B27E7DBB-D33E-4E0C-811A-46F473455D7B}|{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{8ADD1F8D-AF63-4998-97CC-2E2406F3C825}|RGF|取费定额人工费|ds|1.1.1|否|100|人工费|取费表|{8E8CBA5E-E555-4DCE-830B-AE86D20BA946}|{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{32D2E73A-6896-4790-A019-AEA3587F5CDD}|CLF|取费定额乙供材料费不含税|ds|1.1.2|否|100|材料费|取费表|{8E8CBA5E-E555-4DCE-830B-AE86D20BA946}|{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{E7B8A30F-C562-474D-823A-6C27DE9F520F}|JXF|取费定额机械费||1.1.3|否|100|施工机械使用费|取费表|{8E8CBA5E-E555-4DCE-830B-AE86D20BA946}|{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{46490417-BE3A-4175-AC0A-56BD30AEDD25}|FFZ2||sdf|2|否|100|措施费|取费表|{2EF96B62-7EFA-4E78-B2D4-EEF578970753}|{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{4A969822-5333-43D1-A916-F6FEFF221568}|BZF|FFZ1|sdf|2.1|否|3.55|安全文明施工费|取费表|{46490417-BE3A-4175-AC0A-56BD30AEDD25}|{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{46B1E7CB-22F3-46E2-9438-035FC1E014F8}|W|取费定额人工费+200|我加的|2.2|否|100|新费用|取费表|{46490417-BE3A-4175-AC0A-56BD30AEDD25}|{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
|{C9479906-C457-49F4-B1D2-743EE0D88C48}|HJ|FFZ+一笔性费用+W|sd|二|否|100|合计|取费表||{724617D5-3F63-4FDC-962B-4FAB593C401C}|
|
||||
@@ -0,0 +1,87 @@
|
||||
# 线路取费表(余物清理)_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{BE94FFCB-FA01-4E8B-A9B1-9FB29161E440}|FFZ||ds|一|否|100|直接费|取费表||{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{9A4DC1D7-0A24-4F41-A0E6-468F356936FA}|FFZ1||sdf|1|否|100|直接工程费|取费表|{BE94FFCB-FA01-4E8B-A9B1-9FB29161E440}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{DCC69452-0832-4D75-8716-4B1B36C34FC9}|DZF|||1.1|否|100|定额直接费|取费表|{9A4DC1D7-0A24-4F41-A0E6-468F356936FA}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{6E53A71F-235C-48D5-A738-0E68C7162743}|RGF|取费定额人工费|ds|1.1.1|否|100|人工费|取费表|{DCC69452-0832-4D75-8716-4B1B36C34FC9}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{D839833B-A862-485D-B432-90E46EBC115B}|CLF|取费定额乙供材料费不含税|ds|1.1.2|否|100|材料费|取费表|{DCC69452-0832-4D75-8716-4B1B36C34FC9}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{FCDE2FE5-2C6E-4753-82FE-7AF5BF7D2355}|JXF|取费定额机械费||1.1.3|否|100|施工机械使用费|取费表|{DCC69452-0832-4D75-8716-4B1B36C34FC9}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{96F0D55D-CE26-474A-8209-366CACE69262}|FFZ2||sdf|2|否|100|措施费|取费表|{BE94FFCB-FA01-4E8B-A9B1-9FB29161E440}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{35B3D950-7BD6-40B8-8637-952ED005EB33}|BZF|FFZ1|sdf|2.1|否|3.55|安全文明施工费|取费表|{96F0D55D-CE26-474A-8209-366CACE69262}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{81529EEB-96A3-4C95-807E-EAA4E9AB9927}|W|取费定额人工费|我加的|2.2|否|100|新费用|取费表|{96F0D55D-CE26-474A-8209-366CACE69262}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{EFB69F6F-0BE3-414B-BB10-A9F2C8E6CC54}|HJ|FFZ+一笔性费用+W|sd|二|否|100|合计|取费表||{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{E038685B-85A7-4A97-97DA-D3385F322B24}|||||否|100|新费用1|取费表||{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{AB265F93-20D1-49B0-9281-0FF627343E24}||||1|否|100|宏|取费表|{E038685B-85A7-4A97-97DA-D3385F322B24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{02962FEB-3A61-4B08-9F22-6B34F0ECAF1A}||取费定额人工费||1.1|否|100|新费用44|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{FF11B669-A5A5-43C8-9E7E-A8E7F60E040E}||取费定额乙供材料费不含税||1.2|否|100|新费用2|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{04E974BB-0544-4E51-9B02-6F92B522D200}||取费定额机械费||1.3|否|100|新费用3|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{A2B5BD01-A6D2-4F21-A078-A39D2B02C2D9}||甲供主材进项税额||1.4|否|100|新费用4|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{BE436CA0-0603-479D-AB5C-8B84F2EC562F}||甲供取费主材费含税||1.5|否|100|新费用5|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{0474458D-39FA-48BA-BC85-C8AFACC055C3}||乙供取费主材费不含税||1.6|否|100|新费用6|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{37BADC69-6622-49D4-9994-3926038C78B3}||不取费定额费不含税||1.7|否|100|新费用7|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{4AD79BFF-0DB0-44BB-92C9-1542E60544DB}||不取费甲供主材费含税||1.8|否|100|新费用8|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{9A450AAE-5BEB-4966-AE70-5BDD99070823}||不取费乙供主材费不含税||1.9|否|100|新费用9|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{DE20CD7C-11EB-4DC6-BB5D-F0098DA795E3}||工程税率||1.10|否|100|新费用10|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{75965A4E-E0D0-45AB-A085-60F3DE53040B}||一笔性费用||1.11|否|100|新费用11|取费表|{AB265F93-20D1-49B0-9281-0FF627343E24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{F4A7F45A-2CCD-4290-95C1-DE15B41A4FA6}||||2|否|100|基础变量|取费表|{E038685B-85A7-4A97-97DA-D3385F322B24}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{D908BF67-838A-4B86-871B-A25ED6679D8F}||||2.1|否|100|定额|取费表|{F4A7F45A-2CCD-4290-95C1-DE15B41A4FA6}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{24C1D861-C0E8-4455-A0E8-C4D105AEEF5A}||||2.1.1|否|100|取|取费表|{D908BF67-838A-4B86-871B-A25ED6679D8F}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{F79A2603-235D-40CF-BDAA-CE358A1A424B}||定额_取费_人工费||2.1.1.1|否|100|新费用12|取费表|{24C1D861-C0E8-4455-A0E8-C4D105AEEF5A}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{3244C267-E729-438D-A180-20B854D35BEB}||定额_取费_乙供材料费不含税||2.1.1.2|否|100|新费用14|取费表|{24C1D861-C0E8-4455-A0E8-C4D105AEEF5A}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{64622AE4-268D-4BD3-80E0-FCC25724AFD3}||定额_取费_机械费||2.1.1.3|否|100|新费用15|取费表|{24C1D861-C0E8-4455-A0E8-C4D105AEEF5A}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{0A5FB413-4619-40C6-B16E-97E5468C41EA}||||2.1.2|否|100|不取|取费表|{D908BF67-838A-4B86-871B-A25ED6679D8F}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{71FCC55C-EAA0-4C6C-AB18-DB45C17331BE}||定额_不取费_人工费||2.1.2.1|否|100|新费用16|取费表|{0A5FB413-4619-40C6-B16E-97E5468C41EA}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{C69006F6-A788-4976-BD02-94B7248BEA00}||定额_不取费_乙供材料费不含税||2.1.2.2|否|100|新费用13|取费表|{0A5FB413-4619-40C6-B16E-97E5468C41EA}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{91A75F8B-D3AE-42F1-9BBD-C1F7E309C0FE}||定额_不取费_机械费||2.1.2.3|否|100|新费用17|取费表|{0A5FB413-4619-40C6-B16E-97E5468C41EA}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{703BFDFD-9612-4715-B1FC-184FA1C0DBF5}||||2.2|否|100|主材|取费表|{F4A7F45A-2CCD-4290-95C1-DE15B41A4FA6}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{279825D0-1127-4C91-9EF1-10EAB9A4E321}||||2.2.1|否|100|取1|取费表|{703BFDFD-9612-4715-B1FC-184FA1C0DBF5}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{E9D9431E-6298-4AF1-86B0-F172E0283455}||主材_取费_甲供主材费不含税||2.2.1.1|否|100|新费用22|取费表|{279825D0-1127-4C91-9EF1-10EAB9A4E321}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{4D92C554-FE5B-4DB6-A582-444C7FE352A7}||主材_取费_甲供主材费含税||2.2.1.2|否|100|新费用18|取费表|{279825D0-1127-4C91-9EF1-10EAB9A4E321}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{6B5D6954-BE0F-4BF6-A6AA-34D18E4DEEC5}||主材_取费_甲供主材损耗费不含税||2.2.1.3|否|100|新费用20|取费表|{279825D0-1127-4C91-9EF1-10EAB9A4E321}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{333EE3F5-220C-454B-AA33-F74EB23EA90A}||主材_取费_甲供主材损耗费含税||2.2.1.4|否|100|新费用21|取费表|{279825D0-1127-4C91-9EF1-10EAB9A4E321}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{70CD571A-1492-448B-BEF3-D10487184E93}||主材_取费_乙供主材费不含税||2.2.1.5|否|100|新费用23|取费表|{279825D0-1127-4C91-9EF1-10EAB9A4E321}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{A205E1B1-5509-4273-8A1D-B0BD11191694}||主材_取费_乙供主材损耗费不含税||2.2.1.6|否|100|新费用24|取费表|{279825D0-1127-4C91-9EF1-10EAB9A4E321}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{7EF20055-FEB3-4BBA-803E-79860EDE7959}||主材_取费_运输重量||2.2.1.7|否|100|新费用25|取费表|{279825D0-1127-4C91-9EF1-10EAB9A4E321}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{C83708A3-AB6A-408F-8DC4-FF286D5F6560}||||2.2.2|否|100|不取1|取费表|{703BFDFD-9612-4715-B1FC-184FA1C0DBF5}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{EBC9A113-8540-43F5-8B15-E02EFA5C0771}||主材_不取费_甲供主材费不含税||2.2.2.1|否|100|新费用26|取费表|{C83708A3-AB6A-408F-8DC4-FF286D5F6560}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{DE448780-63B8-4FA9-AA5D-B447DA1D726B}||主材_不取费_甲供主材费含税||2.2.2.2|否|100|新费用27|取费表|{C83708A3-AB6A-408F-8DC4-FF286D5F6560}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{59A30CAA-7938-4D9F-9975-DDA8389A1876}||主材_不取费_甲供主材损耗费不含税||2.2.2.3|否|100|新费用28|取费表|{C83708A3-AB6A-408F-8DC4-FF286D5F6560}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{10D2DA8F-2157-4D2A-B560-9CA42BB1D605}||主材_不取费_甲供主材损耗费含税||2.2.2.4|否|100|新费用29|取费表|{C83708A3-AB6A-408F-8DC4-FF286D5F6560}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{7FEB0D34-5574-4B8C-9A2C-AD1662D276FF}||主材_不取费_乙供主材费不含税||2.2.2.5|否|100|新费用30|取费表|{C83708A3-AB6A-408F-8DC4-FF286D5F6560}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{1387CE58-2FB7-4758-80A2-4F1AE59B119A}||主材_不取费_乙供主材损耗费不含税||2.2.2.6|否|100|新费用31|取费表|{C83708A3-AB6A-408F-8DC4-FF286D5F6560}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{80B19A64-E375-4964-A84A-488DEEAA8F7B}||主材_不取费_运输重量||2.2.2.7|否|100|新费用32|取费表|{C83708A3-AB6A-408F-8DC4-FF286D5F6560}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{57609601-A4DB-4D54-9793-538788C8EBC8}||||2.3|否|100|设备|取费表|{F4A7F45A-2CCD-4290-95C1-DE15B41A4FA6}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{E5DE7E42-8E8B-4751-9683-E7D1C41B9D2E}||||2.3.1|否|100|普通|取费表|{57609601-A4DB-4D54-9793-538788C8EBC8}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{CAA56A51-61FE-473F-B852-080259177EA1}||设备_普通设备_甲供设备费不含税||2.3.1.1|否|100|新费用19|取费表|{E5DE7E42-8E8B-4751-9683-E7D1C41B9D2E}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{2E449476-784A-4F1F-9930-81184FC05B9E}||设备_普通设备_甲供设备费含税||2.3.1.2|否|100|新费用33|取费表|{E5DE7E42-8E8B-4751-9683-E7D1C41B9D2E}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{17DA2ADA-91A3-46C7-AE64-C42C451EB4FD}||设备_普通设备_甲供设备运杂费||2.3.1.3|否|100|新费用34|取费表|{E5DE7E42-8E8B-4751-9683-E7D1C41B9D2E}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{E9756933-639D-4793-BBFF-671B4128D7DD}||设备_普通设备_乙供设备费不含税||2.3.1.4|否|100|新费用35|取费表|{E5DE7E42-8E8B-4751-9683-E7D1C41B9D2E}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{569A0E33-8F66-42BC-A5F4-D2D1A6065918}||设备_普通设备_乙供设备运杂费||2.3.1.5|否|100|新费用36|取费表|{E5DE7E42-8E8B-4751-9683-E7D1C41B9D2E}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{868201A0-72FF-47A1-A6CF-9297594E800D}||设备_普通设备_乙供设备税金||2.3.1.6|否|100|新费用37|取费表|{E5DE7E42-8E8B-4751-9683-E7D1C41B9D2E}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{6CD8B2A1-0DCC-46D1-9B28-BDE1DD6EA884}||||2.3.2|否|100|主要|取费表|{57609601-A4DB-4D54-9793-538788C8EBC8}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{36124E58-690D-4666-B2B4-5858C5B4E048}||设备_主要设备_甲供设备费不含税||2.3.2.1|否|100|新费用38|取费表|{6CD8B2A1-0DCC-46D1-9B28-BDE1DD6EA884}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{0CFF5F28-C067-4652-9248-F2D35E8FC058}||设备_主要设备_甲供设备费含税||2.3.2.2|否|100|新费用39|取费表|{6CD8B2A1-0DCC-46D1-9B28-BDE1DD6EA884}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{4B074E2B-C3C0-4C45-AA42-3D35B88F287B}||设备_主要设备_甲供设备运杂费||2.3.2.3|否|100|新费用40|取费表|{6CD8B2A1-0DCC-46D1-9B28-BDE1DD6EA884}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{F6A94B03-A90C-402A-ACAB-2820F0F5DD12}||设备_主要设备_乙供设备费不含税||2.3.2.4|否|100|新费用41|取费表|{6CD8B2A1-0DCC-46D1-9B28-BDE1DD6EA884}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{BC11C4C8-26B7-433B-9BAC-A98F048FCCD0}||设备_主要设备_乙供设备运杂费||2.3.2.5|否|100|新费用42|取费表|{6CD8B2A1-0DCC-46D1-9B28-BDE1DD6EA884}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
|{3B946B5E-110C-4940-BD49-F84C22459D92}||设备_主要设备_乙供设备税金||2.3.2.6|否|100|新费用43|取费表|{6CD8B2A1-0DCC-46D1-9B28-BDE1DD6EA884}|{8C66E123-B33E-494C-8548-4E5BC456C81C}|
|
||||
@@ -0,0 +1,46 @@
|
||||
# 线路取费表(拆除)_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{671489B1-3069-4540-8885-A4653AB1D68F}|FFZ|||一|否|100|直接费|取费表||{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{34895027-670C-4027-B196-B7DD0486F08B}|FFZ1|||1|否|100|直接工程费|取费表|{671489B1-3069-4540-8885-A4653AB1D68F}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{813889E2-58DD-4F32-97EB-321706FA9C34}|RGF|取费定额人工费||1.1|否|100|人工费|取费表|{34895027-670C-4027-B196-B7DD0486F08B}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{C115D7B1-0488-4879-9375-3653DCF5F720}|CLF|取费定额乙供材料费不含税||1.2|否|100|材料费|取费表|{34895027-670C-4027-B196-B7DD0486F08B}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{360CF297-ECC9-409F-8AA6-21D1D4FEFBB5}|JXF|取费定额机械费||1.3|否|100|施工机械使用费|取费表|{34895027-670C-4027-B196-B7DD0486F08B}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{681327A0-6B95-4F4A-8DC8-5415826E953F}|FFZ2|||2|否|100|措施费|取费表|{671489B1-3069-4540-8885-A4653AB1D68F}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{DB8981A0-FE96-4D86-B022-3DA6E7FA1FCE}|DYF|取费定额人工费+取费定额机械费||2.1|否|1.75|冬雨季施工增加费|取费表|{681327A0-6B95-4F4A-8DC8-5415826E953F}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{F2387B8C-E709-4443-A136-9630AD483D0A}|SYF|取费定额人工费+取费定额机械费||2.2|否|0.65|施工工具用具使用费|取费表|{681327A0-6B95-4F4A-8DC8-5415826E953F}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{224DC3C6-A29D-4769-A80A-72CBD2B06FBF}|TDF|取费定额人工费+取费定额机械费||2.3|否|0|特殊地区施工增加费|取费表|{681327A0-6B95-4F4A-8DC8-5415826E953F}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{8635FAED-7F98-45C7-892A-ADEBD721DBD0}|LSF|取费定额人工费+取费定额机械费|独立的拆除工程可计取此项费,与其他工程同期实施的拆除工作不计取此项费用|2.4|否|0|临时设施费|取费表|{681327A0-6B95-4F4A-8DC8-5415826E953F}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{FC1AE4E1-5C62-410B-854C-03C181A4399D}|ZYF|取费定额人工费+取费定额机械费|独立的拆除工程可计取此项费,与其他工程同期实施的拆除工作不计取此项费用|2.5|否|0|施工机构迁移费|取费表|{681327A0-6B95-4F4A-8DC8-5415826E953F}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{83C0E923-F82E-4B4F-8000-2B43C7EF610B}|BZF|取费定额人工费+取费定额机械费||2.6|否|11.31|安全文明施工费|取费表|{681327A0-6B95-4F4A-8DC8-5415826E953F}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{D6840A86-4A8F-4385-A318-1C287A6BD78A}|FFJ|||二|否|100|间接费|取费表||{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{B5488195-1AF4-499D-90A1-7DF6CC93821D}|GF|||1|否|100|规费|取费表|{D6840A86-4A8F-4385-A318-1C287A6BD78A}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{33531376-EC7C-405D-A301-00F466B84CCD}|BZHF|取费定额人工费*1.05||1.1|否|2|社会保险费|取费表|{B5488195-1AF4-499D-90A1-7DF6CC93821D}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{A0CC6D22-F031-436E-B9A6-6863C42CF19F}|GJJ|取费定额人工费*1.05||1.2|否|2|住房公积金|取费表|{B5488195-1AF4-499D-90A1-7DF6CC93821D}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{6A13E7F9-018C-4CD8-B7C8-7B883AF55486}|GLF|取费定额人工费+取费定额机械费||2|否|17.13|企业管理费|取费表|{D6840A86-4A8F-4385-A318-1C287A6BD78A}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{B31A2F7E-81E9-4F8A-A5B2-DB434834D726}|FFR|取费定额人工费+取费定额机械费||三|否|5.24|利润|取费表||{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{11573E7B-EDF3-4D90-B232-EBC01F7829E2}|JC|||四|否|100|编制基准期价差|取费表||{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{9569B2B2-35C3-4ACC-A38A-B5392F9D3536}|RJC|人工价差||1|否|100|人工价差|取费表|{11573E7B-EDF3-4D90-B232-EBC01F7829E2}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{BE8609FF-EE14-4C77-AE90-052F935E4ED2}|CJC|乙供材料价差不含税||2|否|100|材料价差|取费表|{11573E7B-EDF3-4D90-B232-EBC01F7829E2}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{AB75B0DE-89D4-4234-AE2F-9D167B0E5C01}|JJC|机械价差||3|否|100|机械价差|取费表|{11573E7B-EDF3-4D90-B232-EBC01F7829E2}|{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{098FBD97-2A3D-4CBB-B143-474B78A2B86E}|FFS|FFZ+FFJ+FFR+JC+不取费定额费不含税||五|否|9|税金|取费表||{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
|{74E7A256-2564-49FE-8251-357AED61E082}|HJ|FFZ+FFJ+FFR+FFS+JC+一笔性费用+不取费定额费不含税||六|否|100|合计|取费表||{0A3B35A0-1B83-4A73-8677-3A436225DCCE}|
|
||||
@@ -0,0 +1,217 @@
|
||||
# 工程属性
|
||||
备注:工程属性表是用于存储整个工程的重要属性,访问该表都是为了通过属性名查找属性值。通常属性值有工程信息、工程属性、技经参数,表中包含工程总投资、工程总费用,工程主要费用,工程技经参数等。查询示例: SELECT Value FROM ProjectProperties WHERE Name = 'findname'。
|
||||
- 字段名称:名称
|
||||
- 字段名称:值
|
||||
- 备注:属性值,值、变量值、参数值、数值
|
||||
|
||||
|名称|值|
|
||||
|---|---|
|
||||
|设置线材工地运输计算方式|按实际用量计算|
|
||||
|材料调差系数|-0.95|
|
||||
|拆除安装材料按系数调差|1|
|
||||
|甲供材料损耗是否计入甲供材料费|-1|
|
||||
|计税方式|增值税|
|
||||
|地形调整及跳跃施工计算顺序|0|
|
||||
|是否自动计算凿桩头总量|是|
|
||||
|脚手架材料费系数|0.5|
|
||||
|是否首次统计工程量||
|
||||
|云端同步|False|
|
||||
|线路清单组件库|线路组件库(2018版).zjzjk|
|
||||
|固定综合单价模式||
|
||||
|总价万元|77469835.590045|
|
||||
|建筑工程按系数调差|0|
|
||||
|QtyID|21211|
|
||||
|发布版工程量清单||
|
||||
|材机是否按系数调差|1|
|
||||
|材机界面是否只显示新增资源|FALSE|
|
||||
|工程唯一标识码|{2FD2000A-C003-4573-8605-88C7B94EFA0F}|
|
||||
|计价方式|定额计价|
|
||||
|升级历史|1.2.0.111;1.3.0.65;1.3.3.4;1.4.0.72;1.4.1.61;1.4.2.14;1.5.0.6;1.5.1.112;1.5.2.7;1.6.0.73;1.6.1.67;2.0.0.98;2.0.1.6;2.1.0.61;2.1.0.175;2.2.1.2;2.3.0.83;2.3.1.5;2.3.4.3;2.4.0.124;2.4.1.4;2.4.3.3;2.4.4.5;2.5.0.155;2.5.1.14;2.6.0.218;2.6.2.0;2.6.3.0;2.7.0.0;2.8.0.0;3.0.0.0;3.0.1.0;3.1.0.0;3.1.1.0;3.1.2.0;3.1.2.0;|
|
||||
|配置选项|DL/T 54xx导则|
|
||||
|工程税率|9|
|
||||
|取费表显示级别|项目划分级别显示|
|
||||
|投标人||
|
||||
|是否第一次打开工程||
|
||||
|安装人工按系数调差|1|
|
||||
|是否按单位控制工程量精度|否|
|
||||
|安装材料按系数调差|1|
|
||||
|工程阶段||
|
||||
|脚手架费率|5|
|
||||
|市场价唯一|是|
|
||||
|耐张、转角塔导线挂线是否计算综合地形增加费|0|
|
||||
|地方规范||
|
||||
|默认自定义拆除定额库|自定义拆除定额库|
|
||||
|项目类型|架空输电线路工程|
|
||||
|工程文件预览信息|●工程名称:架线南网●项目划分:架空输电线路工程●工程阶段:可行性研究投资估算●地区类型:Ⅰ类●工程所在地:上海●执行规范:南网规约2018年版●工程版本:3.1.2.0●升级历史:1.2.0.111;1.3.0.65;1.3.3.4;1.4.0.72;1.4.1.61;1.4.2.14;1.5.0.6;1.5.1.112;1.5.2.7;1.6.0.73;1.6.1.67;2.0.0.98;2.0.1.6;2.1.0.61;2.1.0.175;2.2.1.2;2.3.0.83;2.3.1.5;2.3.4.3;2.4.0.124;2.4.1.4;2.4.3.3;2.4.4.5;2.5.0.155;2.5.1.14;2.6.0.218;2.6.2.0;2.6.3.0;2.7.0.0;2.8.0.0;3.0.0.0;3.0.1.0;3.1.0.0;3.1.1.0;3.1.2.0;3.1.2.0;●加密属性:|
|
||||
|甲供材料计入综合单价||
|
||||
|工程所在地|上海|
|
||||
|岩石灌浆基础超灌量|8|
|
||||
|阶段类型|概预算|
|
||||
|评审费_架线长度||
|
||||
|余土外运量|583624.490963|
|
||||
|评审费_回路类型||
|
||||
|脚手架人工费系数|0.4|
|
||||
|是否开放组件统计|是|
|
||||
|工程总投资|71503585.3336|
|
||||
|清单规范|2014版|
|
||||
|灌注桩超灌量|17|
|
||||
|线路定额统计规则库|线路定额统计规则(2018版).bwgzk6|
|
||||
|物料增值税率|13|
|
||||
|工程创建模板|南网规约|
|
||||
|国网14升21||
|
||||
|编制单位|qwe|
|
||||
|定额价目本|2006|
|
||||
|加密属性||
|
||||
|费用对比类型||
|
||||
|默认清单组价方式||
|
||||
|甲供材料是否计取税金||
|
||||
|导入发布版工程量清单||
|
||||
|机械调差系数|-0.95|
|
||||
|拆除安装工程默认定额库|拆除预算 第三册 架空线路工程|
|
||||
|建筑项目划分代码前缀|BT|
|
||||
|脚手架计算基数|人工费|
|
||||
|配合比拆分||
|
||||
|报表类型|预算报表|
|
||||
|泥沼地形比例|0|
|
||||
|平地地形比例|0|
|
||||
|BCL版本|3.1.0|
|
||||
|材料单公里用量计算规则|按线路亘长计算|
|
||||
|工程按系数调差|1|
|
||||
|专业扩展类型||
|
||||
|工程编号|qwe|
|
||||
|工程改造性质|新建|
|
||||
|是否组合件库||
|
||||
|基本预备费费率|2|
|
||||
|工程默认人材机库||
|
||||
|是否设置岩石坑排水||
|
||||
|发布版本|0|
|
||||
|专业类型|送电|
|
||||
|相同清单合并|是(清单属性及工程量一致)|
|
||||
|拆除材料调差系数|9.89|
|
||||
|标准清单编码长度|3|
|
||||
|特殊地区|常规地区|
|
||||
|塔材代用部分是否计入主材费||
|
||||
|拆除安装人工按系数调差|1|
|
||||
|规划台数||
|
||||
|安装工程默认定额库|预算 第四册 架空输电线路工程(2018年版)|
|
||||
|线路工程安全文明施工费||
|
||||
|安装其他设备运杂费率||
|
||||
|默认自定义主材库|自定义材料库|
|
||||
|安装工程量是否首次统计工程量|否|
|
||||
|预算转清单||
|
||||
|工程有效性数据|Sz4OdABix8AovWI1BEEUBgBntq9R0RQwHUl8cQRnw8RTqRRBdQUVAwdkwbAppWU3Bw==|
|
||||
|物料价格联动|否|
|
||||
|评审费_电压等级||
|
||||
|拆除建筑人工按系数调差|1|
|
||||
|安装机械按系数调差|1|
|
||||
|拆除建筑材料按系数调差|0|
|
||||
|启用自定义安全文明施工费||
|
||||
|建筑工程默认定额库|预算 第五册 电缆输电线路工程(2018年版)|
|
||||
|组件参数汇总错误||
|
||||
|工程只读密码||
|
||||
|打开工程是否需要刷新招标人信息||
|
||||
|默认自定义设备库|自定义设备库|
|
||||
|工程调差文件|调差系数文件〔2020年14号文〕|
|
||||
|监理费计算依据|预规(2018版)|
|
||||
|工程构成类型||
|
||||
|山地地形比例|0|
|
||||
|塔基占地面积|4218.965188|
|
||||
|高山地形比例|0|
|
||||
|工资津贴补差|0.89|
|
||||
|安装工程默认清单库|送电线路清单库(2014)|
|
||||
|工程默认主材库|装置性材料预算价2018|
|
||||
|录入工程量标记招||
|
||||
|工程名称|架线南网|
|
||||
|组价方式|综合单价|
|
||||
|工程深度||
|
||||
|工程造价咨询法定代表人或其授权人||
|
||||
|措施规费按清单级取费|1|
|
||||
|编制人|qwe|
|
||||
|是否为特高压工程||
|
||||
|组合件模式||
|
||||
|安装工程默认规则库|线路典型清单库|
|
||||
|工程总投资(万元)|81579073.299588|
|
||||
|塔材以大代小|3|
|
||||
|商品砼预算价||
|
||||
|工程默认设备库||
|
||||
|建筑工程默认清单库||
|
||||
|建筑人工按系数调差|1|
|
||||
|区域类型|国网清单工程|
|
||||
|表头设置|估算|
|
||||
|工程模式||
|
||||
|钻孔爆扩基础超灌量|7|
|
||||
|所区占地面积||
|
||||
|项目划分面板数据加载||
|
||||
|插件名称|南网规约插件|
|
||||
|建筑工程默认规则库||
|
||||
|架线长度|5|
|
||||
|默认自定义定额库|自定义定额库|
|
||||
|人工调差系数|4.05|
|
||||
|工程地址|qwe|
|
||||
|是否生成数据|0|
|
||||
|调差系数设置默认地区类型|Ⅰ类 地区|
|
||||
|地方清单规范||
|
||||
|拆除机械调差系数|9.89|
|
||||
|本期单台容量||
|
||||
|工程默认调试库||
|
||||
|塔材代用部分是否自动计算安装费|0|
|
||||
|隐藏中标数据||
|
||||
|安装项目划分代码前缀|BA|
|
||||
|空表显示状态|显示空表|
|
||||
|工程建筑面积||
|
||||
|线路清单统计规则库|线路清单统计规则(2014版清单规范).bwqdk6|
|
||||
|招标控制价导造价接口||
|
||||
|默认自定义清单库|自定义清单库(2014)|
|
||||
|本期台数||
|
||||
|标段||
|
||||
|中介机构法定(授权)代表人||
|
||||
|SID|5100|
|
||||
|丘陵地形比例|0|
|
||||
|架线合并方案预算类型||
|
||||
|拆除安装机械按系数调差|1|
|
||||
|编制时间|2020-10-9|
|
||||
|工程密码||
|
||||
|执行规范|南网规约2018年版|
|
||||
|脚手架机械费系数|0.1|
|
||||
|拆除建筑机械按系数调差|0|
|
||||
|预算类型|可行性研究投资估算|
|
||||
|工程描述||
|
||||
|建筑消材应用调差范围|FALSE|
|
||||
|关联造价工程id||
|
||||
|招标人||
|
||||
|现浇护壁超灌量|17|
|
||||
|脚手架人工工日系数|0.4|
|
||||
|规划单台容量||
|
||||
|拆除工程调差文件|2024年上半年调差系数文件(28号文)|
|
||||
|住房公积金费率|2|
|
||||
|不同土质定额归属不同清单|是|
|
||||
|工程版本|3.1.2.4|
|
||||
|默认组件库|线路组件库(2014版清单规范)|
|
||||
|一笔性施工企业配合调试费|0|
|
||||
|峻岭地形比例|0|
|
||||
|软件名称|博微电力建设计价通软件|
|
||||
|电压等级|35kV|
|
||||
|冷却方式||
|
||||
|资质证书|qwe|
|
||||
|本期容量||
|
||||
|掏挖基础超灌量|7|
|
||||
|地区类型|Ⅰ类|
|
||||
|招标法定代表人或其授权人||
|
||||
|编辑时间||
|
||||
|工程类型|可行性研究投资估算|
|
||||
|定额版本||
|
||||
|架线类型|一般线路|
|
||||
|社会保险费费率|2|
|
||||
|工程历史版本列表||
|
||||
|2.3.4升级工程||
|
||||
|显示全部数据||
|
||||
|线路清理项目安全文明施工费||
|
||||
|机械台班拆分||
|
||||
|线路项目划分代码前缀|BA|
|
||||
|工程造价咨询人||
|
||||
|只读||
|
||||
|拆除人工调差系数|11.03|
|
||||
|拆分材料人工是否调差|是|
|
||||
|导入工程量清单||
|
||||
|是否重算费用||
|
||||
|拆除工程材机按系数调差|0|
|
||||
@@ -0,0 +1,80 @@
|
||||
# 总算表
|
||||
备注:总算表也被称为“工程总费用”、“工程费用”。其中包含本地工程、辅助设施工程、编制基准期价差、设备购置费、其他费用、基本预备费、特殊费用、工程静态投资、动态费用、价差预备费、建设期贷款利息、工程动态投资、可抵扣增值税额。查询示例: SELECT Amount FROM TotalCalculateTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:relTbId
|
||||
- 字段名称:parentId
|
||||
- 字段名称:序号
|
||||
- 备注:序号
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:金额_单位投资,合计投资金额
|
||||
- 字段名称:取费基数
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:金额
|
||||
- 备注:金额_设备费,设备价格,设备金额
|
||||
- 字段名称:编码
|
||||
- 备注:WBS编号,WBS编码
|
||||
- 字段名称:服务内容
|
||||
- 字段名称:费用归属
|
||||
- 字段名称:输出
|
||||
- 字段名称:不可竞争费用
|
||||
- 字段名称:编制依据
|
||||
- 字段名称:备注
|
||||
- 字段名称:表一显示
|
||||
- 字段名称:建筑费
|
||||
- 字段名称:安装费
|
||||
- 备注:安装金额,安装价格,金额_安装费
|
||||
- 字段名称:设备费
|
||||
- 备注:金额_设备费,设备价格,设备金额
|
||||
- 字段名称:其他费
|
||||
- 备注:其他费用金额,其他费用价格,金额_其他费
|
||||
- 字段名称:合计费
|
||||
- 备注:金额,价格
|
||||
- 字段名称:占总计
|
||||
- 备注:总体金额,总的金额,金额_占总计
|
||||
- 字段名称:单位投资
|
||||
- 备注:金额_单位投资,合计投资金额
|
||||
- 字段名称:建安合计费
|
||||
- 字段名称:金额增减
|
||||
|
||||
|_id|nodeType|relTbId|parentId|序号|名称|代码|单位|取费基数|费率|金额|编码|服务内容|费用归属|输出|不可竞争费用|编制依据|备注|表一显示|建筑费|安装费|设备费|其他费|合计费|占总计|单位投资|建安合计费|金额增减|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|31ywrqpe70g0|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||一|架空输电线路本体工程|BTGC|%||100|55105688268.517624|2131243|||是|否|||否|0|55105688268.517624|0|0|55105688268.517624|7.706703|11021137653.703526|0|55105688268.517624|
|
||||
|31ywrqpgowsg|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqpe70g0|(一)|一般线路本体工程|XLBT|%||100|55105688268.517624|wre34|||是|否|||否|0|55105688268.517624|0|0|55105688268.517624|7.706703|11021137653.703526|0|55105688268.517624|
|
||||
|31ywrqpgowsh|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||二|辅助设施工程|FZSS|%||100|403152254301.795654|234|||是|否|||否|0|0|0|403152254301.795654|403152254301.795654|56.382103|80630450860.359131|0|403152254301.795654|
|
||||
|31ywrqpj6t4w|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|||小计|HJ|元||100|458257942570.313293|324|||是|否|||否|0|55105688268.517624|0|403152254301.795654|458257942570.313293|64.088806|91651588514.062653|0|458257942570.313293|
|
||||
|31ywrqplophc|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||三|编制基准期价差|JC|元||100|29246752707.118019|31840000000|||是|否|||否|0|29246752707.118019|0|0|29246752707.118019|4.09025|5849350541.423603|0|29246752707.118019|
|
||||
|31ywrqplophd|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||四|设备购置费|SBGZF|元||100|2567934636.357451|318A0000000|||是|否|||否|0|0|2567934636.357451|0|2567934636.357451|0.359134|513586927.27149|0|2567934636.357451|
|
||||
|31ywrqpo6lts|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||五|其他费用|QTFY|元||100|210942912572.869415|31830000000|||是|否|||否|0|0|0|210942912572.869415|210942912572.869415|29.501026|1231231|0|210942912572.869415|
|
||||
|31ywrqpqoi68|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqpo6lts|1|其中:建设场地征用及清理费||%||100|16831284.228711|23|||是|否|||否|0|0|0|16831284.228711|16831284.228711|0|123|0|16831284.228711|
|
||||
|31ywrqpqoi69|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqpo6lts|2|其中:工程建设检测费||||100|185575370.146398||||否|否|||否|0|0|0|185575370.146398|185575370.146398|0|0|0|185575370.146398|
|
||||
|31ywrqpt6eio|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqpo6lts|3|其中:特种设备安全监测费||||100|0||||否|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ywrqpvoav4|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqpo6lts|4|其中:水土保持监测及验收费||||100|0||||否|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ywrqpvoav5|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||六|基本预备费|JBYBF|%||100|14020310849.733164|318D0000000|||是|否|||否|0|0|0|14020310849.733164|14020310849.733164|1.960784|2804062169.946633|0|14020310849.733164|
|
||||
|31ywrqpy677k|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||七|特殊项目|TSXM|%||100|0|31850000000|||是|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ywrqpy677l|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|||工程静态投资|JTTZ|元||100|715035853336.391357|31860000000|||是|否|||否|0|84352440975.635651|2567934636.357451|628115477724.398193|715035853336.391357|100|2312312|0|715035853336.391357|
|
||||
|31ywrqq0o3k0|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||八|动态费用|DTFY|元||100|61246155757.175179|31870000000|||是|否|||否|0|0|0|61246155757.175179|61246155757.175179|0|0|0|61246155757.175179|
|
||||
|31ywrqq35zwg|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq0o3k0|(一)|价差预备费|JCYBF|元||100|22731130869.665558|31871000000|||是|否|||否|0|0|0|22731130869.665558|22731130869.665558|0|0|0|22731130869.665558|
|
||||
|31ywrqq35zwh|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq0o3k0|(二)|建设期贷款利息|DKLX|元||100|38515024887.509613|31872000000|||是|否|||否|0|0|0|38515024887.509613|38515024887.509613|0|0|0|38515024887.509613|
|
||||
|31ywrqq5nw8w|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|||工程动态投资|DTTZ|元||100|776282009093.566406|318C0000000|||是|否|||否|0|84352440975.635651|2567934636.357451|689361633481.573364|776282009093.566406|0|155256401818.713287|0|776282009093.566406|
|
||||
|31ywrqq5nw8x|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|||其中:可抵扣增值税额|ZZS|%||100|20069645492.28894|318G0000000|||是|否|||否|0|18713773821.487453|321303868.972724|1034567801.828762|20069645492.28894|0|0|0|20069645492.28894|
|
||||
|31ywrqq85slc|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}||12|常用变量||||100|0||||否|否|||否|0|782331434488.350952|0|0|0|0|0|0|0|
|
||||
|31ywrqqanoxs|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.1|本体工程费||||100|0||||否|否|||否|0|55105688268.517624|0|0|0|0|0|0|0|
|
||||
|31ywrqqd5la8|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.2|设备购置费1||||100|0||||否|否|||否|0|2567934636.357451|0|0|0|0|0|0|0|
|
||||
|31ywrqqd5la9|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.3|常用变量:建设期贷款利息||||100|0||||否|否|||否|0|38515024887.509613|0|0|0|0|0|0|0|
|
||||
|31ywrqqfnhmo|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.4|编制基准期价差1||||100|0||||否|否|||否|0|29246752707.118019|0|0|0|0|0|0|0|
|
||||
|31ywrqqfnhmp|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.5|余物清理费||||100|0||||否|否|||否|0|90736.228711|0|0|0|0|0|0|0|
|
||||
|31ywrqqi5dz4|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.6|常用变量:价差预备费||||100|0||||否|否|||否|0|22731130869.665558|0|0|0|0|0|0|0|
|
||||
|31ywrqqi5dz5|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.7|常用变量:其他费用||||100|0||||否|否|||否|0|210942912572.869415|0|0|0|0|0|0|0|
|
||||
|31ywrqqknabk|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.8|辅助费用||||100|0||||否|否|||否|0|403152254301.795654|0|0|0|0|0|0|0|
|
||||
|31ywrqqn56o0|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.9|工程税率||||100|0||||否|否|||否|0|9|0|0|0|0|0|0|0|
|
||||
|31ywrqqpn30g|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.10|基本预备费费率||||100|0||||否|否|||否|0|2|0|0|0|0|0|0|0|
|
||||
|31ywrqqs4zcw|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.11|本体工程可抵扣增值税||||100|0||||否|否|||否|0|18713773821.487453|0|0|0|0|0|0|0|
|
||||
|31ywrqqs4zcx|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.12|设备可抵扣增值税||||100|0||||否|否|||否|0|321303868.972724|0|0|0|0|0|0|0|
|
||||
|31ywrqqumvpc|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.13|其他费用可抵扣增值税||||100|0||||否|否|||否|0|1034567801.828762|0|0|0|0|0|0|0|
|
||||
|31ywrqqumvpd|总算表|{64B460A2-03EB-4408-8CA0-374CA991DF43}|31ywrqq85slc|12.14|线路亘长||||100|0||||否|否|||否|0|5|0|0|0|0|0|0|0|
|
||||
@@ -0,0 +1,68 @@
|
||||
# 项目划分_余物清理
|
||||
备注:项目划分表是用于存储工程项目划分树状数据。内部包含安装工程项目划分,建筑工程项目划分,线路项目划分,工程分部分项。查询示例: SELECT Sum_Price FROM ProjectDivision WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:专业类型
|
||||
- 备注:专业类型
|
||||
- 字段名称:人工调差系数
|
||||
- 备注:拆除人工调差系数
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:单位
|
||||
- 字段名称:取费表
|
||||
- 备注:取费表
|
||||
- 字段名称:合价
|
||||
- 备注:合价,合计
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,名称
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:项目序号,序号,序列号
|
||||
- 字段名称:拆除人工调差系数
|
||||
- 备注:拆除人工调差系数
|
||||
- 字段名称:拆除机械调差系数
|
||||
- 备注:拆除机械调差系数
|
||||
- 字段名称:拆除材料调差系数
|
||||
- 备注:拆除材料调差系数
|
||||
- 字段名称:数量
|
||||
- 备注:数目,数量,个数
|
||||
- 字段名称:机械调差系数
|
||||
- 备注:拆除机械调差系数
|
||||
- 字段名称:材料调差系数
|
||||
- 备注:拆除材料调差系数
|
||||
- 字段名称:编码
|
||||
- 备注:译码,编码
|
||||
- 字段名称:计算式
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用编码
|
||||
- 字段名称:路径
|
||||
- 备注:路径,项目全路径
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|专业类型|人工调差系数|代码|单位|取费表|合价|名称|备注|序号|拆除人工调差系数|拆除机械调差系数|拆除材料调差系数|数量|机械调差系数|材料调差系数|编码|计算式|费率|费用编码|路径|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{B562B2D7-2C6D-4A15-BF4F-CC58EA00EA9A}|余物清理|0||||25411.279078|建筑工程||1|0|0|0||0|0|01||0||建筑工程|项目划分||{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{B5FA19AC-8E12-4E61-AB42-DC422074DDC7}|余物清理|0|||线路取费表(余物清理)|8443.759693|一般砖木结构||1.1|0|0|0||0|0|0101||10||建筑工程/一般砖木结构|项目划分|{B562B2D7-2C6D-4A15-BF4F-CC58EA00EA9A}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{6B94B24B-5CF9-4357-B6C4-46F001C329C2}|余物清理|0||||16967.519385|混合结构||1.2|0|0|0||0|0|0102||20||建筑工程/混合结构|项目划分|{B562B2D7-2C6D-4A15-BF4F-CC58EA00EA9A}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{8ED2CCC2-89B9-443D-9D80-34C5F395495D}|余物清理|0|W1|kW.h|线路取费表(余物清理)(1)|16967.519385|新增项目名称||1.2.1|0|0|0|12|0|0|010201|12|20||建筑工程/混合结构/新增项目名称|项目划分|{6B94B24B-5CF9-4357-B6C4-46F001C329C2}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{3E734273-05F0-464F-9F50-39BE60D1372B}|余物清理|0||||0|混凝土及钢筋混凝土结构||1.3|0|0|0||0|0|0103||0||建筑工程/混凝土及钢筋混凝土结构|项目划分|{B562B2D7-2C6D-4A15-BF4F-CC58EA00EA9A}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{033FC9AC-4E41-427E-9955-84CF77645793}|余物清理|0|||线路取费表(余物清理)|0|(1)有条件爆破的||1.3.1|0|0|0||0|0|010301||20||建筑工程/混凝土及钢筋混凝土结构/(1)有条件爆破的|项目划分|{3E734273-05F0-464F-9F50-39BE60D1372B}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{8F59E581-3BA2-4BE8-8BB7-8A3DF6DD4B28}|余物清理|0|||线路取费表(余物清理)|0|(2)无条件爆破的|费率在30~50区间|1.3.2|0|0|0||0|0|010302||0||建筑工程/混凝土及钢筋混凝土结构/(2)无条件爆破的|项目划分|{3E734273-05F0-464F-9F50-39BE60D1372B}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{8FC91011-52C1-4D5E-9F32-E1E38956A945}|余物清理|0|||线路取费表(余物清理)|0|临时简易建筑||1.4|0|0|0||0|0|0104||8||建筑工程/临时简易建筑|项目划分|{B562B2D7-2C6D-4A15-BF4F-CC58EA00EA9A}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{A9E59E43-8152-4DD7-B28F-C4FA2DAE52F7}|余物清理|0||||0|金属结构||1.5|0|0|0||0|0|0105||0||建筑工程/金属结构|项目划分|{B562B2D7-2C6D-4A15-BF4F-CC58EA00EA9A}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{8C214973-0FA1-46CC-9515-D593F82087E9}|余物清理|0|||线路取费表(余物清理)|0|(1)拆除后能利用||1.5.1|0|0|0||0|0|010501||55||建筑工程/金属结构/(1)拆除后能利用|项目划分|{A9E59E43-8152-4DD7-B28F-C4FA2DAE52F7}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{2E846DB0-2E2F-47DA-8577-D6C61E24C2D9}|余物清理|0|||线路取费表(余物清理)|0|(2)拆除后不能利用||1.5.2|0|0|0||0|0|010502||38||建筑工程/金属结构/(2)拆除后不能利用|项目划分|{A9E59E43-8152-4DD7-B28F-C4FA2DAE52F7}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{7D31B891-834D-40D4-BBCF-ED5B5576AE7D}|余物清理|0|||线路取费表(余物清理)|0|新增项目名称||1.6|0|0|0||0|0|0106||0||建筑工程/新增项目名称|项目划分|{B562B2D7-2C6D-4A15-BF4F-CC58EA00EA9A}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{1214A9EF-CF72-40BF-B565-F6BA007EAE44}|余物清理|0||||65324.949633|安装工程||2|0|0|0||0|0|02||0||安装工程|项目划分||{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{CACFA684-07BD-4C73-9029-8E6BCCBBD044}|余物清理|0|||线路取费表(余物清理)(1)|38176.918617|金属结构及工业管道||2.1|0|0|0||0|0|0201||45||安装工程/金属结构及工业管道|项目划分|{1214A9EF-CF72-40BF-B565-F6BA007EAE44}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{C408C657-9B4E-4519-BF3C-DAE9A9AA3B18}|余物清理|0||||27148.031016|机电设备||2.2|0|0|0||0|0|0202||32||安装工程/机电设备|项目划分|{1214A9EF-CF72-40BF-B565-F6BA007EAE44}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{9490E5FB-D00A-4BFE-AECC-7DF5E1D5C0A8}|余物清理|0||km|线路取费表(余物清理)(1)|27148.031016|新增项目名称||2.2.1|0|0|0|2|0|0|020201|2|32||安装工程/机电设备/新增项目名称|项目划分|{C408C657-9B4E-4519-BF3C-DAE9A9AA3B18}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{7E874CEB-D21D-4300-ACEA-CF993E269E77}|余物清理|0||||0|输电线路及通信线路||2.3|0|0|0||0|0|0203||0||安装工程/输电线路及通信线路|项目划分|{1214A9EF-CF72-40BF-B565-F6BA007EAE44}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{DD1578AD-E370-40A6-8659-09F8E7B2E948}|余物清理|0|||线路取费表(余物清理)|0|(1)拆除后能利用||2.3.1|0|0|0||0|0|020301||62||安装工程/输电线路及通信线路/(1)拆除后能利用|项目划分|{7E874CEB-D21D-4300-ACEA-CF993E269E77}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{120A2784-65E6-477A-BF99-F76A4E0048ED}|余物清理|0|||线路取费表(余物清理)|0|(2)拆除后不能利用||2.3.2|0|0|0||0|0|020302||35||安装工程/输电线路及通信线路/(2)拆除后不能利用|项目划分|{7E874CEB-D21D-4300-ACEA-CF993E269E77}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
|{586F768E-99D7-4A72-A453-C2471841C91F}|余物清理|0|||线路取费表(余物清理)|0|新增项目名称||2.4|0|0|0||0|0|0204||0||安装工程/新增项目名称|项目划分|{1214A9EF-CF72-40BF-B565-F6BA007EAE44}|{4C10E00C-A42E-47DA-8877-C2698F5B351B}|
|
||||
@@ -0,0 +1,96 @@
|
||||
# 项目划分_线路
|
||||
备注:项目划分表是用于存储工程项目划分树状数据。内部包含安装工程项目划分,建筑工程项目划分,线路项目划分,工程分部分项。查询示例: SELECT Sum_Price FROM ProjectDivision WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:专业类型
|
||||
- 备注:专业类型
|
||||
- 字段名称:人工调差系数
|
||||
- 备注:拆除人工调差系数
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:单位
|
||||
- 字段名称:取费表
|
||||
- 备注:取费表
|
||||
- 字段名称:合价
|
||||
- 备注:合价,合计
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,名称
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:项目序号,序号,序列号
|
||||
- 字段名称:拆除人工调差系数
|
||||
- 备注:拆除人工调差系数
|
||||
- 字段名称:拆除机械调差系数
|
||||
- 备注:拆除机械调差系数
|
||||
- 字段名称:拆除材料调差系数
|
||||
- 备注:拆除材料调差系数
|
||||
- 字段名称:数量
|
||||
- 备注:数目,数量,个数
|
||||
- 字段名称:机械调差系数
|
||||
- 备注:拆除机械调差系数
|
||||
- 字段名称:材料调差系数
|
||||
- 备注:拆除材料调差系数
|
||||
- 字段名称:编码
|
||||
- 备注:译码,编码
|
||||
- 字段名称:计算式
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用编码
|
||||
- 字段名称:路径
|
||||
- 备注:路径,项目全路径
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|专业类型|人工调差系数|代码|单位|取费表|合价|名称|备注|序号|拆除人工调差系数|拆除机械调差系数|拆除材料调差系数|数量|机械调差系数|材料调差系数|编码|计算式|费率|费用编码|路径|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|线路|4.05|BTGC|元/km||55105688268.517624|一般线路本体工程||一|11.03|9.89|9.89||-0.95|-0.95|||0|Y1820000000|一般线路本体工程|项目划分||{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{4CC653B1-9AB2-4452-82C2-08194128B670}|线路|4.05|JCGC|元/m³||49051649642.966728|基础工程||1|11.03|9.89|9.89|3|-0.95|-0.95||3|0|Y1821000000|一般线路本体工程/基础工程|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{CB397026-AA60-41AB-AA61-A4FA19B4820B}|线路|4.05||km|线路取费表|15878388617.141884|基础工程材料工地运输||1.1|11.03|9.89|9.89|3|-0.95|-0.95||3|0|Y1821100000|一般线路本体工程/基础工程/基础工程材料工地运输|项目划分|{4CC653B1-9AB2-4452-82C2-08194128B670}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{648EDE70-DCAC-4A48-99BD-17B6AE7EB9F1}|线路|4.05|||线路取费表(调试工程)aa|32872843180.742939|基础土石方工程||1.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1821200000|一般线路本体工程/基础工程/基础土石方工程|项目划分|{4CC653B1-9AB2-4452-82C2-08194128B670}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{B58BE3AE-DC2D-4731-B5BB-9C703081C3F3}|线路|4.05||kW.h||299086175.656503|基础砌筑||1.3|11.03|9.89|9.89|3|-0.95|-0.95||3|0|Y1821300000|一般线路本体工程/基础工程/基础砌筑|项目划分|{4CC653B1-9AB2-4452-82C2-08194128B670}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{4DB0D97A-7C4B-4A05-8C65-3BE37D206FCE}|线路|4.05|||线路取费表|40567.263948|预制基础||1.3.1|11.03|9.89|9.89||-0.95|-0.95|||0|Y1821301000|一般线路本体工程/基础工程/基础砌筑/预制基础|项目划分|{B58BE3AE-DC2D-4731-B5BB-9C703081C3F3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{4DA9BF14-1718-4C43-B6C8-062E69E78EC4}|线路|4.05||工日|大型土石方取费表|236394313.672133|现浇基础||1.3.2|11.03|9.89|9.89|3|-0.95|-0.95||3|0|Y1821302000|一般线路本体工程/基础工程/基础砌筑/现浇基础|项目划分|{B58BE3AE-DC2D-4731-B5BB-9C703081C3F3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{12640B7F-A48C-4365-BCC8-45E13AA8DCF9}|线路|4.05|||线路取费表|43466660.054439|灌注桩基础||1.3.3|11.03|9.89|9.89||-0.95|-0.95|||0|Y1821303000|一般线路本体工程/基础工程/基础砌筑/灌注桩基础|项目划分|{B58BE3AE-DC2D-4731-B5BB-9C703081C3F3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{3083FEBE-7B05-46B2-A2C7-01B00809B2D5}|线路|4.05|||线路取费表|15344967.900295|锚杆基础|综合地形增加费|1.3.4|11.03|9.89|9.89||-0.95|-0.95|||0|Y1821304000|一般线路本体工程/基础工程/基础砌筑/锚杆基础|项目划分|{B58BE3AE-DC2D-4731-B5BB-9C703081C3F3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{EB0DF736-2367-4142-A72E-2F9DF0E6D08D}|线路|4.05|||线路取费表|3839666.765688|其他基础||1.3.5|11.03|9.89|9.89||-0.95|-0.95|||0|Y1821305000|一般线路本体工程/基础工程/基础砌筑/其他基础|项目划分|{B58BE3AE-DC2D-4731-B5BB-9C703081C3F3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{DDFE825A-2FFE-4FB6-A949-211780B90F5A}|线路|4.05|||线路取费表|1331669.425409|基础防护||1.4|11.03|9.89|9.89||-0.95|-0.95|||0|Y1821400000|一般线路本体工程/基础工程/基础防护|项目划分|{4CC653B1-9AB2-4452-82C2-08194128B670}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{BE86FD67-2F31-4904-B277-32E55FF547E9}|线路|4.05|||线路取费表|0|地基处理||1.5|11.03|9.89|9.89||-0.95|-0.95|||0|Y1821500000|一般线路本体工程/基础工程/地基处理|项目划分|{4CC653B1-9AB2-4452-82C2-08194128B670}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{F02F91A2-A66B-46B3-8F4D-2C5148B94B4C}|线路|4.05||t|线路取费表|40620.619487|新增项目名称||2|11.03|9.89|9.89|3|-0.95|-0.95||3|0||一般线路本体工程/新增项目名称|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{1D83EABA-B0D9-403C-AE85-33A293EF198E}|线路|4.05|GTGC|元/t||220969744.905856|杆塔工程||3|11.03|9.89|9.89||-0.95|-0.95|||0|Y1822000000|一般线路本体工程/杆塔工程|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{69D6C707-742E-4A5A-BA63-8C6EAFF1AAD9}|线路|4.05||m³|线路取费表(调试工程)aa|218715838.819873|杆塔工程材料工地运输||3.1|11.03|9.89|9.89|32|-0.95|-0.95||32|0|Y1822100000|一般线路本体工程/杆塔工程/杆塔工程材料工地运输|项目划分|{1D83EABA-B0D9-403C-AE85-33A293EF198E}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{48A176DF-97A9-4670-A525-0FDEF2E32BC2}|线路|4.05||||2253906.085983|杆塔组立||3.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1822200000|一般线路本体工程/杆塔工程/杆塔组立|项目划分|{1D83EABA-B0D9-403C-AE85-33A293EF198E}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{38276E0A-6DC1-40DA-8374-FDC8C1D47650}|线路|4.05||g|大型土石方取费表|23686.405216|混凝土杆组立|12|3.2.1|11.03|9.89|9.89|2|-0.95|-0.95||2|0|Y1822201000|一般线路本体工程/杆塔工程/杆塔组立/混凝土杆组立|项目划分|{48A176DF-97A9-4670-A525-0FDEF2E32BC2}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{CABA2E98-ED97-456D-B9A4-0B3C068FB45E}|线路|4.05|||线路取费表|2230219.680767|铁塔、钢管杆组立||3.2.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1822202000|一般线路本体工程/杆塔工程/杆塔组立/铁塔、钢管杆组立|项目划分|{48A176DF-97A9-4670-A525-0FDEF2E32BC2}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{7A747F1A-78CE-4F89-8B20-C5F9448BA814}|线路|4.05|JDGC|元/基||121964.914965|接地工程||4|11.03|9.89|9.89||-0.95|-0.95|||0|Y1823000000|一般线路本体工程/接地工程|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{2A31D241-CBDE-4F85-AE67-7A7120308C53}|线路|4.05|||线路取费表|97182.716229|接地工程材料工地运输||4.1|11.03|9.89|9.89||-0.95|-0.95|||0|Y1823100000|一般线路本体工程/接地工程/接地工程材料工地运输|项目划分|{7A747F1A-78CE-4F89-8B20-C5F9448BA814}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{18ACAFE5-D0A9-4DDF-9AE7-5E8AA3E56690}|线路|4.05|||线路取费表|18199.265199|接地土石方||4.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1823200000|一般线路本体工程/接地工程/接地土石方|项目划分|{7A747F1A-78CE-4F89-8B20-C5F9448BA814}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{136AA0F5-BCF2-4933-BDF9-79E5866728EC}|线路|4.05|||线路取费表|6582.933537|接地安装||4.3|11.03|9.89|9.89||-0.95|-0.95|||0|Y1823300000|一般线路本体工程/接地工程/接地安装|项目划分|{7A747F1A-78CE-4F89-8B20-C5F9448BA814}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{A000AD2A-24D9-49BC-B3E0-0303E2CF6988}|线路|4.05|JXGC|元/km||4844399648.077858|架线工程||5|11.03|9.89|9.89||-0.95|-0.95|||0|Y1824000000|一般线路本体工程/架线工程|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{9CE13DFF-A7D7-4393-9E6F-B14F50670E31}|线路|4.05|||线路取费表|2088570123.240896|架线工程材料工地运输||5.1|11.03|9.89|9.89||-0.95|-0.95|||0|Y1824100000|一般线路本体工程/架线工程/架线工程材料工地运输|项目划分|{A000AD2A-24D9-49BC-B3E0-0303E2CF6988}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{BEFD4073-34E0-4CD1-BAE8-4A6AD42AE6E8}|线路|4.05|||线路取费表|2755648799.032277|导地线架设||5.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1824200000|一般线路本体工程/架线工程/导地线架设|项目划分|{A000AD2A-24D9-49BC-B3E0-0303E2CF6988}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{B1832D94-B27A-4EC2-9EFF-070243607C71}|线路|4.05|||线路取费表|150204.672365|导地线跨越架设||5.3|11.03|9.89|9.89||-0.95|-0.95|||0|Y1824300000|一般线路本体工程/架线工程/导地线跨越架设|项目划分|{A000AD2A-24D9-49BC-B3E0-0303E2CF6988}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{37A67A77-D2AD-4AE0-A434-81369416E8BC}|线路|4.05|||线路取费表|30521.132319|其他架线工程||5.4|11.03|9.89|9.89||-0.95|-0.95|||0|Y1824400000|一般线路本体工程/架线工程/其他架线工程|项目划分|{A000AD2A-24D9-49BC-B3E0-0303E2CF6988}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{15CED8B2-B4F5-411D-96C3-08DE6E778E89}|线路|4.05|FJAZ|元/基||987118056.00908|附件安装工程||6|11.03|9.89|9.89||-0.95|-0.95|||0|Y1825000000|一般线路本体工程/附件安装工程|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{C020DEA9-12CE-44D3-9F26-3D4430CE98DA}|线路|4.05|||线路取费表|984220884.021268|附件安装工程材料工地运输||6.1|11.03|9.89|9.89||-0.95|-0.95|||0|Y1825100000|一般线路本体工程/附件安装工程/附件安装工程材料工地运输|项目划分|{15CED8B2-B4F5-411D-96C3-08DE6E778E89}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{5BFDA942-AB13-4868-BB8C-61669ED4FDA0}|线路|4.05||||2897171.987812|绝缘子串及金具安装||6.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1825200000|一般线路本体工程/附件安装工程/绝缘子串及金具安装|项目划分|{15CED8B2-B4F5-411D-96C3-08DE6E778E89}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{4FB683E4-6D81-4605-9C36-C82A835186C6}|线路|4.05|||线路取费表|1645706.953768|耐张绝缘子串及金具安装||6.2.1|11.03|9.89|9.89||-0.95|-0.95|||0|Y1825201000|一般线路本体工程/附件安装工程/绝缘子串及金具安装/耐张绝缘子串及金具安装|项目划分|{5BFDA942-AB13-4868-BB8C-61669ED4FDA0}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{B19EEA86-4F92-4F81-BD40-AFACDDC2307F}|线路|4.05|||线路取费表|1251465.034044|悬垂绝缘子串及金具安装||6.2.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1825202000|一般线路本体工程/附件安装工程/绝缘子串及金具安装/悬垂绝缘子串及金具安装|项目划分|{5BFDA942-AB13-4868-BB8C-61669ED4FDA0}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{035EE3E1-09A8-4C52-AE7C-3DB6F74B3A55}|线路|4.05|FZGC|元/km(m³)||1046253.413524|辅助工程||7|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826000000|一般线路本体工程/辅助工程|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{580B87FF-E6D8-4333-9C8C-E7588ABE29F1}|线路|4.05|||线路取费表|325205.417877|尖峰、施工基面土石方工程||7.1|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826100000|一般线路本体工程/辅助工程/尖峰、施工基面土石方工程|项目划分|{035EE3E1-09A8-4C52-AE7C-3DB6F74B3A55}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{4D072EAA-BFAC-4094-A7E3-B33987033455}|线路|4.05||||709931.901393|护坡、挡土墙及排洪沟||7.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826200000|一般线路本体工程/辅助工程/护坡、挡土墙及排洪沟|项目划分|{035EE3E1-09A8-4C52-AE7C-3DB6F74B3A55}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{DF775FE5-9C9A-4667-BB5F-3B2E3BD04600}|线路|4.05|||线路取费表|0|护坡、挡土墙及排洪沟材料工地运输||7.2.1|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826201000|一般线路本体工程/辅助工程/护坡、挡土墙及排洪沟/护坡、挡土墙及排洪沟材料工地运输|项目划分|{4D072EAA-BFAC-4094-A7E3-B33987033455}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{A5915FEF-6831-44B6-9F24-E984779F4884}|线路|4.05|||线路取费表|0|护坡、挡土墙及排洪沟土石方工程||7.2.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826202000|一般线路本体工程/辅助工程/护坡、挡土墙及排洪沟/护坡、挡土墙及排洪沟土石方工程|项目划分|{4D072EAA-BFAC-4094-A7E3-B33987033455}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{77FD6CAC-D2BA-4BDB-9E25-2264FEA7E23E}|线路|4.05|||线路取费表|709931.901393|护坡、挡土墙及排洪沟砌筑||7.2.3|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826203000|一般线路本体工程/辅助工程/护坡、挡土墙及排洪沟/护坡、挡土墙及排洪沟砌筑|项目划分|{4D072EAA-BFAC-4094-A7E3-B33987033455}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{F4C2EF3B-1242-41DF-9189-AE4F2A037DE8}|线路|4.05||||0|基础永久性围堰||7.3|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826300000|一般线路本体工程/辅助工程/基础永久性围堰|项目划分|{035EE3E1-09A8-4C52-AE7C-3DB6F74B3A55}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{323AB7AE-60E8-44DF-9929-6C45325B02C2}|线路|4.05|||线路取费表|0|基础永久性围堰材料工地运输||7.3.1|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826301000|一般线路本体工程/辅助工程/基础永久性围堰/基础永久性围堰材料工地运输|项目划分|{F4C2EF3B-1242-41DF-9189-AE4F2A037DE8}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{3FEB5513-3399-4CBF-B660-E5D5D8C700DD}|线路|4.05|||线路取费表|0|基础永久性围堰土石方工程||7.3.2|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826302000|一般线路本体工程/辅助工程/基础永久性围堰/基础永久性围堰土石方工程|项目划分|{F4C2EF3B-1242-41DF-9189-AE4F2A037DE8}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{254143D7-57DF-43C2-88FD-2E928CD7404C}|线路|4.05|||线路取费表|0|基础永久性围堰砌筑||7.3.3|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826303000|一般线路本体工程/辅助工程/基础永久性围堰/基础永久性围堰砌筑|项目划分|{F4C2EF3B-1242-41DF-9189-AE4F2A037DE8}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{963579D2-02F0-44FC-9A52-CC4A4398593D}|线路|4.05|||线路取费表|0|索道站安装||7.4|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826400000|一般线路本体工程/辅助工程/索道站安装|项目划分|{035EE3E1-09A8-4C52-AE7C-3DB6F74B3A55}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{7D8C3522-1CCD-4D8B-8B56-B9940D9F5351}|线路|4.05|||线路取费表|11116.094254|杆塔上装的各类辅助生产装置||7.5|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826500000|一般线路本体工程/辅助工程/杆塔上装的各类辅助生产装置|项目划分|{035EE3E1-09A8-4C52-AE7C-3DB6F74B3A55}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{91C973AE-4C3F-46AF-8CA3-BBECD94CE08C}|线路|4.05|||线路取费表(调试工程)aa|0|输、送电线路试运||7.6|11.03|9.89|9.89||-0.95|-0.95|||0|Y1826600000|一般线路本体工程/辅助工程/输、送电线路试运|项目划分|{035EE3E1-09A8-4C52-AE7C-3DB6F74B3A55}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{7818F2F3-0538-41F3-8119-7DF286BBD89B}|线路|4.05|||线路取费表|114112.536716|电缆工程||8|11.03|9.89|9.89||-0.95|-0.95|||0|Y1827000000|一般线路本体工程/电缆工程|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{F014C467-967E-4C77-8DE4-C176CA13AC34}|线路|4.05|||线路取费表|114112.536716|通信线路工程||9|11.03|9.89|9.89||-0.95|-0.95|||0|Y1828000000|一般线路本体工程/通信线路工程|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
|{4D8A2C99-1BD5-4A98-BFE1-CF2491B24F39}|线路|4.05|||线路取费表|114112.536716|新增项目名称||10|11.03|9.89|9.89||-0.95|-0.95|01||0||一般线路本体工程/新增项目名称|项目划分|{18C06BBF-4B8B-4390-ABD6-982AFE876DF3}|{29FA8B83-6418-42FF-80E4-150D8A7DFF39}|
|
||||
@@ -0,0 +1,79 @@
|
||||
# 其他费用
|
||||
备注:其他费用表被称为“工程费用中其他费用明细”。其他费用是指为完成工程项目建设所必需的,但不属于建筑工程费、安装工程费、设备购置费、基本预备费的其他相关费用。包括建设场地征用及清理费、项目建设管理费、项目建设技术服务费、生产准备费、大件运输措施费、专业爆破服务费等。查询示例: SELECT Rate FROM OtherFee WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:relTbId
|
||||
- 字段名称:parentId
|
||||
- 字段名称:序号
|
||||
- 备注:序号,序列号
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:金额,价格
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:金额
|
||||
- 备注:金额,价格
|
||||
- 字段名称:编码
|
||||
- 备注:WBS编号,WBS编码
|
||||
- 字段名称:服务内容
|
||||
- 字段名称:费用归属
|
||||
- 字段名称:输出
|
||||
- 字段名称:不可竞争费用
|
||||
- 字段名称:编制依据
|
||||
- 备注:编制依据,编制来源
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:表一显示
|
||||
- 字段名称:税率
|
||||
|
||||
|_id|nodeType|relTbId|parentId|序号|名称|代码|单位|取费基数|费率|金额|编码|服务内容|费用归属|输出|不可竞争费用|编制依据|备注|表一显示|税率|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|31ypohtxibk0|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}||1|建设场地征用及清理费|A||建设场地征用及清理费|100|0|34100000|||否|否|||是|0|
|
||||
|31ypohtxibk1|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}||2|项目建设管理费|B|||100|897670.519514|34200000|||否|否|||否|0|
|
||||
|31ypohtxibk2|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohtxibk1|2.1|项目法人管理费|B1||本体工程费|1.17|114117.972829|34210000|||否|否|||否|0|
|
||||
|31ypohu007wg|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohtxibk1|2.2|招标费|B2||本体工程费|0.28|27310.284096|34220000|||否|否||线路长度超过500km时,超过部分每增加100km,费率乘以0.92系数 |否|6|
|
||||
|31ypohu007wh|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohtxibk1|2.3|工程监理费|B3||工程监理费|100|710400|34230000|||否|否|@工程监理费取费基数|说明:162号文指导费率区间:单回路1.22-1.23(万元/km);同杆(塔)双回1.54-1.55(万元/km)。|否|6|
|
||||
|31ypohu007wi|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohtxibk1|2.4|设备材料监造费|B4|||100|0|34240000|||否|否|||否|6|
|
||||
|31ypohu2i48w|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohtxibk1|2.5|施工过程造价咨询及竣工结算审核费|B5||本体工程费|0.47|45842.262589|34260000|||否|否||1:如只开展工程竣工结算审核工作,按本费率乘以 0.75 系数。2:架空交流输电线路长度超过 300km 时,超过部分乘以 0.8 系数;架空直 流输电线路长度超过 1500km 时,超过部分乘以 0.8 系数。3:费用计算低于 3000 元时,按 3000 元计列。|否|6|
|
||||
|31ypohu2i48x|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohtxibk1|2.6|工程保险费|B6|||100|0|34250000|||否|否|||否|6|
|
||||
|31ypohu2i48y|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}||3|项目建设技术服务费|C|||100|316502.117709|34300000|||否|否|||否|6|
|
||||
|31ypohu2i48z|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48y|3.1|项目前期工作费|C1|||100|0|34310000|||否|否|||否|6|
|
||||
|31ypohu500lc|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.1|可行性研究费用|C11|||100|0||||否|否||说明:162号文指导费用区间:20万元-30万元;20km以上,增加1万元/km;多回路、高海拔等可调整。|否|6|
|
||||
|31ypohu500ld|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.2|环境影响评价费用|C12|||100|0||||否|否||说明:162号文指导费用区间:5万元-10万元;20km以上,增加0.25万元/km;穿越环境敏感区、平行走廊等可调整。|否|6|
|
||||
|31ypohu7hwxs|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.3|建设项目规划选址费|C13|||100|0||||否|否||说明:162号文指导费用区间:5万元-10万元;20km以上,增加0.15万元/km;平行走廊等可调整。|否|6|
|
||||
|31ypohu7hwxt|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.4|水土保持方案编审费用|C14|||100|0||||否|否||说明:162号文指导费用区间:4万元-9万元;20km以上,增加0.2万元/km;平行走廊等可调整。|否|6|
|
||||
|31ypohu7hwxu|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.5|地质灾害危险性评估费用|C15|||100|0||||否|否||说明:162号文指导费用区间:3万元-5万元;20km以上,增加0.15万元/km;平行走廊等可调整。|否|6|
|
||||
|31ypohu9zta8|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.6|地震安全性评价费用|C16|||100|0||||否|否||说明:线路工程原则上不计此费用|否|6|
|
||||
|31ypohu9zta9|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.7|文物调查费用|C17|||100|0||||否|否||说明:162号文指导费用区间:3万元-10万元;20km以上,增加0.05-0.15万元/km;平行走廊等可调整。|否|6|
|
||||
|31ypohu9ztaa|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.8|矿产压覆评估费用|C18|||100|0||||否|否||说明:162号文指导费用区间:5万元-8万元;20km以上,增加0.1-0.4万元/km;平行走廊等可调整。|否|6|
|
||||
|31ypohu9ztab|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.9|用地预审费用|C19|||100|0||||否|否||说明:162号文指导费用区间:5万元-15万元;20km以上,增加0.1-0.3万元/km;平行走廊等可调整。|否|6|
|
||||
|31ypohuchpmo|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.10|节能评估费用|C1A|||100|0||||否|否||说明:162号文指导费用区间:3万元-6万元;20km以上,增加0.01-0.05万元/km;平行走廊等可调整。|否|6|
|
||||
|31ypohuchpmp|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.11|社会稳定风险评估费用|C1B|||100|0||||否|否||说明:162号文指导费用区间:8万元-10万元;20km以上,增加0.01-0.05万元/km;平行走廊等可调整。|否|6|
|
||||
|31ypohuezlz4|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.12|使用林地可行性研究费用|C1C|||100|0||||否|否||说明:162号文指导费用区间:5万元-10万元;20km以上,增加0.1万元/km。|否|6|
|
||||
|31ypohuezlz5|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48z|3.1.13|前期工作管理费用|C1D|||100|0||||否|否||说明:162号文指导费用:20万元;单独的变电站、换流站、输电线路工程按40%-60%调整|否|6|
|
||||
|31ypohuezlz6|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48y|3.2|知识产权转让与研究试验费|C2|||100|0|34320000|||否|否||根据建设项目法人提出的项目和费用计列|否|6|
|
||||
|31ypohuezlz7|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48y|3.3|勘察设计费|C3|||100|0|34330000|||否|否|||否|6|
|
||||
|31ypohuezlz8|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohuezlz7|3.3.1|勘察费|C31||勘察费|100|0||||否|否|||否|6|
|
||||
|31ypohuhhibk|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohuezlz7|3.3.2|设计费|C32||设计费|100|0||||否|否|||否|6|
|
||||
|31ypohuhhibl|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48y|3.4|设计文件评审费|C4|||100|236522|34340000|||否|否|||否|6|
|
||||
|31ypohuhhibm|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohuhhibl|3.4.1|可行性研究文件评审费|C41||可行性研究评审费|100|56914|34341000|||否|否|@可行性研究评审费取费基数||否|6|
|
||||
|31ypohujzeo0|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohuhhibl|3.4.2|初步设计文件评审费|C42||初步设计评审费|100|80652|34342000|||否|否|@初步设计评审费取费基数||否|6|
|
||||
|31ypohujzeo1|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohuhhibl|3.4.3|施工图文件评审费|C43||施工图评审费|100|98956|34343000|||否|否|@施工图评审费取费基数||否|6|
|
||||
|31ypohumhb0g|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48y|3.5|项目后评价费|C5||本体工程费|0.5|48768.364457|34350000|||否|否||线路长度超过500km时,超过部分每增加200km,费率乘以0.92系数|否|6|
|
||||
|31ypohumhb0h|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48y|3.6|工程建设检测费|C6|||100|21458.080361|34360000|||否|否|||否|6|
|
||||
|31ypohumhb0i|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohumhb0h|3.6.1|电力工程质量检测费|C61||本体工程费|0.22|21458.080361|34361000|||否|否|||否|6|
|
||||
|31ypohumhb0j|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohumhb0h|3.6.2|特种设备安全监测费|C62|||100|0|34362000|||否|否|||否|6|
|
||||
|31ypohuoz7cw|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohumhb0h|3.6.3|环境监测及环境保护验收费|C63|||100|0|34363000|||否|否|||否|6|
|
||||
|31ypohuoz7cx|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohumhb0h|3.6.4|水土保持监测及验收费|C64|||100|0|34364000|||否|否|||否|6|
|
||||
|31ypohuoz7cy|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohumhb0h|3.6.5|桩基检测费|C65|||100|0|34365000|||否|否|||否|6|
|
||||
|31ypohuoz7cz|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohu2i48y|3.7|电力工程技术经济标准编制费|C7||本体工程费|0.1|9753.672891|34370000|||否|否|||否|6|
|
||||
|31ypohurh3pc|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}||4|生产准备费|D|||100|54620.568192|34500000|||否|否|||否|0|
|
||||
|31ypohurh3pd|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohurh3pc|4.1|管理车辆购置费|D1||本体工程费|0.25|24384.182228|34510000|||否|否||注:如果管理车辆由项目法人单位统一配置,并且不在工程项目中分摊相关费用时,本项费用不计。|否|13|
|
||||
|31ypohurh3pe|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohurh3pc|4.2|工器具及办公家具购置费|D2||本体工程费|0.21|20482.713072|34520000|||否|否|||否|13|
|
||||
|31ypohutz01s|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}|31ypohurh3pc|4.3|生产职工培训及提前进场费|D3||本体工程费|0.1|9753.672891|34530000|||否|否|||否|0|
|
||||
|31ypohuwgwe8|其他费用|{08D3C3D2-A5F1-4BFB-8ABA-20DE6A4FF7E2}||5|专业爆破服务费|E|||100|0||||否|否|||否|0|
|
||||
@@ -0,0 +1,33 @@
|
||||
# 大型土石方取费表_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{66580D06-D301-47AB-B9B3-EA8E00A0EE81}|FFZ1|||一|否|100|直接工程费|取费表||{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{A2994CFA-9C39-4CC0-931F-CDF3B975096C}|RGF|取费定额人工费||1|否|100|人工费|取费表|{66580D06-D301-47AB-B9B3-EA8E00A0EE81}|{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{189238D9-CCEF-4CBE-9C07-8A163D8F1A60}|CLF|取费定额乙供材料费不含税+乙供取费主材费不含税+甲供取费主材费含税||2|否|100|材料费|取费表|{66580D06-D301-47AB-B9B3-EA8E00A0EE81}|{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{12925CE8-5EBF-40A7-830B-BBC269C110BD}|JXF|取费定额机械费||3|否|100|施工机械使用费|取费表|{66580D06-D301-47AB-B9B3-EA8E00A0EE81}|{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{2B8E4089-C32F-4F71-B717-3CB4BF36965D}|TZHQF|FFZ1-甲供主材进项税额|综合取费费用额(包含措施费、间接费、利润)|二|否|17.79|综合取费费用额|取费表||{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{4BB0249B-EAE2-42AD-81E4-B44953711237}|JC|||三|否|100|编制基准期价差|取费表||{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{C4DEF5ED-4C41-4459-A06D-2408A5E7307E}|RJC|人工价差||1|否|100|人工价差|取费表|{4BB0249B-EAE2-42AD-81E4-B44953711237}|{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{6A6A3327-D33F-4D75-A194-8290B2CDAA97}|CJC|乙供材料价差不含税+乙供主材价差不含税+甲供主材价差含税||2|否|100|材料价差|取费表|{4BB0249B-EAE2-42AD-81E4-B44953711237}|{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{08216E49-E3DA-474F-9A44-1C4997314436}|JJC|机械价差||3|否|100|机械价差|取费表|{4BB0249B-EAE2-42AD-81E4-B44953711237}|{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{21290DD4-8C6C-4920-A18B-BAE24913FFB4}|TFFS|FFZ1+TZHQF+JC-甲供取费主材费含税-甲供主材价差含税+不取费定额费不含税+不取费乙供主材费不含税||四|否|9|税金|取费表||{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
|{FBA7D80D-BAD6-49C6-8331-1DBF238B286D}|THJ|FFZ1+TZHQF+TFFS+JC+一笔性费用+不取费定额费不含税+不取费乙供主材费不含税+不取费甲供主材费含税||五|否|100|合计|取费表||{0EB26EB9-93C0-4DC4-9BE7-1A294CC09231}|
|
||||
@@ -0,0 +1,61 @@
|
||||
# 线路取费表_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{C2BB0788-B663-48D4-ABE4-010F21D6808C}|FFZ|||一|否|100|直接费|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{3220321B-AD5E-45AA-9103-EF047C3DF792}|FFZ1|||1|否|100|直接工程费|取费表|{C2BB0788-B663-48D4-ABE4-010F21D6808C}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{7158E9FA-5C36-42B4-9C39-A974556EDADB}|DZF|||1.1|否|100|定额直接费|取费表|{3220321B-AD5E-45AA-9103-EF047C3DF792}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{43B740B1-5953-4E0E-A2B4-840DF8C96B65}|RGF|取费定额人工费||1.1.1|否|100|人工费|取费表|{7158E9FA-5C36-42B4-9C39-A974556EDADB}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{9CC2293B-D8F5-471F-9EBC-F906C0E60546}|CLF|取费定额乙供材料费不含税||1.1.2|否|100|材料费|取费表|{7158E9FA-5C36-42B4-9C39-A974556EDADB}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{9DABE30D-3E2C-4C2B-BDB3-18668E7B4184}|JXF|取费定额机械费||1.1.3|否|100|施工机械使用费|取费表|{7158E9FA-5C36-42B4-9C39-A974556EDADB}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{0A7CB88C-67A9-4578-878B-3CEACEFFD63E}|ZZCF|||1.2|否|100|装置性材料费|取费表|{3220321B-AD5E-45AA-9103-EF047C3DF792}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{AB28917C-D9F7-4A3C-94A6-99DA9ABB5D51}|JZZCF|甲供取费主材费含税||1.2.1|否|100|甲供装置性材料费|取费表|{0A7CB88C-67A9-4578-878B-3CEACEFFD63E}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{C5FE17B3-E6AC-4326-ACA8-7B5BA750AC05}|YZZCF|乙供取费主材费不含税||1.2.2|否|100|乙供装置性材料费|取费表|{0A7CB88C-67A9-4578-878B-3CEACEFFD63E}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{1F5E655F-A6E4-4853-8838-A79344A80B60}|FFZ2|||2|否|100|措施费|取费表|{C2BB0788-B663-48D4-ABE4-010F21D6808C}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{3E8DA03C-75F9-4054-A638-FBFEBEB38D79}|DYF|取费定额人工费||2.1|否|4.59|冬雨季施工增加费|取费表|{1F5E655F-A6E4-4853-8838-A79344A80B60}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{D80D263C-8251-4075-9BB5-ECDB41C77CAB}|YSF|取费定额人工费||2.2|否|0|夜间施工增加费|取费表|{1F5E655F-A6E4-4853-8838-A79344A80B60}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{E597BC41-1597-4891-8230-F939704B51E4}|SYF|取费定额人工费||2.3|否|3.82|施工工具用具使用费|取费表|{1F5E655F-A6E4-4853-8838-A79344A80B60}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{12A0EE6D-1BDF-4A9B-8F9B-A76A5658B142}|TDF|取费定额人工费||2.4|否|4.73|特殊地区施工增加费|取费表|{1F5E655F-A6E4-4853-8838-A79344A80B60}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{992D8A46-E25D-44E3-87AD-EE283D4D0E76}|LSF|DZF||2.5|否|6.6|临时设施费|取费表|{1F5E655F-A6E4-4853-8838-A79344A80B60}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{C147B8E9-7CF2-489E-B196-D1F4A5BD9EEA}|ZYF|取费定额人工费||2.6|否|2.24|施工机构迁移费|取费表|{1F5E655F-A6E4-4853-8838-A79344A80B60}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{24ED26D7-D9C3-44FC-AAA4-7221EF2C078C}|BZF|FFZ1-甲供主材进项税额||2.7|否|3.55|安全文明施工费|取费表|{1F5E655F-A6E4-4853-8838-A79344A80B60}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{9C52DEA5-8FE5-4D50-BF25-2E4E3B513774}|FFJ|||二|否|100|间接费|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{CC8ED3BC-3A7E-4A7C-8BB5-E478DE0F04C4}|GF|||1|否|100|规费|取费表|{9C52DEA5-8FE5-4D50-BF25-2E4E3B513774}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{EFCF4B8E-DCF7-4F3E-BF69-2CECDE4FABFD}|BZHF|取费定额人工费*1.05||1.1|否|0|社会保险费|取费表|{CC8ED3BC-3A7E-4A7C-8BB5-E478DE0F04C4}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{70DE8958-8BDE-440C-B0E4-D612E4642A53}|GJJ|取费定额人工费*1.05||1.2|否|0|住房公积金|取费表|{CC8ED3BC-3A7E-4A7C-8BB5-E478DE0F04C4}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{BB2E72B2-F3ED-47DF-853E-182E11450C18}|GLF|取费定额人工费||2|否|35.76|企业管理费|取费表|{9C52DEA5-8FE5-4D50-BF25-2E4E3B513774}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{20768999-355E-4C7D-A97E-FBEF73BE11D0}|TSF|DZF||3|否|1.06|施工企业配合调试费|取费表|{9C52DEA5-8FE5-4D50-BF25-2E4E3B513774}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{72681D8D-FD6C-446A-BF6E-91C87E7F1081}|FFR|FFZ+FFJ-甲供主材进项税额||三|否|5|利润|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{5E523944-7B59-41E7-923D-8DBFEDBBA075}|JC|||四|否|100|编制基准期价差|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{E49FD193-1FD7-49A8-B539-0DF5A775F08E}|RJC|人工价差||1|否|100|人工价差|取费表|{5E523944-7B59-41E7-923D-8DBFEDBBA075}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{1CD04D11-91CA-494D-9E6B-015E1045AA9A}|CJC|乙供材料价差不含税||2|否|100|材料价差|取费表|{5E523944-7B59-41E7-923D-8DBFEDBBA075}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{9038C70C-128F-44E5-A572-E605555B620C}|JJC|机械价差||3|否|100|机械价差|取费表|{5E523944-7B59-41E7-923D-8DBFEDBBA075}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{5553B7F5-7675-4A56-84E6-D6A4319A83E6}|ZCJC|||4|否|100|装置性材料价差|取费表|{5E523944-7B59-41E7-923D-8DBFEDBBA075}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{BB9FC5EF-C745-4EFC-AEF2-285E72FDB92B}|JZCJC|甲供主材价差含税||4.1|否|100|甲供装置性材料价差|取费表|{5553B7F5-7675-4A56-84E6-D6A4319A83E6}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{B18A36DE-378E-4BCF-92BE-906A2FB8E9A2}|YZCJC|乙供主材价差不含税||4.2|否|100|乙供装置性材料价差|取费表|{5553B7F5-7675-4A56-84E6-D6A4319A83E6}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{A7906649-518C-428D-B6D2-6A512787923C}|FFS|FFZ+FFJ+FFR+JC-甲供取费主材费含税-甲供主材价差含税+不取费定额费不含税+不取费乙供主材费不含税||五|否|9|税金|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{C56D6329-53EB-4406-9C80-FD824209A11F}|SBF|||六|否|100|设备费|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{250A2E7B-314E-47AF-974D-F046AA556D40}|SBY|乙供设备费不含税+乙供设备税金||1|否|100|乙供设备不含税价|取费表|{C56D6329-53EB-4406-9C80-FD824209A11F}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{A294E14E-41D0-4478-91C6-6F62713E5B23}|SBJ|甲供设备费含税||2|否|100|甲供设备含税价|取费表|{C56D6329-53EB-4406-9C80-FD824209A11F}|{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{2ADA195C-CD85-4263-8049-21A714B30D25}|AZF|DZF+FFZ2+FFJ+FFR+FFS+JC-ZCJC+不取费定额费不含税+一笔性费用||七|否|100|安装费|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{AAE32372-BB8A-42F8-B14A-BAB8B99E74F1}|ZCF|ZZCF+ZCJC+不取费乙供主材费不含税+不取费甲供主材费含税||八|否|100|主材费|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{8F219987-A153-424A-A957-35AB2C6D1DD2}|ZJ|AZF+ZCF+SBF||九|否|100|总计|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
|{BAF0142D-07CC-49EF-BAC6-17BBEB974434}|HJ|ZJ-SBF||十|否|100|合计|取费表||{77980093-5E58-4007-A090-23749D60D5B0}|
|
||||
@@ -0,0 +1,31 @@
|
||||
# 线路取费表(余物清理)_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{E034EFE6-A929-49A9-BF28-900C05CE528E}|FFZ|||一|否|100|直接费|取费表||{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
|{2E18CA1D-BD04-43AF-8870-D8917C3D31F9}|FFZ1|||1|否|100|直接工程费|取费表|{E034EFE6-A929-49A9-BF28-900C05CE528E}|{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
|{BA1176CE-0768-4225-8370-86E1EFE29BEB}|DZF|||1.1|否|100|定额直接费|取费表|{2E18CA1D-BD04-43AF-8870-D8917C3D31F9}|{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
|{381A9E4F-07F6-4CD8-A860-50C08B9004E3}|RGF|取费定额人工费||1.1.1|否|100|人工费|取费表|{BA1176CE-0768-4225-8370-86E1EFE29BEB}|{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
|{B9DE90CA-1159-4120-9815-E761297C3DBE}|CLF|取费定额乙供材料费不含税||1.1.2|否|100|材料费|取费表|{BA1176CE-0768-4225-8370-86E1EFE29BEB}|{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
|{F02F21B5-1A13-48CC-AEEB-C9AC2732F410}|JXF|取费定额机械费||1.1.3|否|100|施工机械使用费|取费表|{BA1176CE-0768-4225-8370-86E1EFE29BEB}|{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
|{E856825F-C2FD-44C8-A104-4A1995F171EC}|FFZ2|||2|否|100|措施费|取费表|{E034EFE6-A929-49A9-BF28-900C05CE528E}|{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
|{40652335-FB10-4FBC-B20E-64E997CEC268}|BZF|FFZ1||2.1|否|3.55|安全文明施工费|取费表|{E856825F-C2FD-44C8-A104-4A1995F171EC}|{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
|{CC2FD840-E9DA-4E18-BBD5-0097FDB3A640}|HJ|FFZ+一笔性费用||二|否|100|合计|取费表||{6B30DC7A-105A-45BD-92F1-ED8455E5D3E0}|
|
||||
@@ -0,0 +1,46 @@
|
||||
# 线路取费表(拆除)_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{8C5BCA4E-0CCF-48A7-AC6F-42B62A1C5167}|FFZ|||一|否|100|直接费|取费表||{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{E744579B-7124-49C6-9FAC-37CC22F01E36}|FFZ1|||1|否|100|直接工程费|取费表|{8C5BCA4E-0CCF-48A7-AC6F-42B62A1C5167}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{20392A4B-F64C-4400-937E-F9D4B4FC3922}|RGF|取费定额人工费||1.1|否|100|人工费|取费表|{E744579B-7124-49C6-9FAC-37CC22F01E36}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{42385797-BF6F-4CA1-A4EE-2F787D427BEB}|CLF|取费定额乙供材料费不含税||1.2|否|100|材料费|取费表|{E744579B-7124-49C6-9FAC-37CC22F01E36}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{5840FCA7-34B9-44FA-8BF3-A7C4AF3CA0B0}|JXF|取费定额机械费||1.3|否|100|施工机械使用费|取费表|{E744579B-7124-49C6-9FAC-37CC22F01E36}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{3D68CDB3-BB8F-4767-B049-056391AC377A}|FFZ2|||2|否|100|措施费|取费表|{8C5BCA4E-0CCF-48A7-AC6F-42B62A1C5167}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{77AB31B4-9641-4CC8-86F3-4A792DC95EDC}|DYF|取费定额人工费+取费定额机械费||2.1|否|2.16|冬雨季施工增加费|取费表|{3D68CDB3-BB8F-4767-B049-056391AC377A}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{7232E573-CD0B-4B33-A0F2-83B02C58D785}|SYF|取费定额人工费+取费定额机械费||2.2|否|0.65|施工工具用具使用费|取费表|{3D68CDB3-BB8F-4767-B049-056391AC377A}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{2F1BA992-F037-40E4-8B4E-E818523E9796}|TDF|取费定额人工费+取费定额机械费||2.3|否|3.1|特殊地区施工增加费|取费表|{3D68CDB3-BB8F-4767-B049-056391AC377A}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{1DA5F8FE-6256-4227-9513-2AE56D8BCBFD}|LSF|取费定额人工费+取费定额机械费|独立的拆除工程可计取此项费,与其他工程同期实施的拆除工作不计取此项费用|2.4|否|0|临时设施费|取费表|{3D68CDB3-BB8F-4767-B049-056391AC377A}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{82E0248B-A916-4262-91DD-8CE22AA8FB78}|ZYF|取费定额人工费+取费定额机械费|独立的拆除工程可计取此项费,与其他工程同期实施的拆除工作不计取此项费用|2.5|否|0|施工机构迁移费|取费表|{3D68CDB3-BB8F-4767-B049-056391AC377A}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{4CFE2267-B895-457F-AE71-7732E31FE39C}|BZF|取费定额人工费+取费定额机械费||2.6|否|11.31|安全文明施工费|取费表|{3D68CDB3-BB8F-4767-B049-056391AC377A}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{B3790072-A433-4934-B99E-1ED92F669FEC}|FFJ|||二|否|100|间接费|取费表||{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{3C9E8743-3DDB-49DE-B7EC-BF591B041CDF}|GF|||1|否|100|规费|取费表|{B3790072-A433-4934-B99E-1ED92F669FEC}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{FA22E0F0-95D2-4E0B-BC1F-66768819952F}|BZHF|取费定额人工费*1.05||1.1|否|0|社会保险费|取费表|{3C9E8743-3DDB-49DE-B7EC-BF591B041CDF}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{20ED2D03-F04F-43DA-95B2-5F60BDBE8EF5}|GJJ|取费定额人工费*1.05||1.2|否|0|住房公积金|取费表|{3C9E8743-3DDB-49DE-B7EC-BF591B041CDF}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{64528BE4-F8DA-4309-B137-957757A4D396}|GLF|取费定额人工费+取费定额机械费||2|否|17.13|企业管理费|取费表|{B3790072-A433-4934-B99E-1ED92F669FEC}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{430AA4DD-76C3-427C-8465-5A545ABD04A0}|FFR|取费定额人工费+取费定额机械费||三|否|5.24|利润|取费表||{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{399635B6-E3AD-46A2-BD75-D32C7C893418}|JC|||四|否|100|编制基准期价差|取费表||{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{4F2DE62A-27A6-4C4D-B63A-A45CF6D31815}|RJC|人工价差||1|否|100|人工价差|取费表|{399635B6-E3AD-46A2-BD75-D32C7C893418}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{1CF69151-BC79-476A-95D1-282137C9436D}|CJC|乙供材料价差不含税||2|否|100|材料价差|取费表|{399635B6-E3AD-46A2-BD75-D32C7C893418}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{B2426FFA-B1FF-470F-823A-2CF9A93E2221}|JJC|机械价差||3|否|100|机械价差|取费表|{399635B6-E3AD-46A2-BD75-D32C7C893418}|{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{B5E15771-82CD-467A-B3E8-EA8EFFBCC6C6}|FFS|FFZ+FFJ+FFR+JC+不取费定额费不含税||五|否|9|税金|取费表||{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
|{6852EB92-6930-4CA0-89DB-EB756398B1FF}|HJ|FFZ+FFJ+FFR+FFS+JC+一笔性费用+不取费定额费不含税||六|否|100|合计|取费表||{01247A42-E488-4FD7-89FE-4756DA791CC7}|
|
||||
@@ -0,0 +1,54 @@
|
||||
# 线路取费表(调试工程)_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{15ABD61A-042B-4BB5-A40B-8CE980A39CAC}|FFZ|||一|否|100|直接费|取费表||{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{93BF1F57-992F-4313-94EC-BCC16E77DCEC}|FFZ1|||1|否|100|直接工程费|取费表|{15ABD61A-042B-4BB5-A40B-8CE980A39CAC}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{3E1F2E4C-5220-462F-8A54-44582CE1B055}|DZF|||1.1|否|100|定额直接费|取费表|{93BF1F57-992F-4313-94EC-BCC16E77DCEC}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{6105958B-8721-498C-A4D5-58720116530C}|RGF|取费定额人工费||1.1.1|否|100|人工费|取费表|{3E1F2E4C-5220-462F-8A54-44582CE1B055}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{13F2B44B-DB9F-4A8E-A5CB-1E68CFB3A072}|CLF|取费定额乙供材料费不含税||1.1.2|否|100|材料费|取费表|{3E1F2E4C-5220-462F-8A54-44582CE1B055}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{77D48426-5E27-4556-8C64-544841E0CFAE}|JXF|取费定额机械费||1.1.3|否|100|施工机械使用费|取费表|{3E1F2E4C-5220-462F-8A54-44582CE1B055}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{7ECB7FF4-7101-431D-8EFF-B96627F2942D}|ZZCF|||1.2|否|100|装置性材料费|取费表|{93BF1F57-992F-4313-94EC-BCC16E77DCEC}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{C5D25B31-3086-4870-B28D-7B824AD10DE6}|JZZCF|甲供取费主材费含税||1.2.1|否|100|甲供装置性材料费|取费表|{7ECB7FF4-7101-431D-8EFF-B96627F2942D}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{6D8E21BF-2A69-4B37-8E5E-C3235351FF79}|YZZCF|乙供取费主材费不含税||1.2.2|否|100|乙供装置性材料费|取费表|{7ECB7FF4-7101-431D-8EFF-B96627F2942D}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{D9897015-5B7E-48CC-BE9E-C92630A741A3}|FFZ2|||2|否|100|措施费|取费表|{15ABD61A-042B-4BB5-A40B-8CE980A39CAC}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{9CA6ED0D-557F-4D41-A454-C4B2A20A1796}|DYF|取费定额人工费||2.1|否|9|冬雨季施工增加费|取费表|{D9897015-5B7E-48CC-BE9E-C92630A741A3}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{6169CAD0-3C75-486D-B749-B9F8E8F730CC}|YSF|取费定额人工费||2.2|否|0|夜间施工增加费|取费表|{D9897015-5B7E-48CC-BE9E-C92630A741A3}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{F526AB28-3AE3-440A-9060-C59F60312609}|SYF|取费定额人工费||2.3|否|3.82|施工工具用具使用费|取费表|{D9897015-5B7E-48CC-BE9E-C92630A741A3}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{2A37FE41-DF35-4630-B07B-F984A362BE97}|TDF|取费定额人工费||2.4|否|4.73|特殊地区施工增加费|取费表|{D9897015-5B7E-48CC-BE9E-C92630A741A3}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{DE5C5568-7231-4DF4-8E7F-E0996291EE80}|LSF|DZF||2.5|否|6.6|临时设施费|取费表|{D9897015-5B7E-48CC-BE9E-C92630A741A3}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{C85AFC7D-8222-4F0A-B01B-E5AF8A76F0D2}|ZYF|取费定额人工费||2.6|否|2.24|施工机构迁移费|取费表|{D9897015-5B7E-48CC-BE9E-C92630A741A3}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{F996F96C-962C-4E2A-949B-4B4ECAEFCE37}|BZF|FFZ1-甲供主材进项税额||2.7|否|3.55|安全文明施工费|取费表|{D9897015-5B7E-48CC-BE9E-C92630A741A3}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{458D3730-C862-47C2-8E79-E40CC2F8CF0C}|FFJ|||二|否|100|间接费|取费表||{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{FD336C8D-C86E-4C65-B45D-BC675AF4ABA2}|GF|||1|否|100|规费|取费表|{458D3730-C862-47C2-8E79-E40CC2F8CF0C}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{908F0983-9649-4570-BB81-0B4A53DF6C50}|BZHF|取费定额人工费*1.05||1.1|否|0|社会保险费|取费表|{FD336C8D-C86E-4C65-B45D-BC675AF4ABA2}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{3D8BE9DA-DD9E-4CB2-9B28-3346115F9185}|GJJ|取费定额人工费*1.05||1.2|否|0|住房公积金|取费表|{FD336C8D-C86E-4C65-B45D-BC675AF4ABA2}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{D63FCFEB-DD3D-4990-A7F1-FAC0F8A6F7BC}|GLF|取费定额人工费||2|否|35.76|企业管理费|取费表|{458D3730-C862-47C2-8E79-E40CC2F8CF0C}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{E74E7565-809E-42CC-886C-5351E5B4D68C}|FFR|FFZ+FFJ-甲供主材进项税额||三|否|5|利润|取费表||{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{2A6A4CF6-F523-4043-987D-A5CB34E16EF9}|JC|||四|否|100|编制基准期价差|取费表||{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{994FA147-C34F-4857-9109-0F0319B73A18}|RJC|人工价差||1|否|100|人工价差|取费表|{2A6A4CF6-F523-4043-987D-A5CB34E16EF9}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{C457CDD7-26E0-4D1B-80BF-4880E8660958}|CJC|乙供材料价差不含税||2|否|100|材料价差|取费表|{2A6A4CF6-F523-4043-987D-A5CB34E16EF9}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{C4700525-5629-4ABE-A4ED-30E1EF37C5B9}|JJC|机械价差||3|否|100|机械价差|取费表|{2A6A4CF6-F523-4043-987D-A5CB34E16EF9}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{100A69D7-12A5-419C-AF6D-B4F952B82257}|ZCJC|||4|否|100|装置性材料价差|取费表|{2A6A4CF6-F523-4043-987D-A5CB34E16EF9}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{F6C2A23D-FDE1-4AFA-8AAF-ACD3056299F5}|JZCJC|甲供主材价差含税||4.1|否|100|甲供装置性材料价差|取费表|{100A69D7-12A5-419C-AF6D-B4F952B82257}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{2EE5A86D-9D41-4C7F-B7E0-656194442E09}|YZCJC|乙供主材价差不含税||4.2|否|100|乙供装置性材料价差|取费表|{100A69D7-12A5-419C-AF6D-B4F952B82257}|{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{B11562C7-0F81-4306-B731-DF2630602BAE}|FFS|FFZ+FFJ+FFR+JC-甲供取费主材费含税-甲供主材价差含税+不取费定额费不含税+不取费乙供主材费不含税||五|否|9|税金|取费表||{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
|{4BDC880D-B658-4874-9F61-9E7B4466BE46}|HJ|FFZ+FFJ+FFR+FFS+JC+一笔性费用+不取费定额费不含税+不取费乙供主材费不含税+不取费甲供主材费含税||六|否|100|合计|取费表||{0DB69100-1398-4258-87A7-6AD28B8A0659}|
|
||||
@@ -0,0 +1,213 @@
|
||||
# 工程属性
|
||||
备注:工程属性表是用于存储整个工程的重要属性,访问该表都是为了通过属性名查找属性值。通常属性值有工程信息、工程属性、技经参数,表中包含工程总投资、工程总费用,工程主要费用,工程技经参数等。查询示例: SELECT Value FROM ProjectProperties WHERE Name = 'findname'。
|
||||
- 字段名称:名称
|
||||
- 字段名称:值
|
||||
- 备注:属性值,值、变量值、参数值、数值
|
||||
|
||||
|名称|值|
|
||||
|---|---|
|
||||
|设置线材工地运输计算方式|按实际用量计算|
|
||||
|材料调差系数|6.2|
|
||||
|拆除安装材料按系数调差|1|
|
||||
|甲供材料损耗是否计入甲供材料费|-1|
|
||||
|计税方式|增值税|
|
||||
|地形调整及跳跃施工计算顺序|0|
|
||||
|是否自动计算凿桩头总量|是|
|
||||
|脚手架材料费系数|0.5|
|
||||
|云端同步|True|
|
||||
|线路清单组件库|线路组件库(2018版).zjzjk|
|
||||
|固定综合单价模式||
|
||||
|总价万元|1119|
|
||||
|建筑工程按系数调差|0|
|
||||
|QtyID|328|
|
||||
|发布版工程量清单||
|
||||
|材机是否按系数调差|1|
|
||||
|材机界面是否只显示新增资源|FALSE|
|
||||
|计价方式|定额计价|
|
||||
|升级历史|2.4.0.124;2.4.1.4;2.4.3.3;2.4.4.5;2.5.0.155;2.5.1.14;2.6.0.218;2.6.2.0;2.6.3.0;2.7.0.0;2.8.0.0;3.0.0.0;3.0.1.0;3.1.0.0;3.1.1.0;3.1.2.0;|
|
||||
|配置选项|2018年版预规|
|
||||
|工程税率|9|
|
||||
|取费表显示级别|项目划分级别显示|
|
||||
|投标人||
|
||||
|是否第一次打开工程||
|
||||
|安装人工按系数调差|1|
|
||||
|是否按单位控制工程量精度|否|
|
||||
|安装材料按系数调差|1|
|
||||
|工程阶段||
|
||||
|脚手架费率|5|
|
||||
|市场价唯一|是|
|
||||
|耐张、转角塔导线挂线是否计算综合地形增加费|0|
|
||||
|地方规范||
|
||||
|默认自定义拆除定额库|自定义拆除定额库|
|
||||
|项目类型|架空输电线路工程|
|
||||
|工程文件预览信息|●工程名称:线路工程20221122●项目划分:架空输电线路工程●工程阶段:初步设计概算●地区类型:Ⅱ类●工程所在地:山东●执行规范:电网预规2018年版●工程版本:3.1.2.4●升级历史:2.4.0.124;2.4.1.4;2.4.3.3;2.4.4.5;2.5.0.155;2.5.1.14;2.6.0.218;2.6.2.0;2.6.3.0;2.7.0.0;2.8.0.0;3.0.0.0;3.0.1.0;3.1.0.0;3.1.1.0;3.1.2.0;●加密属性:|
|
||||
|甲供材料计入综合单价|是|
|
||||
|工程所在地|山东|
|
||||
|岩石灌浆基础超灌量|8|
|
||||
|阶段类型|概预算|
|
||||
|施工费记取甲供设备运杂费||
|
||||
|余土外运量|0|
|
||||
|脚手架人工费系数|0.4|
|
||||
|是否开放组件统计|是|
|
||||
|工程总投资|1118.7803|
|
||||
|清单规范|2014版|
|
||||
|灌注桩超灌量|17|
|
||||
|线路定额统计规则库|线路定额统计规则(2018版).bwgzk6|
|
||||
|物料增值税率|13|
|
||||
|工程创建模板|标准配置|
|
||||
|国网14升21||
|
||||
|编制单位||
|
||||
|定额价目本|2006|
|
||||
|加密属性||
|
||||
|默认清单组价方式||
|
||||
|甲供材料是否计取税金||
|
||||
|导入发布版工程量清单||
|
||||
|机械调差系数|6.2|
|
||||
|拆除安装工程默认定额库|拆除预算 第三册 架空线路工程|
|
||||
|建筑项目划分代码前缀|BT|
|
||||
|脚手架计算基数|人工费|
|
||||
|配合比拆分||
|
||||
|报表类型||
|
||||
|泥沼地形比例|0|
|
||||
|平地地形比例|0|
|
||||
|BCL版本|3.1.2|
|
||||
|材料单公里用量计算规则|按线路亘长计算|
|
||||
|工程按系数调差|0|
|
||||
|专业扩展类型||
|
||||
|工程编号||
|
||||
|工程改造性质|新建|
|
||||
|是否组合件库||
|
||||
|基本预备费费率|1.5|
|
||||
|工程默认人材机库||
|
||||
|是否设置岩石坑排水||
|
||||
|发布版本|0|
|
||||
|专业类型|送电|
|
||||
|相同清单合并|是(清单属性及工程量一致)|
|
||||
|拆除材料调差系数|5.75|
|
||||
|标准清单编码长度|3|
|
||||
|特殊地区|酷热地区|
|
||||
|塔材代用部分是否计入主材费||
|
||||
|拆除安装人工按系数调差|1|
|
||||
|规划台数||
|
||||
|安装工程默认定额库|预算 第四册 架空输电线路工程(2018年版)|
|
||||
|默认自定义主材库|自定义材料库|
|
||||
|安装工程量是否首次统计工程量|否|
|
||||
|预算转清单||
|
||||
|工程有效性数据|S08JAAAXw7BVvRAyBEAUBnEVya8p1WMxHUl6cQNgyLBUqGZGBQUVAwdkw7IooGowBg==|
|
||||
|物料价格联动|是|
|
||||
|生育保险费缴费费率||
|
||||
|拆除建筑人工按系数调差|1|
|
||||
|安装机械按系数调差|1|
|
||||
|拆除建筑材料按系数调差|0|
|
||||
|启用自定义安全文明施工费||
|
||||
|建筑工程默认定额库||
|
||||
|组件参数汇总错误||
|
||||
|打开工程是否需要刷新招标人信息||
|
||||
|浙江接口项目版本|送审版|
|
||||
|默认自定义设备库|自定义设备库|
|
||||
|工程调差文件|调差系数文件〔2022年1号文〕|
|
||||
|监理费计算依据|预规(2018版)|
|
||||
|工程构成类型||
|
||||
|山地地形比例|0|
|
||||
|塔基占地面积|0|
|
||||
|高山地形比例|0|
|
||||
|工资津贴补差|0.89|
|
||||
|安装工程默认清单库|送电线路清单库(2014)|
|
||||
|工程默认主材库|装置性材料预算价2018|
|
||||
|录入工程量标记招||
|
||||
|工程名称|线路工程20221122|
|
||||
|组价方式|综合单价|
|
||||
|工程深度||
|
||||
|失业保险费缴费费率||
|
||||
|浙江接口项目类型|国网版|
|
||||
|工程造价咨询法定代表人或其授权人||
|
||||
|措施规费按清单级取费|1|
|
||||
|是否为特高压工程||
|
||||
|编制人||
|
||||
|安装工程默认规则库|线路典型清单库|
|
||||
|组合件模式|否|
|
||||
|工程默认设备库||
|
||||
|建筑工程默认清单库||
|
||||
|商品砼预算价||
|
||||
|塔材以大代小|3|
|
||||
|建筑人工按系数调差|1|
|
||||
|表头设置|概算|
|
||||
|区域类型|国网清单工程|
|
||||
|工程模式||
|
||||
|项目划分面板数据加载||
|
||||
|所区占地面积||
|
||||
|钻孔爆扩基础超灌量|7|
|
||||
|建筑工程默认规则库||
|
||||
|插件名称||
|
||||
|默认自定义定额库|自定义定额库|
|
||||
|架线长度|20|
|
||||
|工程地址||
|
||||
|人工调差系数|9.58|
|
||||
|是否生成数据|0|
|
||||
|调差系数设置默认地区类型|Ⅱ类 地区|
|
||||
|地方清单规范||
|
||||
|拆除机械调差系数|5.75|
|
||||
|本期单台容量||
|
||||
|工程默认调试库||
|
||||
|塔材代用部分是否自动计算安装费|0|
|
||||
|隐藏中标数据||
|
||||
|工程建筑面积||
|
||||
|空表显示状态|显示空表|
|
||||
|安装项目划分代码前缀|BA|
|
||||
|工伤保险费缴费费率||
|
||||
|线路清单统计规则库|线路清单统计规则(2014版清单规范).bwqdk6|
|
||||
|招标控制价导造价接口||
|
||||
|本期台数||
|
||||
|中介机构法定(授权)代表人||
|
||||
|标段||
|
||||
|拆除安装机械按系数调差|1|
|
||||
|SID|5100|
|
||||
|丘陵地形比例|0|
|
||||
|架线合并方案预算类型||
|
||||
|编制时间|2022-11-22|
|
||||
|工程密码||
|
||||
|拆除建筑机械按系数调差|0|
|
||||
|脚手架机械费系数|0.1|
|
||||
|执行规范|电网预规2018年版|
|
||||
|预算类型|初步设计概算|
|
||||
|工程描述||
|
||||
|建筑消材应用调差范围|FALSE|
|
||||
|养老保险费缴费费率||
|
||||
|脚手架人工工日系数|0.4|
|
||||
|现浇护壁超灌量|17|
|
||||
|招标人||
|
||||
|规划单台容量||
|
||||
|医疗保险费缴费费率||
|
||||
|拆除工程调差文件|2023年上半年调差系数文件(28号文)|
|
||||
|住房公积金费率|0|
|
||||
|不同土质定额归属不同清单|是|
|
||||
|工程版本|3.1.2.4|
|
||||
|默认组件库|线路组件库(2014版清单规范)|
|
||||
|一笔性施工企业配合调试费|0|
|
||||
|峻岭地形比例|0|
|
||||
|软件名称|博微电力建设计价通软件|
|
||||
|电压等级|220kV|
|
||||
|冷却方式||
|
||||
|资质证书||
|
||||
|本期容量||
|
||||
|掏挖基础超灌量|7|
|
||||
|地区类型|Ⅱ类|
|
||||
|负责人工号|P|
|
||||
|招标法定代表人或其授权人||
|
||||
|编辑时间||
|
||||
|工程类型|初步设计概算|
|
||||
|定额版本||
|
||||
|架线类型|一般线路|
|
||||
|社会保险费费率|0|
|
||||
|工程历史版本列表||
|
||||
|2.3.4升级工程||
|
||||
|显示全部数据||
|
||||
|机械台班拆分||
|
||||
|拆除人工调差系数|7.69|
|
||||
|只读||
|
||||
|线路项目划分代码前缀|BA|
|
||||
|工程造价咨询人||
|
||||
|拆分材料人工是否调差|是|
|
||||
|是否重算费用||
|
||||
|导入工程量清单||
|
||||
|拆除工程材机按系数调差|0|
|
||||
@@ -0,0 +1,62 @@
|
||||
# 总算表
|
||||
备注:总算表也被称为“工程总费用”、“工程费用”。其中包含本地工程、辅助设施工程、编制基准期价差、设备购置费、其他费用、基本预备费、特殊费用、工程静态投资、动态费用、价差预备费、建设期贷款利息、工程动态投资、可抵扣增值税额。查询示例: SELECT Amount FROM TotalCalculateTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:relTbId
|
||||
- 字段名称:parentId
|
||||
- 字段名称:序号
|
||||
- 备注:序号
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:金额_单位投资,合计投资金额
|
||||
- 字段名称:取费基数
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:金额
|
||||
- 备注:金额_设备费,设备价格,设备金额
|
||||
- 字段名称:编码
|
||||
- 备注:WBS编号,WBS编码
|
||||
- 字段名称:服务内容
|
||||
- 字段名称:费用归属
|
||||
- 字段名称:输出
|
||||
- 字段名称:不可竞争费用
|
||||
- 字段名称:编制依据
|
||||
- 字段名称:备注
|
||||
- 字段名称:表一显示
|
||||
- 字段名称:建筑费
|
||||
- 字段名称:安装费
|
||||
- 备注:安装金额,安装价格,金额_安装费
|
||||
- 字段名称:设备费
|
||||
- 备注:金额_设备费,设备价格,设备金额
|
||||
- 字段名称:其他费
|
||||
- 备注:其他费用金额,其他费用价格,金额_其他费
|
||||
- 字段名称:合计费
|
||||
- 备注:金额,价格
|
||||
- 字段名称:占总计
|
||||
- 备注:总体金额,总的金额,金额_占总计
|
||||
- 字段名称:单位投资
|
||||
- 备注:金额_单位投资,合计投资金额
|
||||
- 字段名称:建安合计费
|
||||
- 字段名称:金额增减
|
||||
|
||||
|_id|nodeType|relTbId|parentId|序号|名称|代码|单位|取费基数|费率|金额|编码|服务内容|费用归属|输出|不可竞争费用|编制依据|备注|表一显示|建筑费|安装费|设备费|其他费|合计费|占总计|单位投资|建安合计费|金额增减|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|31ypohwaevb4|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}||一|架空输电线路本体工程|BTGC|%||100|9753672.891356||||是|否|||否|0|9753672.891356|0|0|9753672.891356|87.181306|487683.644568|0|9753672.891356|
|
||||
|31ypohwfeo00|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}|31ypohwaevb4|(一)|一般线路本体工程|XLBT|%||100|9753672.891356||||是|否|||否|0|9753672.891356|0|0|9753672.891356|87.181306|487683.644568|0|9753672.891356|
|
||||
|31ypohwfeo01|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}||二|辅助设施工程|FZSS|%||100|0|3A000000|||是|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ypohwhwkcg|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}|||小计|HJ|%||100|9753672.891356||||是|否|||否|0|9753672.891356|0|0|9753672.891356|87.181306|487683.644568|0|9753672.891356|
|
||||
|31ypohwkegow|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}||三|其中:编制基准期价差|JC|元||100|517894.183384|35000000|||是|否|||否|0|517894.183384|0|0|517894.183384|4.629096|25894.709169|0|517894.183384|
|
||||
|31ypohwmwd1c|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}||四|设备购置费|SBGZF|元||100|0||||是|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ypohwpe9ds|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}||五|其他费用|QTFY|元||100|1268793.205415|34000000|||是|否|||否|0|0|0|1268793.205415|1268793.205415|11.340861|63439.660271|0|1268793.205415|
|
||||
|31ypohwrw5q8|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}|31ypohwpe9ds||其中:建设场地征用及清理费||%||100|0||||是|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ypohwue22o|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}||六|基本预备费|JBYBF|%||100|165336.991452|38000000|||是|否|||否|0|0|0|165336.991452|165336.991452|1.477833|8266.849573|0|165336.991452|
|
||||
|31ypohwwvyf4|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}||七|特殊项目|TSXM|%||100|0|36000000|||是|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ypohwzdurk|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}|||工程静态投资(一~七项合计)|JTTZ|元||100|11187803.088223||||是|否|||否|0|9753672.891356|0|1434130.196866|11187803.088223|100|559390.154411|0|11187803.088223|
|
||||
|31ypohx1vr40|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}||八|动态费用|DTFY|元||100|0|37000000|||是|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ypohx4dngg|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}|31ypohx1vr40|(一)|价差预备费|JCYBF|元||100|0|37100000|||是|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ypohx6vjsw|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}|31ypohx1vr40|(二)|建设期贷款利息|DKLX|元||100|0|37200000|||是|否|||否|0|0|0|0|0|0|0|0|0|
|
||||
|31ypohx9dg5c|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}|||工程动态投资(一~八项合计)|DTTZ|元||100|11187803.088223||||是|否|||否|0|9753672.891356|0|1434130.196866|11187803.088223|0|0|0|11187803.088223|
|
||||
|31ypohxbvchs|总算表|{40159452-528E-4482-8E9D-D961B50B57EF}|||其中:可抵扣增值税额|ZZS|%||100|872778.061193||||是|否|||否|0|805349.137818|0|67428.923375|872778.061193|0|0|0|872778.061193|
|
||||
@@ -0,0 +1,64 @@
|
||||
# 项目划分_余物清理
|
||||
备注:项目划分表是用于存储工程项目划分树状数据。内部包含安装工程项目划分,建筑工程项目划分,线路项目划分,工程分部分项。查询示例: SELECT Sum_Price FROM ProjectDivision WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:专业类型
|
||||
- 备注:专业类型
|
||||
- 字段名称:人工调差系数
|
||||
- 备注:拆除人工调差系数
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:单位
|
||||
- 字段名称:取费表
|
||||
- 备注:取费表
|
||||
- 字段名称:合价
|
||||
- 备注:合价,合计
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,名称
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:项目序号,序号,序列号
|
||||
- 字段名称:拆除人工调差系数
|
||||
- 备注:拆除人工调差系数
|
||||
- 字段名称:拆除机械调差系数
|
||||
- 备注:拆除机械调差系数
|
||||
- 字段名称:拆除材料调差系数
|
||||
- 备注:拆除材料调差系数
|
||||
- 字段名称:数量
|
||||
- 备注:数目,数量,个数
|
||||
- 字段名称:机械调差系数
|
||||
- 备注:拆除机械调差系数
|
||||
- 字段名称:材料调差系数
|
||||
- 备注:拆除材料调差系数
|
||||
- 字段名称:编码
|
||||
- 备注:译码,编码
|
||||
- 字段名称:计算式
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用编码
|
||||
- 字段名称:路径
|
||||
- 备注:路径,项目全路径
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|专业类型|人工调差系数|代码|单位|取费表|合价|名称|备注|序号|拆除人工调差系数|拆除机械调差系数|拆除材料调差系数|数量|机械调差系数|材料调差系数|编码|计算式|费率|费用编码|路径|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{5A83B793-0E06-4C31-A90B-6FEBDCF6B21F}|余物清理|0||||0|建筑工程||1|0|0|0||0|0|||0||建筑工程|项目划分||{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{3D836341-C533-453A-BD87-D250D1D4AF0D}|余物清理|0|||线路取费表(余物清理)|0|一般砖木结构||1.1|0|0|0||0|0|||10||建筑工程/一般砖木结构|项目划分|{5A83B793-0E06-4C31-A90B-6FEBDCF6B21F}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{34D75862-8A18-4529-B068-31484FCA64FB}|余物清理|0|||线路取费表(余物清理)|0|混合结构||1.2|0|0|0||0|0|||20||建筑工程/混合结构|项目划分|{5A83B793-0E06-4C31-A90B-6FEBDCF6B21F}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{86BD93D9-3FBB-4364-AC13-E418CBBC6ED7}|余物清理|0||||0|混凝土及钢筋混凝土结构||1.3|0|0|0||0|0|||0||建筑工程/混凝土及钢筋混凝土结构|项目划分|{5A83B793-0E06-4C31-A90B-6FEBDCF6B21F}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{5A6E98BD-3225-425B-BAB1-1EDB1DCBC296}|余物清理|0|||线路取费表(余物清理)|0|(1)有条件爆破的||1.3.1|0|0|0||0|0|||20||建筑工程/混凝土及钢筋混凝土结构/(1)有条件爆破的|项目划分|{86BD93D9-3FBB-4364-AC13-E418CBBC6ED7}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{3947BA59-7ED4-40E6-AADD-1E5D312E29CF}|余物清理|0|||线路取费表(余物清理)|0|(2)无条件爆破的|费率在30~50区间|1.3.2|0|0|0||0|0|||0||建筑工程/混凝土及钢筋混凝土结构/(2)无条件爆破的|项目划分|{86BD93D9-3FBB-4364-AC13-E418CBBC6ED7}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{9E603329-2793-4DA6-90BE-72BD2F4AF4F0}|余物清理|0|||线路取费表(余物清理)|0|临时简易建筑||1.4|0|0|0||0|0|||8||建筑工程/临时简易建筑|项目划分|{5A83B793-0E06-4C31-A90B-6FEBDCF6B21F}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{81BE9F51-3D11-4C79-937D-021B8E7DFDFA}|余物清理|0||||0|金属结构||1.5|0|0|0||0|0|||0||建筑工程/金属结构|项目划分|{5A83B793-0E06-4C31-A90B-6FEBDCF6B21F}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{2D787869-888E-4666-8349-440E3584D2BE}|余物清理|0|||线路取费表(余物清理)|0|(1)拆除后能利用||1.5.1|0|0|0||0|0|||55||建筑工程/金属结构/(1)拆除后能利用|项目划分|{81BE9F51-3D11-4C79-937D-021B8E7DFDFA}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{720CB889-8A4B-49CB-9611-E4A75EA9B9BF}|余物清理|0|||线路取费表(余物清理)|0|(2)拆除后不能利用||1.5.2|0|0|0||0|0|||38||建筑工程/金属结构/(2)拆除后不能利用|项目划分|{81BE9F51-3D11-4C79-937D-021B8E7DFDFA}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{6BEAE0B5-CF26-4272-A59E-ADF990AA96EA}|余物清理|0||||0|安装工程||2|0|0|0||0|0|||0||安装工程|项目划分||{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{D26571BD-9C0D-4E04-B6CA-5B1618C7DCB4}|余物清理|0|||线路取费表(余物清理)|0|金属结构及工业管道||2.1|0|0|0||0|0|||45||安装工程/金属结构及工业管道|项目划分|{6BEAE0B5-CF26-4272-A59E-ADF990AA96EA}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{3FF3E035-8603-4B4C-BA81-3AF5FAA6902F}|余物清理|0|||线路取费表(余物清理)|0|机电设备||2.2|0|0|0||0|0|||32||安装工程/机电设备|项目划分|{6BEAE0B5-CF26-4272-A59E-ADF990AA96EA}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{FF9AC2CF-93F7-41CA-84ED-EB237580F77C}|余物清理|0||||0|输电线路及通信线路||2.3|0|0|0||0|0|||0||安装工程/输电线路及通信线路|项目划分|{6BEAE0B5-CF26-4272-A59E-ADF990AA96EA}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{FE1AC208-65B7-4DD5-AE8A-F563D07C2886}|余物清理|0|||线路取费表(余物清理)|0|(1)拆除后能利用||2.3.1|0|0|0||0|0|||62||安装工程/输电线路及通信线路/(1)拆除后能利用|项目划分|{FF9AC2CF-93F7-41CA-84ED-EB237580F77C}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
|{50AFD995-F0F1-45C9-BD0E-79F50F08D907}|余物清理|0|||线路取费表(余物清理)|0|(2)拆除后不能利用||2.3.2|0|0|0||0|0|||35||安装工程/输电线路及通信线路/(2)拆除后不能利用|项目划分|{FF9AC2CF-93F7-41CA-84ED-EB237580F77C}|{5FCB462B-727C-4E30-AC05-6F463CE1A707}|
|
||||
@@ -0,0 +1,95 @@
|
||||
# 项目划分_线路
|
||||
备注:项目划分表是用于存储工程项目划分树状数据。内部包含安装工程项目划分,建筑工程项目划分,线路项目划分,工程分部分项。查询示例: SELECT Sum_Price FROM ProjectDivision WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:专业类型
|
||||
- 备注:专业类型
|
||||
- 字段名称:人工调差系数
|
||||
- 备注:拆除人工调差系数
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:单位
|
||||
- 字段名称:取费表
|
||||
- 备注:取费表
|
||||
- 字段名称:合价
|
||||
- 备注:合价,合计
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,名称
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:项目序号,序号,序列号
|
||||
- 字段名称:拆除人工调差系数
|
||||
- 备注:拆除人工调差系数
|
||||
- 字段名称:拆除机械调差系数
|
||||
- 备注:拆除机械调差系数
|
||||
- 字段名称:拆除材料调差系数
|
||||
- 备注:拆除材料调差系数
|
||||
- 字段名称:数量
|
||||
- 备注:数目,数量,个数
|
||||
- 字段名称:机械调差系数
|
||||
- 备注:拆除机械调差系数
|
||||
- 字段名称:材料调差系数
|
||||
- 备注:拆除材料调差系数
|
||||
- 字段名称:编码
|
||||
- 备注:译码,编码
|
||||
- 字段名称:计算式
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用编码
|
||||
- 字段名称:路径
|
||||
- 备注:路径,项目全路径
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|专业类型|人工调差系数|代码|单位|取费表|合价|名称|备注|序号|拆除人工调差系数|拆除机械调差系数|拆除材料调差系数|数量|机械调差系数|材料调差系数|编码|计算式|费率|费用编码|路径|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|线路|9.58|BTGC|元/km||9753672.891356|架空输电线路本体工程||一|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程|项目划分||{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{A3FF093B-8710-47A9-B7EC-873FCC712F2D}|线路|9.58|JCGC|元/m³||31501.175855|基础工程||1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{3C4DD6EF-29D9-4D99-8F28-0E49B651B1F0}|线路|9.58|||线路取费表|0|基础工程材料工地运输||1.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础工程材料工地运输|项目划分|{A3FF093B-8710-47A9-B7EC-873FCC712F2D}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{8D99578D-6E1B-4EE0-AC93-5865C48EA52B}|线路|9.58|||线路取费表|31501.175855|基础土石方工程||1.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础土石方工程|项目划分|{A3FF093B-8710-47A9-B7EC-873FCC712F2D}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{8C30BE69-B9B5-4F12-B84D-E5E54CEAB3B3}|线路|9.58||||0|基础砌筑||1.3|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础砌筑|项目划分|{A3FF093B-8710-47A9-B7EC-873FCC712F2D}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{3A4448BE-489D-4159-8B1C-B1863801B8D8}|线路|9.58|||线路取费表|0|预制基础||1.3.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础砌筑/预制基础|项目划分|{8C30BE69-B9B5-4F12-B84D-E5E54CEAB3B3}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{0EB2CE2E-A911-4AAA-BCDB-E47B82CA093B}|线路|9.58|||线路取费表|0|现浇基础||1.3.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础砌筑/现浇基础|项目划分|{8C30BE69-B9B5-4F12-B84D-E5E54CEAB3B3}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{DD1FE7A9-9246-45E8-A81B-1376F3EEFAEF}|线路|9.58|||线路取费表|0|灌注桩基础||1.3.3|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础砌筑/灌注桩基础|项目划分|{8C30BE69-B9B5-4F12-B84D-E5E54CEAB3B3}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{ADF11384-A2A6-45E3-9984-FEB26D350ADD}|线路|9.58|||线路取费表|0|锚杆基础||1.3.4|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础砌筑/锚杆基础|项目划分|{8C30BE69-B9B5-4F12-B84D-E5E54CEAB3B3}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{D5D04846-26E0-4F96-9E58-26BAEC39E6FD}|线路|9.58|||线路取费表|0|其他基础||1.3.5|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础砌筑/其他基础|项目划分|{8C30BE69-B9B5-4F12-B84D-E5E54CEAB3B3}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{5B9D825B-A255-4638-9BA3-93B15267F808}|线路|9.58|||线路取费表|0|基础防护||1.4|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/基础防护|项目划分|{A3FF093B-8710-47A9-B7EC-873FCC712F2D}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{9C79B49F-79ED-4DD5-B5BA-E3025A9500C5}|线路|9.58|||线路取费表|0|地基处理||1.5|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/基础工程/地基处理|项目划分|{A3FF093B-8710-47A9-B7EC-873FCC712F2D}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{0EE7BD7B-AB43-4422-99F1-04DD8AEAE108}|线路|9.58|GTGC|元/t||0|杆塔工程||2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/杆塔工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{8B2DFC9D-5041-4F69-BA32-E4FACC07EC72}|线路|9.58|||线路取费表|0|杆塔工程材料工地运输||2.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/杆塔工程/杆塔工程材料工地运输|项目划分|{0EE7BD7B-AB43-4422-99F1-04DD8AEAE108}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{B9388E51-A827-4E76-A75D-CB421B2D3FD3}|线路|9.58||||0|杆塔组立||2.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/杆塔工程/杆塔组立|项目划分|{0EE7BD7B-AB43-4422-99F1-04DD8AEAE108}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{E875B06B-27C0-475F-A6BA-F1F9B541C3D1}|线路|9.58|||线路取费表|0|混凝土杆组立||2.2.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/杆塔工程/杆塔组立/混凝土杆组立|项目划分|{B9388E51-A827-4E76-A75D-CB421B2D3FD3}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{6C5C5DFB-2F86-4B3F-8636-1F99EE18AF8D}|线路|9.58|||线路取费表|0|铁塔、钢管杆组立||2.2.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/杆塔工程/杆塔组立/铁塔、钢管杆组立|项目划分|{B9388E51-A827-4E76-A75D-CB421B2D3FD3}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{09E6E78A-F5BE-4A09-A773-C2DC984CBDB7}|线路|9.58|JDGC|元/基||0|接地工程||3|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/接地工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{04A67B95-6601-4DEB-8ADB-9F2D34EDE9AE}|线路|9.58|||线路取费表|0|接地工程材料工地运输||3.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/接地工程/接地工程材料工地运输|项目划分|{09E6E78A-F5BE-4A09-A773-C2DC984CBDB7}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{AA2724F1-6C40-41C0-B410-8CEFCC4DF6CC}|线路|9.58|||线路取费表|0|接地土石方||3.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/接地工程/接地土石方|项目划分|{09E6E78A-F5BE-4A09-A773-C2DC984CBDB7}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{23DA6FFE-4741-4C5C-B0CD-73A899CEC0BF}|线路|9.58|||线路取费表|0|接地安装||3.3|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/接地工程/接地安装|项目划分|{09E6E78A-F5BE-4A09-A773-C2DC984CBDB7}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{89D90768-FC57-42AC-BACA-63FA036FF403}|线路|9.58|JXGC|元/km||0|架线工程||4|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/架线工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{A839D9B4-29F9-4B67-8260-17B18604FBC1}|线路|9.58|||线路取费表|0|架线工程材料工地运输||4.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/架线工程/架线工程材料工地运输|项目划分|{89D90768-FC57-42AC-BACA-63FA036FF403}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{D6EB7E76-F087-44FE-84E0-34A381FCEA9C}|线路|9.58|||线路取费表|0|导地线架设||4.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/架线工程/导地线架设|项目划分|{89D90768-FC57-42AC-BACA-63FA036FF403}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{0B9F3695-666B-4170-A0C5-77AE78DD2C56}|线路|9.58|||线路取费表|0|导地线跨越架设||4.3|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/架线工程/导地线跨越架设|项目划分|{89D90768-FC57-42AC-BACA-63FA036FF403}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{E3CCEA65-FA05-4279-B245-A94281E2D7C3}|线路|9.58|||线路取费表|0|其他架线工程||4.4|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/架线工程/其他架线工程|项目划分|{89D90768-FC57-42AC-BACA-63FA036FF403}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{6CE37565-7D19-444C-839E-4C70E5EC3A15}|线路|9.58|FJAZ|元/基||0|附件安装工程||5|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/附件安装工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{AE084DF5-531C-46DC-A443-1BA402C85260}|线路|9.58|||线路取费表|0|附件安装工程材料工地运输||5.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/附件安装工程/附件安装工程材料工地运输|项目划分|{6CE37565-7D19-444C-839E-4C70E5EC3A15}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{E48B1BE7-4463-4552-86AC-4E787E440862}|线路|9.58||||0|绝缘子串及金具安装||5.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/附件安装工程/绝缘子串及金具安装|项目划分|{6CE37565-7D19-444C-839E-4C70E5EC3A15}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{A2AB1180-EB03-452F-8EB3-4D2EBB200058}|线路|9.58|||线路取费表|0|耐张绝缘子串及金具安装||5.2.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/附件安装工程/绝缘子串及金具安装/耐张绝缘子串及金具安装|项目划分|{E48B1BE7-4463-4552-86AC-4E787E440862}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{44BEF6A2-684A-4179-9CD3-D46FC66E819E}|线路|9.58|||线路取费表|0|悬垂绝缘子串及金具安装||5.2.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/附件安装工程/绝缘子串及金具安装/悬垂绝缘子串及金具安装|项目划分|{E48B1BE7-4463-4552-86AC-4E787E440862}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{432AFE7A-E069-43A8-951D-583A280D2913}|线路|9.58|FZGC|元/km、元/m³、元/处||0|辅助工程||6|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{81762019-097C-4C0B-8DD5-EBC3446089FD}|线路|9.58|||线路取费表|0|尖峰、施工基面土石方工程||6.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/尖峰、施工基面土石方工程|项目划分|{432AFE7A-E069-43A8-951D-583A280D2913}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{89CA1CA6-44FF-4EF1-B155-1EDC8096BA19}|线路|9.58||||0|护坡、挡土墙及排洪沟||6.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/护坡、挡土墙及排洪沟|项目划分|{432AFE7A-E069-43A8-951D-583A280D2913}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{CFD85CF6-A6F7-49EA-B608-29E58BC41CD8}|线路|9.58|||线路取费表|0|护坡、挡土墙及排洪沟材料工地运输||6.2.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/护坡、挡土墙及排洪沟/护坡、挡土墙及排洪沟材料工地运输|项目划分|{89CA1CA6-44FF-4EF1-B155-1EDC8096BA19}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{2DC4FFAB-F3BF-4843-A8AF-050B7FBD1830}|线路|9.58|||线路取费表|0|护坡、挡土墙及排洪沟土石方工程||6.2.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/护坡、挡土墙及排洪沟/护坡、挡土墙及排洪沟土石方工程|项目划分|{89CA1CA6-44FF-4EF1-B155-1EDC8096BA19}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{846B357D-9D64-4DCF-A14F-43F358730567}|线路|9.58|||线路取费表|0|护坡、挡土墙及排洪沟砌筑||6.2.3|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/护坡、挡土墙及排洪沟/护坡、挡土墙及排洪沟砌筑|项目划分|{89CA1CA6-44FF-4EF1-B155-1EDC8096BA19}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{59586B2B-E3BD-4827-9015-2A8C218B6904}|线路|9.58||||0|基础永久性围堰||6.3|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/基础永久性围堰|项目划分|{432AFE7A-E069-43A8-951D-583A280D2913}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{178CE9DB-2CD8-4FAF-942C-D23CACB991DE}|线路|9.58|||线路取费表|0|基础永久性围堰材料工地运输||6.3.1|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/基础永久性围堰/基础永久性围堰材料工地运输|项目划分|{59586B2B-E3BD-4827-9015-2A8C218B6904}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{F0884993-7E6E-4BC6-9D7F-CAAB3EA261CB}|线路|9.58|||线路取费表|0|基础永久性围堰土石方工程||6.3.2|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/基础永久性围堰/基础永久性围堰土石方工程|项目划分|{59586B2B-E3BD-4827-9015-2A8C218B6904}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{674D665F-AA82-4E9F-82F5-78BF4A31B6F7}|线路|9.58|||线路取费表|0|基础永久性围堰砌筑||6.3.3|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/基础永久性围堰/基础永久性围堰砌筑|项目划分|{59586B2B-E3BD-4827-9015-2A8C218B6904}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{C4429A35-FFD9-4FDB-A395-69A2672ED2D6}|线路|9.58|||线路取费表|0|索道站安装||6.4|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/索道站安装|项目划分|{432AFE7A-E069-43A8-951D-583A280D2913}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{8F3F9C27-9354-4DC3-AFB4-36603FF20B2E}|线路|9.58|||线路取费表|0|杆塔上装的各类辅助生产装置||6.5|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/杆塔上装的各类辅助生产装置|项目划分|{432AFE7A-E069-43A8-951D-583A280D2913}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{1B689340-80BC-48EB-A79B-D8D9AF7FD1F6}|线路|9.58|||线路取费表|0|输、送电线路试运||6.6|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/辅助工程/输、送电线路试运|项目划分|{432AFE7A-E069-43A8-951D-583A280D2913}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{F8F0651B-2077-433B-8E3E-F8A441F4AEC2}|线路|9.58|||线路取费表|0|电缆工程||7|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/电缆工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{D13C3D5D-A38E-4B0E-B3B4-630FB8904A33}|线路|9.58|||线路取费表|0|通信线路工程||8|7.69|5.75|5.75||6.2|6.2|||0||架空输电线路本体工程/通信线路工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
|{3824000E-A0BA-42F9-9957-55FE9B4CF367}|线路|9.58|QTGC||线路取费表|9722171.715501|其他线路工程||9|7.69|5.75|5.75||6.2|6.2|01||0||架空输电线路本体工程/其他线路工程|项目划分|{9A7491C5-DF31-4228-BB86-1B0982D1C512}|{69305240-E6E2-4ADD-B48C-AF6E199D1AD5}|
|
||||
@@ -0,0 +1,82 @@
|
||||
# 其他费用
|
||||
备注:其他费用表被称为“工程费用中其他费用明细”。其他费用是指为完成工程项目建设所必需的,但不属于建筑工程费、安装工程费、设备购置费、基本预备费的其他相关费用。包括建设场地征用及清理费、项目建设管理费、项目建设技术服务费、生产准备费、大件运输措施费、专业爆破服务费等。查询示例: SELECT Rate FROM OtherFee WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:relTbId
|
||||
- 字段名称:parentId
|
||||
- 字段名称:序号
|
||||
- 备注:序号,序列号
|
||||
- 字段名称:名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:单位
|
||||
- 备注:金额,价格
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:金额
|
||||
- 备注:金额,价格
|
||||
- 字段名称:编码
|
||||
- 备注:WBS编号,WBS编码
|
||||
- 字段名称:服务内容
|
||||
- 字段名称:费用归属
|
||||
- 字段名称:输出
|
||||
- 字段名称:不可竞争费用
|
||||
- 字段名称:编制依据
|
||||
- 备注:编制依据,编制来源
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:表一显示
|
||||
- 字段名称:税率
|
||||
|
||||
|_id|nodeType|relTbId|parentId|序号|名称|代码|单位|取费基数|费率|金额|编码|服务内容|费用归属|输出|不可竞争费用|编制依据|备注|表一显示|税率|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|31yqbmpfp3b4|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}||1|建设场地征用及清理费|A||建设场地征用及清理费|100|25282.5|41831000000|||否|否|||是|0|
|
||||
|31yqbmpi6znk|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}||2|项目建设管理费|B|||100|183066.715962|41832000000|||否|否|||否|0|
|
||||
|31yqbmpi6znl|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpi6znk|2.1|项目法人管理费|B1||(建筑工程费+安装工程费+建筑基准期价差+安装基准期价差)*0.8|3.35|65590.7485|41832100000|||否|否|||否|0|
|
||||
|31yqbmpi6znm|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpi6znk|2.2|招标费|B2||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|1.24|30347.958261|41832200000|||否|否||线路长度超过500km时,超过部分每增加100km,费率乘以0.92系数 |否|6|
|
||||
|31yqbmpkow00|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpi6znk|2.3|工程监理费|B3||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|3.1|75869.895653|41832300000|||否|否||说明:162号文指导费率区间:2.71%-2.73%;35kV及以上箱式变电站按每站1.5-3.5万元计列。|否|6|
|
||||
|31yqbmpkow01|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpi6znk|2.4|设备材料监造费|B4||监造材料费|0|0|41832400000|||否|否|||否|6|
|
||||
|31yqbmpkow02|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpi6znk|2.5|施工过程造价咨询及竣工结算审核费|B5||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|0.46|11258.113548|41832500000|||否|否||费用计算低于3000元时,按3000元计列。|否|6|
|
||||
|31yqbmpn6scg|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpi6znk|2.6|工程保险费|B6|||100|0|41832600000|||否|否|||否|6|
|
||||
|31yqbmpn6sch|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}||3|项目建设技术服务费|C|||100|463215.689047|41833000000|||否|否|||否|6|
|
||||
|31yqbmpn6sci|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sch|3.1|项目前期工作费|C1||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|0.94|23005.710295|41833100000|||否|否|||否|6|
|
||||
|31yqbmppooow|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.1|可行性研究费用|C11|||100|0|41833110000|||否|否||说明:162号文指导费用区间:12万元-20万元;20km以上,增加0.5万元/km;多回路、高海拔等可调整。|否|6|
|
||||
|31yqbmppooox|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.2|环境影响评价费用|C12|||100|0|41833120000|||否|否||说明:162号文指导费用区间:5万元-8万元;20km以上,增加0.25万元/km;穿越环境敏感区、平行走廊等可调整。|否|6|
|
||||
|31yqbmppoooy|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.3|建设项目规划选址费|C13|||100|0|41833130000|||否|否||说明:162号文指导费用区间:3万元-10万元;20km以上,增加0.1万元/km;平行走廊等可调整。|否|6|
|
||||
|31yqbmppoooz|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.4|水土保持方案编审费用|C14|||100|0|41833140000|||否|否||说明:162号文指导费用区间:3万元-6万元;20km以上,增加0.2万元/km;平行走廊等可调整。|否|6|
|
||||
|31yqbmps6l1c|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.5|地质灾害危险性评估费用|C15|||100|0|41833150000|||否|否||说明:162号文指导费用区间:2万元-3万元;20km以上,增加0.15万元/km;平行走廊等可调整。|否|6|
|
||||
|31yqbmps6l1d|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.6|地震安全性评价费用|C16|||100|0|41833160000|||否|否||说明:线路工程原则上不计此费用|否|6|
|
||||
|31yqbmps6l1e|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.7|文物调查费用|C17|||100|0|41833170000|||否|否||说明:162号文指导费用区间:3万元-8万元;20km以上,增加0.05-0.15万元/km;平行走廊等可调整。|否|6|
|
||||
|31yqbmpuohds|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.8|矿产压覆评估费用|C18|||100|0|41833180000|||否|否||说明:162号文指导费用区间:4万元-8万元;20km以上,增加0.1-0.3万元/km;平行走廊等可调整。|否|6|
|
||||
|31yqbmpuohdt|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.9|用地预审费用|C19|||100|0|41833190000|||否|否||说明:162号文指导费用区间:5万元-12万元;20km以上,增加0.1-0.3万元/km;平行走廊等可调整。|否|6|
|
||||
|31yqbmpuohdu|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.10|节能评估费用|C1A|||100|0|418331A0000|||否|否||说明:162号文指导费用区间:2万元-5万元;20km以上,增加0.01-0.05万元/km;平行走廊等可调整。|否|6|
|
||||
|31yqbmpx6dq8|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.11|社会稳定风险评估费用|C1B|||100|0|418331B0000|||否|否||说明:162号文指导费用区间:5万元-10万元;20km以上,增加0.01-0.05万元/km;平行走廊等可调整。|否|6|
|
||||
|31yqbmpx6dq9|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.12|使用林地可行性研究费用|C1C|||100|0|418331C0000|||否|否||说明:162号文指导费用区间:3万元-5万元;20km以上,增加0.1万元/km。|否|6|
|
||||
|31yqbmpzoa2o|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sci|3.1.13|前期工作管理费用|C1D|||100|0|418331D0000|||否|否||说明:162号文指导费用:10万元;单独的变电站、换流站、输电线路工程按40%-60%调整|否|6|
|
||||
|31yqbmpzoa2p|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sch|3.2|知识产权转让与研究试验费|C2|||100|0|41833200000|||否|否||根据建设项目法人提出的项目和费用计列。|否|6|
|
||||
|31yqbmpzoa2q|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sch|3.3|勘察设计费|C3|||100|429686.09|41833300000|||否|否|||否|6|
|
||||
|31yqbmpzoa2r|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpzoa2q|3.3.1|勘察费|C31||勘察费|100|219018.33|41833310000|||否|否|||否|6|
|
||||
|31yqbmq266f4|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpzoa2q|3.3.2|设计费|C32||设计费|100|210667.76|41833320000|||否|否|||否|6|
|
||||
|31yqbmq266f5|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sch|3.4|设计文件评审费|C4|||100|0|41833400000|||否|否|||否|6|
|
||||
|31yqbmq266f6|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmq266f5|3.4.1|可行性研究文件评审费|C41||可行性研究评审费|0|0|41833410000|||否|否|||否|6|
|
||||
|31yqbmq4o2rk|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmq266f5|3.4.2|初步设计文件评审费|C42||初步设计评审费|0|0|41833420000|||否|否|||否|6|
|
||||
|31yqbmq75z40|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmq266f5|3.4.3|施工图文件评审费|C43||施工图评审费|0|0|41833430000|||否|否|||否|6|
|
||||
|31yqbmq75z41|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sch|3.5|项目后评价费|C5||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|0|0|41833500000|||否|否||单项输变电工程,建筑工程费+安装工程费低于2000万元,取费基数取2000万元。|否|6|
|
||||
|31yqbmq9nvgg|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sch|3.6|工程建设检测费|C6|||100|8076.472763|41833600000|||否|否|||否|6|
|
||||
|31yqbmq9nvgh|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmq9nvgg|3.6.1|电力工程质量检测费|C61||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|0.33|8076.472763|41833610000|||否|否|||否|6|
|
||||
|31yqbmq9nvgi|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmq9nvgg|3.6.2|特种设备安全监测费|C62|||100|0|41833620000|||否|否|||否|6|
|
||||
|31yqbmq9nvgj|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmq9nvgg|3.6.3|环境监测及环境保护验收费|C63|||100|0|41833630000|||否|否|||否|6|
|
||||
|31yqbmqc5rsw|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmq9nvgg|3.6.4|水土保持监测及验收费|C64|||100|0|41833640000|||否|否|||否|6|
|
||||
|31yqbmqc5rsx|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmq9nvgg|3.6.5|桩基检测费|C65|||100|0|41833650000|||否|否|||否|6|
|
||||
|31yqbmqc5rsy|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmpn6sch|3.7|电力工程技术经济标准编制费|C7||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|0.1|2447.415989|41833700000|||否|否|||否|6|
|
||||
|31yqbmqc5rsz|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}||4|生产准备费|D|||100|45784.837568|41834000000|||否|否|||否|0|
|
||||
|31yqbmqeno5c|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmqc5rsz|4.1|管理车辆购置费|D1||设备购置费|0.75|18373.778493|41834100000|||否|否||注:如果管理车辆由项目法人单位统一配置,并且不在工程项目中分摊相关费用时,本项费用不计。|否|13|
|
||||
|31yqbmqeno5d|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmqc5rsz|4.2|工器具及办公家具购置费|D2||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|1.07|26187.35108|41834200000|||否|否|||否|13|
|
||||
|31yqbmqeno5e|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmqc5rsz|4.3|生产职工培训及提前进场费|D3||建筑工程费+安装工程费+建筑基准期价差+安装基准期价差|0.05|1223.707994|41834300000|||否|否|||否|0|
|
||||
|31yqbmqh5khs|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}||5|专业爆破服务费|E|||100|0|41835000000|||否|否|||否|0|
|
||||
|31yqbmqjngu8|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}||6|其他|F|||100|18000|41836000000|||否|否|||否|0|
|
||||
|31yqbmqjngu9|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmqjngu8|6.1|白蚁防治费|||360*50|100|18000|41836100000|||否|否|||否|0|
|
||||
|31yqbmqjngua|其他费用|{3A3B6448-D486-4D0C-8074-28554CD36003}|31yqbmqjngu8|6.2|余土消纳费|||(1182.96+33.66+549.575)*15*0|100|0|41836200000|||否|否|||否|0|
|
||||
@@ -0,0 +1,29 @@
|
||||
# 大型土石方取费表_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{0552C4D6-A240-43D7-87E7-459F6AE73E96}|FFZ1|||一|否|100|直接工程费|取费表||{5714D95B-6C68-4D36-B406-6A564D9CA88F}|
|
||||
|{26103E34-3F0C-412B-AAA5-C94AA076C6F9}|RGF|取费定额人工费||1|否|100|人工费|取费表|{0552C4D6-A240-43D7-87E7-459F6AE73E96}|{5714D95B-6C68-4D36-B406-6A564D9CA88F}|
|
||||
|{6F6328CA-D4D9-483C-85E9-D711CE0BB952}|CLF|取费定额乙供材料费不含税+取费定额甲供材料费含税+乙供取费主材费不含税+甲供取费主材费含税||2|否|100|材料费|取费表|{0552C4D6-A240-43D7-87E7-459F6AE73E96}|{5714D95B-6C68-4D36-B406-6A564D9CA88F}|
|
||||
|{6D3985D1-998B-45DA-8BF5-CEA701D55488}|JXF|取费定额机械费||3|否|100|施工机械使用费|取费表|{0552C4D6-A240-43D7-87E7-459F6AE73E96}|{5714D95B-6C68-4D36-B406-6A564D9CA88F}|
|
||||
|{54F88EF2-20E5-4D27-8A44-A486B15EABCC}|TZHQF|FFZ1-甲供消材进项税额-甲供主材进项税额|综合取费费用额(包含措施费、间接费、利润)|二|否|17.79|综合取费费用额|取费表||{5714D95B-6C68-4D36-B406-6A564D9CA88F}|
|
||||
|{774F581D-FD7C-468E-9E3C-4794C4566764}|TFFS|FFZ1+TZHQF-取费定额甲供材料费含税-甲供取费主材费含税+不取费定额费不含税-不取费甲供材料费不含税+不取费乙供主材费不含税||三|否|9|税金|取费表||{5714D95B-6C68-4D36-B406-6A564D9CA88F}|
|
||||
|{EC65C030-D4EC-4AB1-8BB5-D76F494B903C}|THJ|FFZ1+TZHQF+TFFS+一笔性费用+不取费定额费不含税+不取费乙供主材费不含税+不取费甲供材料进项税额+不取费甲供主材费含税||四|否|100|合计|取费表||{5714D95B-6C68-4D36-B406-6A564D9CA88F}|
|
||||
@@ -0,0 +1,53 @@
|
||||
# 安装取费表_取费表
|
||||
备注:取费表是取费设置中各取费表明细。查询示例: SELECT Rate FROM FeeCollectionTable WHERE Name = 'findname'。
|
||||
- 字段名称:_id
|
||||
- 字段名称:代码
|
||||
- 备注:编号,代码,代号
|
||||
- 字段名称:取费基数
|
||||
- 备注:公式,计算式,表达式
|
||||
- 字段名称:备注
|
||||
- 备注:备注,说明
|
||||
- 字段名称:序号
|
||||
- 备注:费用序号,序号,序列号
|
||||
- 字段名称:是否隐藏
|
||||
- 字段名称:费率
|
||||
- 备注:费用利率,费率
|
||||
- 字段名称:费用名称
|
||||
- 备注:项目名,费用名,名称
|
||||
- 字段名称:nodeType
|
||||
- 字段名称:parentId
|
||||
- 字段名称:relTbId
|
||||
|
||||
|_id|代码|取费基数|备注|序号|是否隐藏|费率|费用名称|nodeType|parentId|relTbId|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|{528A23DF-84DF-4A5B-A4F7-3C36946DF10A}|FFZ|||一|否|100|直接费|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{75484B7F-B129-41AC-AC84-951103432A04}|FFZ1|||1|否|100|直接工程费|取费表|{528A23DF-84DF-4A5B-A4F7-3C36946DF10A}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{17192AC1-6F06-4105-98DB-50AAE16FC96D}|DZF|||1.1|否|100|定额直接费|取费表|{75484B7F-B129-41AC-AC84-951103432A04}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{2E0927DF-D1FB-4887-BCD5-843795984C8B}|RGF|取费定额人工费||1.1.1|否|100|人工费|取费表|{17192AC1-6F06-4105-98DB-50AAE16FC96D}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{3F14A3F1-592D-4DAA-AEF6-D77189EEA27B}|CLF|取费定额乙供材料费不含税||1.1.2|否|100|材料费|取费表|{17192AC1-6F06-4105-98DB-50AAE16FC96D}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{18BCC5DA-CF04-4A18-A212-8224412370DC}|JXF|取费定额机械费||1.1.3|否|100|施工机械使用费|取费表|{17192AC1-6F06-4105-98DB-50AAE16FC96D}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{77E89796-F47F-4764-B025-C9DDFD66F7A8}|ZZCF|||1.2|否|100|装置性材料费|取费表|{75484B7F-B129-41AC-AC84-951103432A04}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{3EB92E69-6132-42B6-B337-E8719BD3C514}|JZZCF|甲供取费主材费含税||1.2.1|否|100|甲供装置性材料费|取费表|{77E89796-F47F-4764-B025-C9DDFD66F7A8}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{70487150-31DD-492F-9800-81BFC2E4785A}|YZZCF|乙供取费主材费不含税||1.2.2|否|100|乙供装置性材料费|取费表|{77E89796-F47F-4764-B025-C9DDFD66F7A8}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{B46790E9-FCEB-47B6-955D-7607B48B5852}|FFZ2|||2|否|100|措施费|取费表|{528A23DF-84DF-4A5B-A4F7-3C36946DF10A}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{A74A4ACD-0A40-4E60-8181-61E0C321E0CB}|DYF|取费定额人工费||2.1|否|2.76|冬雨季施工增加费|取费表|{B46790E9-FCEB-47B6-955D-7607B48B5852}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{F048D93A-A7F9-442F-A8B7-C60B8920706E}|YSF|DZF||2.2|否|0.61|夜间施工增加费|取费表|{B46790E9-FCEB-47B6-955D-7607B48B5852}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{45914735-E941-4AD3-B34B-8B57EF794A5E}|SYF|取费定额人工费||2.3|否|3.72|施工工具用具使用费|取费表|{B46790E9-FCEB-47B6-955D-7607B48B5852}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{A1EF2086-2D48-43CF-A0CF-30EE0D70E2C2}|TDF|取费定额人工费||2.4|否|0|特殊地区施工增加费|取费表|{B46790E9-FCEB-47B6-955D-7607B48B5852}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{1D26BA7A-9B13-410F-AF86-124DD5D5369A}|LSF|DZF||2.5|否|11.96|临时设施费|取费表|{B46790E9-FCEB-47B6-955D-7607B48B5852}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{8C5B56B8-1235-488D-BBBC-FCB872EE4592}|ZYF|取费定额人工费||2.6|否|1.64|施工机构迁移费|取费表|{B46790E9-FCEB-47B6-955D-7607B48B5852}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{F6A33651-2AEE-4283-BBC9-0CE08B866C1E}|BZF|FFZ1-甲供主材进项税额||2.7|否|3.25|安全文明施工费|取费表|{B46790E9-FCEB-47B6-955D-7607B48B5852}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{6F501364-0378-4CCB-9A04-BE6340B19991}|FFJ|||二|否|100|间接费|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{7212DD7F-FFC7-498F-BFE4-20A63ECA49D8}|GF|||1|否|100|规费|取费表|{6F501364-0378-4CCB-9A04-BE6340B19991}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{3C4A6C2B-42D4-4CC1-982E-9C76DC96F733}|BZHF|取费定额人工费*1.07||1.1|否|22.78|社会保险费|取费表|{7212DD7F-FFC7-498F-BFE4-20A63ECA49D8}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{B8673C1F-7F8F-4A36-8008-8A82AC9A0622}|GJJ|取费定额人工费*1.07||1.2|否|12|住房公积金|取费表|{7212DD7F-FFC7-498F-BFE4-20A63ECA49D8}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{457FB6CD-B6F4-4DDF-B4A0-F4CAD491612E}|GLF|取费定额人工费||2|否|38.25|企业管理费|取费表|{6F501364-0378-4CCB-9A04-BE6340B19991}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{61A369DF-8125-4BF1-88D9-A63CBBCE7845}|FFR|FFZ+FFJ-甲供主材进项税额||三|否|5|利润|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{A5F09649-F305-4436-B7AF-288CB99F0794}|FFS|FFZ+FFJ+FFR-甲供取费主材费含税+不取费定额费不含税+不取费乙供主材费不含税||四|否|9|税金|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{C5DAB4C1-1654-4401-80FB-223F90D96C85}|SBF|||五|否|100|设备费|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{47015E81-839B-42CD-A9CF-E754BA553820}|SBY|乙供设备费不含税+乙供设备税金||1|否|100|乙供设备不含税价|取费表|{C5DAB4C1-1654-4401-80FB-223F90D96C85}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{1F498CC3-FE40-4136-83E8-1E32F8D9E3D0}|SBJ|甲供设备费含税||2|否|100|甲供设备含税价|取费表|{C5DAB4C1-1654-4401-80FB-223F90D96C85}|{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{F62B9907-1D45-4B09-BE14-0E28010C0CF3}|AZF|DZF+FFZ2+FFJ+FFR+FFS+不取费定额费不含税+一笔性费用||六|否|100|安装费|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{E6E222E9-67B4-474D-AEB3-10F0191B04B9}|ZCF|ZZCF+不取费乙供主材费不含税+不取费甲供主材费含税||七|否|100|主材费|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{0398F2A8-7BED-49F9-8EF1-79C0C28DA7D9}|ZJ|AZF+ZCF+SBF||八|否|100|总计|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
|{8C5B0866-AF80-42ED-82E0-AE5E17703DCC}|HJ|ZJ-SBF||九|否|100|合计|取费表||{5B1AC3D7-E59C-4AB2-8350-8A9D1649E2CE}|
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user