mirror of
https://github.com/RYDE-WORK/Langchain-Chatchat.git
synced 2026-02-06 06:49:48 +08:00
Agent大更新合并 (#1666)
* 更新上agent提示词代码 * 更新部分文档,修复了issue中提到的bge匹配超过1 的bug * 按需修改 * 解决了部分最新用户用依赖的bug,加了两个工具,移除google工具 * Agent大幅度优化 1. 修改了UI界面 (1)高亮所有没有进行agent对齐的模型, (2)优化输出体验和逻辑,使用markdown 2. 降低天气工具使用门槛 3. 依赖更新 (1) vllm 更新到0.2.0,增加了一些参数 (2) torch 建议更新到2.1 (3)pydantic不要更新到1.10.12
This commit is contained in:
parent
387b4cb967
commit
2c8fc95f7a
@ -2,8 +2,8 @@ langchain>=0.0.302
|
|||||||
fschat[model_worker]==0.2.30
|
fschat[model_worker]==0.2.30
|
||||||
openai
|
openai
|
||||||
sentence_transformers
|
sentence_transformers
|
||||||
transformers==4.33.3
|
transformers>=4.34
|
||||||
torch>=2.0.1
|
torch>=2.0.1 # 推荐2.1
|
||||||
torchvision
|
torchvision
|
||||||
torchaudio
|
torchaudio
|
||||||
fastapi>=0.103.2
|
fastapi>=0.103.2
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
langchain>=0.0.302
|
langchain>=0.0.302
|
||||||
fschat[model_worker]==0.2.30
|
fschat[model_worker]>=0.2.30
|
||||||
openai
|
openai
|
||||||
sentence_transformers
|
sentence_transformers
|
||||||
transformers>=4.33.3
|
transformers>=4.34
|
||||||
torch>=2.0.1
|
torch>=2.0.1
|
||||||
torchvision
|
torchvision
|
||||||
torchaudio
|
torchaudio
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class Status:
|
|||||||
agent_action: int = 4
|
agent_action: int = 4
|
||||||
agent_finish: int = 5
|
agent_finish: int = 5
|
||||||
error: int = 6
|
error: int = 6
|
||||||
make_tool: int = 7
|
tool_finish: int = 7
|
||||||
|
|
||||||
|
|
||||||
class CustomAsyncIteratorCallbackHandler(AsyncIteratorCallbackHandler):
|
class CustomAsyncIteratorCallbackHandler(AsyncIteratorCallbackHandler):
|
||||||
@ -29,11 +29,19 @@ class CustomAsyncIteratorCallbackHandler(AsyncIteratorCallbackHandler):
|
|||||||
self.queue = asyncio.Queue()
|
self.queue = asyncio.Queue()
|
||||||
self.done = asyncio.Event()
|
self.done = asyncio.Event()
|
||||||
self.cur_tool = {}
|
self.cur_tool = {}
|
||||||
self.out = True
|
|
||||||
|
|
||||||
async def on_tool_start(self, serialized: Dict[str, Any], input_str: str, *, run_id: UUID,
|
async def on_tool_start(self, serialized: Dict[str, Any], input_str: str, *, run_id: UUID,
|
||||||
parent_run_id: UUID | None = None, tags: List[str] | None = None,
|
parent_run_id: UUID | None = None, tags: List[str] | None = None,
|
||||||
metadata: Dict[str, Any] | None = None, **kwargs: Any) -> None:
|
metadata: Dict[str, Any] | None = None, **kwargs: Any) -> None:
|
||||||
|
|
||||||
|
# 对于截断不能自理的大模型,我来帮他截断
|
||||||
|
stop_words = ["Observation:", "Thought","\"","(", "\n","\t"]
|
||||||
|
for stop_word in stop_words:
|
||||||
|
index = input_str.find(stop_word)
|
||||||
|
if index != -1:
|
||||||
|
input_str = input_str[:index]
|
||||||
|
break
|
||||||
|
|
||||||
self.cur_tool = {
|
self.cur_tool = {
|
||||||
"tool_name": serialized["name"],
|
"tool_name": serialized["name"],
|
||||||
"input_str": input_str,
|
"input_str": input_str,
|
||||||
@ -44,13 +52,13 @@ class CustomAsyncIteratorCallbackHandler(AsyncIteratorCallbackHandler):
|
|||||||
"final_answer": "",
|
"final_answer": "",
|
||||||
"error": "",
|
"error": "",
|
||||||
}
|
}
|
||||||
|
# print("\nInput Str:",self.cur_tool["input_str"])
|
||||||
self.queue.put_nowait(dumps(self.cur_tool))
|
self.queue.put_nowait(dumps(self.cur_tool))
|
||||||
|
|
||||||
async def on_tool_end(self, output: str, *, run_id: UUID, parent_run_id: UUID | None = None,
|
async def on_tool_end(self, output: str, *, run_id: UUID, parent_run_id: UUID | None = None,
|
||||||
tags: List[str] | None = None, **kwargs: Any) -> None:
|
tags: List[str] | None = None, **kwargs: Any) -> None:
|
||||||
self.out = True
|
|
||||||
self.cur_tool.update(
|
self.cur_tool.update(
|
||||||
status=Status.agent_finish,
|
status=Status.tool_finish,
|
||||||
output_str=output.replace("Answer:", ""),
|
output_str=output.replace("Answer:", ""),
|
||||||
)
|
)
|
||||||
self.queue.put_nowait(dumps(self.cur_tool))
|
self.queue.put_nowait(dumps(self.cur_tool))
|
||||||
@ -65,19 +73,11 @@ class CustomAsyncIteratorCallbackHandler(AsyncIteratorCallbackHandler):
|
|||||||
|
|
||||||
async def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
|
async def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
|
||||||
if token:
|
if token:
|
||||||
if "Action" in token:
|
self.cur_tool.update(
|
||||||
self.out = False
|
|
||||||
self.cur_tool.update(
|
|
||||||
status=Status.running,
|
|
||||||
llm_token="\n\n",
|
|
||||||
)
|
|
||||||
self.queue.put_nowait(dumps(self.cur_tool))
|
|
||||||
if self.out:
|
|
||||||
self.cur_tool.update(
|
|
||||||
status=Status.running,
|
status=Status.running,
|
||||||
llm_token=token,
|
llm_token=token,
|
||||||
)
|
)
|
||||||
self.queue.put_nowait(dumps(self.cur_tool))
|
self.queue.put_nowait(dumps(self.cur_tool))
|
||||||
|
|
||||||
async def on_llm_start(self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any) -> None:
|
async def on_llm_start(self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any) -> None:
|
||||||
self.cur_tool.update(
|
self.cur_tool.update(
|
||||||
@ -87,15 +87,13 @@ class CustomAsyncIteratorCallbackHandler(AsyncIteratorCallbackHandler):
|
|||||||
self.queue.put_nowait(dumps(self.cur_tool))
|
self.queue.put_nowait(dumps(self.cur_tool))
|
||||||
|
|
||||||
async def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
|
async def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
|
||||||
self.out = True
|
|
||||||
self.cur_tool.update(
|
self.cur_tool.update(
|
||||||
status=Status.complete,
|
status=Status.complete,
|
||||||
llm_token="",
|
llm_token="\n",
|
||||||
)
|
)
|
||||||
self.queue.put_nowait(dumps(self.cur_tool))
|
self.queue.put_nowait(dumps(self.cur_tool))
|
||||||
|
|
||||||
async def on_llm_error(self, error: Exception | KeyboardInterrupt, **kwargs: Any) -> None:
|
async def on_llm_error(self, error: Exception | KeyboardInterrupt, **kwargs: Any) -> None:
|
||||||
self.out = True
|
|
||||||
self.cur_tool.update(
|
self.cur_tool.update(
|
||||||
status=Status.error,
|
status=Status.error,
|
||||||
error=str(error),
|
error=str(error),
|
||||||
@ -107,4 +105,10 @@ class CustomAsyncIteratorCallbackHandler(AsyncIteratorCallbackHandler):
|
|||||||
tags: Optional[List[str]] = None,
|
tags: Optional[List[str]] = None,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
# 返回最终答案
|
||||||
|
self.cur_tool.update(
|
||||||
|
status=Status.agent_finish,
|
||||||
|
final_answer=finish.return_values["output"],
|
||||||
|
)
|
||||||
|
self.queue.put_nowait(dumps(self.cur_tool))
|
||||||
self.cur_tool = {}
|
self.cur_tool = {}
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from langchain.agents import Tool, AgentOutputParser
|
from langchain.agents import Tool, AgentOutputParser
|
||||||
from langchain.prompts import StringPromptTemplate
|
from langchain.prompts import StringPromptTemplate
|
||||||
from typing import List, Union
|
from typing import List, Union, Tuple, Dict
|
||||||
from langchain.schema import AgentAction, AgentFinish
|
from langchain.schema import AgentAction, AgentFinish
|
||||||
import re
|
import re
|
||||||
|
from configs.model_config import LLM_MODEL, TEMPERATURE, HISTORY_LEN
|
||||||
|
|
||||||
|
begin = False
|
||||||
class CustomPromptTemplate(StringPromptTemplate):
|
class CustomPromptTemplate(StringPromptTemplate):
|
||||||
# The template to use
|
# The template to use
|
||||||
template: str
|
template: str
|
||||||
@ -19,40 +21,78 @@ class CustomPromptTemplate(StringPromptTemplate):
|
|||||||
for action, observation in intermediate_steps:
|
for action, observation in intermediate_steps:
|
||||||
thoughts += action.log
|
thoughts += action.log
|
||||||
thoughts += f"\nObservation: {observation}\nThought: "
|
thoughts += f"\nObservation: {observation}\nThought: "
|
||||||
# Set the agent_scratchpad variable to that value
|
# Set the agent_scratchpad variable to that value
|
||||||
kwargs["agent_scratchpad"] = thoughts
|
kwargs["agent_scratchpad"] = thoughts
|
||||||
# Create a tools variable from the list of tools provided
|
# Create a tools variable from the list of tools provided
|
||||||
kwargs["tools"] = "\n".join([f"{tool.name}: {tool.description}" for tool in self.tools])
|
kwargs["tools"] = "\n".join([f"{tool.name}: {tool.description}" for tool in self.tools])
|
||||||
# Create a list of tool names for the tools provided
|
# Create a list of tool names for the tools provided
|
||||||
kwargs["tool_names"] = ", ".join([tool.name for tool in self.tools])
|
kwargs["tool_names"] = ", ".join([tool.name for tool in self.tools])
|
||||||
|
# Return the formatted templatepr
|
||||||
|
# print( self.template.format(**kwargs), end="\n\n")
|
||||||
return self.template.format(**kwargs)
|
return self.template.format(**kwargs)
|
||||||
class CustomOutputParser(AgentOutputParser):
|
|
||||||
|
|
||||||
def parse(self, llm_output: str) -> AgentFinish | AgentAction | str:
|
|
||||||
|
class CustomOutputParser(AgentOutputParser):
|
||||||
|
begin: bool = False
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.begin = True
|
||||||
|
|
||||||
|
def parse(self, llm_output: str) -> AgentFinish | tuple[dict[str, str], str] | AgentAction:
|
||||||
# Check if agent should finish
|
# Check if agent should finish
|
||||||
|
support_agent = ["gpt","Qwen","qwen-api","baichuan-api"]
|
||||||
|
if not any(agent in LLM_MODEL for agent in support_agent) and self.begin:
|
||||||
|
self.begin = False
|
||||||
|
stop_words = ["Observation:"]
|
||||||
|
min_index = len(llm_output)
|
||||||
|
for stop_word in stop_words:
|
||||||
|
index = llm_output.find(stop_word)
|
||||||
|
if index != -1 and index < min_index:
|
||||||
|
min_index = index
|
||||||
|
llm_output = llm_output[:min_index]
|
||||||
|
|
||||||
if "Final Answer:" in llm_output:
|
if "Final Answer:" in llm_output:
|
||||||
|
output = llm_output.split("Final Answer:", 1)[-1].strip()
|
||||||
|
self.begin = True
|
||||||
return AgentFinish(
|
return AgentFinish(
|
||||||
# Return values is generally always a dictionary with a single `output` key
|
# Return values is generally always a dictionary with a single `output` key
|
||||||
# It is not recommended to try anything else at the moment :)
|
# It is not recommended to try anything else at the moment :)
|
||||||
return_values={"output": llm_output.replace("Final Answer:", "").strip()},
|
# return_values={"output": llm_output.replace("Final Answer:", "").strip()},
|
||||||
|
return_values={"output": output},
|
||||||
log=llm_output,
|
log=llm_output,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Parse out the action and action input
|
# Parse out the action and action input
|
||||||
regex = r"Action\s*\d*\s*:(.*?)\nAction\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
|
parts = llm_output.split("Action:")
|
||||||
match = re.search(regex, llm_output, re.DOTALL)
|
if len(parts) < 2:
|
||||||
if not match:
|
|
||||||
return AgentFinish(
|
return AgentFinish(
|
||||||
return_values={"output": f"调用agent失败: `{llm_output}`"},
|
return_values={"output": f"调用agent失败: `{llm_output}`"},
|
||||||
log=llm_output,
|
log=llm_output,
|
||||||
)
|
)
|
||||||
action = match.group(1).strip()
|
|
||||||
action_input = match.group(2)
|
action = parts[1].split("Action Input:")[0].strip()
|
||||||
|
action_input = parts[1].split("Action Input:")[1].strip()
|
||||||
|
|
||||||
|
# 原来的正则化检查方式
|
||||||
|
# regex = r"Action\s*\d*\s*:(.*?)\nAction\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
|
||||||
|
# print("llm_output",llm_output)
|
||||||
|
# match = re.search(regex, llm_output, re.DOTALL)
|
||||||
|
# print("match",match)
|
||||||
|
# if not match:
|
||||||
|
# return AgentFinish(
|
||||||
|
# return_values={"output": f"调用agent失败: `{llm_output}`"},
|
||||||
|
# log=llm_output,
|
||||||
|
# )
|
||||||
|
# action = match.group(1).strip()
|
||||||
|
# action_input = match.group(2)
|
||||||
|
|
||||||
# Return the action and action input
|
# Return the action and action input
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ans = AgentAction(
|
ans = AgentAction(
|
||||||
tool=action,
|
tool=action,
|
||||||
tool_input=action_input.strip(" ").strip('"'),
|
tool_input=action_input.strip(" ").strip('"'),
|
||||||
log=llm_output
|
log=llm_output
|
||||||
)
|
)
|
||||||
return ans
|
return ans
|
||||||
except:
|
except:
|
||||||
@ -60,6 +100,3 @@ class CustomOutputParser(AgentOutputParser):
|
|||||||
return_values={"output": f"调用agent失败: `{llm_output}`"},
|
return_values={"output": f"调用agent失败: `{llm_output}`"},
|
||||||
log=llm_output,
|
log=llm_output,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
|
## 单独运行的时候需要添加
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||||
|
|
||||||
from langchain.prompts import PromptTemplate
|
from langchain.prompts import PromptTemplate
|
||||||
from langchain.chains import LLMMathChain
|
from langchain.chains import LLMMathChain
|
||||||
from server.utils import wrap_done, get_ChatOpenAI
|
from server.utils import get_ChatOpenAI
|
||||||
from configs.model_config import LLM_MODEL, TEMPERATURE
|
from configs.model_config import LLM_MODEL, TEMPERATURE
|
||||||
from langchain.chat_models import ChatOpenAI
|
_PROMPT_TEMPLATE = """
|
||||||
from langchain.callbacks.manager import CallbackManagerForToolRun
|
将数学问题翻译成可以使用Python的numexpr库执行的表达式。使用运行此代码的输出来回答问题。
|
||||||
|
|
||||||
_PROMPT_TEMPLATE = """将数学问题翻译成可以使用Python的numexpr库执行的表达式。使用运行此代码的输出来回答问题。
|
|
||||||
问题: ${{包含数学问题的问题。}}
|
问题: ${{包含数学问题的问题。}}
|
||||||
```text
|
```text
|
||||||
${{解决问题的单行数学表达式}}
|
${{解决问题的单行数学表达式}}
|
||||||
@ -68,3 +71,8 @@ def calculate(query: str):
|
|||||||
llm_math = LLMMathChain.from_llm(model, verbose=True, prompt=PROMPT)
|
llm_math = LLMMathChain.from_llm(model, verbose=True, prompt=PROMPT)
|
||||||
ans = llm_math.run(query)
|
ans = llm_math.run(query)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = calculate("2的三次方")
|
||||||
|
print("答案:",result)
|
||||||
|
|
||||||
|
|||||||
@ -20,12 +20,12 @@ tools = [
|
|||||||
Tool.from_function(
|
Tool.from_function(
|
||||||
func=translate,
|
func=translate,
|
||||||
name="翻译工具",
|
name="翻译工具",
|
||||||
description="翻译各种语言"
|
description="如果你无法访问互联网,并且需要翻译各种语言,应该使用这个工具"
|
||||||
),
|
),
|
||||||
Tool.from_function(
|
Tool.from_function(
|
||||||
func=weathercheck,
|
func=weathercheck,
|
||||||
name="天气查询工具",
|
name="天气查询工具",
|
||||||
description="查询天气",
|
description="如果你无法访问互联网,并需要查询中国各地未来24小时的天气,你应该使用这个工具,每轮对话仅能使用一次",
|
||||||
),
|
),
|
||||||
Tool.from_function(
|
Tool.from_function(
|
||||||
func=shell,
|
func=shell,
|
||||||
@ -35,12 +35,12 @@ tools = [
|
|||||||
Tool.from_function(
|
Tool.from_function(
|
||||||
func=search_knowledge,
|
func=search_knowledge,
|
||||||
name="知识库查询工具",
|
name="知识库查询工具",
|
||||||
description="使用西交利物浦大学大数据专业的本专业数据库来解答问题",
|
description="访问知识库来获取答案",
|
||||||
),
|
),
|
||||||
Tool.from_function(
|
Tool.from_function(
|
||||||
func=search_internet,
|
func=search_internet,
|
||||||
name="互联网查询工具",
|
name="互联网查询工具",
|
||||||
description="访问Bing互联网来解答问题",
|
description="如果你无法访问互联网,这个工具可以帮助你访问Bing互联网来解答问题",
|
||||||
),
|
),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
from langchain.prompts import PromptTemplate
|
## 单独运行的时候需要添加
|
||||||
from langchain.chains import LLMChain
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from server.utils import get_ChatOpenAI
|
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||||
|
from langchain.prompts import PromptTemplate
|
||||||
|
from langchain.chains import LLMChain
|
||||||
|
from server.utils import get_ChatOpenAI
|
||||||
from langchain.chains.llm_math.prompt import PROMPT
|
from langchain.chains.llm_math.prompt import PROMPT
|
||||||
from configs.model_config import LLM_MODEL,TEMPERATURE
|
from configs.model_config import LLM_MODEL,TEMPERATURE
|
||||||
|
|
||||||
@ -16,25 +15,12 @@ _PROMPT_TEMPLATE = '''
|
|||||||
2. 无论提供的是陈述句或疑问句,只进行翻译
|
2. 无论提供的是陈述句或疑问句,只进行翻译
|
||||||
3. 不添加与原文无关的内容
|
3. 不添加与原文无关的内容
|
||||||
|
|
||||||
原文: ${{用户需要翻译的原文和目标语言}}
|
问题: ${{用户需要翻译的原文和目标语言}}
|
||||||
{question}
|
答案: 你翻译结果
|
||||||
```output
|
|
||||||
${{翻译结果}}
|
现在,这是我的问题:
|
||||||
```
|
问题: {question}
|
||||||
答案: ${{答案}}
|
|
||||||
|
|
||||||
以下是两个例子
|
|
||||||
问题: 翻译13成英语
|
|
||||||
```text
|
|
||||||
13 英语
|
|
||||||
```output
|
|
||||||
thirteen
|
|
||||||
以下是两个例子
|
|
||||||
问题: 翻译 我爱你 成法语
|
|
||||||
```text
|
|
||||||
13 法语
|
|
||||||
```output
|
|
||||||
Je t'aime.
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
PROMPT = PromptTemplate(
|
PROMPT = PromptTemplate(
|
||||||
@ -51,5 +37,8 @@ def translate(query: str):
|
|||||||
)
|
)
|
||||||
llm_translate = LLMChain(llm=model, prompt=PROMPT)
|
llm_translate = LLMChain(llm=model, prompt=PROMPT)
|
||||||
ans = llm_translate.run(query)
|
ans = llm_translate.run(query)
|
||||||
|
return ans
|
||||||
|
|
||||||
return ans
|
if __name__ == "__main__":
|
||||||
|
result = translate("Can Love remember the question and the answer? 这句话如何诗意的翻译成中文")
|
||||||
|
print("答案:",result)
|
||||||
@ -1,10 +1,12 @@
|
|||||||
## 使用和风天气API查询天气
|
## 使用和风天气API查询天气,这个模型仅仅对免费的API进行了适配
|
||||||
|
## 这个模型的提示词非常复杂,我们推荐使用GPT4模型进行运行
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
## 单独运行的时候需要添加
|
## 单独运行的时候需要添加
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
# sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||||
|
|
||||||
|
|
||||||
from server.utils import get_ChatOpenAI
|
from server.utils import get_ChatOpenAI
|
||||||
@ -26,9 +28,71 @@ from langchain.schema.language_model import BaseLanguageModel
|
|||||||
import requests
|
import requests
|
||||||
from typing import List, Any, Optional
|
from typing import List, Any, Optional
|
||||||
from configs.model_config import LLM_MODEL, TEMPERATURE
|
from configs.model_config import LLM_MODEL, TEMPERATURE
|
||||||
|
from datetime import datetime
|
||||||
|
from langchain.prompts import PromptTemplate
|
||||||
|
|
||||||
|
|
||||||
## 使用和风天气API查询天气
|
## 使用和风天气API查询天气
|
||||||
KEY = ""
|
KEY = "ac880e5a877042809ac7ffdd19d95b0d"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_PROMPT_TEMPLATE = """
|
||||||
|
用户会提出一个关于天气的问题,你的目标是拆分出用户问题中的区,市 并按照我提供的工具回答。
|
||||||
|
例如 用户提出的问题是: 上海浦东未来1小时天气情况?
|
||||||
|
则 提取的市和区是: 上海 浦东
|
||||||
|
如果用户提出的问题是: 上海未来1小时天气情况?
|
||||||
|
则 提取的市和区是: 上海 None
|
||||||
|
请注意以下内容:
|
||||||
|
1. 如果你没有找到区的内容,则一定要使用 None 替代,否则程序无法运行
|
||||||
|
2. 如果用户没有指定市 则直接返回缺少信息
|
||||||
|
|
||||||
|
问题: ${{用户的问题}}
|
||||||
|
|
||||||
|
你的回答格式应该按照下面的内容,请注意,格式内的```text 等标记都必须输出,这是我用来提取答案的标记。
|
||||||
|
```text
|
||||||
|
|
||||||
|
${{拆分的市和区,中间用空格隔开}}
|
||||||
|
```
|
||||||
|
... weathercheck(市 区)...
|
||||||
|
```output
|
||||||
|
|
||||||
|
${{提取后的答案}}
|
||||||
|
```
|
||||||
|
答案: ${{答案}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
这是一个例子:
|
||||||
|
问题: 上海浦东未来1小时天气情况?
|
||||||
|
|
||||||
|
|
||||||
|
```text
|
||||||
|
上海 浦东
|
||||||
|
```
|
||||||
|
...weathercheck(上海 浦东)...
|
||||||
|
|
||||||
|
```output
|
||||||
|
预报时间: 1小时后
|
||||||
|
具体时间: 今天 18:00
|
||||||
|
温度: 24°C
|
||||||
|
天气: 多云
|
||||||
|
风向: 西南风
|
||||||
|
风速: 7级
|
||||||
|
湿度: 88%
|
||||||
|
降水概率: 16%
|
||||||
|
|
||||||
|
Answer: 上海浦东一小时后的天气是多云。
|
||||||
|
|
||||||
|
现在,这是我的问题:
|
||||||
|
|
||||||
|
问题: {question}
|
||||||
|
"""
|
||||||
|
PROMPT = PromptTemplate(
|
||||||
|
input_variables=["question"],
|
||||||
|
template=_PROMPT_TEMPLATE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_city_info(location, adm, key):
|
def get_city_info(location, adm, key):
|
||||||
base_url = 'https://geoapi.qweather.com/v2/city/lookup?'
|
base_url = 'https://geoapi.qweather.com/v2/city/lookup?'
|
||||||
@ -38,12 +102,9 @@ def get_city_info(location, adm, key):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
from datetime import datetime
|
def format_weather_data(data,place):
|
||||||
|
|
||||||
|
|
||||||
def format_weather_data(data):
|
|
||||||
hourly_forecast = data['hourly']
|
hourly_forecast = data['hourly']
|
||||||
formatted_data = ''
|
formatted_data = f"\n 这是查询到的关于{place}未来24小时的天气信息: \n"
|
||||||
for forecast in hourly_forecast:
|
for forecast in hourly_forecast:
|
||||||
# 将预报时间转换为datetime对象
|
# 将预报时间转换为datetime对象
|
||||||
forecast_time = datetime.strptime(forecast['fxTime'], '%Y-%m-%dT%H:%M%z')
|
forecast_time = datetime.strptime(forecast['fxTime'], '%Y-%m-%dT%H:%M%z')
|
||||||
@ -71,12 +132,11 @@ def format_weather_data(data):
|
|||||||
elif hours_diff >= 24:
|
elif hours_diff >= 24:
|
||||||
# 如果超过24小时,转换为天数
|
# 如果超过24小时,转换为天数
|
||||||
days_diff = hours_diff // 24
|
days_diff = hours_diff // 24
|
||||||
hours_diff_str = str(int(days_diff)) + '天后'
|
hours_diff_str = str(int(days_diff)) + '天'
|
||||||
else:
|
else:
|
||||||
hours_diff_str = str(int(hours_diff)) + '小时后'
|
hours_diff_str = str(int(hours_diff)) + '小时'
|
||||||
# 将预报时间和当前时间的差值添加到输出中
|
# 将预报时间和当前时间的差值添加到输出中
|
||||||
formatted_data += '预报时间: ' + hours_diff_str + '\n'
|
formatted_data += '预报时间: ' + forecast_time_str + ' 距离现在有: ' + hours_diff_str + '\n'
|
||||||
formatted_data += '具体时间: ' + forecast_time_str + '\n'
|
|
||||||
formatted_data += '温度: ' + forecast['temp'] + '°C\n'
|
formatted_data += '温度: ' + forecast['temp'] + '°C\n'
|
||||||
formatted_data += '天气: ' + forecast['text'] + '\n'
|
formatted_data += '天气: ' + forecast['text'] + '\n'
|
||||||
formatted_data += '风向: ' + forecast['windDir'] + '\n'
|
formatted_data += '风向: ' + forecast['windDir'] + '\n'
|
||||||
@ -84,53 +144,54 @@ def format_weather_data(data):
|
|||||||
formatted_data += '湿度: ' + forecast['humidity'] + '%\n'
|
formatted_data += '湿度: ' + forecast['humidity'] + '%\n'
|
||||||
formatted_data += '降水概率: ' + forecast['pop'] + '%\n'
|
formatted_data += '降水概率: ' + forecast['pop'] + '%\n'
|
||||||
# formatted_data += '降水量: ' + forecast['precip'] + 'mm\n'
|
# formatted_data += '降水量: ' + forecast['precip'] + 'mm\n'
|
||||||
formatted_data += '\n\n'
|
formatted_data += '\n'
|
||||||
return formatted_data
|
return formatted_data
|
||||||
|
|
||||||
|
|
||||||
def get_weather(key, location_id, time: str = "24"):
|
def get_weather(key, location_id,place):
|
||||||
if time:
|
url = "https://devapi.qweather.com/v7/weather/24h?"
|
||||||
url = "https://devapi.qweather.com/v7/weather/" + time + "h?"
|
|
||||||
else:
|
|
||||||
time = "3" # 免费订阅只能查看3天的天气
|
|
||||||
url = "https://devapi.qweather.com/v7/weather/" + time + "d?"
|
|
||||||
params = {
|
params = {
|
||||||
'location': location_id,
|
'location': location_id,
|
||||||
'key': key,
|
'key': key,
|
||||||
}
|
}
|
||||||
response = requests.get(url, params=params)
|
response = requests.get(url, params=params)
|
||||||
data = response.json()
|
data = response.json()
|
||||||
return format_weather_data(data)
|
return format_weather_data(data,place)
|
||||||
|
|
||||||
|
|
||||||
def split_query(query):
|
def split_query(query):
|
||||||
parts = query.split()
|
parts = query.split()
|
||||||
location = parts[0] if parts[0] != 'None' else parts[1]
|
adm = parts[0]
|
||||||
adm = parts[1]
|
location = parts[1] if parts[1] != 'None' else adm
|
||||||
time = parts[2]
|
return location, adm
|
||||||
return location, adm, time
|
|
||||||
|
|
||||||
|
|
||||||
def weather(query):
|
def weather(query):
|
||||||
location, adm, time = split_query(query)
|
location, adm= split_query(query)
|
||||||
key = KEY
|
key = KEY
|
||||||
if time != "None" and int(time) > 24:
|
|
||||||
return "只能查看24小时内的天气,无法回答"
|
|
||||||
if time == "None":
|
|
||||||
time = "24" # 免费的版本只能24小时内的天气
|
|
||||||
if key == "":
|
if key == "":
|
||||||
return "请先在代码中填入和风天气API Key"
|
return "请先在代码中填入和风天气API Key"
|
||||||
city_info = get_city_info(location=location, adm=adm, key=key)
|
try:
|
||||||
location_id = city_info['location'][0]['id']
|
city_info = get_city_info(location=location, adm=adm, key=key)
|
||||||
weather_data = get_weather(key=key, location_id=location_id, time=time)
|
location_id = city_info['location'][0]['id']
|
||||||
return weather_data
|
place = adm + "市" + location + "区"
|
||||||
|
|
||||||
|
|
||||||
|
weather_data = get_weather(key=key, location_id=location_id,place=place)
|
||||||
|
return weather_data + "以上是查询到的天气信息,请你查收\n"
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
city_info = get_city_info(location=adm, adm=adm, key=key)
|
||||||
|
location_id = city_info['location'][0]['id']
|
||||||
|
place = adm + "市"
|
||||||
|
weather_data = get_weather(key=key, location_id=location_id,place=place)
|
||||||
|
return weather_data + "重要提醒:用户提供的市和区中,区的信息不存在,或者出现错别字,因此该信息是关于市的天气,请你查收\n"
|
||||||
|
except KeyError:
|
||||||
|
return "输入的地区不存在,无法提供天气预报"
|
||||||
class LLMWeatherChain(Chain):
|
class LLMWeatherChain(Chain):
|
||||||
llm_chain: LLMChain
|
llm_chain: LLMChain
|
||||||
llm: Optional[BaseLanguageModel] = None
|
llm: Optional[BaseLanguageModel] = None
|
||||||
"""[Deprecated] LLM wrapper to use."""
|
"""[Deprecated] LLM wrapper to use."""
|
||||||
prompt: BasePromptTemplate
|
prompt: BasePromptTemplate = PROMPT
|
||||||
"""[Deprecated] Prompt to use to translate to python if necessary."""
|
"""[Deprecated] Prompt to use to translate to python if necessary."""
|
||||||
input_key: str = "question" #: :meta private:
|
input_key: str = "question" #: :meta private:
|
||||||
output_key: str = "answer" #: :meta private:
|
output_key: str = "answer" #: :meta private:
|
||||||
@ -175,7 +236,8 @@ class LLMWeatherChain(Chain):
|
|||||||
output = weather(expression)
|
output = weather(expression)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
output = "输入的信息有误,请再次尝试"
|
output = "输入的信息有误,请再次尝试"
|
||||||
# raise ValueError(f"错误: {expression},输入的信息不对")
|
return {self.output_key: output}
|
||||||
|
raise ValueError(f"错误: {expression},输入的信息不对")
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
@ -198,7 +260,8 @@ class LLMWeatherChain(Chain):
|
|||||||
elif "Answer:" in llm_output:
|
elif "Answer:" in llm_output:
|
||||||
answer = "Answer: " + llm_output.split("Answer:")[-1]
|
answer = "Answer: " + llm_output.split("Answer:")[-1]
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"unknown format from LLM: {llm_output}")
|
return {self.output_key: f"输入的格式不对: {llm_output},应该输入 (市 区)的组合"}
|
||||||
|
# raise ValueError(f"unknown format from LLM: {llm_output}")
|
||||||
return {self.output_key: answer}
|
return {self.output_key: answer}
|
||||||
|
|
||||||
async def _aprocess_llm_result(
|
async def _aprocess_llm_result(
|
||||||
@ -259,92 +322,13 @@ class LLMWeatherChain(Chain):
|
|||||||
def from_llm(
|
def from_llm(
|
||||||
cls,
|
cls,
|
||||||
llm: BaseLanguageModel,
|
llm: BaseLanguageModel,
|
||||||
prompt: BasePromptTemplate,
|
prompt: BasePromptTemplate = PROMPT,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> LLMWeatherChain:
|
) -> LLMWeatherChain:
|
||||||
llm_chain = LLMChain(llm=llm, prompt=prompt)
|
llm_chain = LLMChain(llm=llm, prompt=prompt)
|
||||||
return cls(llm_chain=llm_chain, **kwargs)
|
return cls(llm_chain=llm_chain, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
from langchain.prompts import PromptTemplate
|
|
||||||
|
|
||||||
_PROMPT_TEMPLATE = """用户将会向您咨询天气问题,您不需要自己回答天气问题,而是将用户提问的信息提取出来区,市和时间三个元素后使用我为你编写好的工具进行查询并返回结果,格式为 区+市+时间 每个元素用空格隔开。如果缺少信息,则用 None 代替。
|
|
||||||
问题: ${{用户的问题}}
|
|
||||||
|
|
||||||
```text
|
|
||||||
|
|
||||||
${{拆分的区,市和时间}}
|
|
||||||
```
|
|
||||||
|
|
||||||
... weather(提取后的关键字,用空格隔开)...
|
|
||||||
```output
|
|
||||||
|
|
||||||
${{提取后的答案}}
|
|
||||||
```
|
|
||||||
答案: ${{答案}}
|
|
||||||
|
|
||||||
这是两个例子:
|
|
||||||
问题: 上海浦东未来1小时天气情况?
|
|
||||||
|
|
||||||
```text
|
|
||||||
浦东 上海 1
|
|
||||||
```
|
|
||||||
...weather(浦东 上海 1)...
|
|
||||||
|
|
||||||
```output
|
|
||||||
|
|
||||||
预报时间: 1小时后
|
|
||||||
具体时间: 今天 18:00
|
|
||||||
温度: 24°C
|
|
||||||
天气: 多云
|
|
||||||
风向: 西南风
|
|
||||||
风速: 7级
|
|
||||||
湿度: 88%
|
|
||||||
降水概率: 16%
|
|
||||||
|
|
||||||
Answer:
|
|
||||||
预报时间: 1小时后
|
|
||||||
具体时间: 今天 18:00
|
|
||||||
温度: 24°C
|
|
||||||
天气: 多云
|
|
||||||
风向: 西南风
|
|
||||||
风速: 7级
|
|
||||||
湿度: 88%
|
|
||||||
降水概率: 16%
|
|
||||||
|
|
||||||
问题: 北京市朝阳区未来24小时天气如何?
|
|
||||||
```text
|
|
||||||
|
|
||||||
朝阳 北京 24
|
|
||||||
```
|
|
||||||
...weather(朝阳 北京 24)...
|
|
||||||
```output
|
|
||||||
预报时间: 23小时后
|
|
||||||
具体时间: 明天 17:00
|
|
||||||
温度: 26°C
|
|
||||||
天气: 霾
|
|
||||||
风向: 西南风
|
|
||||||
风速: 11级
|
|
||||||
湿度: 65%
|
|
||||||
降水概率: 20%
|
|
||||||
Answer:
|
|
||||||
预报时间: 23小时后
|
|
||||||
具体时间: 明天 17:00
|
|
||||||
温度: 26°C
|
|
||||||
天气: 霾
|
|
||||||
风向: 西南风
|
|
||||||
风速: 11级
|
|
||||||
湿度: 65%
|
|
||||||
降水概率: 20%
|
|
||||||
|
|
||||||
现在,这是我的问题:
|
|
||||||
问题: {question}
|
|
||||||
"""
|
|
||||||
PROMPT = PromptTemplate(
|
|
||||||
input_variables=["question"],
|
|
||||||
template=_PROMPT_TEMPLATE,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def weathercheck(query: str):
|
def weathercheck(query: str):
|
||||||
model = get_ChatOpenAI(
|
model = get_ChatOpenAI(
|
||||||
@ -357,9 +341,4 @@ def weathercheck(query: str):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
result = weathercheck("苏州工姑苏区今晚热不热?")
|
||||||
## 检测api是否能正确返回
|
|
||||||
query = "上海浦东未来1小时天气情况"
|
|
||||||
# ans = weathercheck(query)
|
|
||||||
ans = weather("浦东 上海 1")
|
|
||||||
print(ans)
|
|
||||||
@ -53,13 +53,11 @@ async def agent_chat(query: str = Body(..., description="用户输入", examples
|
|||||||
agent = LLMSingleActionAgent(
|
agent = LLMSingleActionAgent(
|
||||||
llm_chain=llm_chain,
|
llm_chain=llm_chain,
|
||||||
output_parser=output_parser,
|
output_parser=output_parser,
|
||||||
stop=["Observation:", "Observation:\n", "<|im_end|>"], # Qwen模型中使用这个
|
stop=["\nObservation:", "Observation:", "<|im_end|>"], # Qwen模型中使用这个
|
||||||
# stop=["Observation:", "Observation:\n"], # 其他模型,注意模板
|
|
||||||
allowed_tools=tool_names,
|
allowed_tools=tool_names,
|
||||||
)
|
)
|
||||||
# 把history转成agent的memory
|
# 把history转成agent的memory
|
||||||
memory = ConversationBufferWindowMemory(k=HISTORY_LEN * 2)
|
memory = ConversationBufferWindowMemory(k=HISTORY_LEN * 2)
|
||||||
|
|
||||||
for message in history:
|
for message in history:
|
||||||
# 检查消息的角色
|
# 检查消息的角色
|
||||||
if message.role == 'user':
|
if message.role == 'user':
|
||||||
@ -74,29 +72,41 @@ async def agent_chat(query: str = Body(..., description="用户输入", examples
|
|||||||
memory=memory,
|
memory=memory,
|
||||||
)
|
)
|
||||||
input_msg = History(role="user", content="{{ input }}").to_msg_template(False)
|
input_msg = History(role="user", content="{{ input }}").to_msg_template(False)
|
||||||
task = asyncio.create_task(wrap_done(
|
while True:
|
||||||
agent_executor.acall(query, callbacks=[callback], include_run_info=True),
|
try:
|
||||||
callback.done),
|
task = asyncio.create_task(wrap_done(
|
||||||
)
|
agent_executor.acall(query, callbacks=[callback], include_run_info=True),
|
||||||
|
callback.done))
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
pass
|
||||||
if stream:
|
if stream:
|
||||||
async for chunk in callback.aiter():
|
async for chunk in callback.aiter():
|
||||||
tools_use = []
|
tools_use = []
|
||||||
# Use server-sent-events to stream the response
|
# Use server-sent-events to stream the response
|
||||||
data = json.loads(chunk)
|
data = json.loads(chunk)
|
||||||
if data["status"] == Status.error:
|
|
||||||
tools_use.append("工具调用失败:\n" + data["error"])
|
|
||||||
yield json.dumps({"tools": tools_use}, ensure_ascii=False)
|
|
||||||
yield json.dumps({"answer": "(工具调用失败,请查看工具栏报错) \n\n"}, ensure_ascii=False)
|
|
||||||
if data["status"] == Status.start or data["status"] == Status.complete:
|
if data["status"] == Status.start or data["status"] == Status.complete:
|
||||||
continue
|
continue
|
||||||
if data["status"] == Status.agent_action:
|
if data["status"] == Status.error:
|
||||||
yield json.dumps({"answer": "(正在使用工具,请注意工具栏变化) \n\n"}, ensure_ascii=False)
|
|
||||||
if data["status"] == Status.agent_finish:
|
|
||||||
tools_use.append("工具名称: " + data["tool_name"])
|
tools_use.append("工具名称: " + data["tool_name"])
|
||||||
|
tools_use.append("工具状态: " + "调用失败")
|
||||||
|
tools_use.append("错误信息: " + data["error"])
|
||||||
|
tools_use.append("重新开始尝试")
|
||||||
|
tools_use.append("\n```\n")
|
||||||
|
yield json.dumps({"tools": tools_use}, ensure_ascii=False)
|
||||||
|
if data["status"] == Status.agent_action:
|
||||||
|
yield json.dumps({"answer": "\n\n```\n\n"}, ensure_ascii=False)
|
||||||
|
if data["status"] == Status.tool_finish:
|
||||||
|
tools_use.append("工具名称: " + data["tool_name"])
|
||||||
|
tools_use.append("工具状态: " + "调用成功")
|
||||||
tools_use.append("工具输入: " + data["input_str"])
|
tools_use.append("工具输入: " + data["input_str"])
|
||||||
tools_use.append("工具输出: " + data["output_str"])
|
tools_use.append("工具输出: " + data["output_str"])
|
||||||
|
tools_use.append("\n```\n")
|
||||||
yield json.dumps({"tools": tools_use}, ensure_ascii=False)
|
yield json.dumps({"tools": tools_use}, ensure_ascii=False)
|
||||||
yield json.dumps({"answer": data["llm_token"]}, ensure_ascii=False)
|
if data["status"] == Status.agent_finish:
|
||||||
|
yield json.dumps({"final_answer": data["final_answer"]}, ensure_ascii=False)
|
||||||
|
else:
|
||||||
|
yield json.dumps({"answer": data["llm_token"]}, ensure_ascii=False)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -44,7 +44,8 @@ class ApiModelWorker(BaseModelWorker):
|
|||||||
|
|
||||||
def count_token(self, params):
|
def count_token(self, params):
|
||||||
# TODO:需要完善
|
# TODO:需要完善
|
||||||
print("count token")
|
# print("count token")
|
||||||
|
print("\n\n\n")
|
||||||
print(params)
|
print(params)
|
||||||
prompt = params["prompt"]
|
prompt = params["prompt"]
|
||||||
return {"count": len(str(prompt)), "error_code": 0}
|
return {"count": len(str(prompt)), "error_code": 0}
|
||||||
|
|||||||
@ -26,10 +26,10 @@ class ChatGLMWorker(ApiModelWorker):
|
|||||||
# 这里的是chatglm api的模板,其它API的conv_template需要定制
|
# 这里的是chatglm api的模板,其它API的conv_template需要定制
|
||||||
self.conv = conv.Conversation(
|
self.conv = conv.Conversation(
|
||||||
name=self.model_names[0],
|
name=self.model_names[0],
|
||||||
system_message="你是一个聪明、对人类有帮助的人工智能,你可以对人类提出的问题给出有用、详细、礼貌的回答。",
|
system_message="你是一个聪明的助手,请根据用户的提示来完成任务",
|
||||||
messages=[],
|
messages=[],
|
||||||
roles=["Human", "Assistant"],
|
roles=["Human", "Assistant"],
|
||||||
sep="\n### ",
|
sep="\n###",
|
||||||
stop_str="###",
|
stop_str="###",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ class ChatGLMWorker(ApiModelWorker):
|
|||||||
def get_embeddings(self, params):
|
def get_embeddings(self, params):
|
||||||
# TODO: 支持embeddings
|
# TODO: 支持embeddings
|
||||||
print("embedding")
|
print("embedding")
|
||||||
print(params)
|
# print(params)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@ -158,7 +158,7 @@ def create_model_worker_app(log_level: str = "INFO", **kwargs) -> FastAPI:
|
|||||||
else:
|
else:
|
||||||
from fastchat.serve.model_worker import app, GptqConfig, AWQConfig, ModelWorker
|
from fastchat.serve.model_worker import app, GptqConfig, AWQConfig, ModelWorker
|
||||||
args.gpus = "0" # GPU的编号,如果有多个GPU,可以设置为"0,1,2,3"
|
args.gpus = "0" # GPU的编号,如果有多个GPU,可以设置为"0,1,2,3"
|
||||||
args.max_gpu_memory = "20GiB"
|
args.max_gpu_memory = "22GiB"
|
||||||
args.num_gpus = 1 # model worker的切分是model并行,这里填写显卡的数量
|
args.num_gpus = 1 # model worker的切分是model并行,这里填写显卡的数量
|
||||||
|
|
||||||
args.load_8bit = False
|
args.load_8bit = False
|
||||||
@ -170,7 +170,7 @@ def create_model_worker_app(log_level: str = "INFO", **kwargs) -> FastAPI:
|
|||||||
args.awq_ckpt = None
|
args.awq_ckpt = None
|
||||||
args.awq_wbits = 16
|
args.awq_wbits = 16
|
||||||
args.awq_groupsize = -1
|
args.awq_groupsize = -1
|
||||||
args.model_names = []
|
args.model_names = [""]
|
||||||
args.conv_template = None
|
args.conv_template = None
|
||||||
args.limit_worker_concurrency = 5
|
args.limit_worker_concurrency = 5
|
||||||
args.stream_interval = 2
|
args.stream_interval = 2
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import os
|
|||||||
from configs import LLM_MODEL, TEMPERATURE
|
from configs import LLM_MODEL, TEMPERATURE
|
||||||
from server.utils import get_model_worker_config
|
from server.utils import get_model_worker_config
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
|
|
||||||
chat_box = ChatBox(
|
chat_box = ChatBox(
|
||||||
assistant_avatar=os.path.join(
|
assistant_avatar=os.path.join(
|
||||||
"img",
|
"img",
|
||||||
@ -16,6 +15,9 @@ chat_box = ChatBox(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_messages_history(history_len: int, content_in_expander: bool = False) -> List[Dict]:
|
def get_messages_history(history_len: int, content_in_expander: bool = False) -> List[Dict]:
|
||||||
'''
|
'''
|
||||||
返回消息历史。
|
返回消息历史。
|
||||||
@ -104,6 +106,8 @@ def dialogue_page(api: ApiRequest):
|
|||||||
temperature = st.slider("Temperature:", 0.0, 1.0, TEMPERATURE, 0.05)
|
temperature = st.slider("Temperature:", 0.0, 1.0, TEMPERATURE, 0.05)
|
||||||
|
|
||||||
history_len = st.number_input("历史对话轮数:", 0, 20, HISTORY_LEN)
|
history_len = st.number_input("历史对话轮数:", 0, 20, HISTORY_LEN)
|
||||||
|
LLM_MODEL_WEBUI = llm_model
|
||||||
|
TEMPERATURE_WEBUI = temperature
|
||||||
|
|
||||||
def on_kb_change():
|
def on_kb_change():
|
||||||
st.toast(f"已加载知识库: {st.session_state.selected_kb}")
|
st.toast(f"已加载知识库: {st.session_state.selected_kb}")
|
||||||
@ -155,9 +159,17 @@ def dialogue_page(api: ApiRequest):
|
|||||||
|
|
||||||
elif dialogue_mode == "自定义Agent问答":
|
elif dialogue_mode == "自定义Agent问答":
|
||||||
chat_box.ai_say([
|
chat_box.ai_say([
|
||||||
f"正在思考和寻找工具 ...",])
|
f"正在思考...",
|
||||||
|
Markdown("...", in_expander=True, title="思考过程", state="complete"),
|
||||||
|
])
|
||||||
text = ""
|
text = ""
|
||||||
element_index = 0
|
ans = ""
|
||||||
|
support_agent = ["gpt", "Qwen", "qwen-api", "baichuan-api"] # 目前支持agent的模型
|
||||||
|
if not any(agent in llm_model for agent in support_agent):
|
||||||
|
ans += "正在思考... \n\n <span style='color:red'>改模型并没有进行Agent对齐,无法正常使用Agent功能!</span>\n\n\n<span style='color:red'>请更换 GPT4或Qwen-14B等支持Agent的模型获得更好的体验! </span> \n\n\n"
|
||||||
|
chat_box.update_msg(ans, element_index=0, streaming=False)
|
||||||
|
|
||||||
|
|
||||||
for d in api.agent_chat(prompt,
|
for d in api.agent_chat(prompt,
|
||||||
history=history,
|
history=history,
|
||||||
model=llm_model,
|
model=llm_model,
|
||||||
@ -169,14 +181,17 @@ def dialogue_page(api: ApiRequest):
|
|||||||
if error_msg := check_error_msg(d): # check whether error occured
|
if error_msg := check_error_msg(d): # check whether error occured
|
||||||
st.error(error_msg)
|
st.error(error_msg)
|
||||||
|
|
||||||
|
elif chunk := d.get("final_answer"):
|
||||||
|
ans += chunk
|
||||||
|
chat_box.update_msg(ans, element_index=0)
|
||||||
elif chunk := d.get("answer"):
|
elif chunk := d.get("answer"):
|
||||||
text += chunk
|
text += chunk
|
||||||
chat_box.update_msg(text, element_index=0)
|
chat_box.update_msg(text, element_index=1)
|
||||||
elif chunk := d.get("tools"):
|
elif chunk := d.get("tools"):
|
||||||
element_index += 1
|
text += "\n\n".join(d.get("tools", []))
|
||||||
chat_box.insert_msg(Markdown("...", in_expander=True, title="使用工具...", state="complete"))
|
chat_box.update_msg(text, element_index=1)
|
||||||
chat_box.update_msg("\n\n".join(d.get("tools", [])), element_index=element_index, streaming=False)
|
chat_box.update_msg(ans, element_index=0, streaming=False)
|
||||||
chat_box.update_msg(text, element_index=0, streaming=False)
|
chat_box.update_msg(text, element_index=1, streaming=False)
|
||||||
elif dialogue_mode == "知识库问答":
|
elif dialogue_mode == "知识库问答":
|
||||||
chat_box.ai_say([
|
chat_box.ai_say([
|
||||||
f"正在查询知识库 `{selected_kb}` ...",
|
f"正在查询知识库 `{selected_kb}` ...",
|
||||||
|
|||||||
@ -250,7 +250,7 @@ class ApiRequest:
|
|||||||
logger.error(f'{e.__class__.__name__}: {msg}',
|
logger.error(f'{e.__class__.__name__}: {msg}',
|
||||||
exc_info=e if log_verbose else None)
|
exc_info=e if log_verbose else None)
|
||||||
else:
|
else:
|
||||||
print(chunk, end="", flush=True)
|
# print(chunk, end="", flush=True)
|
||||||
yield chunk
|
yield chunk
|
||||||
except httpx.ConnectError as e:
|
except httpx.ConnectError as e:
|
||||||
msg = f"无法连接API服务器,请确认 ‘api.py’ 已正常启动。({e})"
|
msg = f"无法连接API服务器,请确认 ‘api.py’ 已正常启动。({e})"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user