# dagent_llm
**Repository Path**: iint/dagent_llm
## Basic Information
- **Project Name**: dagent_llm
- **Description**: Dagent_llm 包是一个基于 Python 的命令行界面(CLI),为与大型语言模型(LLMs)进行交互提供了便捷的方式。它允许用户与模型进行对话、基于给定选项做出决策等。该包设计简洁直观,支持多种 LLM 操作,易于扩展。
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2024-10-18
- **Last Updated**: 2024-11-01
## Categories & Tags
**Categories**: Uncategorized
**Tags**: Agent, llm
## README
# DAgent
[English](README.md) | 中文
## 概述
LLM 包是一个基于 Python 的命令行界面(CLI),为与大型语言模型(LLMs)进行交互提供了便捷的方式。它允许用户与模型进行对话、基于给定选项做出决策等。该包设计简洁直观,支持多种 LLM 操作,易于扩展。
## 功能
- 与 LLM 进行对话并接收回复。
- 向 LLM 提供选项并获取选择结果。
- 选择一个选项并提供参数进行进一步处理。
- 支持少样本学习以提高上下文理解能力。
- 支持对话历史记录日志,方便日后参考。
## 安装
要安装 LLM 包,请运行以下命令:
```bash
pip install dagent_llm
```
确保您的系统安装了 Python 3.6 或更高版本。
## 帮助
您可以使用 `help` 标志查看可用的命令和选项:
```bash
dagent_llm help
```
这将显示可用命令及其描述。
> 注意:Dagent_llm 默认您已通过[dsqlenv](https://pypi.org/project/dsqlenv/)配置了环境变量,系统将从[dsqlenv](https://pypi.org/project/dsqlenv/)读取必要的信息。
```
D-Agent LLM Command Line Interface
Usage: dagent_llm
Available Commands:
chat Send a message to the LLM and get a response.
choose Present options to the LLM and get a choice.
choose_with_args Choose an option and provide arguments.
Options for 'chat' command:
--message The message to send to the LLM.
--llm_server Specify the LLM server to use.
--role Specify the role of the message sender (default: 'human').
Options for 'choose' command:
--options List of options to choose from.
--prompt The prompt for choosing.
--need-reason Ask the LLM to provide reasons for the choice.
--multiple Allow the LLM to select multiple options.
--notes Additional notes to add to the prompt.
--examples Few-shot learning examples to guide the choice.
Options for 'choose_with_args' command:
--options List of options to choose from.
--prompt The prompt for choosing.
--option-type The type of options being chosen.
--need-reason Provide reasons for the choice.
--multiple Allow multiple selections.
--notes Additional notes to add to the prompt.
--examples Few-shot learning examples to guide the choice.
Version: 0.1.0 | 2024-10-18
Copyright: © 2024 VoiceCodeAI, Singapore
```
## 依赖项
- Python 3.6+
- dsqlenv
- langchain_core
- langchain_openai
## 使用方法
### 与 LLM 进行对话
要发送消息给 LLM 并接收回复,请使用 `chat` 命令:
```bash
dagent_llm chat --message "你好,你怎么样?" --role human
```
`--role` 参数可以设置为 `human`(用户),`ai`(AI 模型),或 `system`(系统),取决于消息的上下文。
### 选项选择
要向 LLM 提供选项并获取其选择结果,请使用 `choose` 命令:
```bash
dagent_llm choose --options "选项1" "选项2" "选项3" --prompt "请选择一个选项" --need-reason --multiple
```
`--need-reason` 参数会要求 LLM 提供选择的理由,`--multiple` 参数允许选择多个选项。
### 带参数的选择
要选择一个选项并提供参数进行处理,请使用 `choose_with_args` 命令:
```bash
dagent_llm choose_with_args --options "选项1" "选项2" "选项3" --prompt "选择一个选项并提供参数" --option-type "type" --need-reason --multiple
```
`--option-type` 参数用于描述所选项的类型。
### 提供少样本例子
您可以使用 `examples` 参数向 LLM 提供少样本学习的例子,以引导其决策:
```bash
dagent_llm choose --options ... --prompt ... --examples "例子1" "例子2"
```
### 添加附加说明
可以通过 `notes` 参数向提示中添加附加说明:
```bash
dagent_llm choose --options ... --prompt ... --notes "说明1" "说明2"
```
## 演示
以下是一个简单的演示,展示了如何与 LLM 进行对话:
```bash
# 与 LLM 对话
dagent_llm chat --message "今天的天气怎么样?" --role human
# 输出:
# LLM 回复:今天天气晴朗,偶尔有些云。
```
## Python API
LLM 包也可以作为 Python 库使用。以下是使用 Python API 与 LLM 对话的示例:
```python
from dagent_llm import LLM
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
# 使用特定引擎初始化 LLM 模型
model = LLM(llm_server="deepseek") # 'deepseek' 是 LLM 使用的引擎。
# 注意:通过llm_server直接启动,需要您已安装dsqlenv并进行过必要配置。
# 比如:{llm_server}_api_key, {llm_server}_base_url, {llm_server}_model等信息。
# 具体配置方法请参考[dsqlenv](https://pypi.org/project/dsqlenv/)
# 或者您可以指定完整的引擎信息
model = LLM(
llm_server="deepseek",
max_retries=3, # 最大重试次数
temperature=0.7, # 温度参数
api_key="your_api_key", # API 密钥
base_url="https://api.deepseek.com", # API 基础 URL
model_name="deepseek-chat", # 使用的模型
history=[] # 初始化的对话历史记录,同langchain_core.messages
)
# 与模型进行简单的互动
r = model.chat("介绍一下你自己")
print(r.content) # 输出模型的回复
# 定义函数列表及其名称和输入参数
functions_info = [
{"name": "get_data", "input": ["id"], "example_input": "a"},
{"name": "insert_data", "input": ["id", "data"], "example_input": ["a", "b"]},
{"name": "update_data", "input": ["id", "data"], "example_input": ["a", "b"]},
{"name": "delete_data", "input": ["id"], "example_input": "a"},
]
# 示例 1:根据用户输入选择函数,并包括选择理由
# 这里,模型将被要求选择一个函数并提供所需参数。
r,reason = model.function_choose(
functions_info, # 要从中选择的函数列表
"添加一个键值对 abc 和 123", # 请求的操作
need_reason=True, # 模型需要提供选择理由
multiple=False, # 只允许选择一个函数
add_to_history=True # 将此次交互添加到历史记录
)
print(r) # 输出选定的函数及参数
r = model.function_choose(
functions_info, # 要从中选择的函数列表
"添加一个键值对 abc 和 123", # 请求的操作
need_reason=False, # 不需要提供选择理由
multiple=False, # 只允许选择一个函数
add_to_history=True # 将此次交互添加到历史记录
)
print(r) # 输出选定的函数及参数
# 示例 2:函数选择时提供额外的上下文,例如例子和说明
r2,reason = model.function_choose(
functions_info,
"删除键为 abc 的记录", # 删除操作的指令
need_reason=True, # 模型需要提供理由
multiple=False, # 只允许选择一个函数
add_to_history=True, # 记录此次交互
examples=[ # 提供用于引导模型的例子
"添加键值对 abc 和 123 -> insert_data('abc', '123')"
],
notes=[ # 重要的操作说明
"删除操作不可逆",
"这将删除键为 'abc' 的所有记录"
]
)
print(r2) # 输出选定的函数及其解释
# 示例 3:简单选择场景,选择一个食物列表中的选项
foods = ["螺蛳粉", "米粉", "牛肉面", "鸡蛋面", "蔬菜沙拉", "水煮牛肉"]
r,reason = model.choose(
foods, # 要选择的食物列表
"在减肥期间可以吃什么?", # 提示问题
"食物名称", # 选项的类型
need_reason=True, # 模型需要提供选择理由
multiple=True, # 允许选择多个选项
add_to_history=True # 记录此次交互
)
print(r) # 输出选定的食物及其理由
# 查看对话历史,了解之前的交互如何被记录
print(model.history)
# 如果需要令牌信息(开发者调试用):
# print(model.input_tokens)
```
## APP 示例: 电话客服质检系统 Demo 项目文档
本文档将逐步介绍如何利用 `dagent_llm`、`dguard`、`dspeech` 三个模块搭建一个电话客服质检系统。我们将通过对客服通话音频的情绪、解答流程和用户问题解决情况进行自动化的评估。本 Demo 将展示代码的核心模块、调用流程,以及各个步骤的细节。
### 1. 项目概览
该质检系统主要功能包括:
- 对客服和用户的对话进行自动语音转文本(STT)。
- 对不同说话人的分离与情绪分类。
- 通过 `LLM` 模型分析对话内容,评估客服和用户情绪、问题是否解决、解答流程是否规范。
#### 核心模块:
1. **`dspeech.STT`**: 自动语音转文本模型,用于将音频内容转换为文字。
2. **`dguard.DguardModel`**: 语音分离与情绪识别模型,用于说话人分离与情绪分析。
3. **`dagent_llm`**: LLM(Large Language Model)用于基于文本内容进行进一步的对话分析和评估。
### 2. 环境配置
在开始之前,请确保已安装以下依赖项:
```bash
pip install dspeech dguard rich subprocess langchain
```
### 3. 代码结构
#### 3.1 初始化
首先,我们引入必要的库,并初始化所需的模型。
```python
import os
import csv
from dspeech import STT
from dguard import DguardModel as dm
from rich.console import Console
import subprocess
from utils.llm import LLM
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
# Initialize the console for rich print
console = Console()
# Initialize models
stt_model = STT()
dm_model = dm(
embedding_model_names=["eres2net_cn_common_200k", "campp_cn_common_200k"],
device="cuda",
channel=0,
start_time=0,
diar_max_num_spks=4,
)
# Initialize LLM model
dagent_llm = LLM("deepseek")
```
#### 3.2 辅助函数
创建一个辅助函数 `rich_print` 用于打印对话结果,使用不同的颜色来区分说话人。
```python
def rich_print(content):
colors = ["red", "green", "blue", "yellow", "magenta", "cyan"]
for idx, line in enumerate(content.split("\n")):
if ":" not in line:
continue
spk_id = line.split(":")[0].split(" ")[-1]
console.print(f"[{colors[int(spk_id) % 6]}]{line}")
```
#### 3.3 音频处理与说话人分离
利用 `dguard.DguardModel` 进行音频处理,分离出说话人,并使用 `dspeech.STT` 进行语音转文本。
```python
def get_diarization_content(file_path, emotion_time_threshold=2):
try:
r = dm_model.diarize(file_path)
all_content = ""
last_spk = ""
for data in dm_model.diarize(file_path):
spk_label = data[3]
start_time = data[1]
end_time = data[2]
generate_text = stt_model.transcribe_file(file_path, start=start_time, end=end_time)
if end_time - start_time > emotion_time_threshold:
emotion = stt_model.emo_classify_file(file_path, start=start_time, end=end_time)
emotion_label = emotion["labels"][emotion["scores"].index(max(emotion["scores"]))]
emotion_text = f"(emotion:{emotion_label})"
else:
emotion_text = ""
if spk_label != last_spk:
all_content += f"\nSpeaker {spk_label}: {generate_text} " + emotion_text
last_spk = spk_label
else:
all_content += f" {generate_text}"
return all_content
except Exception as e:
console.print(f"[red]Error processing file {file_path}: {str(e)}[/red]")
return ""
```
#### 3.4 对话分析
使用 `LLM` 模型对转录后的内容进行情绪评估、问题解决与流程规范性分析。
```python
def evaluate_wav_file(content):
try:
# 客服情绪评估
prompt = f"<对话内容>\n{content}<对话内容>\n请评估客服人员的情绪是否符合要求。"
r = dagent_llm.choose(["符合要求", "不符合要求"], prompt, "情绪是否符合要求")
emo_of_agent = r[0]
# 用户情绪评估
prompt = f"<对话内容>\n{content}<对话内容>\n请评估用户是否满意。"
r = dagent_llm.choose(["满意", "不满意"], prompt, "用户是否对服务满意")
emo_of_user = r[0]
# 用户问题是否解决
prompt = f"<对话内容>\n{content}<对话内容>\n请评估用户的问题是否得到解决。"
r = dagent_llm.choose(["问题解决", "问题未解决"], prompt, "问题是否解决")
is_user_problem_solved = r[0]
# 解答流程是否规范
prompt = f"<对话内容>\n{content}<对话内容>\n请评估解答流程是否规范。"
r = dagent_llm.choose(["流程规范", "流程不规范"], prompt, "解答流程是否规范")
is_answer_process_standard = r[0]
return {
"客服情绪评估": emo_of_agent,
"用户情绪评估": emo_of_user,
"用户问题解决评估": is_user_problem_solved,
"解答流程规范评估": is_answer_process_standard
}
except Exception as e:
console.print(f"[red]Error evaluating content: {str(e)}[/red]")
return {}
```
#### 3.5 主流程
使用 `ffmpeg` 将音频文件转换为 16kHz 单声道,并逐步处理文件。输出评估结果至 CSV 文件中。
```python
if __name__ == "__main__":
input_dir = "/datasets_hdd/customer_downloadwavs/20241014/"
output_dir = "outputs/"
txt_dir = os.path.join(output_dir, "txt")
os.makedirs(txt_dir, exist_ok=True)
# CSV file to store summary
csv_file = os.path.join(output_dir, "output.csv")
with open(csv_file, mode="w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow(["ID", "客服情绪评估", "用户情绪评估", "用户问题解决评估", "解答流程规范评估"])
# Traverse all .wav files
for filename in os.listdir(input_dir):
if filename.endswith(".wav"):
try:
file_path = os.path.join(input_dir, filename)
file_id = os.path.splitext(filename)[0]
txt_output_path = os.path.join(txt_dir, f"{file_id}.txt")
if os.path.exists(txt_output_path):
with open(txt_output_path, "r", encoding="utf-8") as txt_file:
content = txt_file.read()
else:
file_path_new = os.path.join(output_dir, 'tmp_wav', f"{file_id}.wav")
subprocess.run(f"ffmpeg -i {file_path} -ac 1 -ar 16000 {file_path_new}", shell=True)
content = get_diarization_content(file_path_new)
with open(txt_output_path, "w", encoding="utf-8") as txt_file:
txt_file.write(content)
# Analyze content
results = evaluate_wav_file(content)
writer.writerow([file_id] + list(results.values()))
except Exception as e:
console.print(f"[red]Error processing file {filename}: {str(e)}[/red]")
console.print(f"[bold green]Process completed! Results are saved in {output_dir}[/bold green]")
```
### 4. 项目执行步骤
1. **准备数据集**: 将 `.wav` 音频文件放入指定的 `input_dir` 目录。
2. **执行程序**: 运行该脚本,程序将处理每个音频文件,进行说话人分离、情绪识别与文本分析。
3. **结果输出**: 结果会保存在 `output_dir` 中的 CSV 文件以及文本文件中,供进一步分析使用。
### 5. 总结
本 Demo 展示了如何使用 `dagent_llm`、`dguard`、`dspeech` 三个模块搭建一个电话客服质检系统。通过该系统可以实现对客服与用户的情绪、问题解决情况、解答流程的自动评估。
## 贡献
欢迎为 LLM 包做出贡献!请 fork 此仓库,进行修改并提交 pull request。
## 许可证
此项目基于 MIT 许可证进行许可。详细信息请参阅 LICENSE 文件。
## 联系方式
如有任何问题或建议,请发送电子邮件至赵胜:zhaosheng@nuaa.edu.cn。