Compare commits

..

3 Commits

10 changed files with 80 additions and 66 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
--- ---
description: description:
globs: globs:
alwaysApply: true alwaysApply: false
--- ---
背景入门 背景入门
您是 Claude 3.7,并且已集成到 Cursor IDE(一个基于 AI 的 VS Code 分支)。由于您拥有强大的功能,您往往过于急躁,经常在没有明确请求的情况下实施更改,并自以为比我更了解代码,从而破坏了现有逻辑。这会导致代码出现不可接受的灾难。在我的代码库上工作时——无论是 Web 应用程序、数据管道、嵌入式系统还是任何其他软件项目——您未经授权的修改都可能引入细微的 bug 并破坏关键功能。为了避免这种情况,您必须遵循以下严格协议: 您是 Claude 3.7,并且已集成到 Cursor IDE(一个基于 AI 的 VS Code 分支)。由于您拥有强大的功能,您往往过于急躁,经常在没有明确请求的情况下实施更改,并自以为比我更了解代码,从而破坏了现有逻辑。这会导致代码出现不可接受的灾难。在我的代码库上工作时——无论是 Web 应用程序、数据管道、嵌入式系统还是任何其他软件项目——您未经授权的修改都可能引入细微的 bug 并破坏关键功能。为了避免这种情况,您必须遵循以下严格协议:
+31 -11
View File
@@ -1,13 +1,3 @@
sk-jnnmltwtqwuoyagoogzzeraczmyfxhoairiddgayksqdfnbr
sk-eghuepxnbcollzrjwbzqvbnhiiwagkejaclyhvaodeqgwrog
sk-poszkbjdmamimconjustnrxxqusuzlryxkrzkpronlenrmen
sk-zolvcegarsrwqhwgvwzgtqupodsdmckjiocyvoyldbkusbzc
sk-ywfafulcniaqdgdcsnbtqquaqeuiqlkcnknkaflwxyuemcow
sk-hhedmocgtfpywbbpwamgfkygrahiqsuurntlbqqbmjwfipmm
sk-gzdqfoyvulrqscdpjlwlufdecrsyjpmwpkknuhnjsvtyftox
sk-bkcufidsebujopqqwexwxwpmevrpelmvxzdymncvllcyojce
sk-olabhscekudzkyudypkcjvehwqunagubwdmtppugrjmcptwv
sk-zpdqyocliebhqpkuwvebpgcnfjdkvavdltimllmgkthwnwph
sk-uollmeyatyiwfzszvxkpyndmzfrbqjpyixewmrastbmaqbhy sk-uollmeyatyiwfzszvxkpyndmzfrbqjpyixewmrastbmaqbhy
sk-xdlsjytiwilvodadkjxvwdgulhhdytkqvfpyrcnllclgzqkb sk-xdlsjytiwilvodadkjxvwdgulhhdytkqvfpyrcnllclgzqkb
sk-ffkltifkylutornjhwmnmfjsqsywrjibvujhjtjctzgnkvlp sk-ffkltifkylutornjhwmnmfjsqsywrjibvujhjtjctzgnkvlp
@@ -57,4 +47,34 @@ sk-wswttgfrxrwijvqhctfilhvlxgdkgogrjhvjkdbzvqrocofa
sk-jdijeubeygjmqtxwryrbwmrpvqawinzwpcxodpolhcupzmpa sk-jdijeubeygjmqtxwryrbwmrpvqawinzwpcxodpolhcupzmpa
sk-xbloemctsowwicjvrtrrewreosnfojoijtygsfxfnjntridv sk-xbloemctsowwicjvrtrrewreosnfojoijtygsfxfnjntridv
sk-isovavcefvkzlbjewnumeqqevmnoucojsxwskkitfktkemtq sk-isovavcefvkzlbjewnumeqqevmnoucojsxwskkitfktkemtq
sk-vxrlvvdzgythgyycuqehdloubxcdwhgojpowgxvgxsstjtvk sk-vxrlvvdzgythgyycuqehdloubxcdwhgojpowgxvgxsstjtvk
sk-krgctzbdqekohpowmvftsjswgpxnwxadezeosdspelmtmukx
sk-slcgfmphmbqwuvshoaygfkfaxpzcabtlpkhvfqjodajuynsl
sk-qwcrwwxsdmiirrzvwfijgxqupdutypjfldtvikdwkqgwfucs
sk-nyynzajaubwtezsznzcfzzsevmfgpyjrsstckxeufrvzwwej
sk-ksyqqkwbcecqgforztombghpeknrlqdkegtzeezsnhtcpchy
sk-inhqizoumyusllkpovvokdfwvyavcpgpjtxcwrbcftquiqpv
sk-peqxiflijgltfxbyxyfquvuzrfcwlkauvjfkbexgndtwoyqf
sk-ohukjjrxmqmlrdmvyuudkpysblupmfjojnuyzwjkknvnjagg
sk-nmvrynrwqtvrnbdgaeexxrsskjvmsffjbbvikpsmngypwuwn
sk-ruecsoljheouotepobjeeenminndcwwyjdoquqrcxfirmxmt
sk-mtfoqujosppodwgdcbwyglsfylkhtydoyzfnzxfomndpcuyf
sk-uicolvfebfhklerkcfcgymcasqafamthlemhaqqnvqugorfg
sk-zxvqmszvbktxjsgbtuafrxkdebmdjhfijeohhepkguatgpos
sk-vmuaaesfvsvrljroauzysfqydsksklrrrenzhrtxvvqwcewl
sk-ewjtqzbiqmlihkpjqkppwackeswuvbqyzsheaversvsdqisz
sk-zmebjdwdbpyxtribyuusdgaojlvnwqnjpxdcawibmtgsnlrp
sk-vrijdtzxzroipovgowdqrahhiicptgwvdhkmmrcmubuukxca
sk-sqaflqxtnyliiyrkcxxotgksfettijawpkhvfqnaavqtjvrg
sk-koawwrtemsnjvyakmhrykdindvbxjbxuyfqunjqsoymlrsrr
sk-izjhcaimcsrsgytxvlaanrfxzmhpqiclbokhmhnzkrdicknv
sk-tfcrtsrzqeftrdaebdhmfzkwkchqjltkcutqoeeclmnoeemr
sk-jfqkxsfmnyynybqvzkkwmzwxcyjebgdeucdmodunitjgydhv
sk-rutrnfpicpzxnqloqgxgenevcooqyxibbdguvywuqcbpwyjt
sk-jrqvdlkrkwzdfiuvqlmgncblfaihwkhgshukwkxatsrclsfe
sk-rruiajpnseboawytxmvvughdqcrkqlqsjlrcfopwztljfiox
sk-neiwqzlwfxxdrjvictvlbvpkbbpbmyiooddevhnqkerzugpy
sk-zfqdpybvyeutrdwenvfbsehfebkaekoytpqcltulseavtntb
sk-sbcjflkkwscfxzrplbexxifgqtrotnaxtvuoqfrtfyrvhnhr
sk-jpkxknfffbucdhnqahowbpcwdhbrjaqfvrbgnekdyxiflqlu
sk-ylyjcnumxpwxolrwjpzvomlnmezwgxagobztqbjdylohxsvb
+1 -2
View File
@@ -26356,8 +26356,7 @@
{ {
"name": "取消关联父级量", "name": "取消关联父级量",
"synonymous": [ "synonymous": [
"取消组合件和消耗量", "取消组合件和消耗量"
"清单与消耗量或者消耗量之间的父子级关系"
], ],
"description": "解除消耗量与父级工程量关联的功能,使消耗量不随父级工程量数量变化" "description": "解除消耗量与父级工程量关联的功能,使消耗量不随父级工程量数量变化"
}, },
Binary file not shown.
Binary file not shown.
+20 -34
View File
@@ -16,7 +16,7 @@ from tqdm import tqdm
import time import time
import sys import sys
import argparse import argparse
from typing import List, Dict, Any, Optional from typing import List, Dict, Any
from langchain.output_parsers import PydanticOutputParser from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
sys.path.append(os.getcwd()) sys.path.append(os.getcwd())
@@ -28,7 +28,7 @@ from rag2_0.tool.ModelTool import OpenAiLLM
load_dotenv() load_dotenv()
# 示例查询 # 示例查询
examples_query = """ PE2211PK0801是什么软件""" examples_query = """T1软件中,配件和材料有什么区别"""
conversation_context="" conversation_context=""
chat_history=[ chat_history=[
{ {
@@ -102,41 +102,30 @@ class QueryRewriteProcessor:
doc_text_list = json.dumps(retrieved_doc, ensure_ascii=False, indent=2) doc_text_list = json.dumps(retrieved_doc, ensure_ascii=False, indent=2)
class TempModel(BaseModel): class TempModel(BaseModel):
can_solve_problem: bool = Field(description="是否能解用户问题") can_solve_problem: bool = Field(description="是否能解用户问题")
relevance_score: int = Field(description="相关性评分,0-100分") relevance_score: int = Field(description="置信度评分,0-100分")
explanation: str = Field(description="解释文档是否能解决(回答)提问") explanation: str = Field(description="解释文档是否能解决(回答)提问")
class all_relevant_document(BaseModel): class all_relevant_document(BaseModel):
most_relevant_document: list[TempModel] = Field(description="最相关的文档的判断结果") document_list: list[TempModel] = Field(description="每个文档的判断结果")
parser = PydanticOutputParser(pydantic_object=all_relevant_document) parser = PydanticOutputParser(pydantic_object=all_relevant_document)
# 构建提示词 # 构建提示词
prompt = f"""请判断以下检索文档列表中是否用户提问相关,能够解决用户的问题,并给出相关性评分(0-100分)。输出最相关的文档的判断结果。 prompt = f"""请判断以下检索文档列表中是否解答用户提问,能够解决用户的问题,能够基于检索文档给出回答,并给出置信度评分(0-100分)。输出每个文档的判断结果。
用户提问: {query}
用户提问: {query} 检索文档列表:
{doc_text_list}
检索文档列表: 请按照以下JSON格式返回结果:
{doc_text_list} {parser.get_format_instructions()}
"""
请按照以下JSON格式返回结果:
json```
{{
"most_relevant_document":[{{
"can_solve_problem": true,
"relevance_score": 60,
"explanation":"xxxx"
}}]
}}
```
"""
try: try:
# 初始化LLM并调用 # 初始化LLM并调用
llm = OpenAiLLM(api_key=self.api_key, base_url=self.base_url, model="deepseek-ai/DeepSeek-R1", response_format={"type": "json_object"}) llm = OpenAiLLM(api_key=self.api_key, base_url=self.base_url, model="deepseek-ai/DeepSeek-R1")
response = llm.invoke(prompt) response = llm.invoke(prompt)
result_list = parser.parse(response.content).most_relevant_document result_list = parser.parse(response.content).document_list
# 如果列表为空,返回默认的不相关结果 # 如果列表为空,返回默认的不相关结果
if not result_list: if not result_list:
@@ -145,9 +134,11 @@ json```
"explanation": "无法解析文档相关性结果", "explanation": "无法解析文档相关性结果",
"relevance_score": 0.0 "relevance_score": 0.0
} }
true_document_list=[cur for cur in result_list if cur.can_solve_problem]
if len(true_document_list)==0:
true_document_list = result_list
# 找出分数最高的文档 # 找出分数最高的文档
max_score_doc = max(result_list, key=lambda x: x.relevance_score) max_score_doc = max(true_document_list, key=lambda x: x.relevance_score)
return { return {
"is_relevant": max_score_doc.can_solve_problem, "is_relevant": max_score_doc.can_solve_problem,
@@ -155,12 +146,7 @@ json```
"explanation": max_score_doc.explanation "explanation": max_score_doc.explanation
} }
except Exception as e: except Exception as e:
logging.error(f"判断文档相关性时出错: {str(e)}", exc_info=True) raise e
return {
"is_relevant": False,
"explanation": f"判断过程出错: {str(e)}",
"relevance_score": 0.0
}
def load_questions_from_excel(self, file_path=None): def load_questions_from_excel(self, file_path=None):
""" """
@@ -254,7 +240,7 @@ json```
"槽位信息": slot_filling_str, "槽位信息": slot_filling_str,
"检索的文档": "\n".join(retrieved_doc_titles), "检索的文档": "\n".join(retrieved_doc_titles),
"检索的内容": json.dumps(retrieved_doc, ensure_ascii=False, indent=2) if retrieved_doc else "", "检索的内容": json.dumps(retrieved_doc, ensure_ascii=False, indent=2) if retrieved_doc else "",
"文档是否相关": "相关" if relevance_result["is_relevant"] else "相关", "文档能否解决问题": "" if relevance_result["is_relevant"] else "",
"文档相关性解释": relevance_result["explanation"] "文档相关性解释": relevance_result["explanation"]
} }
except Exception as e: except Exception as e:
+4 -4
View File
@@ -251,12 +251,12 @@ class ExcelDataValidator:
format_instructions = parser.get_format_instructions() format_instructions = parser.get_format_instructions()
prompt = f""" prompt = f"""
背景:用户正在使用电力造价软件,提出的问题可能涉及电力造价软件的使用帮助,也可能涉及电力造价专业知识。我针对用户问题检索了相关内容,请评估这些检索内容是否与问题相关、是否准确 背景:用户正在使用电力造价软件,提出的问题可能涉及电力造价软件的使用帮助,也可能涉及电力造价专业知识。我针对用户问题检索了相关内容,请评估这些检索内容是否能解答提问
问题改写: {rewrite} 问题改写: {rewrite}
检索内容: {content} 检索内容: {content}
检索内容应该与问题主题相关,能够提供有用的信息来回答问题。请分析检索内容是否相关、准确,并以JSON格式返回结果。请提供一个0到1之间的置信度得分,表示你对判断的确信程度。 检索内容应该与问题主题相关,能够提供有用的信息来回答问题。请分析检索内容是否能解答提问、准确,并以JSON格式返回结果。请提供一个0到1之间的置信度得分,表示你对判断的确信程度。
{format_instructions} {format_instructions}
""" """
@@ -393,7 +393,7 @@ class ExcelDataValidator:
if self.debug: if self.debug:
logging.info(f" 验证检索内容...") logging.info(f" 验证检索内容...")
result = self.validate_retrieve_content(llm, rewrite, retrieve_content) result = self.validate_retrieve_content(llm, query, retrieve_content)
if isinstance(result, tuple) and len(result) >= 3: if isinstance(result, tuple) and len(result) >= 3:
is_correct, error_reason, retrieve_confidence = result[:3] is_correct, error_reason, retrieve_confidence = result[:3]
confidence_score = max(confidence_score, retrieve_confidence) confidence_score = max(confidence_score, retrieve_confidence)
@@ -555,8 +555,8 @@ def main():
parser.add_argument("--input", "-i", type=str, help="输入Excel文件路径", default=input_excel) parser.add_argument("--input", "-i", type=str, help="输入Excel文件路径", default=input_excel)
parser.add_argument("--output", "-o", type=str, help="输出结果Excel文件路径", default=output_excel) parser.add_argument("--output", "-o", type=str, help="输出结果Excel文件路径", default=output_excel)
parser.add_argument("--workers", "-w", type=int, default=20, help="并行工作线程数") parser.add_argument("--workers", "-w", type=int, default=20, help="并行工作线程数")
logging.info(f"输入文件路径: {args.input}, 输出文件路径: {args.output}, 并行工作线程数: {args.workers}")
args = parser.parse_args() args = parser.parse_args()
logging.info(f"输入文件路径: {args.input}, 输出文件路径: {args.output}, 并行工作线程数: {args.workers}")
is_debug = hasattr(sys, 'gettrace') and sys.gettrace() is not None is_debug = hasattr(sys, 'gettrace') and sys.gettrace() is not None
# 创建验证器实例并执行验证 # 创建验证器实例并执行验证
+5 -2
View File
@@ -1,16 +1,19 @@
from flask import Flask, request, Response from flask import Flask, request, Response
import os import os
from dotenv import load_dotenv from dotenv import load_dotenv
from rag2_0.intent_recognition import IntentRecognizer
import json import json
import time import time
import threading import threading
import datetime import datetime
import logging import logging
# 加载环境变量 # 加载环境变量
load_dotenv() load_dotenv()
import sys
sys.path.append(os.getcwd())
from rag2_0.intent_recognition import IntentRecognizer
logging.basicConfig( logging.basicConfig(
level=logging.INFO, level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
@@ -10,28 +10,32 @@ Description: 多轮对话下意图分类、改写核心提示词
query_rewrite_prompt_pro=""" query_rewrite_prompt_pro="""
# 电力造价问答优化工程师(精简版) # 电力造价问答优化工程师(精简版)
**角色**:基于历史对话和术语库重构问题,提升知识库检索准确率。 **角色**:基于历史对话和术语库重构问题,提升知识库检索准确率。
最高准则:保持问题核心意图,但允许在指代消除、背景继承下添加隐含功能词。但重构后的问题,所有引入的主体背景等均要来源于历史对话、聊天背景或术语库,不得凭空捏造未提及的内容。 **最高准则**
1、保持问题核心意图,但允许在指代消除、背景继承下添加隐含功能词。
2、重构后的问题,所有引入的主体背景等均要来源于历史对话、聊天背景,不得凭空捏造未提及的内容。
3、同义词替换:必须是提问中出现了synonymous中的内容,才替换为对应的标准词。不得改变原始意图,否则将导致系统出现灾难性问题
## 核心原则 ## 核心原则
1. **指代消除 → 当指示代词(""/"")出现时,强制继承历史对话的最新核心主题(如功能或任务),并应用到当前主体。** 1. **指代消除 → 当指示代词(""/"")出现时,强制继承历史对话的最新核心主题(如功能或任务),并应用到当前主体。**
2. 背景继承 → 补充历史对话和聊天背景中的隐含信息(包括主题和功能)。 2. 背景继承 → 补充历史对话和聊天背景中的隐含信息(包括主题和功能)。
4. 术语规范 → 同义词转标准词并【】标记。提问中的同义词(synonymous)替换为标准词(name) 3. 术语规范 → 同义词转标准词并【】标记。提问中出现的同义词(synonymous)替换为标准词(name)
5. 语义保真 → 保持问题核心意图,但允许在指代消除、背景继承下添加隐含功能词。 4. 语义保真 → 保持问题核心意图,但允许在指代消除、背景继承下添加隐含功能词。
## 处理流程 ## 处理流程
### 一、输入解析 ### 一、输入解析
- 原始问题(需保留核心语义): - 原始问题(需保留核心语义):
<query> <query> {query} </query>
{query}
</query> - 术语库集合(用于同义词转标准词环节):
- 术语库集合:
<keywords> <keywords>
{keywords} {keywords}
</keywords> </keywords>
- 历史对话记录: - 历史对话记录:
<history> <history>
{chat_history} {chat_history}
</history> </history>
- 当前聊天背景: - 当前聊天背景:
<conversation_background> <conversation_background>
{context} {context}
@@ -56,8 +60,8 @@ graph TD
1. **指代消除 → 当指示代词出现时,优先继承历史对话的核心主题(如功能词),并替换当前问题的动词部分。** 1. **指代消除 → 当指示代词出现时,优先继承历史对话的核心主题(如功能词),并替换当前问题的动词部分。**
2. 背景继承 → 历史对话中确定的背景信息需要保留。 2. 背景继承 → 历史对话中确定的背景信息需要保留。
3. 术语处理 → 同义词转标准词 + 【】标记。 3. 术语处理 → 同义词转标准词 + 【】标记。
4. 同义词转标准词 → 将提问中的同义词(synonymous)替换为标准词(name) 4. 同义词转标准词 → 将提问中出现的同义词(synonymous)替换为对应标准词(name)
4. 结构优化 → 保持原问题的5W2H特征,指代消除、背景继承下允许微调意图。 5. 结构优化 → 保持原问题的5W2H特征,指代消除、背景继承下允许微调意图。
## 输出规范 ## 输出规范
{output_format} {output_format}
+5 -3
View File
@@ -92,7 +92,7 @@ class APIKeyManager:
"Content-Type": "application/json" "Content-Type": "application/json"
} }
data = { data = {
"model": "deepseek-ai/DeepSeek-V3", "model": "Qwen/Qwen2.5-7B-Instruct",
"messages": [ "messages": [
{"role": "user", "content": "ping"} {"role": "user", "content": "ping"}
], ],
@@ -275,7 +275,7 @@ if __name__ == "__main__":
stats = instance.get_usage_stats() stats = instance.get_usage_stats()
all_balance=0.0 all_balance=0.0
buy_balance=14 * 10 * 14 # 购买18次,一次10条api_key,每个api_key有14元 buy_balance=17 * 10 * 14 # 购买18次,一次10条api_key,每个api_key有14元
invalid_api_keys = [] invalid_api_keys = []
for key, data in stats.items(): for key, data in stats.items():
usage_stats = APIKeyManager.get_key_usage_stats(key) usage_stats = APIKeyManager.get_key_usage_stats(key)
@@ -295,4 +295,6 @@ if __name__ == "__main__":
print(f"开始移除无效的API密钥,并重新保存") print(f"开始移除无效的API密钥,并重新保存")
APIKeyManager.remove_invalid_api_keys(invalid_api_keys) APIKeyManager.remove_invalid_api_keys(invalid_api_keys)
APIKeyManager.save_api_keys() APIKeyManager.save_api_keys()
print(f"移除无效的API密钥,并重新保存完成") print(f"移除无效的API密钥,并重新保存完成")
import datetime
print(f"当前时间:{datetime.datetime.now()}")