1、修改api文件位置

2、意图识别继承langfuse
This commit is contained in:
2025-08-27 11:22:54 +08:00
parent 53ac47f4a5
commit c9c7f13060
12 changed files with 1385 additions and 1321 deletions
+9 -4
View File
@@ -1,11 +1,10 @@
OPENAI_API_KEY=sk-xxaiabmfhzwwpijuledllkmkzhzwsqeicjxmjwnvriqpwmpk
OPENAI_API_BASE=https://api.siliconflow.cn/v1/ OPENAI_API_BASE=https://api.siliconflow.cn/v1/
MODEL_NAME=deepseek-ai/DeepSeek-V3 MODEL_NAME=deepseek-ai/DeepSeek-V3
MINI_MODEL_NAME=Qwen/Qwen2.5-72B-Instruct-128K
XINFERENCE_URL=http://10.1.16.39:9995
RERANKER_MODEL_NAME=bge-reranker-v2-m3 RERANKER_MODEL_NAME=bge-reranker-v2-m3
EMBEDDING_MODEL_NAME=bge-m3 EMBEDDING_MODEL_NAME=bge-m3
XINFERENCE_URL=http://10.1.16.39:9995
DIFY_BSAE_URL=http://10.1.16.39/v1 DIFY_BSAE_URL=http://10.1.16.39/v1
DIFY_APP_KEY=app-CPoOMaGDsLRPAe9TW7Xjhszy DIFY_APP_KEY=app-CPoOMaGDsLRPAe9TW7Xjhszy
@@ -15,4 +14,10 @@ DIFY_PG_HOST = 10.1.16.39
DIFY_PG_PORT = 5432 DIFY_PG_PORT = 5432
DIFY_PG_USER = postgres DIFY_PG_USER = postgres
DIFY_PG_PASSWORD = difyai123456 DIFY_PG_PASSWORD = difyai123456
DIFY_PG_DATABASE = dify DIFY_PG_DATABASE = dify
ENABLE_LANGFUSE=true
LANGFUSE_PUBLIC_KEY=pk-lf-4e9b7cbe-528c-4697-b73c-33257a60072c
LANGFUSE_SECRET_KEY=sk-lf-cd8a78c5-2538-455e-a85a-87b6e1aa69d0
LANGFUSE_HOST=http://10.1.6.34:3000
+3 -5
View File
@@ -32,8 +32,6 @@ dependencies = [
"xlsxwriter>=3.2.5", "xlsxwriter>=3.2.5",
] ]
[[project.source]] [[tool.uv.index]]
name = "aliyun" url = "https://mirrors.aliyun.com/pypi/simple"
url = "https://mirrors.aliyun.com/pypi/simple/" default = true
type = "index"
priority = 1
@@ -44,6 +44,7 @@ class RetrieveRequest(BaseModel):
data_set_list: str data_set_list: str
query_expand_dict: dict | str = Field(default="{}") query_expand_dict: dict | str = Field(default="{}")
topk: int = Field(default=4) topk: int = Field(default=4)
metadata_filtering_conditions : dict = Field(default={})
# 创建FastAPI应用 # 创建FastAPI应用
app = FastAPI( app = FastAPI(
@@ -103,7 +104,8 @@ async def retrieve(request: RetrieveRequest):
query_list, query_list,
data_set_list, data_set_list,
query_expand_dict=query_expand_dict, query_expand_dict=query_expand_dict,
top_k=request.topk top_k=request.topk,
metadata_filtering_conditions=request.metadata_filtering_conditions
) )
end_time = time.time() end_time = time.time()
@@ -116,11 +118,11 @@ async def retrieve(request: RetrieveRequest):
if __name__ == "__main__": if __name__ == "__main__":
# 使用Uvicorn运行FastAPI应用 # 使用Uvicorn运行FastAPI应用
import uvicorn import uvicorn
uvicorn.run("rag2_0.dify.DifyQueryRetrieval_api:app", host="0.0.0.0", port=8002, reload=False, workers=1, log_level="info") uvicorn.run("rag2_0.api.DifyQueryRetrieval_api:app", host="0.0.0.0", port=9002, reload=False, workers=1, log_level="info")
# # 使用uvicorn启动服务 # # 使用uvicorn启动服务
# import uvicorn # import uvicorn
# uvicorn.run( # uvicorn.run(
# "rag2_0.dify.intent_recognition_api:app", # "rag2_0.api.DifyQueryRetrieval_api:app",
# host="0.0.0.0", # host="0.0.0.0",
# port=8001, # port=8001,
# reload=False, # 开发环境启用热重载 # reload=False, # 开发环境启用热重载
+14 -6
View File
@@ -23,12 +23,13 @@ class DifyQueryRetrieval:
datasets_json = datasets.json() datasets_json = datasets.json()
return {dataset["name"]:dataset for dataset in datasets_json["data"]} return {dataset["name"]:dataset for dataset in datasets_json["data"]}
def retrieve_by_dataset(self, query: str, dataset_name: str) -> Dict[str, Any]: def retrieve_by_dataset(self, query: str, dataset_name: str, metadata_filtering_conditions:dict = {}) -> Dict[str, Any]:
try: try:
dataset_id = self._datasets_list[dataset_name]["id"] dataset_id = self._datasets_list[dataset_name]["id"]
retrieval_model = self._datasets_list[dataset_name]["retrieval_model_dict"] retrieval_model = self._datasets_list[dataset_name]["retrieval_model_dict"]
knowledge_base_client = KnowledgeBaseClient(api_key=self._dify_dataset_key, base_url=self._dify_base_url, dataset_id=dataset_id) knowledge_base_client = KnowledgeBaseClient(api_key=self._dify_dataset_key, base_url=self._dify_base_url, dataset_id=dataset_id)
if len(metadata_filtering_conditions) !=0:
retrieval_model["metadata_filtering_conditions"]=metadata_filtering_conditions
documents = knowledge_base_client.retrieve(query, retrieval_model=retrieval_model, timeout=300) documents = knowledge_base_client.retrieve(query, retrieval_model=retrieval_model, timeout=300)
retrieved_documents = documents.json().get("records", []) retrieved_documents = documents.json().get("records", [])
@@ -51,7 +52,7 @@ class DifyQueryRetrieval:
"documents": [] "documents": []
} }
async def retrieve_by_dataset_async(self, query: str, dataset_name: str) -> Dict[str, Any]: async def retrieve_by_dataset_async(self, query: str, dataset_name: str, metadata_filtering_conditions:dict = {}) -> Dict[str, Any]:
""" """
异步版本的retrieve_by_dataset方法 异步版本的retrieve_by_dataset方法
@@ -67,7 +68,8 @@ class DifyQueryRetrieval:
return await asyncio.to_thread( return await asyncio.to_thread(
self.retrieve_by_dataset, self.retrieve_by_dataset,
query, query,
dataset_name dataset_name,
metadata_filtering_conditions
) )
except Exception as e: except Exception as e:
logging.error(f"异步检索数据集 {dataset_name} 时出错: {str(e)}", exc_info=True) logging.error(f"异步检索数据集 {dataset_name} 时出错: {str(e)}", exc_info=True)
@@ -77,7 +79,13 @@ class DifyQueryRetrieval:
"documents": [] "documents": []
} }
async def retrieve_api_async(self, original_query: str, query_list: List[str], data_set_list: List[str], query_expand_dict: dict, top_k: int = 5)->Dict[str, Any]: async def retrieve_api_async(self,
original_query: str,
query_list: List[str],
data_set_list: List[str],
query_expand_dict: dict,
top_k: int = 5,
metadata_filtering_conditions:dict = {})->Dict[str, Any]:
""" """
异步版本的retrieve_api方法,使用asyncio代替线程池 异步版本的retrieve_api方法,使用asyncio代替线程池
@@ -105,7 +113,7 @@ class DifyQueryRetrieval:
continue continue
# 创建异步任务 # 创建异步任务
task = self.retrieve_by_dataset_async(query, dataset) task = self.retrieve_by_dataset_async(query, dataset, metadata_filtering_conditions)
tasks.append(task) tasks.append(task)
# 并发执行所有异步任务 # 并发执行所有异步任务
+76 -25
View File
@@ -19,6 +19,8 @@ import jieba
import time import time
import threading import threading
from langchain_openai import ChatOpenAI
from .PromptTemplates import (classification_prompt, query_rewrite_prompt_pro, from .PromptTemplates import (classification_prompt, query_rewrite_prompt_pro,
extract_nouns_prompt, classification_info, extract_nouns_prompt, classification_info,
slot_filling_prompt, step_back_prompt, slot_filling_prompt, step_back_prompt,
@@ -32,7 +34,10 @@ from .DataModels import (
StepBackPrompt, HypotheticalDocument StepBackPrompt, HypotheticalDocument
) )
from .ProfessionalNounVector import ProfessionalNounRetriever, AsyncProfessionalNounRetriever from .ProfessionalNounVector import ProfessionalNounRetriever, AsyncProfessionalNounRetriever
from rag2_0.tool.ModelTool import XinferenceReRankerModel, OpenAiLLM from rag2_0.tool.APIKeyManager import APIKeyManager
TEMPERATURE = 0.4
TOP_P = 0.7
class AsyncIntentRecognizer: class AsyncIntentRecognizer:
SOFT_WIKI_PATH = "data/wiki_data" SOFT_WIKI_PATH = "data/wiki_data"
@@ -59,21 +64,6 @@ class AsyncIntentRecognizer:
model_name: 要使用的模型名称 model_name: 要使用的模型名称
vector_index_dir: 向量索引目录,如果为None则使用默认目录 vector_index_dir: 向量索引目录,如果为None则使用默认目录
""" """
api_key = os.getenv("OPENAI_API_KEY")
base_url = os.getenv("OPENAI_API_BASE")
model_name = os.getenv("MODEL_NAME", "gpt-3.5-turbo")
# 初始化LLM
llm_params = {
"temperature": 0.4, # 降低随机性,使结果更确定
"top_p": 0.7,
"model": model_name,
"api_key": api_key,
"base_url": base_url
}
self._llm = OpenAiLLM(**llm_params)
llm_params["model"] = os.getenv("MINI_MODEL_NAME", "gpt-3.5-turbo")
self._llm_mini = OpenAiLLM(**llm_params)
# 加载suffix关键词 # 加载suffix关键词
self._suffix_keywords = self._load_suffix_keywords() self._suffix_keywords = self._load_suffix_keywords()
@@ -199,7 +189,15 @@ class AsyncIntentRecognizer:
# 解析输出 # 解析输出
try: try:
# 异步调用LLM # 异步调用LLM
response = await self._llm.invoke_async(formatted_prompt, False) llm = ChatOpenAI(
api_key=APIKeyManager.get_api_key(),
openai_api_base=os.getenv("OPENAI_API_BASE"),
model_name=os.getenv("MODEL_NAME"),
temperature=TEMPERATURE,
top_p=TOP_P
)
llm.with_structured_output(Classification)
response = await llm.ainvoke(formatted_prompt)
# 尝试直接解析JSON响应 # 尝试直接解析JSON响应
response.content = response.content.strip() response.content = response.content.strip()
@@ -266,8 +264,17 @@ class AsyncIntentRecognizer:
terms_list_parser = PydanticOutputParser(pydantic_object=TermList) terms_list_parser = PydanticOutputParser(pydantic_object=TermList)
formatted_prompt = formatted_prompt.replace("{output_format}", terms_list_parser.get_format_instructions()) formatted_prompt = formatted_prompt.replace("{output_format}", terms_list_parser.get_format_instructions())
llm = ChatOpenAI(
api_key=APIKeyManager.get_api_key(),
openai_api_base=os.getenv("OPENAI_API_BASE"),
model_name=os.getenv("MODEL_NAME"),
temperature=TEMPERATURE,
top_p=TOP_P
)
llm.with_structured_output(TermList)
# 异步调用LLM # 异步调用LLM
response = await self._llm.invoke_async(formatted_prompt, False) response = await llm.ainvoke(formatted_prompt)
# 尝试使用Pydantic解析器解析TermList # 尝试使用Pydantic解析器解析TermList
response.content = response.content.strip() response.content = response.content.strip()
@@ -349,7 +356,16 @@ class AsyncIntentRecognizer:
""" """
try: try:
response = await self._llm.invoke_async(prompt, False, response_format={"type": "json_object"})
llm = ChatOpenAI(
api_key=APIKeyManager.get_api_key(),
openai_api_base=os.getenv("OPENAI_API_BASE"),
model_name=os.getenv("MODEL_NAME"),
temperature=TEMPERATURE,
top_p=TOP_P
)
response = await llm.ainvoke(prompt, response_format={"type": "json_object"})
response.content = response.content.strip() response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL) clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = JsonOutputParser().parse(clean_output) parsed_output = JsonOutputParser().parse(clean_output)
@@ -389,8 +405,17 @@ class AsyncIntentRecognizer:
context=context) context=context)
# 解析输出 # 解析输出
try: try:
llm = ChatOpenAI(
api_key=APIKeyManager.get_api_key(),
openai_api_base=os.getenv("OPENAI_API_BASE"),
model_name=os.getenv("MODEL_NAME"),
temperature=TEMPERATURE,
top_p=TOP_P
)
llm.with_structured_output(QueryRewrite)
# 异步调用LLM # 异步调用LLM
response = await self._llm.invoke_async(formatted_prompt, False) response = await llm.ainvoke(formatted_prompt)
response.content = response.content.strip() response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL) clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = query_rewrite_parser.parse(clean_output) parsed_output = query_rewrite_parser.parse(clean_output)
@@ -634,8 +659,18 @@ class AsyncIntentRecognizer:
previous_slots=json.dumps(previous_slots,ensure_ascii=False), previous_slots=json.dumps(previous_slots,ensure_ascii=False),
) )
try: try:
llm = ChatOpenAI(
api_key=APIKeyManager.get_api_key(),
openai_api_base=os.getenv("OPENAI_API_BASE"),
model_name=os.getenv("MODEL_NAME"),
temperature=TEMPERATURE,
top_p=TOP_P
)
llm.with_structured_output(slot_model_class)
# 异步调用LLM # 异步调用LLM
response = await self._llm.invoke_async(formatted_prompt, False) response = await llm.ainvoke(formatted_prompt)
response.content = response.content.strip() response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL) clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
# 尝试解析LLM响应 # 尝试解析LLM响应
@@ -669,10 +704,17 @@ class AsyncIntentRecognizer:
) )
try: try:
llm = ChatOpenAI(
api_key=APIKeyManager.get_api_key(),
openai_api_base=os.getenv("OPENAI_API_BASE"),
model_name=os.getenv("MODEL_NAME"),
temperature=TEMPERATURE,
top_p=TOP_P
)
llm.with_structured_output(StepBackPrompt)
# 异步调用LLM # 异步调用LLM
response = await self._llm.invoke_async(formatted_prompt, False) response = await llm.ainvoke(formatted_prompt)
# 解析输出
response.content = response.content.strip() response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL) clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = step_back_parser.parse(clean_output) parsed_output = step_back_parser.parse(clean_output)
@@ -728,9 +770,18 @@ class AsyncIntentRecognizer:
""" """
try: try:
llm = ChatOpenAI(
api_key=APIKeyManager.get_api_key(),
openai_api_base=os.getenv("OPENAI_API_BASE"),
model_name=os.getenv("MODEL_NAME"),
temperature=TEMPERATURE,
top_p=TOP_P,
)
# 异步调用LLM # 异步调用LLM
start_time = time.time() start_time = time.time()
response = await self._llm.invoke_async(prompt, False, response_format={"type": "json_object"}) response = await llm.ainvoke(prompt, response_format={"type": "json_object"})
end_time = time.time() end_time = time.time()
# 解析JSON响应 # 解析JSON响应
+1 -1
View File
@@ -10,7 +10,7 @@ else
# 启动一个名为AnswerType的screen会话,并在其中执行后续命令 # 启动一个名为AnswerType的screen会话,并在其中执行后续命令
screen -dmS AnswerType bash -c " screen -dmS AnswerType bash -c "
cd \"$SCRIPT_DIR\" cd \"$SCRIPT_DIR\"
uv run uvicorn rag2_0.dify.AnswerType:app --host 0.0.0.0 --port 8003 --workers 1 uv run uvicorn rag2_0.api.AnswerType_api:app --host 0.0.0.0 --port 8003 --workers 1
" "
# 输出提示信息 # 输出提示信息
+1 -1
View File
@@ -10,7 +10,7 @@ else
# 启动一个名为DifyQueryRetrieval_api的screen会话,并在其中执行后续命令 # 启动一个名为DifyQueryRetrieval_api的screen会话,并在其中执行后续命令
screen -dmS DifyQueryRetrieval_api bash -c " screen -dmS DifyQueryRetrieval_api bash -c "
cd \"$SCRIPT_DIR\" cd \"$SCRIPT_DIR\"
uv run uvicorn rag2_0.dify.DifyQueryRetrieval_api:app --host 0.0.0.0 --port 8002 --workers 25 uv run uvicorn rag2_0.api.DifyQueryRetrieval_api:app --host 0.0.0.0 --port 8002 --workers 25
" "
# 输出提示信息 # 输出提示信息
+1 -1
View File
@@ -10,7 +10,7 @@ else
# 启动一个名为intent_recognition_api的screen会话,并在其中执行后续命令 # 启动一个名为intent_recognition_api的screen会话,并在其中执行后续命令
screen -dmS intent_recognition_api bash -c " screen -dmS intent_recognition_api bash -c "
cd \"$SCRIPT_DIR\" cd \"$SCRIPT_DIR\"
uv run uvicorn rag2_0.dify.intent_recognition_api:app --host 0.0.0.0 --port 8001 --workers 25 uv run uvicorn rag2_0.api.intent_recognition_api:app --host 0.0.0.0 --port 8001 --workers 25
" "
# 输出提示信息 # 输出提示信息
Generated
+1275 -1275
View File
File diff suppressed because it is too large Load Diff