Skip to content

Commit b452945

Browse files
authored
feat(web): add dev tools add format code (#247)
1 parent aaa2329 commit b452945

19 files changed

+134
-52
lines changed

README_zh.md

-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ Web 版视频教程见 [BiliBili](https://www.bilibili.com/video/BV1S2421N7mn)
112112

113113
如果你只有 2G 显存,或追求性价比💰,[看这个知乎文档](https://zhuanlan.zhihu.com/p/685205206)
114114

115-
116115
# 🔥 运行
117116

118117
我们将以 mmpose 和一些 `word`/`excel`/`pdf`/`ppt` 测试文档为例,介绍如何把知识助手部署到飞书群

docs/rag_annotate_sft_data_zh.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
RAG 标注训练数据是否有用,请参考论文:
44

5-
* [Reformatted Alignment](https://arxiv.org/abs/2402.12219)
6-
* [CherryLLM](https://arxiv.org/abs/2308.12032)
5+
- [Reformatted Alignment](https://arxiv.org/abs/2402.12219)
6+
- [CherryLLM](https://arxiv.org/abs/2308.12032)
77

88
本文介绍如何使用 HuixiangDou 在脏数据上标注 openmmlab+internlm 知识类问题,使用 10 个 repo(见配置文件)的文档做知识库。
99

@@ -55,10 +55,10 @@ python3 -m huixiangdou.rag --config_path config-alignment-example.ini
5555
}
5656
```
5757

58-
* code 是错误码,所有错误见 service/helper.py
59-
* direct_reply 是 LLM 原本回复,当 code 为 0 时才调用
60-
* reason 是错误的原因
61-
* refs 是参考文档
58+
- code 是错误码,所有错误见 service/helper.py
59+
- direct_reply 是 LLM 原本回复,当 code 为 0 时才调用
60+
- reason 是错误的原因
61+
- refs 是参考文档
6262

6363
下面是个示例,`rag_reply` 更具体,不会像原始的 `direct_reply` 更“务虚”。可以进入下一阶段清洗流程。
6464

huixiangdou/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Copyright (c) OpenMMLab. All rights reserved.
22
"""import module."""
33
# only import frontend when needed, not here
4-
from .version import __version__
54
from .service import ChatClient # noqa E401
65
from .service import ErrorCode # noqa E401
76
from .service import FeatureStore # noqa E401
87
from .service import HybridLLMServer # noqa E401
98
from .service import WebSearch # noqa E401
109
from .service import Worker # noqa E401
1110
from .service import llm_serve # noqa E401
11+
from .version import __version__

huixiangdou/rag.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,14 @@ def rag(process_id: int, task: list, output_dir: str):
7878
assistant = Worker(work_dir=args.work_dir, config_path=args.config_path)
7979

8080
# assistant.TOPIC_TEMPLATE = '告诉我这句话的关键字和主题,直接说主题不要解释:“{}”'
81-
81+
8282
output_path = os.path.join(output_dir, 'output{}.json'.format(process_id))
8383
for item in task:
8484
query = item.query
8585

86-
code, response, refs = assistant.generate(query=query, history=[], groupname='')
86+
code, response, refs = assistant.generate(query=query,
87+
history=[],
88+
groupname='')
8789

8890
item.rag_reply = response
8991
item.code = int(code)
@@ -99,7 +101,7 @@ def rag(process_id: int, task: list, output_dir: str):
99101

100102

101103
def split_tasks(json_path: str, processes: int):
102-
"""Split queries for multiple prcesses"""
104+
"""Split queries for multiple processes."""
103105
queries = []
104106
tasks = []
105107
_all = []
@@ -133,7 +135,8 @@ def split_tasks(json_path: str, processes: int):
133135
else:
134136
pool = Pool(args.processes)
135137
for process_id in range(args.processes):
136-
pool.apply_async(rag, (process_id, tasks[process_id], args.output_dir))
138+
pool.apply_async(rag,
139+
(process_id, tasks[process_id], args.output_dir))
137140
pool.close()
138141
logger.debug('waiting for preprocess read finish..')
139142
pool.join()

huixiangdou/service/helper.py

-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ class ErrorCode(Enum):
4747
SG_SEARCH_FAIL = 16, 'SourceGraph search fail, please check TOKEN'
4848
LLM_NOT_RESPONSE_SG = 17, 'LLM not response query with sg search'
4949

50-
5150
def __new__(cls, value, description):
5251
"""Create new instance of ErrorCode."""
5352
obj = object.__new__(cls)

huixiangdou/service/llm_server_hybrid.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ def call_kimi(self, prompt, history):
291291
elif prompt_len <= int(32768 * 1.5) - 1024:
292292
model = 'moonshot-v1-32k'
293293
else:
294-
prompt = prompt[0: int(128000 * 1.5) -1024]
294+
prompt = prompt[0:int(128000 * 1.5) - 1024]
295295
model = 'moonshot-v1-128k'
296296

297297
logger.info('choose kimi model {}'.format(model))
@@ -432,7 +432,7 @@ def generate_response(self, prompt, history=[], backend='local'):
432432
prompt (str): The prompt to send to the LLM.
433433
history (list, optional): List of previous interactions. Defaults to []. # noqa E501
434434
remote (bool, optional): Flag to determine whether to use a remote server. Defaults to False. # noqa E501
435-
backend (str): LLM type to call. Support 'local', 'remote' and specfied LLM name ('kimi', 'deepseek' and so on)
435+
backend (str): LLM type to call. Support 'local', 'remote' and specified LLM name ('kimi', 'deepseek' and so on)
436436
437437
Returns:
438438
str: Generated response from the LLM.

huixiangdou/service/web_search.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ def logging_search_query(self, query: str):
220220
f.write(query)
221221
f.write('\n')
222222

223-
224223
def get(self, query: str, max_article=1):
225224
"""Executes a google search with cache.
226225
@@ -230,10 +229,10 @@ def get(self, query: str, max_article=1):
230229
"""
231230
query = query.strip()
232231
query = query[0:32]
233-
232+
234233
try:
235234
self.logging_search_query(query=query)
236-
235+
237236
articles = self.google(query=query, max_article=max_article)
238237
self.save_search_result(query=query, articles=articles)
239238
return articles, None

huixiangdou/service/worker.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def __init__(self, work_dir: str, config_path: str, language: str = 'zh'):
8181
self.GENERATE_TEMPLATE = 'Background Information: "{}"\n Question: "{}"\n Please read the reference material carefully and answer the question.' # noqa E501
8282

8383
def direct_chat(self, query: str):
84-
""""Generate reply with LLM"""
84+
""""Generate reply with LLM."""
8585
return self.llm.generate_response(prompt=query, backend='remote')
8686

8787
def single_judge(self, prompt, tracker, throttle: int, default: int):
@@ -219,7 +219,8 @@ def generate(self, query, history, groupname):
219219
search_prompt = self.llm.generate_response(prompt)
220220
tracker.log('search prompt', search_prompt)
221221

222-
articles, error = web_search.get(query=search_prompt, max_article=2)
222+
articles, error = web_search.get(query=search_prompt,
223+
max_article=2)
223224
if error is not None:
224225
return ErrorCode.SEARCH_FAIL, response, references
225226

@@ -280,9 +281,15 @@ def generate(self, query, history, groupname):
280281
return ErrorCode.SG_SEARCH_FAIL, response, references
281282

282283
if sg_context is not None and len(sg_context) > 2:
283-
prompt, _ = self.llm.build_prompt(instruction=query, context=sg_context, history_pair=history, template=self.GENERATE_TEMPLATE)
284-
285-
response = self.llm.generate_response(prompt=prompt, history=history, backend='remote')
284+
prompt, _ = self.llm.build_prompt(
285+
instruction=query,
286+
context=sg_context,
287+
history_pair=history,
288+
template=self.GENERATE_TEMPLATE)
289+
290+
response = self.llm.generate_response(prompt=prompt,
291+
history=history,
292+
backend='remote')
286293
tracker.log('source graph', [sg_context, response])
287294

288295
if response is None or len(response) < 1:

resource/rag_example_input.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,4 @@
8484
"想请教下大佬,",
8585
"Better models of human high-level visual cortex emerge from natural language supervision with a large and diverse dataset\n有大佬, 可以帮忙下载一下这篇nature论文吗[可怜][可怜][可怜][可怜]",
8686
"大佬居然不知道?"
87-
]
87+
]

setup.py

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def get_version():
1919
exec(compile(f.read(), version_file, 'exec'))
2020
return locals()['__version__']
2121

22+
2223
def read_requirements():
2324
lines = []
2425
with open('requirements.txt', 'r') as f:
@@ -31,6 +32,7 @@ def read_requirements():
3132
lines.append(line)
3233
return lines
3334

35+
3436
install_packages = read_requirements()
3537

3638
if __name__ == '__main__':

web/model/qalib.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,6 @@ class AddDocError(BaseModel):
6565

6666

6767
class AddDocsRes(BaseModel):
68-
docBase: Optional[str] = ""
68+
docBase: Optional[str] = ''
6969
docs: Optional[List[str]] = []
7070
errors: Optional[List[AddDocError]] = []

web/proxy/main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def chat_with_featue_store(cache: CacheRetriever,
147147
worker = WebWorker(work_dir=workdir, config_path=configpath)
148148

149149
history = format_history(payload.history)
150-
query_log = "{} {}\n".format(fs_id, payload.content)
150+
query_log = '{} {}\n'.format(fs_id, payload.content)
151151
with open('query.log', 'a') as f:
152152
f.write(query_log)
153153
error, response, references = worker.generate(query=payload.content,

web/proxy/web_worker.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ def generate(self, query, history, retriever, groupname):
239239
tracker.log('feature store doc', [chunk, response])
240240
if response is not None and len(response) < 1:
241241
# llm error
242-
return ErrorCode.INTERNAL_ERROR, "LLM API 没给回复,见 https://github.com/InternLM/HuixiangDou/issues/214 ", retrieve_ref
242+
return ErrorCode.INTERNAL_ERROR, 'LLM API 没给回复,见 https://github.com/InternLM/HuixiangDou/issues/214 ', retrieve_ref
243243

244244
if response is not None and len(response) > 0:
245245
prompt = self.PERPLESITY_TEMPLATE.format(query, response)

web/service/agent.py

+28-17
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
import json
22
import re
33
from enum import Enum
4-
from typing import Union, List
4+
from typing import List, Union
55

66
import lark_oapi as lark
77
import requests
88
from fastapi import Request, Response
9-
from lark_oapi import RawRequest, RawResponse, UTF_8, USER_AGENT, AUTHORIZATION, X_TT_LOGID, X_REQUEST_ID, CONTENT_TYPE, \
10-
Content_Disposition, LARK_REQUEST_TIMESTAMP, LARK_REQUEST_NONCE, LARK_REQUEST_SIGNATURE
11-
from lark_oapi.api.im.v1 import GetChatRequest, P2ImMessageReceiveV1, MentionEvent, ReplyMessageRequest, \
12-
ReplyMessageRequestBody, GetMessageResourceRequest
9+
from lark_oapi import (AUTHORIZATION, CONTENT_TYPE, LARK_REQUEST_NONCE,
10+
LARK_REQUEST_SIGNATURE, LARK_REQUEST_TIMESTAMP,
11+
USER_AGENT, UTF_8, X_REQUEST_ID, X_TT_LOGID,
12+
Content_Disposition, RawRequest, RawResponse)
13+
from lark_oapi.api.im.v1 import (GetChatRequest, GetMessageResourceRequest,
14+
MentionEvent, P2ImMessageReceiveV1,
15+
ReplyMessageRequest, ReplyMessageRequestBody)
1316

1417
from web.config.env import HuixiangDouEnv
1518
from web.constant import biz_constant
16-
from web.model.base import standard_error_response, BaseBody
17-
from web.model.chat import ChatRequestBody, ChatType, LarkChatDetail, ChatQueryInfo, WechatRequest, WechatType, \
18-
WechatPollItem, WechatResponse
19+
from web.model.base import BaseBody, standard_error_response
20+
from web.model.chat import (ChatQueryInfo, ChatRequestBody, ChatType,
21+
LarkChatDetail, WechatPollItem, WechatRequest,
22+
WechatResponse, WechatType)
1923
from web.service import qalib
2024
from web.service.cache import ChatCache
2125
from web.service.chat import ChatService
@@ -79,7 +83,7 @@ def get_event_handler(cls):
7983
HuixiangDouEnv.get_lark_encrypt_key(),
8084
HuixiangDouEnv.get_lark_verification_token(),
8185
lark.LogLevel.DEBUG).register_p2_im_message_receive_v1(
82-
cls._on_im_message_received).build()
86+
cls._on_im_message_received).build()
8387

8488
@classmethod
8589
def _on_im_message_received(cls, data: P2ImMessageReceiveV1):
@@ -123,7 +127,9 @@ def _on_im_message_received(cls, data: P2ImMessageReceiveV1):
123127
ChatCache.mark_agent_used(app_id, ChatType.LARK)
124128

125129
if msg.root_id or msg.parent_id:
126-
logger.debug(f"[lark] app_id: {app_id}, name: {chat_name} got reply message, omit")
130+
logger.debug(
131+
f'[lark] app_id: {app_id}, name: {chat_name} got reply message, omit'
132+
)
127133
return
128134

129135
# parse lark content
@@ -142,8 +148,11 @@ def _on_im_message_received(cls, data: P2ImMessageReceiveV1):
142148
if len(lark_content.images) > 0:
143149
query_id = chat_svc.generate_query_id(lark_content.content)
144150
for index in range(len(lark_content.images)):
145-
image_store_path = chat_svc.gen_image_store_path(query_id, str(index), ChatType.LARK)
146-
if cls._store_image(client, message_id, lark_content.images[index], image_store_path):
151+
image_store_path = chat_svc.gen_image_store_path(
152+
query_id, str(index), ChatType.LARK)
153+
if cls._store_image(client, message_id,
154+
lark_content.images[index],
155+
image_store_path):
147156
# replace image_key with actually store path
148157
lark_content.images[index] = image_store_path
149158

@@ -153,7 +162,7 @@ def _on_im_message_received(cls, data: P2ImMessageReceiveV1):
153162
chat_detail = LarkChatDetail(appId=app_id,
154163
appSecret=app_secret,
155164
messageId=msg.message_id)
156-
unique_id = data.event.sender.sender_id.open_id + "@" + chat_id
165+
unique_id = data.event.sender.sender_id.open_id + '@' + chat_id
157166
chat_svc.chat_by_agent(lark_content, ChatType.LARK, chat_detail,
158167
unique_id, query_id)
159168

@@ -241,8 +250,10 @@ def _get_content_type_when_at_user_exists(
241250
return LarkContentType.AT_OTHER_PERSON_TEXT
242251

243252
@classmethod
244-
def _store_image(cls, client: lark.client, message_id: str, image_key: str, path: str) -> bool:
245-
body = GetMessageResourceRequest.builder().message_id(message_id).file_key(image_key).build()
253+
def _store_image(cls, client: lark.client, message_id: str, image_key: str,
254+
path: str) -> bool:
255+
body = GetMessageResourceRequest.builder().message_id(
256+
message_id).file_key(image_key).build()
246257
response = client.im.v1.message_resource.get(body)
247258
if not response.success():
248259
logger.error(
@@ -329,7 +340,7 @@ def action(cls, body: WechatRequest,
329340
chat_request_body = ChatRequestBody(content=body.query.content)
330341

331342
# push into chat queue
332-
unique_id = body.username + "@" + body.groupname
343+
unique_id = body.username + '@' + body.groupname
333344
chat_svc.chat_by_agent(chat_request_body, ChatType.WECHAT, body,
334345
unique_id, query_id)
335346
# record query_id
@@ -369,7 +380,7 @@ def _fetch_response(cls, feature_store_id: str) -> WechatResponse:
369380
l.append(
370381
WechatPollItem(req=WechatRequest.model_validate_json(
371382
json.dumps(item.detail)),
372-
rsp=item.response))
383+
rsp=item.response))
373384
complete_query_id_list.append(item.queryId)
374385
ret.root = l
375386

web/service/qalib.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
from web.model.huixiangdou import (HxdTask, HxdTaskPayload, HxdTaskType,
1414
HxdToken)
1515
from web.model.integrate import IntegrateLarkBody, IntegrateWebSearchBody
16-
from web.model.qalib import (Lark, QalibInfo, QalibPositiveNegative,
17-
QalibSample, WebSearch, Wechat, AddDocsRes, AddDocError)
16+
from web.model.qalib import (AddDocError, AddDocsRes, Lark, QalibInfo,
17+
QalibPositiveNegative, QalibSample, WebSearch,
18+
Wechat)
1819
from web.mq.hxd_task import HuixiangDouTask
1920
from web.orm.redis import r
2021
from web.util.log import log
@@ -108,9 +109,13 @@ async def add_docs(self, files: List[UploadFile] = File(...)):
108109
write_size = 0
109110
# store files
110111
for file in files:
111-
if file.filename and len(file.filename.encode("utf-8")) > 255:
112-
logger.error(f"filename: {file.filename} too long, maximum 255 bytes, omit current filename")
113-
ret.errors.append(AddDocError(fileName=file.filename, reason="filename is too long"))
112+
if file.filename and len(file.filename.encode('utf-8')) > 255:
113+
logger.error(
114+
f'filename: {file.filename} too long, maximum 255 bytes, omit current filename'
115+
)
116+
ret.errors.append(
117+
AddDocError(fileName=file.filename,
118+
reason='filename is too long'))
114119
continue
115120

116121
with open(os.path.join(store_dir, file.filename), 'wb') as f:

web/tools/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# 运维工具
2+
3+
- dump_redis_query.py 保存所有问题,无答复
4+
- get_puyu_model_list.py 获取 puyu 所有 model list
5+
- test_update_fs_max_len.py 更新所有用户的 remote LLM 最大长度

tests/tool_dump_redis_query.py web/tools/dump_redis_query.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
from redis import Redis
1+
import json
22
import os
3+
34
from loguru import logger
4-
import json
5+
from redis import Redis
6+
57

68
def redis_host():
79
host = os.getenv('REDIS_HOST')
@@ -29,7 +31,11 @@ def feature_store_base_dir():
2931
return 'feature_stores'
3032

3133

32-
db = Redis(host=redis_host(), port=redis_port(), password=redis_passwd(), charset='utf-8', decode_responses=True)
34+
db = Redis(host=redis_host(),
35+
port=redis_port(),
36+
password=redis_passwd(),
37+
charset='utf-8',
38+
decode_responses=True)
3339
keys = db.keys('HuixiangDou:query:*')
3440

3541
with open('query.jsonl', 'a') as f:

0 commit comments

Comments
 (0)