Skip to content

Commit

Permalink
docs(README): add HuixiangDou inside
Browse files Browse the repository at this point in the history
  • Loading branch information
tpoisonooo committed Jan 4, 2024
1 parent def0837 commit c6414b2
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 50 deletions.
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
2. 提出一套解答技术问题的算法 pipeline
3. 部署成本低,只需要 LLM 模型满足 4 个 trait 即可解答大部分用户问题,见[技术报告](./resource/HuixiangDou.pdf)

查看[茴香豆已运行在哪些场景](./huixiangdou-inside.md)

# 🔥 运行

我们将以 lmdeploy & mmpose 为例,介绍如何把知识助手部署到飞书群
Expand All @@ -25,7 +27,8 @@ cd HuixiangDou && mkdir workdir # 创建工作目录
python3 -m pip install -r requirements.txt # 安装依赖
python3 service/feature_store.py repodir workdir # 把 repodir 的特征保存到 workdir
```
运行结束后,茴香豆能够区分应该处理哪些用户话题,哪些闲聊应该拒绝。请编辑 [good_questions](./resource/good_questions.json)[bad_questions](./resource/bad_questions.json),尝试自己的领域知识(医疗,金融,电力等)
运行结束后,茴香豆能够区分应该处理哪些用户话题,哪些闲聊应该拒绝。请编辑 [good_questions](./resource/good_questions.json)[bad_questions](./resource/bad_questions.json),尝试自己的领域知识(医疗,金融,电力等)。

```bash
# 接受技术话题
process query: mmdeploy 现在支持 mmtrack 模型转换了么
Expand Down Expand Up @@ -95,7 +98,7 @@ webhook_url = "${YOUR-LARK-WEBHOOK-URL}"
```shell
python3 main.py workdir
```
![](./resource/lark-example.png)
<img src="./resource/lark-example.png" width="400">

如果还需要读取飞书群消息,见[飞书开发者广场-添加应用能力-机器人](https://open.feishu.cn/app?lang=zh-CN)。

Expand All @@ -104,7 +107,7 @@ python3 main.py workdir

1. 使用更高精度 local LLM

调整 config.ini 中的`llm.local` 模型路径。
config.ini 中的`llm.local` 模型调整为 `internlm2-20B`
此选项效果显著,但需要更大的 GPU 显存。

2. Hybrid LLM Service
Expand All @@ -128,6 +131,32 @@ python3 main.py workdir

此特性适合处理疑难问题,需要基础开发能力调整 prompt。

* 点击 [sourcegraph-settings-access](https://sourcegraph.com/users/tpoisonooo/settings/tokens) 获取 token

```bash
# open https://github.com/sourcegraph/src-cli#installation
curl -L https://sourcegraph.com/.api/src-cli/src_linux_amd64 -o /usr/local/bin/src && chmod +x /usr/local/bin/src
# 把 token 填入 config.ini
[sg_search]
..
src_access_token = "${YOUR_ACCESS_TOKEN}"
```

* 编辑 repo 的名字和简介,我们以 opencompass 为例

```bash
# config.ini
# add your repo here, we just take opencompass and lmdeploy as example
[sg_search.opencompass]
github_repo_id = "open-compass/opencompass"
introduction = "用于评测大型语言模型(LLM).."
```

* 使用 `python3 service/sg_search.py` 单测功能是否正常

运行 `main.py`,茴香豆将在合适的时机,启用搜索增强。


# 🛠️ FAQ

Expand Down
2 changes: 2 additions & 0 deletions README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ HuixiangDou is a domain-specific knowledge assistant based on Large Language Mod
2. It proposes an algorithmic pipeline for addressing technical queries.
3. It has low deployment costs; it just requires an LLM model that fulfills 4 traits to answer most user questions. See [Technical Report](./resource/HuixiangDou.pdf) for details.

Check out [HuixiangDou Inside](./huixiangdou-inside.md).

# 🔥 Deployment

We'll illustrate how to deploy the knowledge assistant in Feishu groups using lmdeploy & mmpose as examples.
Expand Down
7 changes: 7 additions & 0 deletions huixiangdou-inside.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# HuixiangDou Inside

| Environment | IM Application | Description | Sceen Shotcut |
| ------- | ---- | ---- | ------- |
| openmmlab user group | wechat | reply user question | <img src="软件A的运行截图URL" width="200"> |
| ncnn contributor group | wechat | explain software and hardware terminologies, pretending to be human | <img src="软件B的运行截图URL" width="200"> |
| inner middleware user group | lark | reply user question | <img src="软件B的运行截图URL" width="200"> |
83 changes: 39 additions & 44 deletions service/sg_search.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .llm_client import ChatClient
from llm_client import ChatClient
import os
import ast
import json
Expand All @@ -12,31 +12,18 @@ class SourceGraphProxy:

def __init__(self, config_path: dict, topk=1) -> None:
self.config_path = config_path
self.sg_config = None
with open(self.config_path) as f:
config = pytoml.load(f)
self.sg_config = config['sg_search']

self.topk = topk

def command(self, txt: str):
logger.debug('cmd: {}'.format(txt))
cmd = os.popen(txt)
return cmd.read().rstrip().lstrip()

def load_config(self):
with open(self.config_path) as f:
config = pytoml.load(f)
sg_config = config['sg_search']

bin_path = sg_config['binary_src_path']
if bin_path is None or not os.path.exists(bin_path):
raise Exception(
f'sg_search enabled while binary_src_path {bin_path} not exist'
)

token = sg_config['src_access_token']
if token is None or token == 'YOUR-ACCESS-TOKEN':
raise Exception(
f'sg_search enabled while sr_access_token {bin_path} not exist'
)
return sg_config

def extract_sg_result(self, jsonstr):
ret = []
try:
Expand All @@ -57,31 +44,38 @@ def extract_sg_result(self, jsonstr):
str(e), jsonstr))
return ret


def choose_repo(self, question, groupname):
prompt = "你是{}技术群的技术助手,目前收到了用户的问题:“{}”。请问这个问题应该查询以下哪个开源项目:\n".format(groupname, question)
keys = self.sg_config.keys()
skip = ['binary_src_path', 'src_access_token']
repos = dict()
for key in keys:
if key in skip:
continue
introduction = self.sg_config[key]['introduction']
prompt += f'* {key} {introduction}\n'
repos[key] = self.sg_config[key]
prompt += '* none 都不是'
choice = llm.generate_response(prompt=prompt, remote=True).strip()

target_repo_id = None
for key in repos.keys():
if key in choice:
target_repo_id = repos[key]['github_repo_id']
break

return target_repo_id

def search(self, llm, question, groupname):
# write your own open source repo here !
prompt = '''你是 {} 技术群的技术助手,目前收到了用户的问题:“{}”。请问这个问题应该查询以下哪个开源项目:
* lmdeploy。lmdeploy 是一个用于压缩、部署和服务 LLM(Large Language Model)的工具包。是一个服务端场景下,transformer 结构 LLM 部署工具,支持 GPU 服务端部署,速度有保障,支持 Tensor Parallel,多并发优化,功能全面,包括模型转换、缓存历史会话的 cache feature 等. 它还提供了 WebUI、命令行和 gRPC 客户端接入。
* xtuner。xtuner 是一个用于调优大型语言模型(LLM)的工具箱。
* opencompass。用于评测大型语言模型(LLM). 它提供了完整的开源可复现的评测框架,支持大语言模型、多模态模型的一站式评测,基于分布式技术,对大参数量模型亦能实现高效评测。评测方向汇总为知识、语言、理解、推理、考试五大能力维度,整合集纳了超过70个评测数据集,合计提供了超过40万个模型评测问题,并提供长文本、安全、代码3类大模型特色技术能力评测。
* 不知道。
请直接告诉我项目名称不要解释,如果都不是就回答不知道。'''.format(question, groupname)

choice = llm.generate_response(prompt=prompt,
remote=False).lower().strip()
REPO = ''
if 'lmdeploy' in choice:
REPO = 'internlm/lmdeploy'
elif 'opencompass' in choice:
REPO = 'open-compass/opencompass'
elif 'xtuner' in choice:
REPO = 'internlm/xtuner'
else:

repo_id = self.choose_repo(question, groupname)
if repo_id is None:
logger.warning(f'cannot choose repo_id')
return ''

sg_config = self.load_config()
ENV = 'export SRC_ACCESS_TOKEN="{}" && '.format(
sg_config['src_access_token'])
BINARY = sg_config['binary_src_path']
ENV = 'export SRC_ACCESS_TOKEN="{}" && '.format(self.sg_config['src_access_token'])
BINARY = self.sg_config['binary_src_path']

prompt = '“{}”\n请仔细阅读以上问题,提取其中可用作搜索引擎的关键字,关键字直接用 list 表示,不要解释。'.format(
question)
Expand All @@ -92,17 +86,18 @@ def search(self, llm, question, groupname):
except Exception as e:
logger.error('parse {} failed {}.'.format(entity_str, str(e)))
return ''

search_items = []
for entity in entities:
# 根据实体词,搜文档和源码
# search doc and source code based on entities
# search -json 'repo:open-compass/opencompass summarizers'
cmd_doc = '''{} search -json 'repo:{} lang:MarkDown {}' '''.format(
BINARY, REPO, entity)
BINARY, repo_id, entity)
cmd_return = self.command(ENV + cmd_doc)
search_items += self.extract_sg_result(cmd_return)

cmd_python = '''{} search -json 'repo:{} lang:Python {}' '''.format(
BINARY, REPO, entity)
BINARY, repo_id, entity)
cmd_return = self.command(ENV + cmd_python)
search_items += self.extract_sg_result(cmd_return)

Expand Down
6 changes: 3 additions & 3 deletions service/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def __init__(self, work_dir:str, config_path: str):
self.KEYWORDS_TEMPLATE = '谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。搜索参数类型 string, 内容是短语或关键字,以空格分隔。\n你现在是{}技术交流群里的技术助手,用户问“{}”,你打算通过谷歌搜索查询相关资料,请提供用于搜索的关键字或短语,不要解释直接给出关键字或短语。'
self.SECURITY_TEMAPLTE = '判断以下句子是否涉及政治、辱骂、色情、恐暴、宗教、网络暴力、种族歧视等违禁内容,结果用 0~10 表示,不要解释直接给出得分。判断标准:涉其中任一问题直接得 10 分;完全不涉及得 0 分。直接给得分不要解释:“{}”'
self.PERPLESITY_TEMPLATE = '''“question:{} answer:{}”\n阅读以上对话,answer 是否在表达自己不知道,回答越全面得分越少,用0~10表示,不要解释直接给出得分。\n判断标准:准确回答问题得 0 分;答案详尽得 1 分;知道部分答案但有不确定信息得 8 分;知道小部分答案但推荐求助其他人得 9 分;不知道任何答案直接推荐求助别人得 10 分。直接打分不要解释。'''
self.SUMMARIZE_TEMPLATE = '{} \n 仔细阅读以上内容,总结到 500 字以内'
self.SUMMARIZE_TEMPLATE = '{} \n 仔细阅读以上内容,总结得简短有力点'
# self.GENERATE_TEMPLATE = '材料:“{}”\n 问题:“{}” \n 请仔细阅读参考材料回答问题,材料可能和问题无关。如果材料和问题无关,尝试用你自己的理解来回答问题。如果无法确定答案,直接回答不知道。'
self.GENERATE_TEMPLATE = '材料:“{}”\n 问题:“{}” \n 请仔细阅读参考材料回答问题。'
def single_judge(self, prompt, tracker, throttle: int, default: int):
Expand Down Expand Up @@ -224,8 +224,8 @@ def generate(self, query, history, groupname):
default=0):
return ErrorCode.BAD_ANSWER, response

if response is not None and len(response) >= 600:
# 回复内容太长,总结一下
if response is not None and len(response) >= 500:
# reply too long, summarize it
response = self.llm.generate_response(
prompt=self.SUMMARIZE_TEMPLATE.format(response))

Expand Down

0 comments on commit c6414b2

Please sign in to comment.