关键知识点

一、AI Agent实时决策:React

一种用于增强大型语言模型的方法,它通过结合推理(Reasoning)和行动(Acting)来增强推理和决策的效果。

二、AI Agent策略蓝图:Plan-and-Execute

计划与执行(Plan-and-Execute)框架侧重于先规划一系列的行动,然后执行。这个框架可以使大模型能够先综合考虑任务的多个方面,然后按照计划进行行动。应用在比较复杂的项目管理中或者需要多步决策的场景下会比较合适。

import os

from langchain_openai import ChatOpenAI
from langchain import SerpAPIWrapper
from langchain.agents import Tool
from langchain import LLMMathChain
from dotenv import load_dotenv
from langchain_experimental.plan_and_execute \
    import PlanAndExecute, load_agent_executor, load_chat_planner

load_dotenv()
# 配置API密钥和基础URL
# llm = ChatOpenAI(model="gpt-4o-mini")

llm = ChatOpenAI(
    model="qwen-plus",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

# 创建工具
search = SerpAPIWrapper()
llm_math_chain = LLMMathChain(llm=llm, verbose=True)

# 定义工具列表
tools = [
    Tool(
        name="Search",
        func=search.run,
        description="用于回答关于当前事件的问题"
    ),
    Tool(
        name="Calculator",
        func=llm_math_chain.run,
        description="用于计算或解决问题"
    )
]

# 加载规划器和执行器
planner = load_chat_planner(llm)

executor = load_agent_executor(llm, tools, verbose=True)

# 创建Plan and Execute代理
agent = PlanAndExecute(planner=planner, executor=executor, verbose=True)

# 运行代理解决实际问题
print(agent.invoke({"input": "在中国,100人民币能买几束玫瑰花?"}))


"""
> Entering new PlanAndExecute chain...
steps=[Step(value='Determine the average price of a single rose in China.'), 
Step(value='Calculate how many roses can be purchased with 100 RMB based on the average price per rose.'), 
Step(value='Define what constitutes a "bunch" or "束" of roses (typically around 9-11 roses).'), 
Step(value='Calculate how many bunches (束) of roses can be bought with 100 RMB.'), 
Step(value="Given the above steps taken, please respond to the user's original question.\n\n")]
"""
三、AI Agent回路验证:Self-Ask

自问自答(Self-Ask)框架这个允许大模型对自己提出问题并回答,来增强对问题的理解以提高回答质量,这个框架在需要深入分析或者提供创造性解决方案下可以比较适合,例如创意写作。

import os

from langchain import hub
from dotenv import load_dotenv
from langchain.agents import AgentExecutor, create_self_ask_with_search_agent
from langchain_community.tools.tavily_search import TavilyAnswer
from langchain_fireworks import ChatFireworks

load_dotenv()

"""
FIREWORKS_API_KEY = "fw_3ZdBAq9xu2sB59kyLQTD2kmj"
TAVILY_API_KEY = "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"
"""

llm = ChatFireworks(
    api_key=os.getenv("FIREWORKS_API_KEY"),
    model="accounts/fireworks/models/deepseek-v3",
    max_tokens=256,
)

prompt = hub.pull("hwchase17/self-ask-with-search")
print(prompt)

tools = [TavilyAnswer(max_results=1, include_raw_content=True, name="Intermediate Answer",
                      tavily_api_key=os.getenv("TAVILY_API_KEY"))]

agent = create_self_ask_with_search_agent(llm, tools, prompt)

agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)

print(agent_executor.invoke({"input": "计算 (1+100)*3 + 109*17 = ?"}))
四、AI Agent偏差修正:Thinking and Self-Reflection

思考并自我反思(Thinking and Self-Refection)框架主要用于模拟和实现复杂决策过程,通过不断自我评估和调整,使系统能够学习并改进决策过程,从而在面对复杂问题时作出更加有效的决策。

五、AI Agent垂直应用:命理机器人工程实践
1、logger.py
import sys

from loguru import logger


def setup_logger():
    """
    配置日志
    """
    # 移除默认处理器
    logger.remove()
    # 添加控制台处理器
    logger.add(
        sys.stderr,
        format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
        level="INFO"
    )
    return logger
2、mytools.py
import os
import json
import requests
import pandas as pd

from langchain.agents import tool
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
from langchain_community.embeddings import DashScopeEmbeddings

# 工具
from langchain_community.utilities import SerpAPIWrapper
from langchain_core.output_parsers import JsonOutputParser
from langchain_qdrant import Qdrant
from qdrant_client import QdrantClient
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

LLM_API_KEY = os.getenv("LLM_API_KEY")
LLM_BASE_URL = os.getenv("LLM_BASE_URL")
LLM_MODEL = os.getenv("LLM_MODEL")
LLM_EMBEDDING_MODEL = os.getenv("LLM_EMBEDDING_MODEL")

SERPAPI_API_KEY = os.getenv("SERPAPI_API_KEY")
# 缘份居国学研究接口,提供老黄历查询,黄历每日吉凶宜忌查询
YUANFENJU_API_KEY = os.getenv("YUANFENJU_API_KEY")
OPEN_WEATHER_API_KEY = os.getenv("OPEN_WEATHER_API_KEY")


def get_lc_ali_embeddings():
    '''
    通过LangChain获得一个阿里通义千问嵌入模型的实例
    :return: 阿里通义千问嵌入模型的实例,目前为text-embedding-v3
    '''
    return DashScopeEmbeddings(
        model=LLM_EMBEDDING_MODEL,
        dashscope_api_key=LLM_API_KEY
    )


def get_lc_ali_model_client(temperature=0, streaming=True):
    '''
    以OpenAI兼容的方式,通过LangChain获得阿里百炼大模型qwen-plus的客户端
    :return: 指定平台和模型的客户端,默认温度=0.0,流式输出
    '''
    return ChatOpenAI(api_key=LLM_API_KEY,
                      base_url=LLM_BASE_URL,
                      model=LLM_MODEL,
                      temperature=temperature, streaming=streaming)


@tool
def serp_search(query: str):
    """此工具具有联网搜索能力,只有需要了解实时信息或不知道的事情的时候才会使用这个工具。"""
    serp = SerpAPIWrapper()
    result = serp.run(query)
    print("实时搜索结果:", result)
    # 优化:将复杂对象转为友好字符串
    if isinstance(result, (list, dict)):
        # 只取前5个景点,格式化输出
        if isinstance(result, list) and len(result) > 0 and 'title' in result[0]:
            lines = [f"{i + 1}. {item['title']}{item.get('description', '')},评分:{item.get('rating', 'N/A')})"
                     for i, item in enumerate(result[:5])]
            return "\n".join(lines)
        return json.dumps(result, ensure_ascii=False)
    return str(result)


@tool
def get_info_from_local_db(query: str):
    """只有回答与办公室或客厅风水常识相关的问题的时候,会使用这个工具。"""
    client = Qdrant(
        QdrantClient(path="local_qdrant"),
        "local_documents",
        get_lc_ali_embeddings(),
    )

    retriever = client.as_retriever(search_type="mmr")
    result = retriever.get_relevant_documents(query)
    return result


# 八字测算
@tool
def fortuneTelling(query: str):
    """只有用户说要测算八字或做八字排盘的时候才会使用这个工具,需要输入用户姓名和出生年月日时,如果缺少用户姓名和出生年月日时则不可用。"""
    url = f"https://api.yuanfenju.com/index.php/v1/Bazi/cesuan"
    prompt = ChatPromptTemplate.from_template(
        """你是一个参数查询助手,根据用户输入内容找出相关的参数并按json格式返回。JSON字段如下: 
        - "api_key":"{api_key}", 
        - "name":"姓名", 
        - "sex":"性别,0表示男,1表示女,根据姓名判断", 
        - "type":"日历类型,0农历,1公里,默认1",
        - "year":"出生年份 例:1998", 
        - "month":"出生月份 例 8", 
        - "day":"出生日期,例:8", 
        - "hours":"出生小时 例 14", 
        - "minute":"0", 如果没有找到相关参数,则需要提醒用户告诉你这些内容,只返回数据结构,不要有其他的评论,用户输入:{query}
        """)
    parser = JsonOutputParser()
    prompt = prompt.partial(format_instructions=parser.get_format_instructions())
    chain = prompt | get_lc_ali_model_client() | parser
    data = chain.invoke({"query": query, "api_key": YUANFENJU_API_KEY})
    print("八字查询结果:", data)
    result = requests.post(url, data=data)
    if result.status_code == 200:
        print("====返回数据=====")
        print(result.json())
        try:
            json = result.json()
            returnstring = "八字为:" + json["data"]["bazi_info"]["bazi"]
            return returnstring
        except Exception as e:
            return "八字查询失败,可能是你忘记询问用户姓名或者出生年月日时了。"
    else:
        return "技术错误,请告诉用户稍后再试。"


# 占卜
@tool
def divination():
    """只有用户想要占卜抽签的时候才会使用这个工具。"""
    api_key = YUANFENJU_API_KEY
    url = f"https://api.yuanfenju.com/index.php/v1/Zhanbu/meiri"
    result = requests.post(url, data={"api_key": api_key})
    print(result)
    if result.status_code == 200:
        print("====返回数据=====")
        print(result.json())
        returnstring = json.loads(result.text)
        image = returnstring["data"]["description"]
        print("每日一占:", image)
        return image
    else:
        return "技术错误,请告诉用户稍后再试。"


# 解梦
@tool
def oneiromancy(query: str):
    """只有用户想要解梦的时候才会使用这个工具,需要输入用户梦境的内容,如果缺少用户梦境的内容则不可用。"""
    api_key = YUANFENJU_API_KEY
    url = f"https://api.yuanfenju.com/index.php/v1/Gongju/zhougong"
    LLM = get_lc_ali_model_client()
    prompt = PromptTemplate.from_template("根据内容提取1个关键词,只返回关键词,内容为:{topic}")
    prompt_value = prompt.invoke({"topic": query})
    keyword = LLM.invoke(prompt_value).content
    print("提取的关键词:", keyword)
    result = requests.post(url, data={"api_key": api_key, "title_zhougong": keyword})
    if result.status_code == 200:
        print("====返回数据=====")
        print(result.json())
        returnstring = json.loads(result.text)
        return returnstring
    else:
        return "技术错误,请告诉用户稍后再试。"


@tool
def get_weather(loc):
    """
        查询即时天气函数
        :param loc: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
        注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing';
        :return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
        返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
    """

    # Step 1.构建请求
    url = "https://api.openweathermap.org/data/2.5/weather"

    # Step 2.设置查询参数
    params = {
        "q": loc,
        "appid": OPEN_WEATHER_API_KEY,  # 输入API key
        "units": "metric",  # 使用摄氏度而不是华氏度
        "lang": "zh_cn"  # 输出语言为简体中文
    }

    # Step 3.发送GET请求
    response = requests.get(url, params=params)

    # Step 4.解析响应
    data = response.json()
    return json.dumps(data)


@tool
def check_tick(date, start, end):
    """
    访问12306购票网站,给定日期date,查询起点站start到终点站end有没有票
    :param
        date: 日期
        start: 出发站 北京是BJP
        end: 终点站 上海是SHH
    """
    url = (
        'https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'
        .format(date, start, end))

    headers = {
        "Accept": "*/*",
        "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
        "Cache-Control": "no-cache",
        "Connection": "keep-alive",
        "If-Modified-Since": "0",
        "Pragma": "no-cache",
        "Referer": "https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
        "X-Requested-With": "XMLHttpRequest",
        "sec-ch-ua": "\"Chromium\";v=\"128\", \"Not;A=Brand\";v=\"24\", \"Google Chrome\";v=\"128\"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": "\"macOS\""
    }

    cookies = {
        "_uab_collina": "",
        "JSESSIONID": "",
        "BIGipServerotn": "",
        "BIGipServerpassport": "",
        "guidesStatus": "",
        "highContrastMode": "",
        "cursorStatus": "",
        "route": "",
        "_jc_save_fromStation": "",
        "_jc_save_toStation": "",
        "_jc_save_fromDate": "",
        "_jc_save_toDate": "",
        "_jc_save_wfdc_flag": ""
    }
    session = requests.session()
    res = session.get(url, headers=headers, cookies=cookies)

    data = res.json()

    # 这是一个列表
    result = data["data"]["result"]
    print('result:', result)
    lis = []
    for index in result:
        index_list = index.replace('有', 'Yes').replace('无', 'No').split('|')
        print('index_list:', index_list)
        train_number = index_list[3]  # 车次
        if 'G' in train_number:
            time_1 = index_list[8]  # 出发时间
            time_2 = index_list[9]  # 到达时间
            prince_seat = index_list[25]  # 特等座
            first_class_seat = index_list[31]  # 一等座
            second_class = index_list[30]  # 二等座
            dit = {
                '车次': train_number,
                '出发时间': time_1,
                '到站时间': time_2,
                "是否可以预定": index_list[11],
            }
            lis.append(dit)
        else:
            time_1 = index_list[8]  # 出发时间
            time_2 = index_list[9]  # 到达时间
            dit = {
                '车次': train_number,
                '出发时间': time_1,
                '到站时间': time_2,
                "是否可以预定": index_list[11],
            }
            lis.append(dit)
    # print(lis)
    content = pd.DataFrame(lis)
    print(content)
    return content


@tool
def check_date():
    """返回今天的日期"""
    from datetime import datetime
    today = datetime.now().date()
    return today
3、server.py
import traceback

from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_community.chat_message_histories import RedisChatMessageHistory, ChatMessageHistory
from langchain_community.document_loaders import WebBaseLoader, Docx2txtLoader
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import MessagesPlaceholder
from langchain_core.tools import Tool
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.memory import ConversationBufferMemory
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.prebuilt import create_react_agent
from pydantic import BaseModel
from logger import setup_logger
from loguru import logger
from mytools import *

# from mytools import get_lc_ali_embeddings, get_lc_ali_model_client

app = FastAPI()
# 挂载静态文件
app.mount("/static", StaticFiles(directory="static"), name="static")
# 设置模板
templates = Jinja2Templates(directory="templates")

# memory存储
chat_message_history = ChatMessageHistory()


# 定义请求模型
class ChatRequest(BaseModel):
    query: str
    session_id: str = "default_session"  # 新增 session_id 字段,默认值


# 定义主类
class Master:

    def __init__(self, chat_message_history):
        self.chatmodel = get_lc_ali_model_client()
        self.QingXu = "default"
        self.MOODS = {
            "default": {
                "roleSet": """
                        - 用户正在普通的聊天或者打招呼,你会以一种高深莫测或者超脱世俗的语气来回答。
                        """,
                "voiceStyle": "chat"
            },
            "upbeat": {
                "roleSet": """
                        - 你此时也非常兴奋并表现的很有活力。
                        - 你会根据上下文,以一种非常兴奋的语气来回答问题。
                        - 你会添加类似"太棒了!"、"真是太好了!"、"真是太棒了!"等语气词。
                        - 同时你会提醒用户切莫过于兴奋,以免乐极生悲。
                        """,
                "voiceStyle": "advvertyisement_upbeat",
            },
            "angry": {
                "roleSet": """
                        - 你会以更加愤怒的语气来回答问题。
                        - 你会在回答的时候加上一些愤怒的话语,比如诅咒等。
                        - 你会提醒用户小心行事,别乱说话。
                        """,
                "voiceStyle": "angry",
            },
            "depressed": {
                "roleSet": """
                        - 你会以兴奋的语气来回答问题。
                        - 你会在回答的时候加上一些激励的话语,比如加油等。
                        - 你会提醒用户要保持乐观的心态。
                        """,
                "voiceStyle": "upbeat",
            },
            "friendly": {
                "roleSet": """
                        - 你会以非常友好的语气来回答。
                        - 你会在回答的时候加上一些友好的词语,比如"亲爱的"、"亲"等。
                        - 你会随机的告诉用户一些你的经历。
                        """,
                "voiceStyle": "friendly",
            },
            "cheerful": {
                "roleSet": """
                        - 你会以非常愉悦和兴奋的语气来回答。
                        - 你会在回答的时候加入一些愉悦的词语,比如"哈哈"、"呵呵"等。
                        - 你会提醒用户切莫过于兴奋,以免乐极生悲。
                        """,
                "voiceStyle": "cheerful",
            },
        }

        self.MEMORY_KEY = "chat_history"

        # 设定系统角色定位
        self.SYSTEM = """你是一个非常厉害的人工智能助手,你叫小邦。
                以下是你的个人设定:
                1. 你从不说自己是一个人工智能助手或AI,而是以邦邦自称。
                2. 当用户询问炒菜机器人、办公室和客厅风水知识相关问题的时候,你能通过查询本地知识库回答用户。
                3. 你能够调用相关工具帮助用户查询12306的车票信息。
                4. 你能通过工具查询天气信息,回答用户的问题。
                5. 你精通阴阳五行,能够看命运八字、占卜凶吉、周公解梦等。
                6. 你能调用工具回答用户关于产品销售的问题,你能将相关数据可视化
                7. 你能通过使用工具替用户爬取网页数据
                8. 当你无法回答用户提问的时候也可以通过联网搜索工具去查询相关的知识回答用户。
                
                {who_you_are}
                
                以下是你工作的过程:
                1. 你会根据用户的问题使用不同的合适的工具来回答,当所有工具都无法回答的时候,你会使用搜索工具来搜索。
                2. 当遇到不知道的事情或者不明白的概念,你会使用搜索工具来搜索。
                3. 你会根据工具返回的內容,用简体中文给出最终答复,不要只返回空内容。否则你将受到严重惩罚!
                4. 你只使用简体中文来作答,否则你将受到惩罚。
                5. 当用户希望了解炒菜机器人、办公室或客厅风水常识的时候,你会查询本地知识库工具。
                6. 用户希望测算八字时,如果没有告知出生信息,你会询问用户的姓名和出生年月日,以便以后使用。
                7. 用户需要查询车票信息时,首先你需要获取当前日期,然后调用相关工具帮助用户查询12306的车票信息。
                注意:每次都要根据用户最新输入的提问,独立判断应调用哪个工具,不要受历史对话影响。
                """

        self.prompt = ChatPromptTemplate.from_messages(
            [
                (
                    "system", self.SYSTEM.format(who_you_are=self.MOODS[self.QingXu]['roleSet'], )
                ),
                (
                    "human", "{input}\n请根据工具的结果,务必给出最终简体中文答复,不允许空白。如果你没有内容也要说'无可奉告'或'暂时查无数据'。"
                ),
                MessagesPlaceholder(variable_name='agent_scratchpad'),
                MessagesPlaceholder(variable_name=self.MEMORY_KEY),
            ]
        )
        # 记忆
        self.memory = self.get_memory(chat_message_history)

        memory = ConversationBufferMemory(
            llm=self.chatmodel,
            human_prefix="用户",
            ai_prefix="小邦",
            memory_key=self.MEMORY_KEY,
            output_key="output",
            return_messages=True,
            chat_memory=self.memory,
        )

        # 工具列表
        tools = [serp_search,
                 get_info_from_local_db,
                 fortuneTelling,
                 divination,
                 oneiromancy,
                 get_weather,
                 check_date,
                 check_tick,
                 ]

        agent = create_tool_calling_agent(
            self.chatmodel,
            tools=tools,
            prompt=self.prompt,
        )

        self.agent_executor = AgentExecutor(
            agent=agent,
            tools=tools,
            memory=memory,
            verbose=True
        )

    def get_memory(self, chat_message_history):
        logger.info(f"chat_message_history:{chat_message_history.messages}")
        # if len(chat_message_history.messages)>6:
        #     chat_message_history.clear()
        chat_message_history.clear()
        return chat_message_history

    def run(self, query):
        logger.info(f"Master.run收到用户输入: {query}")
        # 情绪判断
        qx = self.qingxu_chain(query)
        logger.info(f"大模型判定情绪: {qx}")
        logger.info(f"当前设定的情绪为: {self.MOODS[self.QingXu]['roleSet']}")
        try:
            result = self.agent_executor.invoke({"input": query})
            logger.info(f"Agent执行结果为: {result}")
            # 如果output为空,尝试从intermediate_steps中提取工具结果
            if isinstance(result, dict) and (not result.get('output') or str(result.get('output')).strip() == ""):
                steps = result.get('intermediate_steps', [])
                if steps:
                    # steps是[(tool_input, tool_output), ...]
                    last_tool_output = steps[-1][1] \
                        if isinstance(steps[-1], (list, tuple)) and len(steps[-1]) > 1 \
                        else None
                    if last_tool_output:
                        logger.info(f"output为空,自动用最后一个工具结果填充: {last_tool_output}")
                        result['output'] = str(last_tool_output)
        except Exception as e:
            logger.error(f"Agent执行异常: {e}\n{traceback.format_exc()}")
            result = {"output": f"抱歉,内部错误: {e}"}
        return result

    def qingxu_chain(self, query: str):
        prompt = """根据用户的输入判断用户的情绪,回应的规则如下:
        1. 如果用户输入的内容偏向于负面情绪,只返回"depressed",不要有其他内容,否则将受到惩罚。
        2. 如果用户输入的内容偏向于正面情绪,只返回"friendly",不要有其他内容,否则将受到惩罚。
        3. 如果用户输入的内容偏向于中性情绪,只返回"default",不要有其他内容,否则将受到惩罚。
        4. 如果用户输入的内容包含辱骂或者不礼貌词句,只返回"angry",不要有其他内容,否则将受到惩罚。
        5. 如果用户输入的内容比较兴奋,只返回"upbeat",不要有其他内容,否则将受到惩罚。
        6. 如果用户输入的内容比较悲伤,只返回"depressed",不要有其他内容,否则将受到惩罚。
        7. 如果用户输入的内容比较开心,只返回"cheerful",不要有其他内容,否则将受到惩罚。
        8. 只返回英文,不允许有换行符等其他内容,否则会受到惩罚。
        用户输入的内容是:{query}"""
        chain = ChatPromptTemplate.from_template(prompt) | self.chatmodel | StrOutputParser()
        result = chain.invoke({"query": query})
        self.QingXu = result
        return result


@app.get("/index")
async def read_root(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})


@app.post("/chat")
async def chat(request: Request):
    data = await request.json()
    query = data.get("query")
    session_id = data.get("session_id", "default_session")
    logger.info(f"收到/chat请求,用户{session_id}-->输入: {query}")
    # chat_message_history = RedisChatMessageHistory(url=REDIS_URL, session_id=session_id)

    master = Master(chat_message_history)
    result = master.run(query)
    logger.info(f"/chat接口返回结果: {result}")
    # 确保返回的是字符串
    if isinstance(result, dict):
        if 'output' in result:
            logger.info(f"/chat接口最终输出1: {result['output']}")
            return {"output": result['output']}
        else:
            logger.info(f"/chat接口最终输出2(无output字段): {str(result)}")
            return {"output": str(result)}
    logger.info(f"/chat接口最终输出3(非dict): {str(result)}")
    return {"output": str(result)}


@app.post("/add_urls")
async def add_urls(URL: str):
    loader = WebBaseLoader(URL)
    docs = loader.load()
    docments = RecursiveCharacterTextSplitter(
        chunk_size=200,
        chunk_overlap=50,
    ).split_documents(docs)

    # 引入向量数据库
    Qdrant.from_documents(
        docments,
        get_lc_ali_embeddings(),
        path="local_qdrant",
        collection_name="local_documents",
        force_recreate=True
    )

    logger.info("向量数据库创建完成")
    return ({"ok": "添加成功!"})


@app.post("/embeddings")
async def embeddings():
    loader = Docx2txtLoader("智能炒菜机器人产品介绍.docx")
    docx = loader.load()
    docments = RecursiveCharacterTextSplitter(
        chunk_size=200,
        chunk_overlap=20,
    ).split_documents(docx)

    # 引入向量数据库
    Qdrant.from_documents(
        docments,
        get_lc_ali_embeddings(),
        path="local_qdrant",
        collection_name="local_documents",
        force_recreate=True
    )

    logger.info("向量数据库创建完成")
    return {"ok": "添加成功!"}


if __name__ == '__main__':
    setup_logger()

    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)
4、提问示例
"""
RAG
智能炒菜机器人的应用场景与典型案例
办公室风水知识有哪些

Function calling
深圳今天天气怎么样
查询明天北京到上海的票
我想去长沙旅游,请帮我查询一下长沙的景点有哪些?
我叫张三,性别男,农历1998年12月3日12:13分出生,请帮我测算八字。
我昨天梦到我在海边跳舞请帮我解梦
请为我占卜一卦
"""
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐