更新python后端
This commit is contained in:
@@ -1,6 +1,34 @@
|
||||
|
||||
from langchain_community.chat_models.tongyi import ChatTongyi
|
||||
from utils.Tools import all_tools
|
||||
from langchain.chat_models import init_chat_model
|
||||
from langchain_openai import ChatOpenAI
|
||||
from openai import OpenAI
|
||||
import os
|
||||
from langchain_openai import OpenAIEmbeddings
|
||||
# 通义千文Key
|
||||
tongyiKey = "sk-9464b2498c184982a9fe9d2c2e725ab5"
|
||||
# DeepSeekKey
|
||||
deepseekKey = "sk-6129a200ae294b9f86553505191fa477"
|
||||
|
||||
llm = ChatTongyi(streaming=False, api_key="sk-fb46eefb6b404382a0a5325202e923a6")
|
||||
llm = ChatTongyi(streaming=False, api_key=tongyiKey)
|
||||
llm_with_tools = llm.bind_tools(all_tools)
|
||||
|
||||
llmThink = ChatOpenAI(
|
||||
api_key=tongyiKey,
|
||||
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
model="qwen-max",
|
||||
stream = False
|
||||
)
|
||||
from langchain_community.embeddings import DashScopeEmbeddings
|
||||
embeddings = DashScopeEmbeddings(
|
||||
model="text-embedding-v3",
|
||||
dashscope_api_key= tongyiKey,
|
||||
)
|
||||
|
||||
# from langchain_deepseek import ChatDeepSeek
|
||||
# llm = ChatDeepSeek(
|
||||
# model="deepseek-reasoner",
|
||||
# api_key=deepseekKey,
|
||||
# api_base="https://api.deepseek.com"
|
||||
# )
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
from langchain_milvus import BM25BuiltInFunction, Milvus
|
||||
from config.llm import embeddings
|
||||
|
||||
URI = "http://10.10.10.9:19530"
|
||||
|
||||
knVectorstore = Milvus(
|
||||
embedding_function=embeddings,
|
||||
connection_args={"uri": URI, "token": "root:Milvus", "db_name": "bbit_ai_lab"},
|
||||
collection_name="knowledge",
|
||||
index_params={"index_type": "FLAT", "metric_type": "L2"},
|
||||
consistency_level="Strong",
|
||||
auto_id=True,
|
||||
|
||||
primary_field = "id",
|
||||
text_field="text",
|
||||
vector_field="vector",
|
||||
partition_key_field = "kn_id",
|
||||
enable_dynamic_field = True,
|
||||
drop_old=False, # set to True if seeking to drop the collection with that name if it exists
|
||||
)
|
||||
memVectorstore = Milvus(
|
||||
embedding_function=embeddings,
|
||||
connection_args={"uri": URI, "token": "root:Milvus", "db_name": "bbit_ai_lab"},
|
||||
collection_name="memory",
|
||||
index_params={"index_type": "FLAT", "metric_type": "L2"},
|
||||
consistency_level="Strong",
|
||||
auto_id=True,
|
||||
|
||||
primary_field = "id",
|
||||
text_field="text",
|
||||
vector_field="vector",
|
||||
partition_key_field = "ai_id",
|
||||
enable_dynamic_field = True,
|
||||
drop_old=False, # set to True if seeking to drop the collection with that name if it exists
|
||||
)
|
||||
+64
-17
@@ -1,22 +1,69 @@
|
||||
|
||||
import psycopg
|
||||
from langchain_postgres import PostgresChatMessageHistory
|
||||
from psycopg_pool import ConnectionPool
|
||||
import logging
|
||||
import time
|
||||
from contextlib import contextmanager
|
||||
from typing import Optional
|
||||
import psycopg
|
||||
from psycopg_pool import ConnectionPool
|
||||
|
||||
# conn = psycopg.connect("postgresql://postgres:123456@10.10.10.9/ktor2")
|
||||
database_name = "ai_chat_history"
|
||||
pool = ConnectionPool("postgresql://postgres:123456@10.10.10.9/ktor2")
|
||||
logger = logging.getLogger("PGPool")
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
@contextmanager
|
||||
def getConn():
|
||||
with pool.connection() as temp:
|
||||
temp.autocommit = True # 如果你想所有连接默认 autocommit
|
||||
yield temp # 把 conn 暴露给外部使用
|
||||
class PGPool:
|
||||
"""
|
||||
PostgreSQL 连接池封装
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
uri: str,
|
||||
min_size: int = 1,
|
||||
max_size: int = 20,
|
||||
max_idle: int = 30,
|
||||
max_lifetime: int = 300,
|
||||
timeout: int = 10,
|
||||
check: bool = False,
|
||||
):
|
||||
"""
|
||||
:param uri: PostgreSQL 连接 URI
|
||||
"""
|
||||
self.uri = uri
|
||||
self.pool = ConnectionPool(
|
||||
self.uri,
|
||||
min_size=min_size,
|
||||
max_size=max_size,
|
||||
max_idle=max_idle,
|
||||
max_lifetime=max_lifetime,
|
||||
timeout=timeout,
|
||||
check=check,
|
||||
)
|
||||
|
||||
def init():
|
||||
with getConn() as connection:
|
||||
PostgresChatMessageHistory.create_tables(connection, database_name)
|
||||
|
||||
init()
|
||||
@contextmanager
|
||||
def getConn(self, retries: int = 2, delay: float = 1.0):
|
||||
"""
|
||||
获取数据库连接,带重试机制,自动健康检查。
|
||||
使用方式:
|
||||
with pg_pool.get_conn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(...)
|
||||
"""
|
||||
attempt = 0
|
||||
while attempt <= retries:
|
||||
try:
|
||||
with self.pool.connection() as conn:
|
||||
conn.autocommit = True
|
||||
yield conn
|
||||
return
|
||||
except psycopg.OperationalError as e:
|
||||
logger.warning(f"数据库连接异常: {e}. 尝试重试 ({attempt+1}/{retries})")
|
||||
self.pool.check() # 丢掉坏连接,重新建
|
||||
attempt += 1
|
||||
time.sleep(delay)
|
||||
except Exception as e:
|
||||
logger.error(f"SQL执行异常: {e}")
|
||||
raise
|
||||
raise psycopg.OperationalError("无法获取数据库连接,多次重试失败")
|
||||
pg_pool = PGPool(
|
||||
uri="postgresql://postgres:123456@10.10.10.9/ktor2",
|
||||
min_size=1,
|
||||
max_size=20,
|
||||
)
|
||||
@@ -2,11 +2,81 @@ from langchain_community.utilities import SQLDatabase
|
||||
from langchain_community.agent_toolkits import create_sql_agent
|
||||
from langchain_community.chat_models.tongyi import ChatTongyi
|
||||
# SQLAlchemy URI
|
||||
uri = "mssql+pyodbc://f8_db_test:APN^QPr!K9@122.114.58.23/f8_db_test?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes"
|
||||
uri = "mssql+pyodbc://f8_db_test:APN^QPr!K9@122.114.58.23/f8_db_test?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes&Encrypt=no"
|
||||
|
||||
# 建立数据库对象
|
||||
ssDB = SQLDatabase.from_uri(
|
||||
ssDBLC = SQLDatabase.from_uri(
|
||||
uri,
|
||||
include_tables=["NONGHU_INFO"], # 不加 schema 前缀试试
|
||||
include_tables=["NONGHU_INFO","NONGHU_BLACKLIST",],
|
||||
schema="dbo" # 显式指定 schema
|
||||
)
|
||||
)
|
||||
import logging
|
||||
import time
|
||||
from contextlib import contextmanager
|
||||
from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.exc import OperationalError as SQLOperationalError
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
logger = logging.getLogger("MSSQLPool")
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
class MSSQLPool:
|
||||
"""
|
||||
SQL Server 连接池封装
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
user: str,
|
||||
password: str,
|
||||
host: str,
|
||||
database: str,
|
||||
driver: str = "ODBC Driver 18 for SQL Server",
|
||||
encrypt: str = "no",
|
||||
trust_server_certificate: str = "yes",
|
||||
min_size: int = 1,
|
||||
max_size: int = 10,
|
||||
pool_timeout: int = 10,
|
||||
):
|
||||
self.user = user
|
||||
self.password = quote_plus(password) # 处理特殊字符
|
||||
self.host = host
|
||||
self.database = database
|
||||
self.driver = driver
|
||||
self.encrypt = encrypt
|
||||
self.trust_server_certificate = trust_server_certificate
|
||||
|
||||
self.engine = create_engine(
|
||||
f"mssql+pyodbc://{self.user}:{self.password}@{self.host}/{self.database}"
|
||||
f"?driver={self.driver}&Encrypt={self.encrypt}&TrustServerCertificate={self.trust_server_certificate}",
|
||||
pool_size=min_size,
|
||||
max_overflow=max_size - min_size,
|
||||
pool_timeout=pool_timeout,
|
||||
)
|
||||
|
||||
@contextmanager
|
||||
def getConn(self, retries: int = 2, delay: float = 1.0):
|
||||
"""
|
||||
获取连接,带重试
|
||||
"""
|
||||
attempt = 0
|
||||
while attempt <= retries:
|
||||
try:
|
||||
with self.engine.connect() as conn:
|
||||
yield conn
|
||||
return
|
||||
except SQLOperationalError as e:
|
||||
logger.warning(f"数据库连接异常: {e}. 尝试重试 ({attempt+1}/{retries})")
|
||||
attempt += 1
|
||||
time.sleep(delay)
|
||||
except Exception as e:
|
||||
logger.error(f"SQL执行异常: {e}")
|
||||
raise
|
||||
raise SQLOperationalError("无法获取数据库连接,多次重试失败")
|
||||
|
||||
mssql_pool = MSSQLPool(
|
||||
user="f8_db_test",
|
||||
password="APN^QPr!K9",
|
||||
host="122.114.58.23",
|
||||
database="f8_db_test",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user