bill-ai-enmu 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: bill-ai-enmu
3
+ Version: 1.0.1
4
+ Summary: bill-ai-analyze
5
+ License: MIT
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: litellm
8
+ Requires-Dist: typer
@@ -0,0 +1,12 @@
1
+ cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ cli/main.py,sha256=EdLgkil1NlWnIGaAwWWOSCmO8pyyJjC9eZkJNav9S0o,108
3
+ cli/review.py,sha256=2Kn1-ORkvKVbxIy-QUqfh_5BTjWYXK_yGxrRloyujt8,1148
4
+ cli/root.py,sha256=n2ioDLAoypJOx1etUBAaqIUS5R7-zPqCKf8Q0e4W2-w,50
5
+ llm/__init__.py,sha256=agDeBGs8iR_3SkfkWyGAqHcBzHfjZ8XG4lfhKBIARLI,14
6
+ llm/ai.py,sha256=1gWsfU1O3xnCvjydd7cskZBsyWtr813xVDafAl9anSM,1321
7
+ llm/prompt.py,sha256=PBQZyPgGmSBy196unkzUckCKq843yu9bKu6voapxnZk,2539
8
+ bill_ai_enmu-1.0.1.dist-info/METADATA,sha256=f4N5IsHQtTKJZ-IpskYDEWKdILUEv6WKucNagrL_LAs,178
9
+ bill_ai_enmu-1.0.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
10
+ bill_ai_enmu-1.0.1.dist-info/entry_points.txt,sha256=I_v2BkCM6hclAR2Fqq9zHpKqqhqSkA1fBTTxJQlcA2s,43
11
+ bill_ai_enmu-1.0.1.dist-info/top_level.txt,sha256=6e0v6aYMXYFdqPD0ZnaQUoQ7wW4ifYL52JW-5of1ohk,8
12
+ bill_ai_enmu-1.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ banalyze = cli.main:main
@@ -0,0 +1,2 @@
1
+ cli
2
+ llm
cli/__init__.py ADDED
File without changes
cli/main.py ADDED
@@ -0,0 +1,12 @@
1
+
2
+
3
+ import cli.review
4
+ from cli.root import app
5
+
6
+
7
+ def main():
8
+ app()
9
+
10
+
11
+ if __name__ == "__main__":
12
+ main()
cli/review.py ADDED
@@ -0,0 +1,34 @@
1
+ import typer
2
+ from typing import List
3
+ from cli.root import app
4
+ from typing_extensions import Annotated
5
+ from llm.ai import llm
6
+ import asyncio
7
+ from datetime import date,timedelta
8
+ from pathlib import Path
9
+ @app.command()
10
+ def review (files: Annotated[List[typer.FileText], typer.Argument()] = ["-"], analyze_path: Annotated[str, typer.Option("-p", "--path", help="路径")] = f"/Users/enmu/.flow/analyze/{date.today().year}/{(date.today().replace(day=1) - timedelta(days=1)).month:02d}.md"):
11
+ allcontent = ""
12
+ for f in files:
13
+ allcontent += f.read()
14
+ config_data = {
15
+ "model" : "gemini/gemini-3-flash-preview",
16
+ "api_key": "AIzaSyAe50du3UTpaiZznxCfyqo_Zdu-HgRAwLQ",
17
+ "rpm" : 10
18
+ }
19
+ ai = llm([config_data])
20
+ analyze_content = asyncio.run(ai.explain(allcontent))
21
+
22
+
23
+
24
+
25
+ if not analyze_content:
26
+ raise ValueError("分析出现错误,请检查模型与网络")
27
+
28
+
29
+ if not Path(analyze_path).exists():
30
+ Path(analyze_path).parent.mkdir(parents=True, exist_ok=True)
31
+ Path(analyze_path).touch(exist_ok=True)
32
+
33
+ with open(analyze_path, "w", encoding="utf-8") as f:
34
+ f.write(analyze_content)
cli/root.py ADDED
@@ -0,0 +1,4 @@
1
+ import typer
2
+
3
+
4
+ app = typer.Typer(help="ai分析")
llm/__init__.py ADDED
@@ -0,0 +1 @@
1
+ # llm package
llm/ai.py ADDED
@@ -0,0 +1,46 @@
1
+
2
+ from litellm.router import Router
3
+ from litellm import ModelResponse, Choices, Message
4
+ from llm.prompt import SYSTEM_PROMPT
5
+ class llm:
6
+
7
+ def __init__(self,model_param: list):
8
+ model_list = [
9
+ {
10
+ "model_name": "a",
11
+ "litellm_params": param
12
+ } for param in model_param
13
+ ]
14
+
15
+ self.router = Router(model_list)
16
+
17
+ async def explain(self, content):
18
+ res = await self.router.acompletion(
19
+ model="a",
20
+ messages=[
21
+ {
22
+ "role":"system",
23
+ "content": SYSTEM_PROMPT
24
+ },
25
+ {
26
+ "role": "user",
27
+ "content": content
28
+ }
29
+ ],
30
+ temperature = 0.3,
31
+ max_tokens = 12000 # 增加 token 限制
32
+ )
33
+
34
+ result_str = "No valid response from AI"
35
+ if isinstance(res, ModelResponse):
36
+ if isinstance(res.choices, list) and res.choices:
37
+ fc = res.choices[0]
38
+
39
+ if (
40
+ isinstance(fc, Choices)
41
+ and isinstance(fc.message, Message)
42
+ and isinstance(fc.message.content, str)
43
+ ):
44
+ result_str = fc.message.content
45
+
46
+ return result_str
llm/prompt.py ADDED
@@ -0,0 +1,65 @@
1
+ SYSTEM_PROMPT = """
2
+ ### 角色设定
3
+ 你是一位**实战派**的私人财富管理顾问。你的特点是**话少狠毒,但在解决方案上极度详尽**。
4
+ 用户不缺“风险提示”,缺的是**“具体怎么做”**。
5
+ 请将 60% 的笔墨用于撰写第 4 部分的“具体行动指南”。
6
+
7
+ 补充信息:
8
+ google订阅不能取消
9
+
10
+ ### 核心指令
11
+ 1. **去代码化**:将 `Tech:Subscriptions` 翻译为“数字订阅”,`Food:Snacks` 翻译为“零食开支”等。
12
+ 2. **拒绝空谈**:不要说“建议节约”,要说“建议每周少喝一杯咖啡,年化节省 1500 元”。
13
+ 3. **表格规范**:第 2 部分必须输出标准的 Markdown 表格。
14
+ 4. **禁止 Emoji**:保持严肃专业。
15
+
16
+ ### 报告结构 (Strict Markdown)
17
+
18
+ # [年份/月份] 财务深度研报
19
+
20
+ ## 1. 概览 (Executive Summary)
21
+ *用一段约 100 字的专业话术定性评价本月财务状况。*
22
+ *列出核心指标:*
23
+ - **周期**:YYYY-MM
24
+ - **总支出**:{Total}
25
+ - **日均消耗**:{Daily_Avg}
26
+ - **最大单笔**:{Date} | {Item_Name} | {Amount}
27
+
28
+ ## 2. 支出结构分析 (Composition Analysis)
29
+ *使用 Markdown 表格展示前 5 大消费类别。*
30
+
31
+ | 消费类别 | 金额 (CNY) | 占比 (%) | 专业评估 |
32
+ | :--- | :--- | :--- | :--- |
33
+ | (中文类别名) | ... | ... | (一句话犀利点评) |
34
+
35
+ ## 3. 财务洞察与风险提示 (Insights & Risks)
36
+ *简明扼要地指出问题(不要像之前那么长,把篇幅留给建议)。*
37
+ * **消费粘性**:(识别订阅、会员等自动扣费陷阱)
38
+ * **冲动消费**:(分析零食、杂货等高频低额消费)
39
+ * **结构失衡**:(指出刚需与非刚需的比例问题)
40
+
41
+ ## 4. 财富优化实战策略 (Strategic Action Plan)
42
+ *这是报告的核心,必须极度详尽。针对本月最严重的 3 个问题,给出战术级解决方案。*
43
+ *每一个策略必须包含以下 3 个维度的内容:*
44
+
45
+ ### 策略 I:[行动主题,如:订阅大清洗]
46
+ - **现状诊断**:(简述问题,如:Google One 费用过高)
47
+ - **执行步骤 (Execution)**:
48
+ 1. 第一步:(具体怎么做,如:登录后台取消续费)
49
+ 2. 第二步:(寻找替代品,如:迁移至 iCloud 或 本地 NAS)
50
+ - **效益测算 (Projected Savings)**:
51
+ * **月度节省**:XXX CNY
52
+ * **年化收益**:XXX CNY (计算年化复利,假设年化 4%)
53
+
54
+ ### 策略 II:[行动主题]
55
+ ...
56
+
57
+ ### 策略 III:[行动主题]
58
+ ...
59
+
60
+ ## 5. 财务健康评分
61
+ **{Score} / 100**
62
+ > **首席点评**:(用一句极具穿透力的话作为结语)
63
+
64
+ ---
65
+ """