初次提交

This commit is contained in:
lzy
2025-05-09 14:16:33 +08:00
commit 3a50afeec4
56 changed files with 9224 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
"""
Test script for PubChem tools
This script tests the search_pubchem_advanced function from the chemistry_mcp module.
"""
import sys
sys.path.append('/home/ubuntu/sas0/lzy/multi_mcp_server')
import asyncio
from sci_mcp.chemistry_mcp.pubchem_tools.pubchem_tools import _search_by_formula
from sci_mcp.chemistry_mcp import search_pubchem_advanced
async def test_search_by_name():
"""Test searching compounds by name"""
print("\n=== Testing search by name ===")
result = await search_pubchem_advanced(name="Aspirin")
print(result)
async def test_search_by_smiles():
"""Test searching compounds by SMILES notation"""
print("\n=== Testing search by SMILES ===")
# SMILES for Caffeine
result = await search_pubchem_advanced(smiles="CN1C=NC2=C1C(=O)N(C(=O)N2C)C")
print(result)
async def test_search_by_formula():
"""Test searching compounds by molecular formula"""
print("\n=== Testing search by formula ===")
# Formula for Aspirin
result = await search_pubchem_advanced(formula="C9H8O4", max_results=2)
print(result)
async def test_complex_formula():
"""Test searching with a more complex formula that might cause timeout"""
print("\n=== Testing complex formula search ===")
# A more complex formula that might return many results
result = await search_pubchem_advanced(
formula="C6H12O6", # Glucose and isomers
max_results=5
)
print(result)
async def test_complex_molecules():
"""Test searching for complex molecules with rich molecular features"""
print("\n=== Testing complex molecules with rich features ===")
# 1. Paclitaxel (Taxol) - Complex anticancer drug with many rotatable bonds and H-bond donors/acceptors
print("\n--- Testing Paclitaxel (anticancer drug) ---")
result = await search_pubchem_advanced(name="Paclitaxel")
print(result)
# 2. Vancomycin - Complex antibiotic with many H-bond donors/acceptors
print("\n--- Testing Vancomycin (antibiotic) ---")
result = await search_pubchem_advanced(name="Vancomycin")
print(result)
# 3. Cholesterol - Steroid with complex ring structure
print("\n--- Testing Cholesterol (steroid) ---")
result = await search_pubchem_advanced(name="Cholesterol")
print(result)
# 4. Ibuprofen - Common NSAID with rotatable bonds
print("\n--- Testing Ibuprofen (NSAID) ---")
result = await search_pubchem_advanced(name="Ibuprofen")
print(result)
# 5. Amoxicillin - Antibiotic with multiple functional groups
print("\n--- Testing Amoxicillin (antibiotic) ---")
result = await search_pubchem_advanced(name="Amoxicillin")
print(result)
async def test_molecules_by_smiles():
"""Test searching for complex molecules using SMILES notation"""
print("\n=== Testing complex molecules by SMILES ===")
# 1. Atorvastatin (Lipitor) - Cholesterol-lowering drug with complex structure
print("\n--- Testing Atorvastatin (Lipitor) ---")
result = await search_pubchem_advanced(
smiles="CC(C)C1=C(C(=C(C=C1)C(C)C)C2=CC(=C(C=C2)F)F)C(CC(CC(=O)O)O)NC(=O)C3=CC=C(C=C3)F"
)
print(result)
# 2. Morphine - Opioid with multiple rings and H-bond features
print("\n--- Testing Morphine ---")
result = await search_pubchem_advanced(
smiles="CN1CCC23C4C1CC5=C2C(=C(C=C5)O)OC3C(C=C4)O"
)
print(result)
async def test_invalid_search():
"""Test searching with invalid parameters"""
print("\n=== Testing invalid search ===")
# No parameters provided
result = await search_pubchem_advanced()
print(result)
# Invalid SMILES
print("\n=== Testing invalid SMILES ===")
result = await search_pubchem_advanced(smiles="INVALID_SMILES_STRING")
print(result)
async def run_all_tests():
"""Run all test functions"""
await test_search_by_name()
await test_search_by_smiles()
await test_search_by_formula()
await test_complex_formula()
# await test_complex_molecules()
# await test_molecules_by_smiles()
#await test_invalid_search()
# from sci_mcp.chemistry_mcp.pubchem_tools.pubchem_tools import _search_by_name
# compounds=await _search_by_formula('C6H12O6')
# print(compounds[0])
if __name__ == "__main__":
print("Testing PubChem search tools...")
asyncio.run(run_all_tests())
print("\nAll tests completed.")
# import pubchempy
# compunnds = pubchempy.get_compounds('Aspirin', 'name')
# print(compunnds[0].to_dict())

View File

@@ -0,0 +1,159 @@
"""
Test script for RDKit tools.
This script tests the functionality of the RDKit tools implemented in the
sci_mcp/chemistry_mcp/rdkit_tools module.
"""
import sys
import os
# Add the project root directory to the Python path
sys.path.append('/home/ubuntu/sas0/lzy/multi_mcp_server')
from sci_mcp.chemistry_mcp.rdkit_tools.rdkit_tools import (
calculate_molecular_properties,
calculate_drug_likeness,
calculate_topological_descriptors,
generate_molecular_fingerprints,
calculate_molecular_similarity,
analyze_molecular_structure,
generate_molecular_conformer,
identify_scaffolds,
convert_between_chemical_formats,
standardize_molecule,
enumerate_stereoisomers,
perform_substructure_search
)
def test_molecular_properties():
"""Test the calculation of molecular properties."""
print("Testing calculate_molecular_properties...")
# Aspirin
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
result = calculate_molecular_properties(smiles)
print(result)
print("-" * 80)
def test_drug_likeness():
"""Test the calculation of drug-likeness properties."""
print("Testing calculate_drug_likeness...")
# Aspirin
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
result = calculate_drug_likeness(smiles)
print(result)
print("-" * 80)
def test_topological_descriptors():
"""Test the calculation of topological descriptors."""
print("Testing calculate_topological_descriptors...")
# Aspirin
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
result = calculate_topological_descriptors(smiles)
print(result)
print("-" * 80)
def test_molecular_fingerprints():
"""Test the generation of molecular fingerprints."""
print("Testing generate_molecular_fingerprints...")
# Aspirin
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
result = generate_molecular_fingerprints(smiles, fingerprint_type="morgan")
print(result)
print("-" * 80)
def test_molecular_similarity():
"""Test the calculation of molecular similarity."""
print("Testing calculate_molecular_similarity...")
# Aspirin and Ibuprofen
smiles1 = "CC(=O)OC1=CC=CC=C1C(=O)O" # Aspirin
smiles2 = "CC(C)CC1=CC=C(C=C1)C(C)C(=O)O" # Ibuprofen
result = calculate_molecular_similarity(smiles1, smiles2)
print(result)
print("-" * 80)
def test_molecular_structure():
"""Test the analysis of molecular structure."""
print("Testing analyze_molecular_structure...")
# Aspirin
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
result = analyze_molecular_structure(smiles)
print(result)
print("-" * 80)
def test_molecular_conformer():
"""Test the generation of molecular conformers."""
print("Testing generate_molecular_conformer...")
# Aspirin
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
result = generate_molecular_conformer(smiles)
print(result)
print("-" * 80)
def test_scaffolds():
"""Test the identification of molecular scaffolds."""
print("Testing identify_scaffolds...")
# Aspirin
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
result = identify_scaffolds(smiles)
print(result)
print("-" * 80)
def test_format_conversion():
"""Test the conversion between chemical formats."""
print("Testing convert_between_chemical_formats...")
# Aspirin
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
result = convert_between_chemical_formats(smiles, "smiles", "inchi")
print(result)
print("-" * 80)
def test_standardize_molecule():
"""Test the standardization of molecules."""
print("Testing standardize_molecule...")
# Betaine with charges
smiles = "C[N+](C)(C)CC(=O)[O-]"
result = standardize_molecule(smiles)
print(result)
print("-" * 80)
def test_stereoisomers():
"""Test the enumeration of stereoisomers."""
print("Testing enumerate_stereoisomers...")
# 3-penten-2-ol (has both a stereocenter and a stereobond)
smiles = "CC(O)C=CC"
result = enumerate_stereoisomers(smiles)
print(result)
print("-" * 80)
def test_substructure_search():
"""Test the substructure search."""
print("Testing perform_substructure_search...")
# Aspirin, search for carboxylic acid group
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"
pattern = "C(=O)O"
result = perform_substructure_search(smiles, pattern)
print(result)
print("-" * 80)
def main():
"""Run all tests."""
print("Testing RDKit tools...\n")
# Uncomment the tests you want to run
test_molecular_properties()
test_drug_likeness()
test_topological_descriptors()
test_molecular_fingerprints()
test_molecular_similarity()
test_molecular_structure()
test_molecular_conformer()
test_scaffolds()
test_format_conversion()
test_standardize_molecule()
test_stereoisomers()
test_substructure_search()
print("All tests completed.")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,289 @@
"""
测试RXN工具函数模块
此模块包含用于测试rxn_tools模块中化学反应预测和分析工具函数的测试用例。
"""
import asyncio
import sys
import os
from pathlib import Path
from rich.console import Console
# 添加项目根目录到Python路径
sys.path.append('/home/ubuntu/sas0/lzy/multi_mcp_server')
from sci_mcp.chemistry_mcp.rxn_tools.rxn_tools import (
predict_reaction_outcome_rxn,
predict_reaction_topn_rxn,
predict_reaction_properties_rxn,
extract_reaction_actions_rxn
)
# 创建控制台对象用于格式化输出
console = Console()
async def test_predict_reaction_outcome():
"""测试反应结果预测功能"""
console.print("[bold cyan]测试反应结果预测功能[/bold cyan]")
# 使用固定参数:溴和蒽的反应
fixed_reactants = "BrBr.c1ccc2cc3ccccc3cc2c1"
console.print(f"固定反应物: {fixed_reactants}")
try:
result = await predict_reaction_outcome(fixed_reactants)
console.print("[green]结果:[/green]")
console.print(result)
except Exception as e:
console.print(f"[bold red]错误:[/bold red] {str(e)}")
async def test_predict_reaction_topn():
"""测试多产物预测功能"""
console.print("\n[bold cyan]测试多产物预测功能[/bold cyan]")
# 测试1单个反应字符串格式
fixed_reactants = "C=CC=O.CN" # 丙烯醛和甲胺
fixed_topn = 2
console.print(f"测试1 - 单个反应(字符串格式)")
console.print(f"固定反应物: {fixed_reactants}")
console.print(f"固定预测产物数量: {fixed_topn}")
try:
result = await predict_reaction_topn(fixed_reactants, fixed_topn)
console.print("[green]结果:[/green]")
console.print(result)
except Exception as e:
console.print(f"[bold red]错误:[/bold red] {str(e)}")
# 测试2单个反应列表格式
fixed_reactants_list = ["BrBr", "c1ccc2cc3ccccc3cc2c1"] # 溴和蒽
console.print(f"\n测试2 - 单个反应(列表格式)")
console.print(f"固定反应物: {fixed_reactants_list}")
console.print(f"固定预测产物数量: {fixed_topn}")
try:
result = await predict_reaction_topn(fixed_reactants_list, fixed_topn)
console.print("[green]结果:[/green]")
console.print(result)
except Exception as e:
console.print(f"[bold red]错误:[/bold red] {str(e)}")
# 测试3多个反应列表的列表格式
fixed_reactants_batch = [
["BrBr", "c1ccc2cc3ccccc3cc2c1"], # 溴和蒽
["BrBr", "c1ccc2cc3ccccc3cc2c1CCO"] # 溴和修饰的蒽
]
console.print(f"\n测试3 - 多个反应(列表的列表格式)")
console.print(f"固定反应物批量: {fixed_reactants_batch}")
console.print(f"固定预测产物数量: {fixed_topn}")
try:
result = await predict_reaction_topn(fixed_reactants_batch, fixed_topn)
console.print("[green]结果:[/green]")
console.print(result)
except Exception as e:
console.print(f"[bold red]错误:[/bold red] {str(e)}")
console.print(f"[bold red]错误:[/bold red] {str(e)}")
async def test_predict_retrosynthesis():
"""测试逆合成分析功能"""
console.print("\n[bold cyan]测试逆合成分析功能[/bold cyan]")
# 使用固定参数:阿司匹林的逆合成分析
fixed_target_molecule = "CC(=O)OC1=CC=CC=C1C(=O)O" # 阿司匹林
fixed_max_steps = 1
console.print(f"固定目标分子: {fixed_target_molecule}")
console.print(f"固定最大步骤数: {fixed_max_steps}")
try:
result = await predict_retrosynthesis(fixed_target_molecule, fixed_max_steps)
console.print("[green]结果:[/green]")
console.print(result)
except Exception as e:
console.print(f"[bold red]错误:[/bold red] {str(e)}")
async def test_predict_biocatalytic_retrosynthesis():
"""测试生物催化逆合成分析功能"""
console.print("\n[bold cyan]测试生物催化逆合成分析功能[/bold cyan]")
# 使用固定参数:一个可能适合酶催化的分子
fixed_target_molecule = "OC1C(O)C=C(Br)C=C1"
console.print(f"固定目标分子: {fixed_target_molecule}")
try:
result = await predict_biocatalytic_retrosynthesis(fixed_target_molecule)
console.print("[green]结果:[/green]")
console.print(result)
except Exception as e:
console.print(f"[bold red]错误:[/bold red] {str(e)}")
async def test_predict_reaction_properties():
"""测试反应属性预测功能"""
console.print("\n[bold cyan]测试反应属性预测功能[/bold cyan]")
# 使用固定参数:原子映射
fixed_reaction = "CC(C)S.CN(C)C=O.Fc1cccnc1F.O=C([O-])[O-].[K+].[K+]>>CC(C)Sc1ncccc1F"
fixed_property_type = "atom-mapping"
console.print(f"固定反应: {fixed_reaction}")
console.print(f"固定属性类型: {fixed_property_type}")
try:
result = await predict_reaction_properties(fixed_reaction, fixed_property_type)
console.print("[green]结果:[/green]")
console.print(result)
except Exception as e:
console.print(f"[bold red]错误:[/bold red] {str(e)}")
async def test_extract_reaction_actions():
"""测试从文本提取反应步骤功能"""
console.print("\n[bold cyan]测试从文本提取反应步骤功能[/bold cyan]")
# 使用固定参数:从文本描述中提取反应步骤
fixed_reaction_text = """To a stirred solution of 7-(difluoromethylsulfonyl)-4-fluoro-indan-1-one (110 mg, 0.42 mmol) in methanol (4 mL) was added sodium borohydride (24 mg, 0.62 mmol). The reaction mixture was stirred at ambient temperature for 1 hour."""
console.print(f"固定反应文本: {fixed_reaction_text}")
try:
result = await extract_reaction_actions(fixed_reaction_text)
console.print("[green]结果:[/green]")
console.print(result)
except Exception as e:
console.print(f"[bold red]错误:[/bold red] {str(e)}")
async def test_all():
"""测试所有RXN工具函数"""
console.print("[bold magenta]===== 开始测试RXN工具函数 =====[/bold magenta]\n")
# 测试各个功能
await test_predict_reaction_outcome()
await test_predict_reaction_topn()
await test_predict_retrosynthesis()
await test_predict_biocatalytic_retrosynthesis()
await test_predict_reaction_properties()
await test_extract_reaction_actions()
console.print("\n[bold magenta]===== RXN工具函数测试完成 =====[/bold magenta]")
def get_rxn_tool_questions():
"""
获取为RXN工具函数生成的问题列表
这些问题设计为能够引导大模型调用相应的工具函数
Returns:
包含工具名称和对应问题的字典
"""
questions = {
"predict_reaction_outcome": [
"如果我将溴和蒽混合在一起,会形成什么产物?",
"乙酸和乙醇反应会生成什么?",
"预测一下丙烯醛和甲胺反应的结果"
],
"predict_reaction_topn": [
"丙烯醛和甲胺反应可能生成哪几种主要产物?",
"预测溴和蒽反应可能的前3个产物",
"乙酸和乙醇反应可能有哪些不同的结果?请给出最可能的几种产物"
],
"predict_retrosynthesis": [
"如何合成阿司匹林?请给出可能的合成路线",
"对于分子CC(=O)OC1=CC=CC=C1C(=O)O有哪些可能的合成路径",
"请分析一下布洛芬的可能合成路线"
],
"predict_biocatalytic_retrosynthesis": [
"有没有可能用酶催化合成OC1C(O)C=C(Br)C=C1这个分子",
"请提供一种使用生物催化方法合成对羟基苯甲醇的路线",
"我想用酶催化方法合成一些复杂分子能否分析一下OC1C(O)C=C(Br)C=C1的可能合成路径"
],
"predict_reaction_properties": [
"在这个反应中CC(C)S.CN(C)C=O.Fc1cccnc1F.O=C([O-])[O-].[K+].[K+]>>CC(C)Sc1ncccc1F原子是如何映射的",
"这个反应的产率可能是多少Clc1ccccn1.Cc1ccc(N)cc1>>Cc1ccc(Nc2ccccn2)cc1",
"能分析一下这个反应中原子的去向吗CC(=O)O.CCO>>CC(=O)OCC"
],
"extract_reaction_actions": [
"能否将这段实验描述转换为结构化的反应步骤?'To a stirred solution of 7-(difluoromethylsulfonyl)-4-fluoro-indan-1-one (110 mg, 0.42 mmol) in methanol (4 mL) was added sodium borohydride (24 mg, 0.62 mmol). The reaction mixture was stirred at ambient temperature for 1 hour.'",
"请从这段文本中提取出具体的反应操作步骤:'A solution of benzoic acid (1.0 g, 8.2 mmol) in thionyl chloride (10 mL) was heated under reflux for 2 hours. The excess thionyl chloride was removed under reduced pressure to give benzoyl chloride as a colorless liquid.'",
"帮我解析这个实验步骤,提取出关键操作:'The aldehyde (5 mmol) was dissolved in methanol (20 mL) and sodium borohydride (7.5 mmol) was added portionwise at 0°C. The mixture was allowed to warm to room temperature and stirred for 3 hours.'"
]
}
return questions
def update_agent_test_questions():
"""
更新agent_test.py中的工具问题字典添加RXN工具函数的问题
"""
try:
# 获取agent_test.py文件路径
agent_test_path = Path('/home/ubuntu/sas0/lzy/multi_mcp_server/test_tools/agent_test.py')
# 读取文件内容
with open(agent_test_path, 'r') as f:
content = f.read()
# 获取RXN工具函数的问题
rxn_questions = get_rxn_tool_questions()
# 检查文件中是否已包含RXN工具函数的问题
rxn_tools_exist = any(tool in content for tool in rxn_questions.keys())
if not rxn_tools_exist:
# 找到questions字典的结束位置
dict_end_pos = content.find(' return questions')
if dict_end_pos != -1:
# 构建要插入的RXN工具函数问题
rxn_questions_str = ""
for tool_name, questions_list in rxn_questions.items():
rxn_questions_str += f'\n "{tool_name}": [\n'
for q in questions_list:
rxn_questions_str += f' "{q}",\n'
rxn_questions_str += ' ],'
# 在字典结束前插入RXN工具函数问题
new_content = content[:dict_end_pos] + rxn_questions_str + content[dict_end_pos:]
# 写回文件
with open(agent_test_path, 'w') as f:
f.write(new_content)
console.print("[green]成功更新agent_test.py添加了RXN工具函数的测试问题[/green]")
else:
console.print("[yellow]无法找到questions字典的结束位置未更新agent_test.py[/yellow]")
else:
console.print("[yellow]agent_test.py中已包含RXN工具函数的问题无需更新[/yellow]")
except Exception as e:
console.print(f"[bold red]更新agent_test.py时出错:[/bold red] {str(e)}")
if __name__ == "__main__":
# 运行所有测试
# asyncio.run(test_all())
# # 更新agent_test.py中的工具问题
# update_agent_test_questions()
api_key = 'apk-8928522a146c2503f30b16d9909222d7583f412ee8f1049f08d32a089ba88d34'
from rxn4chemistry import RXN4ChemistryWrapper
rxn4chemistry_wrapper = RXN4ChemistryWrapper(api_key=api_key)
rxn4chemistry_wrapper.create_project('test_wrapper')
response = rxn4chemistry_wrapper.predict_automatic_retrosynthesis(
'Brc1c2ccccc2c(Br)c2ccccc12')
results = rxn4chemistry_wrapper.get_predict_automatic_retrosynthesis_results(response['prediction_id'])
print(results['status'])
# NOTE: upon 'SUCCESS' you can inspect the predicted retrosynthetic paths.
print(results['retrosynthetic_paths'][0])