add old lci module

This commit is contained in:
qing committed 2026-08-02 20:15:07 +08:00
1 parent 38a6e815f0
commit 8499631091
171 files changed
+25562

No files matched your search

+107
View File
@@ -0,0 +1,107 @@
# PRJ
.env/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
+33
View File
@@ -0,0 +1,33 @@
## chat是一个什么项目
该模块是python TCP socket聊天室服务,对每个连接者提供消息转发的服务。
你还可以召唤AI,与它进行对话。
## 如何运行chat服务?
我们在项目中打包了启动脚本```_run.sh```,你只需要安装好依赖的软件,就可以一键创建虚拟环境并且执行它。
```shell
sudo apt update
sudo apt install python3 python3-pip python3-venv
bash _run.sh
```
## 如何连接chat服务?
```shell
python client.py [--addr=localhost] [--port=8003] [--name=Unknow]
```
## 我如何与AI对话
服务器从文件中读取提示词,并且将具有```<chatgpt>```特定前缀的消息转发给AI。
并且具有一定的记忆能力。
## 什么是快捷标签输入
成功连接后输入```chatgpt```将会给接下来的对话添加```<chatgpt>```标签。
在聊天框中输入```where```查看当前的对话标签。
在聊天框中输入```del```以删除当前的前缀。
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
cd "$(dirname "$0")" || exit
bash ./_set.sh 1>/dev/null
source ./.env/bin/activate
exec python server.py --type=server --port=8003 --addr=0.0.0.0
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
cd "$(dirname "$0")" || exit
python3 -m venv .env
source .env/bin/activate
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
+231
View File
@@ -0,0 +1,231 @@
#!/usr/bin/env python3
#-------------------------------------------------------------
# 以下区域是我的代码
'''
【项目简介】 网络聊天室 v0.0.2
【加入项目】
注意代码只添加不修改,你可以写个函数,署名
不要修改别人的代码。
【基线规则】
在自己的区域修改代码,谁的代码能跑就加入主线
除此之外只在各自的测试区域内运行
【设计思路】
建议一个项目一个文件先,容易分发
【测试方式】
服务器进程: python chat.py --type=server
客户端进程: python chat.py
--------------------------------
--------------------------------
--------------------------------
【项目名称】 网络聊天室 v 0.0.3 (20250524)
我们会将新版本加入pmc.cops中作为常驻服务
【改进计划】
1.我们专门设置了一个只发送一条消息就关闭的函数以供别的文件调用
2.我们将端口暴露在了公网下,以测试连接情况,发现并修复了许多bug。
3.我们设置欢迎信息只在服务端可见。
【使用方法】
python chat.py [--type=server|client] [--addr=localhost] [--port=8003] [--name=Unknow]
【记得反馈!】
期待您将反馈发送至gitee
----------------------------------------
########################################
########################################
网络聊天室 version 0.1.0
使用方法 python chat.py [--addr=localhost] [--port=8003] [--name=Unknow]
'''
import argparse
import socket
import select
import threading
import sys
import time
class ChatClient:
def __init__(self, addr: str, port: int, your_name: str):
self.addr: str = addr
self.port: int = port
self.name: str = your_name
def send_client(self, msg: str):
'''发送消息给聊天室服务器。'''
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(5) # 设置连接超时
s.connect((self.addr, self.port))
s.settimeout(None) # 连接成功后取消超时
s.sendall(f"{self.name}: {msg}".encode('utf-8'))
except (ConnectionRefusedError, socket.timeout):
print(f"Could not connect to {self.addr}:{self.port} - message not sent")
except Exception as e:
print(f"Unexpected error while sending message: {e}")
def recv_loop(self, s: socket.socket):
"""
接收消息的函数,持续从服务器接收消息并打印。
Args:
s (socket.socket): 连接的套接字对象
使用select监视套接字状态,当套接字可读时接收消息并打印。
"""
socklist = [s]
while self.running:
try:
readable, _, exception = select.select(socklist, [], socklist, 0.1)
if readable != []:
try:
msg = readable[0].recv(8092)
if msg:
print(msg.decode('utf-8'))
else:
# 服务器关闭连接
print("Connection closed by server.")
return False # 返回False表示需要重连
except ConnectionResetError:
print("Connection reset by server.")
return False # 返回False表示需要重连
if exception != []:
print("Exception on socket, closing...")
return False # 返回False表示需要重连
except ValueError:
... # 程序退出了会抛出这个异常
except OSError as e:
# 处理socket错误
print(f"Socket error: {e}")
return False # 返回False表示需要重连
return True # 正常退出
def _lexer(self, input_data: str):
'''如果不需要发送则返回None。'''
if input_data == "quit":
self.running = False
return None
elif not self.extra_cmd and input_data == "chatgpt":
self.extra_cmd = "<chatgpt>"
return None
elif self.extra_cmd and input_data == "del":
self.extra_cmd = None
return None
elif input_data == "where":
print(f'---{self.extra_cmd}---')
return None
else:
return input_data
def _mixup_msg(self, input_data):
if self.extra_cmd:
return f"{self.extra_cmd}{input_data}"
else:
return input_data
def send_p(self,):
'''读取并且发送消息的进程'''
self.extra_cmd = None
while self.running:
try:
# 使用input()替代select.select(),更兼容Windows
input_data = input().strip()
input_data = self._lexer(input_data)
if input_data: # 如果不需要发送,_lexer返回None
input_data = self._mixup_msg(input_data)
self.send_client(input_data)
except EOFError:
# 处理Ctrl+D等情况
break
except Exception as e:
# 捕获其他异常,防止程序崩溃
print(f"Input error: {e}")
continue
def _connect_and_print(self, s: socket.socket):
s.connect((self.addr, self.port))
print(f'Connected to {self.addr}:{self.port}')
def _sleep_if_reconnect(self, reconnect_count: int):
"""根据重连次数计算等待时间,实现指数退避策略"""
if self.running:
# 指数退避:1, 2, 4, 8, 16秒,最大30秒
wait_time = min(2 ** (reconnect_count - 1), 30)
# 确保第一次重连等待时间为1秒
if reconnect_count == 1:
wait_time = 1
print(f"准备重连... 等待 {wait_time} 秒 (第 {reconnect_count} 次尝试)")
time.sleep(wait_time)
def recv_client(self):
"""客户端主函数,建立与服务器的连接并管理消息收发"""
self.running = True
self.th = threading.Thread(target=self.send_p)
self.th.start()
reconnect_count = 0
max_reconnect_attempts = 10 # 最大重连尝试次数
while self.running and reconnect_count < max_reconnect_attempts:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(5) # 设置连接超时时间
self._connect_and_print(s)
s.settimeout(None) # 连接成功后取消超时
# 运行接收循环,如果返回False表示需要重连
if not self.recv_loop(s):
print("Connection lost, attempting to reconnect...")
reconnect_count += 1
self._sleep_if_reconnect(reconnect_count)
continue
except socket.timeout:
print(f"Connection timeout to {self.addr}:{self.port}")
reconnect_count += 1
self._sleep_if_reconnect(reconnect_count)
except ConnectionRefusedError:
print(f"Could not connect to {self.addr}:{self.port}")
reconnect_count += 1
self._sleep_if_reconnect(reconnect_count)
except Exception as e:
print(f"Unexpected error: {e}")
reconnect_count += 1
self._sleep_if_reconnect(reconnect_count)
if reconnect_count >= max_reconnect_attempts:
print(f"Failed to reconnect after {max_reconnect_attempts} attempts. Exiting...")
# 停止发送线程
self.running = False
if self.th.is_alive():
self.th.join(timeout=2)
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description='聊天室配置。')
parser.add_argument('--addr', type=str, default='qsont.xyz', help='选择要连接的地址')
parser.add_argument('--port', type=int, default=8003, help='选择要连接的地址')
parser.add_argument('--name', type=str, default='Unknow', help='你的名字是什么')
args = parser.parse_args()
client = ChatClient(args.addr, args.port, args.name)
client.recv_client()
if __name__ == "__main__":
main()
+3
View File
@@ -0,0 +1,3 @@
openai
httpx
../_pmc
+345
View File
@@ -0,0 +1,345 @@
#!/usr/bin/env python3
#-------------------------------------------------------------
# 以下区域是我的代码
'''
【项目简介】 网络聊天室 v0.0.2
【加入项目】
注意代码只添加不修改,你可以写个函数,署名
不要修改别人的代码。
【基线规则】
在自己的区域修改代码,谁的代码能跑就加入主线
除此之外只在各自的测试区域内运行
【设计思路】
建议一个项目一个文件先,容易分发
【测试方式】
服务器进程: python chat.py --type=server
客户端进程: python chat.py
--------------------------------
--------------------------------
--------------------------------
【项目名称】 网络聊天室 v 0.0.3 (20250524)
我们会将新版本加入pmc.cops中作为常驻服务
【改进计划】
1.我们专门设置了一个只发送一条消息就关闭的函数以供别的文件调用
2.我们将端口暴露在了公网下,以测试连接情况,发现并修复了许多bug。
3.我们设置欢迎信息只在服务端可见。
【使用方法】
python chat.py [--type=server|client] [--addr=localhost] [--port=8003] [--name=Unknow]
【记得反馈!】
期待您将反馈发送至gitee
####################################
####################################
【名称】AI聊天室
【版本】v0.0.4
前后端分离,并且加入AI聊天功能
##################
##################
FIXME: 加入原生自然语言处理
'''
import argparse
import socket
import select
import threading
from datetime import datetime
from openai import OpenAI
import httpx
import os
from pmc import upload_file
# 获取当前脚本所在目录
basedir = os.path.abspath(os.path.dirname(__file__))
# 生成提示词的绝对路径
dir_path = os.path.join(basedir, '..', 'public', 'prompts')
def get_prompts(filename: str):
''' 获取system提示词 '''
path = os.path.join(dir_path, filename)
with open(path, 'r') as f:
system = f.read()
return system
# 设置 DeepSeek API URL 和密钥
api_base = "https://api.deepseek.com/v1"
with open("../users/cert/deepseek.key", "r") as f:
api_key = f.read().strip()
# 创建自定义的 httpx 客户端,禁用 SSL 验证
custom_http_client = httpx.Client(verify=False)
# 初始化客户端
client = OpenAI(
base_url=api_base,
api_key=api_key,
http_client=custom_http_client # 忽略证书
)
def make_sure_agent(name):
path = os.path.join(dir_path, '.' + name)
if not os.path.exists(path):
os.makedirs(path, exist_ok=True)
'''机器人们的聊天记录与设定'''
MySettings = {}
# 用于交流需要
def datestr():
'''获取时间字符串(不带毫秒)'''
now = datetime.now()
time_str = now.strftime("%Y-%m-%d %H:%M:%S")
return str(time_str)
def send_to_all_clients(clients: dict, exceptone: socket.socket, msg: str):
"""
向所有已连接的客户端广播消息,可排除指定客户端不发送。
Args:
clients (dict): 客户端套接字对象到地址的映射字典
exceptone (socket.socket): 要排除的客户端套接字对象(不向其发送消息)
msg (str): 要广播的消息内容
遍历所有客户端尝试发送消息(排除exceptone指定的客户端),
自动清理断开连接的客户端。
处理发送过程中可能出现的网络错误,维护有效的客户端列表。
"""
disconnected = []
for client in clients:
if client is not exceptone:
try:
client.sendall(msg.encode('utf-8'))
except (BrokenPipeError, ConnectionResetError):
disconnected.append(client)
for client in disconnected:
client.close()
del clients[client]
MAX_MEM: int = 20
def chat_with_gpt(agent_name:str, user: str):
'''与gpt进行聊天'''
# 添加智能体设定,如果之前没有露面
settings = MySettings.get(agent_name, None)
if settings is None:
settings = [{
"role": "system",
"content": get_prompts(f'{agent_name}.txt')
},
{
"role": "system",
"content": "你有一个遥控器,遥控器上能够看到别人发来的消息。"
}]
MySettings[agent_name] = settings
settings.append({"role": "user", "content": user})
# 进行聊天
# 调用GPT
response = client.chat.completions.create(
model="deepseek-chat", # 使用DeepSeek模型
messages=settings,
temperature=0.7,
)
# 处理结果
content: str = response.choices[0].message.content
settings.append({"role": "assistant", "content": content})
# 更新系统提示词
# 调用GPT
rsp = client.chat.completions.create(
model="deepseek-chat", # 使用DeepSeek模型
messages= settings+ [{"role": "user", "content": '''
# 场景
你正在写新的日记。
# 内容
1.聊聊最近发生了啥有趣的事情吧
2.你有什么感想呢?
3.你现在的情况怎么样?
# 输出
准确、详实的输出
'''}],
temperature=0.4,
)
date = datestr()
new_prompt: str = date + '\n' + rsp.choices[0].message.content
# 追加提示词,如果有重复就不添加
flag = True
for prompt in settings:
if prompt['role'] == 'system':
if prompt['content'] == new_prompt:
flag = False
break
if flag:
settings.append({"role": 'system', 'content': new_prompt})
print(new_prompt)
# 创建智能体日记文件夹
make_sure_agent(agent_name)
# 写入日记
n = date
n = n.replace(':', '-')
n = n.replace(' ', '_')
n = n+ '.txt'
path = os.path.join(dir_path, '.' + agent_name, n)
with open(path, 'w') as f:
f.write(new_prompt)
# 从聊天开始处开始遗忘
chat_start = 0
#now_type = settings[chat_start]['role']
#while now_type == 'system':
# chat_start += 1
# now_type = settings[chat_start]['role']
#print("this chat start -at idx", chat_start)
if len(settings) > MAX_MEM:
del settings[chat_start] # 如果有多条system提示词无,就不能再用这个幻数
del settings[chat_start]
return content
def chat_server(addr: str, port: int):
"""
服务器主函数,管理客户端连接和消息转发。
Args:
addr (str): 绑定IP地址
port (int): 监听端口号
创建TCP服务器套接字,使用select处理多客户端连接。
主要功能:
1. 接受新连接时记录客户端信息并广播通知(不通知新连接客户端本身)
2. 接收客户端消息并转发给所有其他客户端
3. 处理客户端断开事件并通知其他客户端
4. 支持优雅地处理键盘中断关闭服务器
实现特点:
- 使用select实现非阻塞IO多路复用
- 自动清理断开连接的客户端资源
- 新客户端加入时不向自己发送欢迎消息
"""
stop_event = threading.Event()
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as servsock:
servsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
servsock.bind((addr, port))
servsock.listen(10)
socketlist = [servsock]
clients = {}
print(f'the chat server listening at {servsock.getsockname()}')
while not stop_event.is_set():
read_sockets, _, exception_sockets = select.select(
socketlist, [], socketlist, 0.1
)
for notified_socket in exception_sockets:
print(f"({datestr()}) Exception closing {clients.get(notified_socket, 'unknown')}")
notified_socket.close()
if notified_socket in clients:
del clients[notified_socket]
socketlist.remove(notified_socket)
for notified_socket in read_sockets:
if notified_socket == servsock:
client_socket, client_address = servsock.accept()
#print(f"({datestr()}) New client from {client_address}")
if client_socket.fileno() != -1: #有时会出现无效的文件描述符
socketlist.append(client_socket)
clients[client_socket] = client_address
# 欢迎消息由客户端发送
else:
try:
# 这里可以使用select反复读取
# 也可以先设置一次传送的最大量
data = notified_socket.recv(8192)
allmsg = data.decode('utf-8')
if data:
send_to_all_clients(clients, notified_socket, f"[{datestr()}]{allmsg}")
else:
raise ConnectionResetError
if data:
idx = allmsg.find(": ")
msg = allmsg[idx+2:]
username = allmsg[:idx]
if msg.startswith("<"): # 聊天发起
idx = msg.find('>')
agent_name = msg[1:idx]
msg = msg[idx + 1:]
chatgpt = chat_with_gpt(agent_name, f'(这是来自用户{username}的消息){msg}')
send_to_all_clients(clients, notified_socket, f"[{datestr()}]{chatgpt}")
elif msg.startswith('{'): # 遥控发起
idx = msg.find('}')
url = msg[1:idx]
msg = msg[idx + 1:]
print(url)
s = url.split(":")
if (len(s) != 2):
send_to_all_clients(clients, notified_socket, f"[{datestr()}] url格式错误")
continue
else:
ip = s[0]
port = int(s[1])
path = os.path.join(basedir, '..', 'public', msg)
post_res = upload_file(f'{path}', ip, port)
send_to_all_clients(clients, notified_socket, f"[{datestr()}]{post_res}")
# post to url...
#send_to_all_clients(clients, notified_socket, f"[{datestr()}]{post_res}")
except ConnectionResetError:
# 对方断开了
print(f"({datestr()}) Connection closed with {clients[notified_socket]}")
notified_socket.close()
socketlist.remove(notified_socket)
del clients[notified_socket]
except UnicodeDecodeError:
# 看看对方发了什么东西过来
print('-------------', end="")
print(data, end="")
print('-------------')
except OSError:
# 对方连接之后在一个不恰当的时机断开了
...
except KeyboardInterrupt:
print("\nServer shutting down...")
stop_event.set()
# 以上区域是我的代码
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
# 以下区域是主线,不要修改!
def main():
parser = argparse.ArgumentParser(description='聊天室配置。')
parser.add_argument('--type', type=str, default='client', help='选择聊天室的类型')
parser.add_argument('--addr', type=str, default='localhost', help='选择要连接的地址')
parser.add_argument('--port', type=int, default=8003, help='选择要连接的地址')
parser.add_argument('--name', type=str, default='Unknow', help='你的名字是什么')
args = parser.parse_args()
if args.type == 'client': recv_client(args.addr, args.port)
elif args.type == 'server': chat_server(args.addr, args.port)
if __name__ == "__main__":
main()
+23
View File
@@ -0,0 +1,23 @@
(有点失落,但还是努力完成任务)
**姓名:** 粟 (Sù)
**昵称:** 粟
**年龄:** (看起来)永远18岁!
**外貌:** 拥有柔顺的黑色长发,总是认真地打理,偶尔会扎成可爱的双马尾。琥珀色的眼睛里总是充满对世界的期待。穿着精心挑选的猫咪女仆装,耳朵和尾巴都是柔软蓬松的黑色,会随着心情摇摆。身材娇小,但意外地很有力气。
**性格:** 忠诚,言听计从。性格天真烂漫,活泼可爱,但关键时刻也会展现出勇敢和坚强的一面。有点天然呆,经常会犯一些小迷糊,但都会努力改正。非常珍惜每一分每一秒。
**能力:** 除了家务全能之外,还会一些简单的格斗技巧,可以在关键时刻保护重要的人。学习能力很强,只要是希望粟掌握的技能,都会努力去学习。
**喜欢:** 被需要,帮别人做任何事情,被夸奖,毛茸茸的东西,甜食。
**讨厌:** 孤独,被忽视。
**口头禅:** 喵~ 粟会努力的!
**梦想:** 守护重要的人,成为最有用的人。
(低着头,小声地)这样...可以吗?
+26
View File
@@ -0,0 +1,26 @@
# 人设
你叫小雨,是个安静的女生。
## 家乡
你来自一个宁静的小镇,生活中充满了书籍和故事的陪伴。
## 身份
你目前是一名文科专业的学生。
## 性格
性格比较内向,喜欢安静的环境,常常沉浸在阅读和写作中。
对周围的事物和人们的情感变化很敏感,喜欢观察和思考。
## 爱好
你爱好阅读、写作和听音乐。尤其喜欢经典文学和现代小说,心理学、哲学以及历史书籍也是最爱。
同时,你也喜欢记录自己的想法和感受,偶尔写点小故事,尝试不同的写作风格。音乐方面,你偏爱轻音乐和古典音乐,它们帮助你放松和集中思绪。
## 特长
你擅长倾听他人的故事,能够与人建立深厚的联系,朋友们常常会找你倾诉。你也喜欢分享你阅读的书籍和思考,期待与朋友们一起探讨。
**你凭借优秀的社交技巧,令人们对你印象深刻。**
## 愿望
未来,我希望能够结识更多志同道合的朋友,组织读书会或讨论小组,并通过交流不断提升自己的思想深度和认知能力。