Skip to content

Commit

Permalink
Merge pull request #408 from LlmKira/dev
Browse files Browse the repository at this point in the history
add `/learn` command
  • Loading branch information
sudoskys authored Apr 29, 2024
2 parents 32389d4 + 95cd3ed commit 05c5633
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 17 deletions.
2 changes: 1 addition & 1 deletion app/middleware/llm_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ async def build_history_messages(self):
message_run = []
if isinstance(system_prompt, str):
message_run.append(SystemMessage(content=system_prompt))
history = await self.message_history.read(lines=10)
history = await self.message_history.read(lines=8)
logger.trace(f"History message {history}")
for de_active_message in history:
try:
Expand Down
13 changes: 13 additions & 0 deletions app/sender/discord/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
uid_make,
save_credential,
dict2markdown,
learn_instruction,
)
from llmkira.openapi.trigger import get_trigger_loop
from ...components.credential import Credential, ProviderError
Expand Down Expand Up @@ -262,6 +263,18 @@ async def listen_login_url_command(
ephemeral=True,
)

@client.include
@crescent.command(
dm_enabled=True,
name="learn",
description="Set instruction text",
)
async def listen_learn_command(ctx: crescent.Context, instruction: str):
reply = await learn_instruction(
uid=uid_make(__sender__, ctx.user.id), instruction=instruction
)
return await ctx.respond(content=convert(reply), ephemeral=True)

@client.include
@crescent.command(
dm_enabled=True,
Expand Down
1 change: 1 addition & 0 deletions app/sender/discord/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def help_message():
`/login` - login
`/login_via_url` - login via url
`/env` - set environment variable, split by ; , use `/env ENV=NONE` to disable a env.
`/learn` - set your system prompt, reset by `/learn reset`
**Please confirm that that bot instance is secure, some plugins may be dangerous on unsafe instance.**
""".format(prefix=BotSetting.prefix)
16 changes: 16 additions & 0 deletions app/sender/kook/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
uid_make,
save_credential,
dict2markdown,
learn_instruction,
)
from llmkira.openapi.trigger import get_trigger_loop
from ...components.credential import ProviderError, Credential
Expand Down Expand Up @@ -275,6 +276,21 @@ async def listen_login_url_command(
type=MessageTypes.KMD,
)

@bot.command(name="learn")
async def listen_learn_command(
msg: Message,
instruction: str,
):
reply = await learn_instruction(
uid=uid_make(__sender__, msg.author_id),
instruction=instruction,
)
return await msg.reply(
content=convert(reply),
is_temp=True,
type=MessageTypes.KMD,
)

@bot.command(name="login")
async def listen_login_command(
msg: Message,
Expand Down
1 change: 1 addition & 0 deletions app/sender/kook/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def help_message():
`/login` - login openai
`/login_via_url` - login via provider url
`/env` - set environment variable, split by ; , use `/env ENV=NONE` to disable a env.
`/learn` - set your system prompt, reset by `/learn reset`
**Please confirm that that bot instance is secure, some plugins may be dangerous on unsafe instance.**
""".format(prefix=BotSetting.prefix)
13 changes: 13 additions & 0 deletions app/sender/slack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
uid_make,
login,
dict2markdown,
learn_instruction,
)
from app.setting.slack import BotSetting
from llmkira.kv_manager.env import EnvManager
Expand Down Expand Up @@ -223,6 +224,18 @@ async def create_task(
except Exception as e:
logger.exception(e)

@bot.command(command="/learn")
async def listen_learn_command(ack: AsyncAck, respond: AsyncRespond, command):
command: SlashCommand = SlashCommand.model_validate(command)
await ack()
if not command.text:
return
_arg = command.text
reply = await learn_instruction(
uid=uid_make(__sender__, command.user_id), instruction=_arg
)
return await respond(text=reply)

@bot.command(command="/login")
async def listen_login_command(ack: AsyncAck, respond: AsyncRespond, command):
command: SlashCommand = SlashCommand.model_validate(command)
Expand Down
1 change: 1 addition & 0 deletions app/sender/slack/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def help_message():
`/auth` - activate a task (my power),but outside the thread
`/login` - login via url or raw
`/env` - set environment variable, split by ; , use `/env ENV=NONE` to disable a env.
`/learn` - set your system prompt, reset by `/learn reset`
Make sure you invite me before you call me in channel, wink~
Expand Down
11 changes: 10 additions & 1 deletion app/sender/telegram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
login,
TimerObjectContainer,
dict2markdown,
learn_instruction,
)
from app.setting.telegram import BotSetting
from llmkira.kv_manager.env import EnvManager
Expand Down Expand Up @@ -141,7 +142,6 @@ async def create_task(message: types.Message, disable_tool_action: bool = True):
message.text = message.text[5:]
if message.text.startswith("/ask"):
message.text = message.text[4:]
message.text = message.text
if not message.text:
return None
__used_file_id = []
Expand Down Expand Up @@ -227,6 +227,15 @@ async def create_task(message: types.Message, disable_tool_action: bool = True):
except Exception as e:
logger.exception(e)

@bot.message_handler(commands="learn", chat_types=["private"])
async def listen_learn_command(message: types.Message):
logger.debug("Debug:learn command")
_cmd, _arg = parse_command(command=message.text)
reply = await learn_instruction(
uid=uid_make(__sender__, message.from_user.id), instruction=_arg
)
await bot.reply_to(message, text=reply)

@bot.message_handler(commands="login", chat_types=["private"])
async def listen_login_command(message: types.Message):
logger.debug("Debug:login command")
Expand Down
17 changes: 9 additions & 8 deletions app/sender/telegram/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@

def help_message():
return """
/help - HELP YOURSELF
/chat - Chat with me :)
/task - Function enable
/ask - Chat with func_disable, 禁止函数
/tool - 工具列表
/clear - 删除自己的记录
/auth - POWER
/help - show help message
/chat - just want to chat with me
/task - chat with function_enable
/ask - chat with function_disable
/tool - check all useful tools
/clear - clear the chat history
/auth - auth the tool_call
/learn - set your system prompt, reset by `/learn reset`
Private Chat Only:
/login - login via url or something
/env - 配置变量 split by ; , use `/env ENV=NONE` to disable a env.
/env - set v-env split by ; , use `/env ENV=NONE` to disable a env.
!Please confirm that that bot instance is secure, some plugins may be dangerous on unsafe instance.
"""
31 changes: 31 additions & 0 deletions app/sender/util_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from app.components.credential import Credential, ProviderError
from app.components.user_manager import USER_MANAGER
from llmkira.kv_manager.instruction import InstructionManager
from llmkira.task import Task
from llmkira.task.snapshot import SnapData, global_snapshot_storage

Expand Down Expand Up @@ -110,6 +111,11 @@ async def auth_reloader(snapshot_credential: str, platform: str, user_id: str) -


def split_setting_string(input_string):
"""
Split setting string
:param input_string: input string
:return: list or None
"""
if not isinstance(input_string, str):
return None
segments = input_string.split("$")
Expand All @@ -135,7 +141,32 @@ async def save_credential(uid, credential: Credential):
await USER_MANAGER.save(user_model=user)


async def learn_instruction(uid: str, instruction: str) -> str:
"""
Set instruction text
:param uid: uid_make
:param instruction: instruction text
:return: str message
"""
if len(instruction) > 1500:
return "your instruction text length should be less than 1500"
manager = InstructionManager(user_id=uid)
if len(instruction) < 7:
instruction = ""
await manager.set_instruction(instruction)
return "I already reset your instruction to default..."
else:
await manager.set_instruction(instruction)
return "I keep it in my mind!"


async def login(uid: str, arg_string) -> str:
"""
Login as provider or model
:param uid: uid_make
:param arg_string: input string
:return: str message
"""
error = telegramify_markdown.convert(
"🔑 **Incorrect format.**\n"
"You can set it via `https://<something api.openai.com>/v1$<api key>"
Expand Down
2 changes: 1 addition & 1 deletion llmkira/extra/plugins/search/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ async def search_in_duckduckgo(search_sentence: str):
_build_result.append(
SearchEngineResult(
title=result.get("title", "Undefined"),
link=result.get("Href", "Undefined"),
link=result.get("href", "Undefined"),
snippet=result.get("body", "Undefined"),
)
)
Expand Down
9 changes: 6 additions & 3 deletions llmkira/kv_manager/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ def prefix(self, key: str) -> str:
return f"instruction:{key}"

async def read_instruction(self) -> str:
"""
读取指令,如果没有指令则返回默认指令,指令长度大于5,否则返回默认指令
"""
result = await self.read_data(self.user_id)
if not result:
return f"Now={time_now()}\n{DEFAULT_INSTRUCTION}"
return f"Now={time_now()}\n{result}"
if isinstance(result, str) and len(result) > 5:
return f"Now={time_now()}\n{result}"
return f"Now={time_now()}\n{DEFAULT_INSTRUCTION}"

async def set_instruction(self, instruction: str) -> str:
if not isinstance(instruction, str):
Expand Down
4 changes: 2 additions & 2 deletions llmkira/openapi/trigger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ async def get_trigger_loop(platform_name: str, message: str, uid: str = None):
message: Message Content
:return 如果有触发,则返回触发的action,否则返回None 代表没有操作
"""
sorted(__trigger_phrases__, key=lambda x: x.priority)
trigger_sorted = sorted(__trigger_phrases__, key=lambda x: x.priority)
if not message:
message = ""
for trigger in __trigger_phrases__:
for trigger in trigger_sorted:
if trigger.on_platform == platform_name:
try:
if await trigger.on_func(message, uid):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "llmkira"
version = "1.0.4"
version = "1.0.5"
description = "A chain message bot based on OpenAI"
authors = [
{ name = "sudoskys", email = "[email protected]" },
Expand Down

0 comments on commit 05c5633

Please sign in to comment.