feat:添加demo,function call
This commit is contained in:
48
.env
Normal file
48
.env
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# LLM配置
|
||||||
|
MODEL_NAME="qwen3-max"
|
||||||
|
API_KEY="sk-7a1334a1e5f1449ca05f642d7f68590a"
|
||||||
|
BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
|
||||||
|
DASHSCOPE_MODEL_NAME="qwen3-vl-plus"
|
||||||
|
|
||||||
|
# 本地部署qwen3-14b模型配置(vLLM默认不需要API_KEY认证,但是需要提供任意值)
|
||||||
|
LOCAL_MODEL_NAME="qwen3-14b"
|
||||||
|
LOCAL_API_KEY="whatever_api_key"
|
||||||
|
LOCAL_BASE_URL="http://115.190.61.185:6008/v1"
|
||||||
|
|
||||||
|
# 向量模型配置
|
||||||
|
BGE_M3_MODEL_NAME="bge-m3"
|
||||||
|
BGE_M3_BASE_URL="http://115.190.61.185:6006/v1"
|
||||||
|
BGE_M3_API_KEY="whatever_api_key"
|
||||||
|
|
||||||
|
# 排序模型配置
|
||||||
|
BGE_RERANKER_MODEL_NAME="bge-reranker-v2-m3"
|
||||||
|
BGE_RERANKER_BASE_URL="http://115.190.61.185:8899/score"
|
||||||
|
|
||||||
|
# Mysql配置
|
||||||
|
MYSQL_HOST="115.190.61.185"
|
||||||
|
MYSQL_PORT="6033"
|
||||||
|
MYSQL_USER="root"
|
||||||
|
MYSQL_PASSWORD="liangfangxing123"
|
||||||
|
MYSQL_DATABASE="medical_assistant"
|
||||||
|
|
||||||
|
# ES配置
|
||||||
|
ES_HOST="https://115.190.61.185:9200"
|
||||||
|
ES_USERNAME="elastic"
|
||||||
|
ES_PASSWORD="v*0tedJ=PEhfYkHj8Lge"
|
||||||
|
|
||||||
|
# Milvus配置
|
||||||
|
MILVUS_HOST="115.190.61.185"
|
||||||
|
MILVUS_PORT="19530"
|
||||||
|
MILVUS_USER="root"
|
||||||
|
MILVUS_PASSWORD="liangfangxing123"
|
||||||
|
|
||||||
|
# Redis配置
|
||||||
|
REDIS_HOST="115.190.61.185"
|
||||||
|
REDIS_PORT="6379"
|
||||||
|
REDIS_PASSWORD="liangfangxing123"
|
||||||
|
RAG_CACHE_EXPIRE=36000
|
||||||
|
|
||||||
|
# 其他配置
|
||||||
|
MAX_DOC_LENGTH=5
|
||||||
|
FAQ_THRESHOLD=0.82
|
||||||
|
RECALL_THRESHOLD=0.5
|
||||||
79
conf.py
Normal file
79
conf.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
from pydantic_settings import BaseSettings
|
||||||
|
from pydantic import ConfigDict
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
APP_DIR = pathlib.Path(__file__).parent
|
||||||
|
|
||||||
|
|
||||||
|
class Settings(BaseSettings):
|
||||||
|
# LLM配置
|
||||||
|
model_name: str
|
||||||
|
api_key: str
|
||||||
|
base_url: str
|
||||||
|
dashscope_model_name:str
|
||||||
|
|
||||||
|
# 本地部署qwen3-14b模型配置
|
||||||
|
local_model_name: str
|
||||||
|
local_api_key: str
|
||||||
|
local_base_url: str
|
||||||
|
|
||||||
|
# 向量模型配置
|
||||||
|
bge_m3_model_name: str
|
||||||
|
bge_m3_base_url: str
|
||||||
|
bge_m3_api_key: str
|
||||||
|
|
||||||
|
# 排序模型配置
|
||||||
|
bge_reranker_model_name: str
|
||||||
|
bge_reranker_base_url: str
|
||||||
|
|
||||||
|
# Mysql配置
|
||||||
|
mysql_host: str
|
||||||
|
mysql_port: str
|
||||||
|
mysql_user: str
|
||||||
|
mysql_password: str
|
||||||
|
mysql_database: str
|
||||||
|
|
||||||
|
# ES配置
|
||||||
|
es_host: str
|
||||||
|
es_username: str
|
||||||
|
es_password: str
|
||||||
|
|
||||||
|
# ES配置
|
||||||
|
milvus_host: str
|
||||||
|
milvus_port: str
|
||||||
|
milvus_user: str
|
||||||
|
milvus_password: str
|
||||||
|
|
||||||
|
# Redis配置
|
||||||
|
redis_host: str
|
||||||
|
redis_port: str
|
||||||
|
redis_password: str
|
||||||
|
rag_cache_expire: int
|
||||||
|
|
||||||
|
# 其他配置
|
||||||
|
max_doc_length: int
|
||||||
|
faq_threshold: float
|
||||||
|
recall_threshold: float
|
||||||
|
|
||||||
|
|
||||||
|
# 映射配置文件的配置
|
||||||
|
model_config = ConfigDict(
|
||||||
|
extra='allow',
|
||||||
|
env_file=str(APP_DIR / '.env'),
|
||||||
|
case_sensitive=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
# @property
|
||||||
|
# def url(self):
|
||||||
|
# mysql_url = f"mysql+pymysql://{settings.mysql_user}:{self.mysql_password}@{self.mysql_host}:{self.mysql_port}/{self.mysql_database}"
|
||||||
|
# return mysql_url
|
||||||
|
|
||||||
|
|
||||||
|
settings = Settings()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print(APP_DIR)
|
||||||
|
print(settings.model_name)
|
||||||
|
print(settings.api_key)
|
||||||
|
print(settings.base_url)
|
||||||
69
demo_function_call/_@tool.py
Normal file
69
demo_function_call/_@tool.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
from langchain_openai import ChatOpenAI
|
||||||
|
from langchain_core.messages import HumanMessage, ToolMessage
|
||||||
|
from langchain_core.tools import tool
|
||||||
|
from conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
# todo: 第一步:定义工具函数
|
||||||
|
@tool
|
||||||
|
def add(a: int, b: int) -> int:
|
||||||
|
"""
|
||||||
|
将数字a与数字b相加
|
||||||
|
Args:
|
||||||
|
a: 第一个数字
|
||||||
|
b: 第二个数字
|
||||||
|
"""
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
@tool
|
||||||
|
def multiply(a: int, b: int) -> int:
|
||||||
|
"""
|
||||||
|
将数字a与数字b相乘
|
||||||
|
Args:
|
||||||
|
a: 第一个数字
|
||||||
|
b: 第二个数字
|
||||||
|
"""
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
# 定义 JSON 格式的工具 schema
|
||||||
|
tools = [add, multiply]
|
||||||
|
|
||||||
|
|
||||||
|
# todo: 第二步:初始化模型
|
||||||
|
llm = ChatOpenAI(
|
||||||
|
base_url=settings.base_url,
|
||||||
|
api_key=settings.api_key,
|
||||||
|
model=settings.model_name,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
# 绑定工具,允许模型自动选择工具
|
||||||
|
llm_with_tools = llm.bind_tools(tools, tool_choice="auto")
|
||||||
|
|
||||||
|
# todo: 第三步:调用回复
|
||||||
|
query = "2+1等于多少?"
|
||||||
|
messages = [HumanMessage(query)]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# todo: 第一次调用
|
||||||
|
ai_msg = llm_with_tools.invoke(messages)
|
||||||
|
messages.append(ai_msg)
|
||||||
|
print(f"\n第一轮调用后结果:\n{messages}")
|
||||||
|
|
||||||
|
# 处理工具调用
|
||||||
|
# 判断消息中是否有tool_calls,以判断工具是否被调用
|
||||||
|
if hasattr(ai_msg, 'tool_calls') and ai_msg.tool_calls:
|
||||||
|
for tool_call in ai_msg.tool_calls:
|
||||||
|
# todo: 处理工具调用
|
||||||
|
selected_tool = {"add": add, "multiply": multiply}[tool_call["name"].lower()]
|
||||||
|
tool_output = selected_tool.invoke(tool_call["args"]) # 需要使用invoke进行调用
|
||||||
|
messages.append(ToolMessage(content=tool_output, tool_call_id=tool_call["id"]))
|
||||||
|
print(f"\n第二轮 message中增加tool_output 之后:\n{messages}")
|
||||||
|
|
||||||
|
# todo: 第二次调用,将工具结果传回模型以生成最终回答
|
||||||
|
final_response = llm_with_tools.invoke(messages)
|
||||||
|
print(f"\n最终模型响应:\n{final_response.content}")
|
||||||
|
else:
|
||||||
|
print("模型未生成工具调用,直接返回文本:")
|
||||||
|
print(ai_msg.content)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"模型调用失败: {str(e)}")
|
||||||
83
demo_function_call/_pydantic.py
Normal file
83
demo_function_call/_pydantic.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
from langchain_openai import ChatOpenAI
|
||||||
|
from langchain_core.messages import HumanMessage, ToolMessage
|
||||||
|
"""
|
||||||
|
Pydantic 是一个 Python 库,用于数据验证和序列化。
|
||||||
|
它通过使用 Python 类型注解(type hints)来定义数据模型,
|
||||||
|
并提供强大的数据验证功能。Pydantic 基于 Python 的 dataclasses 和 typing 模块,
|
||||||
|
允许开发者定义结构化的数据模型,并自动验证输入数据是否符合指定的类型和约束。
|
||||||
|
"""
|
||||||
|
from pydantic.v1 import BaseModel, Field
|
||||||
|
|
||||||
|
from conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# todo: 第一步:定义工具函数
|
||||||
|
class Add(BaseModel):
|
||||||
|
"""
|
||||||
|
将两个数字相加
|
||||||
|
"""
|
||||||
|
a: int = Field(..., description="第一个数字")
|
||||||
|
b: int = Field(..., description="第二个数字")
|
||||||
|
|
||||||
|
def invoke(self, args):
|
||||||
|
# 验证参数
|
||||||
|
tool_instance = self.__class__(**args) # 自动验证 a 和 b
|
||||||
|
return tool_instance.a + tool_instance.b
|
||||||
|
|
||||||
|
class Multiply(BaseModel):
|
||||||
|
"""
|
||||||
|
将两个数字相乘
|
||||||
|
"""
|
||||||
|
a: int = Field(..., description="第一个数字")
|
||||||
|
b: int = Field(..., description="第二个数字")
|
||||||
|
|
||||||
|
def invoke(self, args):
|
||||||
|
# 验证参数
|
||||||
|
tool_instance = self.__class__(**args) # 自动验证 a 和 b
|
||||||
|
return tool_instance.a * tool_instance.b
|
||||||
|
|
||||||
|
# 定义 JSON 格式的工具 schema
|
||||||
|
tools = [Add, Multiply]
|
||||||
|
|
||||||
|
|
||||||
|
# todo: 第二步:初始化模型
|
||||||
|
llm = ChatOpenAI(
|
||||||
|
base_url=settings.base_url,
|
||||||
|
api_key=settings.api_key,
|
||||||
|
model=settings.model_name,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
# 绑定工具,允许模型自动选择工具
|
||||||
|
llm_with_tools = llm.bind_tools(tools, tool_choice="auto")
|
||||||
|
|
||||||
|
# todo: 第三步:调用回复
|
||||||
|
query = "2+1等于多少?"
|
||||||
|
messages = [HumanMessage(query)]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# todo: 第一次调用
|
||||||
|
ai_msg = llm_with_tools.invoke(messages)
|
||||||
|
messages.append(ai_msg)
|
||||||
|
print(f"\n第一轮调用后结果:\n{messages}")
|
||||||
|
|
||||||
|
# 处理工具调用
|
||||||
|
# 判断消息中是否有tool_calls,以判断工具是否被调用
|
||||||
|
if hasattr(ai_msg, 'tool_calls') and ai_msg.tool_calls:
|
||||||
|
for tool_call in ai_msg.tool_calls:
|
||||||
|
# todo: 处理工具调用
|
||||||
|
selected_tool = {"add": Add, "multiply": Multiply}[tool_call["name"].lower()]
|
||||||
|
# 实例化工具类并调用 invoke
|
||||||
|
tool_instance = selected_tool(**tool_call["args"])
|
||||||
|
tool_output = tool_instance.invoke(tool_call["args"])
|
||||||
|
messages.append(ToolMessage(content=tool_output, tool_call_id=tool_call["id"]))
|
||||||
|
print(f"\n第二轮 message中增加tool_output 之后:\n{messages}")
|
||||||
|
|
||||||
|
# todo: 第二次调用,将工具结果传回模型以生成最终回答
|
||||||
|
final_response = llm_with_tools.invoke(messages)
|
||||||
|
print(f"\n最终模型响应:\n{final_response.content}")
|
||||||
|
else:
|
||||||
|
print("模型未生成工具调用,直接返回文本:")
|
||||||
|
print(ai_msg.content)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"模型调用失败: {str(e)}")
|
||||||
51
demo_function_call/agent.py
Normal file
51
demo_function_call/agent.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
from langchain.agents import initialize_agent, AgentType
|
||||||
|
from langchain_openai import ChatOpenAI
|
||||||
|
from langchain_core.tools import tool
|
||||||
|
|
||||||
|
from conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
# todo: 第一步:定义工具函数
|
||||||
|
@tool
|
||||||
|
def add(a: int, b: int) -> int:
|
||||||
|
"""
|
||||||
|
将数字a与数字b相加
|
||||||
|
Args:
|
||||||
|
a: 第一个数字
|
||||||
|
b: 第二个数字
|
||||||
|
"""
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
@tool
|
||||||
|
def multiply(a: int, b: int) -> int:
|
||||||
|
"""
|
||||||
|
将数字a与数字b相乘
|
||||||
|
Args:
|
||||||
|
a: 第一个数字
|
||||||
|
b: 第二个数字
|
||||||
|
"""
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
# 加载工具
|
||||||
|
tools = [add, multiply]
|
||||||
|
|
||||||
|
# todo: 第二步:初始化模型
|
||||||
|
llm = ChatOpenAI(
|
||||||
|
base_url=settings.base_url,
|
||||||
|
api_key=settings.api_key,
|
||||||
|
model=settings.model_name,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
# todo: 第三步:创建Agent
|
||||||
|
agent = initialize_agent(
|
||||||
|
tools,
|
||||||
|
llm,
|
||||||
|
AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
|
||||||
|
verbose=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# todo: 第四步:调用Agent
|
||||||
|
query = "2+1等于多少?"
|
||||||
|
result = agent.invoke(query)
|
||||||
|
print(f'result: {result["output"]}')
|
||||||
115
demo_function_call/json_schema.py
Normal file
115
demo_function_call/json_schema.py
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
from langchain_openai import ChatOpenAI
|
||||||
|
from langchain_core.messages import HumanMessage, ToolMessage
|
||||||
|
|
||||||
|
from conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
# todo: 第一步:定义工具函数
|
||||||
|
def add(a: int, b: int) -> int:
|
||||||
|
"""
|
||||||
|
将数字a与数字b相加
|
||||||
|
Args:
|
||||||
|
a: 第一个数字
|
||||||
|
b: 第二个数字
|
||||||
|
"""
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
|
||||||
|
def multiply(a: int, b: int) -> int:
|
||||||
|
"""
|
||||||
|
将数字a与数字b相乘
|
||||||
|
Args:
|
||||||
|
a: 第一个数字
|
||||||
|
b: 第二个数字
|
||||||
|
"""
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
tools = [
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "add",
|
||||||
|
"description": "将数字a与数字b相加",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "第一个数字"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "第二个数字"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["a", "b"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "multiply",
|
||||||
|
"description": "将数字a与数字b相乘",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "第一个数字"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "第二个数字"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["a", "b"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# todo: 第二步:初始化模型
|
||||||
|
llm = ChatOpenAI(
|
||||||
|
base_url=settings.base_url,
|
||||||
|
api_key=settings.api_key,
|
||||||
|
model=settings.model_name,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
llm_with_tools = llm.bind(tools=tools, tool_choice="auto")
|
||||||
|
|
||||||
|
|
||||||
|
# todo: 第三步:调用回复
|
||||||
|
query = "2+1等于多少?"
|
||||||
|
messages = [HumanMessage(query)]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# todo: 第一次调用
|
||||||
|
ai_msg = llm_with_tools.invoke(messages)
|
||||||
|
messages.append(ai_msg)
|
||||||
|
print(f"\n第一轮调用后结果:\n{messages}")
|
||||||
|
|
||||||
|
# 处理工具调用
|
||||||
|
# 判断消息中是否有tool_calls,以判断工具是否被调用
|
||||||
|
if hasattr(ai_msg, "tool_calls") and ai_msg.tool_calls:
|
||||||
|
for tool_call in ai_msg.tool_calls:
|
||||||
|
# todo: 处理工具调用
|
||||||
|
selected_tool = {"add": add, "multiply": multiply}[tool_call["name"].lower()]
|
||||||
|
tool_output = selected_tool(**tool_call["args"])
|
||||||
|
messages.append(ToolMessage(content=tool_output, tool_call_id=tool_call["id"]))
|
||||||
|
print(f"\n第二轮 message中增加tool_output 之后:\n{messages}")
|
||||||
|
|
||||||
|
# todo: 第二次调用,将工具结果传回模型以生成最终回答
|
||||||
|
final_response = llm_with_tools.invoke(messages)
|
||||||
|
print(f"\n最终模型响应:\n{final_response.content}")
|
||||||
|
else:
|
||||||
|
print("模型未生成工具调用,直接返回文本:")
|
||||||
|
print(ai_msg.content)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"模型调用失败: {str(e)}")
|
||||||
|
|
||||||
|
# llm.invoke(messages, tools=tools, ...):
|
||||||
|
# 绑定方式: 直接在 .invoke() 调用中传入 tools 参数。这是一种临时、一次性的绑定方式,仅对本次调用有效。
|
||||||
|
# 调用方式: 如果你想再次调用模型并使用工具,你必须在下一次 .invoke() 调用中再次传递 tools 参数。
|
||||||
|
# 适用场景: 适用于简单、单次的工具调用需求,
|
||||||
@@ -1 +0,0 @@
|
|||||||
广州
|
|
||||||
127
requirements.txt
Normal file
127
requirements.txt
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
aiohappyeyeballs==2.6.1
|
||||||
|
aiohttp==3.12.15
|
||||||
|
aiosignal==1.4.0
|
||||||
|
altair==5.5.0
|
||||||
|
annotated-types==0.7.0
|
||||||
|
anthropic==0.60.0
|
||||||
|
anyio==4.9.0
|
||||||
|
attrs==25.3.0
|
||||||
|
beautifulsoup4==4.13.4
|
||||||
|
blinker==1.9.0
|
||||||
|
boto3==1.39.16
|
||||||
|
botocore==1.39.16
|
||||||
|
bs4==0.0.2
|
||||||
|
cachetools==6.1.0
|
||||||
|
certifi==2025.7.14
|
||||||
|
cffi==1.17.1
|
||||||
|
charset-normalizer==3.4.2
|
||||||
|
click==8.2.1
|
||||||
|
colorama==0.4.6
|
||||||
|
colorlog==6.9.0
|
||||||
|
cryptography==45.0.5
|
||||||
|
dashscope==1.24.0
|
||||||
|
dataclasses-json==0.6.7
|
||||||
|
distro==1.9.0
|
||||||
|
fastapi==0.116.1
|
||||||
|
filelock==3.18.0
|
||||||
|
Flask==3.1.1
|
||||||
|
frozenlist==1.7.0
|
||||||
|
fsspec==2025.7.0
|
||||||
|
gitdb==4.0.12
|
||||||
|
GitPython==3.1.45
|
||||||
|
greenlet==3.2.3
|
||||||
|
h11==0.16.0
|
||||||
|
hf-xet==1.1.5
|
||||||
|
httpcore==1.0.9
|
||||||
|
httpx==0.28.1
|
||||||
|
httpx-sse==0.4.1
|
||||||
|
huggingface-hub==0.34.3
|
||||||
|
idna==3.10
|
||||||
|
itsdangerous==2.2.0
|
||||||
|
Jinja2==3.1.6
|
||||||
|
jiter==0.10.0
|
||||||
|
jmespath==1.0.1
|
||||||
|
jsonpatch==1.33
|
||||||
|
jsonpointer==3.0.0
|
||||||
|
jsonschema==4.25.0
|
||||||
|
jsonschema-specifications==2025.4.1
|
||||||
|
langchain==0.3.26
|
||||||
|
langchain-community==0.3.27
|
||||||
|
langchain-core==0.3.72
|
||||||
|
langchain-deepseek==0.1.4
|
||||||
|
langchain-openai==0.3.28
|
||||||
|
langchain-text-splitters==0.3.9
|
||||||
|
langsmith==0.3.45
|
||||||
|
lxml==6.0.0
|
||||||
|
MarkupSafe==3.0.2
|
||||||
|
marshmallow==3.26.1
|
||||||
|
mcp==1.18.0
|
||||||
|
mcp-server==0.1.4
|
||||||
|
mpmath==1.3.0
|
||||||
|
multidict==6.6.3
|
||||||
|
mypy_extensions==1.1.0
|
||||||
|
mysql-connector-python==9.4.0
|
||||||
|
mysqlclient==2.2.7
|
||||||
|
narwhals==2.0.1
|
||||||
|
networkx==3.5
|
||||||
|
numpy==2.3.2
|
||||||
|
openai==1.97.1
|
||||||
|
orjson==3.11.1
|
||||||
|
packaging==25.0
|
||||||
|
pandas==2.3.1
|
||||||
|
pillow==11.3.0
|
||||||
|
propcache==0.3.2
|
||||||
|
protobuf==6.31.1
|
||||||
|
pyarrow==21.0.0
|
||||||
|
pycparser==2.22
|
||||||
|
pydantic==2.11.7
|
||||||
|
pydantic-settings==2.10.1
|
||||||
|
pydantic_core==2.33.2
|
||||||
|
pydeck==0.9.1
|
||||||
|
PyMySQL==1.1.1
|
||||||
|
python-a2a==0.5.4
|
||||||
|
python-dateutil==2.9.0.post0
|
||||||
|
python-dotenv==1.1.1
|
||||||
|
python-multipart==0.0.20
|
||||||
|
pytz==2025.2
|
||||||
|
pywin32==311
|
||||||
|
PyYAML==6.0.2
|
||||||
|
referencing==0.36.2
|
||||||
|
regex==2025.7.31
|
||||||
|
requests==2.32.4
|
||||||
|
requests-toolbelt==1.0.0
|
||||||
|
rpds-py==0.26.0
|
||||||
|
s3transfer==0.13.1
|
||||||
|
safetensors==0.5.3
|
||||||
|
setuptools==78.1.1
|
||||||
|
six==1.17.0
|
||||||
|
smmap==5.0.2
|
||||||
|
sniffio==1.3.1
|
||||||
|
soupsieve==2.7
|
||||||
|
SQLAlchemy==2.0.42
|
||||||
|
sse-starlette==3.0.2
|
||||||
|
starlette==0.47.2
|
||||||
|
streamlit==1.47.1
|
||||||
|
sympy==1.14.0
|
||||||
|
tenacity==9.1.2
|
||||||
|
tiktoken==0.9.0
|
||||||
|
tokenizers==0.21.4
|
||||||
|
toml==0.10.2
|
||||||
|
torch==2.7.1
|
||||||
|
tornado==6.5.1
|
||||||
|
tqdm==4.67.1
|
||||||
|
transformers==4.54.1
|
||||||
|
typing-inspect==0.9.0
|
||||||
|
typing-inspection==0.4.1
|
||||||
|
typing_extensions==4.14.1
|
||||||
|
tzdata==2025.2
|
||||||
|
urllib3==2.5.0
|
||||||
|
uvicorn==0.35.0
|
||||||
|
watchdog==6.0.0
|
||||||
|
websocket-client==1.8.0
|
||||||
|
Werkzeug==3.1.3
|
||||||
|
wheel==0.45.1
|
||||||
|
yarl==1.20.1
|
||||||
|
zstandard==0.23.0
|
||||||
|
schedule==1.2.2
|
||||||
|
langchain-mcp-adapters==0.1.11
|
||||||
Reference in New Issue
Block a user