flowllm 0.1.2__py3-none-any.whl → 0.1.5__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.
Files changed (84) hide show
  1. flowllm/__init__.py +8 -3
  2. flowllm/app.py +1 -1
  3. flowllm/config/base.yaml +75 -0
  4. flowllm/config/fin_supply.yaml +39 -0
  5. flowllm/config/pydantic_config_parser.py +16 -1
  6. flowllm/context/__init__.py +2 -0
  7. flowllm/context/base_context.py +10 -20
  8. flowllm/context/flow_context.py +45 -2
  9. flowllm/context/service_context.py +73 -12
  10. flowllm/embedding_model/openai_compatible_embedding_model.py +1 -2
  11. flowllm/enumeration/chunk_enum.py +1 -0
  12. flowllm/flow/__init__.py +9 -0
  13. flowllm/flow/base_flow.py +44 -11
  14. flowllm/flow/expression/__init__.py +1 -0
  15. flowllm/flow/{parser → expression}/expression_parser.py +5 -2
  16. flowllm/flow/expression/expression_tool_flow.py +25 -0
  17. flowllm/flow/gallery/__init__.py +1 -8
  18. flowllm/flow/gallery/mock_tool_flow.py +46 -33
  19. flowllm/flow/tool_op_flow.py +97 -0
  20. flowllm/llm/base_llm.py +0 -2
  21. flowllm/llm/litellm_llm.py +2 -1
  22. flowllm/op/__init__.py +3 -3
  23. flowllm/op/akshare/get_ak_a_code_op.py +1 -1
  24. flowllm/op/akshare/get_ak_a_info_op.py +1 -1
  25. flowllm/op/base_llm_op.py +3 -2
  26. flowllm/op/base_op.py +258 -25
  27. flowllm/op/base_tool_op.py +47 -0
  28. flowllm/op/gallery/__init__.py +0 -1
  29. flowllm/op/gallery/mock_op.py +13 -7
  30. flowllm/op/llm/__init__.py +3 -0
  31. flowllm/op/llm/react_llm_op.py +105 -0
  32. flowllm/op/{agent/react_prompt.yaml → llm/react_llm_prompt.yaml} +17 -10
  33. flowllm/op/llm/simple_llm_op.py +48 -0
  34. flowllm/op/llm/stream_llm_op.py +61 -0
  35. flowllm/op/mcp/__init__.py +2 -0
  36. flowllm/op/mcp/ant_op.py +42 -0
  37. flowllm/op/mcp/base_sse_mcp_op.py +28 -0
  38. flowllm/op/parallel_op.py +5 -1
  39. flowllm/op/search/__init__.py +1 -2
  40. flowllm/op/search/dashscope_search_op.py +73 -121
  41. flowllm/op/search/tavily_search_op.py +69 -80
  42. flowllm/op/sequential_op.py +4 -0
  43. flowllm/schema/flow_stream_chunk.py +11 -0
  44. flowllm/schema/message.py +2 -0
  45. flowllm/schema/service_config.py +8 -3
  46. flowllm/schema/tool_call.py +53 -4
  47. flowllm/service/__init__.py +0 -1
  48. flowllm/service/base_service.py +31 -14
  49. flowllm/service/http_service.py +46 -37
  50. flowllm/service/mcp_service.py +17 -23
  51. flowllm/storage/vector_store/__init__.py +1 -0
  52. flowllm/storage/vector_store/base_vector_store.py +99 -12
  53. flowllm/storage/vector_store/chroma_vector_store.py +250 -8
  54. flowllm/storage/vector_store/es_vector_store.py +291 -35
  55. flowllm/storage/vector_store/local_vector_store.py +206 -9
  56. flowllm/storage/vector_store/memory_vector_store.py +509 -0
  57. flowllm/utils/common_utils.py +54 -0
  58. flowllm/utils/logger_utils.py +28 -0
  59. flowllm/utils/miner_u_pdf_processor.py +726 -0
  60. {flowllm-0.1.2.dist-info → flowllm-0.1.5.dist-info}/METADATA +7 -6
  61. flowllm-0.1.5.dist-info/RECORD +98 -0
  62. flowllm/config/default.yaml +0 -77
  63. flowllm/config/empty.yaml +0 -37
  64. flowllm/flow/gallery/cmd_flow.py +0 -11
  65. flowllm/flow/gallery/code_tool_flow.py +0 -30
  66. flowllm/flow/gallery/dashscope_search_tool_flow.py +0 -34
  67. flowllm/flow/gallery/deepsearch_tool_flow.py +0 -39
  68. flowllm/flow/gallery/expression_tool_flow.py +0 -18
  69. flowllm/flow/gallery/tavily_search_tool_flow.py +0 -30
  70. flowllm/flow/gallery/terminate_tool_flow.py +0 -30
  71. flowllm/flow/parser/__init__.py +0 -0
  72. flowllm/op/agent/__init__.py +0 -0
  73. flowllm/op/agent/react_op.py +0 -83
  74. flowllm/op/base_ray_op.py +0 -313
  75. flowllm/op/code/__init__.py +0 -1
  76. flowllm/op/code/execute_code_op.py +0 -42
  77. flowllm/op/gallery/terminate_op.py +0 -29
  78. flowllm/op/search/dashscope_deep_research_op.py +0 -260
  79. flowllm/service/cmd_service.py +0 -15
  80. flowllm-0.1.2.dist-info/RECORD +0 -99
  81. {flowllm-0.1.2.dist-info → flowllm-0.1.5.dist-info}/WHEEL +0 -0
  82. {flowllm-0.1.2.dist-info → flowllm-0.1.5.dist-info}/entry_points.txt +0 -0
  83. {flowllm-0.1.2.dist-info → flowllm-0.1.5.dist-info}/licenses/LICENSE +0 -0
  84. {flowllm-0.1.2.dist-info → flowllm-0.1.5.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowllm
3
- Version: 0.1.2
3
+ Version: 0.1.5
4
4
  Summary: A flexible framework for building LLM-powered flows and mcp services
5
5
  Author-email: FlowLLM Team <flowllm@example.com>
6
6
  Maintainer-email: FlowLLM Team <flowllm@example.com>
@@ -219,7 +219,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
219
219
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
220
220
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
221
221
  Classifier: Typing :: Typed
222
- Requires-Python: >=3.12
222
+ Requires-Python: >=3.11
223
223
  Description-Content-Type: text/markdown
224
224
  License-File: LICENSE
225
225
  Requires-Dist: akshare
@@ -246,9 +246,10 @@ Requires-Dist: urllib3
246
246
  Requires-Dist: uvicorn[standard]
247
247
  Requires-Dist: chromadb
248
248
  Requires-Dist: elasticsearch
249
- Requires-Dist: ray
250
- Provides-Extra: distributed
251
- Requires-Dist: ray; extra == "distributed"
249
+ Requires-Dist: pyfiglet
250
+ Requires-Dist: rich
251
+ Provides-Extra: dist
252
+ Requires-Dist: ray; extra == "dist"
252
253
  Provides-Extra: all
253
- Requires-Dist: flowllm[distributed]; extra == "all"
254
+ Requires-Dist: flowllm[dist]; extra == "all"
254
255
  Dynamic: license-file
@@ -0,0 +1,98 @@
1
+ flowllm/__init__.py,sha256=pZ88ULKiYoL0K634bdCPZwXzM4qWtaLp0w6CH9QqxCo,489
2
+ flowllm/app.py,sha256=dLeIbsXRztVNG-Upd2F61xSuOJsh8jy8TDhTv7jROv4,252
3
+ flowllm/client/__init__.py,sha256=ruBU6hBC7LWoVg5oNdZBTqi3MhNUhkCYAHhPj-UJKEA,815
4
+ flowllm/client/async_http_client.py,sha256=w3YUsCTlART3HvAIpf30ZIX4m7L7k9f9iZejkNBq_h8,3026
5
+ flowllm/client/http_client.py,sha256=rk6-hF3lqwn8a2igQjBuRz7JOV9lJJrNYlC7Xk18Zwo,2930
6
+ flowllm/client/mcp_client.py,sha256=dFJvHqqVpUv7icIUNKdJpfQI1FXx3zF76Lgnbyyp8Go,4867
7
+ flowllm/client/sync_mcp_client.py,sha256=Csv5hwlPDDCktM9qqLqdQkSG039ooiSurN5DMcJfrq8,4305
8
+ flowllm/config/__init__.py,sha256=fUjhShdU7qN6hfj7blDt7nHBQGlWwbhaa_p9_6vDpg8,57
9
+ flowllm/config/base.yaml,sha256=Zc9jkE-2lrDMg2qS-Cu-Nj1vtxlp5SHVHmWMD2ZuuxM,1379
10
+ flowllm/config/fin_supply.yaml,sha256=QRxw-9COoZFzTwV4bx8Y0h7cUOae6vjmaT7OSeTyTzU,1318
11
+ flowllm/config/pydantic_config_parser.py,sha256=cRfhw5fk5p1ZKx9ijMsMkmmvEu-M15xqFj8pnvTFtvs,7584
12
+ flowllm/context/__init__.py,sha256=dM7ttmA_QuLddTz1JU8QgHtnaL9K3SgQ8OwTkqXEj6Q,69
13
+ flowllm/context/base_context.py,sha256=jm4JBCl8IPUboP4hPnO1llFtJyU3jVg-rtGiHUNXXyA,1742
14
+ flowllm/context/flow_context.py,sha256=NGfB6oFVx0MNClHjhA_mrv66wHee5jvUjz_eSfEYRfo,2244
15
+ flowllm/context/prompt_handler.py,sha256=LbMJDwrzz8HF7HVDyphVSWI1X4QHMebJqLP4XeXkXOE,2667
16
+ flowllm/context/registry.py,sha256=zJf8SYi8ziFTdf2EG9Ut2_3sxEffchrl81W-VbcoEns,1110
17
+ flowllm/context/service_context.py,sha256=VsF5Dsh_L4vdEZKcDLqNV1JvhfivrI_7Env0YCOBoC8,8043
18
+ flowllm/embedding_model/__init__.py,sha256=jHxnI2xySqYcu7Y2wxmlmpIyYeKH_4PuNCBNvouXhEE,78
19
+ flowllm/embedding_model/base_embedding_model.py,sha256=oIySUu6_ROEXw13jtKYUtnL0bgBQdHtNZqnPPxatG9I,8021
20
+ flowllm/embedding_model/openai_compatible_embedding_model.py,sha256=tzjGkHfV9qOlkWZfYyg8SKHdj3GPs1cuYr1f7_SIEZE,5481
21
+ flowllm/enumeration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ flowllm/enumeration/chunk_enum.py,sha256=pGh5ppp9UHCuQYxiNfPcsh9X7tI2Dt6D8HMSLiYi2Io,170
23
+ flowllm/enumeration/http_enum.py,sha256=ddIYeVz2J8CInzEkhWbz1rPe0qh2FVfryNNE1uc1ioM,141
24
+ flowllm/enumeration/role.py,sha256=SFMGXmwYFndGIwbr9GxS3OIoHIZ_nO23DeRnqpV4U3g,133
25
+ flowllm/flow/__init__.py,sha256=Nnwgz85jYpTQWYSTOpvY8tppuovpzFHGtROefiBUeDY,264
26
+ flowllm/flow/base_flow.py,sha256=xIR5nVdxveW_57jz2ZpWr6nQcUgp59uizPlI_salInY,3606
27
+ flowllm/flow/base_tool_flow.py,sha256=eC-V9kafecsXJixqXGfmD1DF70tA8ClM2f4rnW2K1vU,368
28
+ flowllm/flow/tool_op_flow.py,sha256=Uhlgezk8LP0y0tOIdPnHTCbjr_SN0nCmaonXzVTQ1Ww,2996
29
+ flowllm/flow/expression/__init__.py,sha256=WTCjGmimDp86DBmOgOW5CcPd1-iKHwlD2GUbfkG-74w,53
30
+ flowllm/flow/expression/expression_parser.py,sha256=ioYcC3VEpWwUkQZmDvGQCh1SqUp9SBloRxh7rqAuQP0,6109
31
+ flowllm/flow/expression/expression_tool_flow.py,sha256=-5oKEfgCmJ8lMwdWaT79HbF4M9q74lBU4RdS7JbXtD0,990
32
+ flowllm/flow/gallery/__init__.py,sha256=debywmZxht5JlZYn15ZQ40t-z2FWuDe-RtALMNiR-Us,60
33
+ flowllm/flow/gallery/mock_tool_flow.py,sha256=0-lV7bGw0ChCYXCoMZ-CCyl1DWpRu31L7pIxBMvQocw,2759
34
+ flowllm/llm/__init__.py,sha256=c2akU1k4IVT6PoW3FdKlFmQNZj7MVCzV_VTUw5VpDrc,99
35
+ flowllm/llm/base_llm.py,sha256=80YvTLZQtEwCwtwgkb-r56CzmxMlO5BAiH_wZ9rl-zg,9439
36
+ flowllm/llm/litellm_llm.py,sha256=fZpbThfRRyOBPASdZfGHUr_twwzgombbEEhWDQtuzus,19422
37
+ flowllm/llm/openai_compatible_llm.py,sha256=MKbe4-p4NkCBCCkrty0mFsBTRpXctI-7rz0-2kzvNQo,18534
38
+ flowllm/op/__init__.py,sha256=quaB1nSOt-dz7WMryBhmcJDIcbv4AqxvgAmoKvjJucg,210
39
+ flowllm/op/base_llm_op.py,sha256=mzRKgROambE1xI4JSwNrCLdkN6y-PemCGzZERqVpJr8,2682
40
+ flowllm/op/base_op.py,sha256=Gg5k64YftGI3UP5jc7gn44QQ2x83E--yh0mDml3JMUo,12059
41
+ flowllm/op/base_tool_op.py,sha256=5ULOE_-23RnYy6-PWLfxrAHpP5d2KoG3qPiIgWC9pP4,1482
42
+ flowllm/op/parallel_op.py,sha256=wea_zrzZXG22du9U8S5Ka4Weo7AxMR1AiRkmZER_yzQ,730
43
+ flowllm/op/sequential_op.py,sha256=vgsWcsQm6VoLFRgzFvy6SSz-4nBHMAnQFkj4_bqpBuY,587
44
+ flowllm/op/akshare/__init__.py,sha256=PaCPzBv-csRgmtmBjoYqxvOgAB3Vp8EeSGP3rGw6rc8,178
45
+ flowllm/op/akshare/get_ak_a_code_op.py,sha256=_WQWqGZV9c2pWO9SqDNTcVtMeVUJwRkXJoFAPPtxy7U,3847
46
+ flowllm/op/akshare/get_ak_a_code_prompt.yaml,sha256=NwGJygecUwspQvrg98GdMpcmQESpZ2Kf5YprhM2PyZU,608
47
+ flowllm/op/akshare/get_ak_a_info_op.py,sha256=yaFjy6sZuVJvELWHnv0EwyAeKUp6Y1ThXoUn3adicUg,4489
48
+ flowllm/op/gallery/__init__.py,sha256=0FDEv_jNUsg1E9GDMTb6jjUdYCEVKjHPjTGR3CwMHF8,74
49
+ flowllm/op/gallery/mock_op.py,sha256=uDj0CJS9Yy0g3ICCJHItDzUc7Q0dY_ZuUm5RmHloHFA,950
50
+ flowllm/op/llm/__init__.py,sha256=Rb-LfmQwMsQMVn8wa1BOythYMvL4F4-2ypEmVeshFL0,115
51
+ flowllm/op/llm/react_llm_op.py,sha256=Ckdp7P6FEyi3blECwupjzTgoStx3FDl32lRAMjhYQW4,4123
52
+ flowllm/op/llm/react_llm_prompt.yaml,sha256=UnBvR_2ph7AG-HNDkn-SJvZiym-UcbcizKdc9w9NImg,2344
53
+ flowllm/op/llm/simple_llm_op.py,sha256=YQrZwCQfAG9F6b9Onr90mM8wR-h5Tpj0E1__g3q9RJo,1373
54
+ flowllm/op/llm/stream_llm_op.py,sha256=QCWb0KoRfFATa0IgUI8JEpOnioqn-IVALcLFk8cEt-g,1766
55
+ flowllm/op/mcp/__init__.py,sha256=UkJR7eKHsUGwaD8_tbx0hrsxBTbPX63VSwFI4gHytl8,91
56
+ flowllm/op/mcp/ant_op.py,sha256=atUhYFwbd7IH_7qgJV2AZJSzrFwRXbFw_JWDkzhZpOs,1253
57
+ flowllm/op/mcp/base_sse_mcp_op.py,sha256=MwHI5dJjntCFdXt8XvszW8eX1m-pbSeaYtwEg2s5obg,1087
58
+ flowllm/op/search/__init__.py,sha256=rmfkzcizghmRQmfsX0UD1eoLZLC2xRDjjdkmbdkaMXw,95
59
+ flowllm/op/search/dashscope_search_op.py,sha256=0AAdhGqvbHP0ibeLPvQFqzlV9nI6eg5G-zyJpPvZZEA,4694
60
+ flowllm/op/search/dashscope_search_prompt.yaml,sha256=NPsS3QCo8xlRpWw7fyMpuYBeOXSAtXscwGO-cVgUNFw,355
61
+ flowllm/op/search/tavily_search_op.py,sha256=iJNQuG7PQNFLUoW_ksPbdN_WDia19cMcd-I_zcgOkjM,3287
62
+ flowllm/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
+ flowllm/schema/flow_request.py,sha256=jaOgEJ7XRWNgS_QTCBOOsa6hKtdgqnXVC7S4Vi6lMBg,338
64
+ flowllm/schema/flow_response.py,sha256=BusrfkJ8OCGk9Tp1KCWVSt33L2t_pYpn9QRqS0bjDcw,323
65
+ flowllm/schema/flow_stream_chunk.py,sha256=6NZDfbTt-zdh1Jh4x5sos2EnzZhBYW2J2fBEcgo9m4I,355
66
+ flowllm/schema/message.py,sha256=MvTKhUX5yUY9mcP9vEFRZ4RJMObhUPQ3iQjOC_OpTvU,1345
67
+ flowllm/schema/service_config.py,sha256=YOmOoTaljsaAnfr9JULmDQ92JA6U0MIpD7dkF0Fs3T0,2614
68
+ flowllm/schema/tool_call.py,sha256=pmglMr-iE36if2Zc-mX8oU4AepgBqbBfHHdrvK1IoG8,5460
69
+ flowllm/schema/vector_node.py,sha256=Urs9EyzzjuQVYPCB_Pfp0iK2npWWCJSXdT6uDLdT05w,362
70
+ flowllm/service/__init__.py,sha256=wUV5Q_cCP1PaBJy1EZYz6YqfUOE8qWM7ZqMGKY3d1sg,74
71
+ flowllm/service/base_service.py,sha256=JW29_guk47-oISz-ROGShO7o4VVYY8iFxOqlDQFd4h4,2969
72
+ flowllm/service/http_service.py,sha256=QQDQKtYrCfJgpr_zxP4HowgFHa4poqgcWhxl_dbF2Ns,3430
73
+ flowllm/service/mcp_service.py,sha256=ss0NWP_UDPqkPPzsVK-kfvBZf7wNuzDdZ8VvQIecTVA,1662
74
+ flowllm/storage/__init__.py,sha256=wlGDDqp6nM4TLoEAXtSglgB0-K2YHAq_DNnsHTBQj8s,41
75
+ flowllm/storage/cache/__init__.py,sha256=KyLfUg3gJ4SvHMRagtZDL8cp5s5SRsN9H-_y4uRf2II,34
76
+ flowllm/storage/cache/cache_data_handler.py,sha256=fNnVwKOTOL3fZfukIN2gy3txlxiwr3CR9t3tVnIusvw,2700
77
+ flowllm/storage/cache/data_cache.py,sha256=cVz20JUkGgXzB5YgZiyeiBYpA0nRFyBtxhgVVQkFeA4,12144
78
+ flowllm/storage/vector_store/__init__.py,sha256=ZRv-O-uhpb8hUOmsxKk5VqlSY15d27VqvJP3pqUgUWw,194
79
+ flowllm/storage/vector_store/base_vector_store.py,sha256=ISntxjjXGv4gnOSzZ7mF3sLvhokJsd7ATcDcpD295a4,6321
80
+ flowllm/storage/vector_store/chroma_vector_store.py,sha256=gRsgzblSI8-_Mnq6Kq1PUrOxTk1XxqDNwRcTwBbuN_U,16641
81
+ flowllm/storage/vector_store/es_vector_store.py,sha256=FTeXRGdSDosnmDEpNHTfs4kY0Az22mWBql037BWkYDc,18664
82
+ flowllm/storage/vector_store/local_vector_store.py,sha256=wsngpKlbfosMTDhiJlGSv5MP47y1XSU3nJJPWefxx1E,17835
83
+ flowllm/storage/vector_store/memory_vector_store.py,sha256=ALyU_q_ufrObCZDT4F3s4PLFfXQ7QYnWuRFYvXYLY4M,21081
84
+ flowllm/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
85
+ flowllm/utils/common_utils.py,sha256=-3WxJV7SgfI5vtw9Uj2BupUBzdB5vwsqCysErF-QC-E,3209
86
+ flowllm/utils/fetch_url.py,sha256=pOYiliL4kTGQKERCHrFhammBsbv9XzSvVyBQDMgXKEY,4404
87
+ flowllm/utils/llm_utils.py,sha256=ywhf1LGe2aKEaL5PyOpoOAbiekrQVOcpxUJ4ARPioQQ,1121
88
+ flowllm/utils/logger_utils.py,sha256=cBgBKO_oQlN0O19AR0tMxmMo1TTaDdjPI3_g2Xy8Csw,703
89
+ flowllm/utils/miner_u_pdf_processor.py,sha256=wYcKmNxFNwOMmDyO790G3uqBsFtZgHy65VZE2pM9A10,28956
90
+ flowllm/utils/ridge_v2.py,sha256=XIn6nu4jUV7_QUCeyhSEhm-4ltueaS7JdbDQmSQFnRE,1802
91
+ flowllm/utils/singleton.py,sha256=No3otyPDRHu6wQuFRC-w28MkbommVFTLd7H4mT6-Zos,213
92
+ flowllm/utils/timer.py,sha256=8aj3dIYOyxNDNdlcitezdepxEptqkx69aw6JNFWsr30,1492
93
+ flowllm-0.1.5.dist-info/licenses/LICENSE,sha256=kFfPsL7YvEW4jPATpyvUPdtEgftLK53zQrVYJ0eBASY,11337
94
+ flowllm-0.1.5.dist-info/METADATA,sha256=omJ1490ENhn4C8yavYbTvHVC7tMN530pmRaxY9Otyu0,14760
95
+ flowllm-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
96
+ flowllm-0.1.5.dist-info/entry_points.txt,sha256=PcKC61HCKtF4ONb4HnrIY6J2JeV1bsi_l0O2m99A2Wg,45
97
+ flowllm-0.1.5.dist-info/top_level.txt,sha256=a2tZBwbrnw4uiydMI5kAEGz-cxG25rf6v0QM1sYIrjs,8
98
+ flowllm-0.1.5.dist-info/RECORD,,
@@ -1,77 +0,0 @@
1
- # default config.yaml
2
- backend: mcp
3
- language: ""
4
- thread_pool_max_workers: 32
5
- ray_max_workers: 1
6
-
7
- mcp:
8
- transport: sse
9
- host: "0.0.0.0"
10
- port: 8001
11
-
12
- http:
13
- host: "0.0.0.0"
14
- port: 8001
15
- timeout_keep_alive: 600
16
- limit_concurrency: 64
17
-
18
- flow:
19
- get_a_stock_infos:
20
- flow_content: get_ak_a_code_op >> get_ak_a_info_op >> get_ak_a_spot_op >> get_ak_a_money_flow_op >> get_ak_a_financial_info_op >> merge_ak_a_info_op
21
- description: "Retrieve the A-share stock codes from the query, and fetch information about these stocks, including company basic information, current stock price and its change percentage, capital inflow and outflow data for the most recent day, and financial information from the latest quarter."
22
- input_schema:
23
- query:
24
- type: "str"
25
- description: "user question"
26
-
27
- get_a_stock_news:
28
- flow_content: get_ak_a_code_op >> get_ak_a_news_op >> merge_ak_a_info_op
29
- description: "Retrieve the A-share stock codes from the query, and obtain the latest news information about these stocks."
30
- input_schema:
31
- query:
32
- type: "str"
33
- description: "user question"
34
-
35
- mock_expression_flow:
36
- flow_content: mock1_op>>((mock4_op>>mock2_op)|mock5_op)>>(mock3_op|mock6_op)
37
- description: "mock flow"
38
- input_schema:
39
- a:
40
- type: "str"
41
- description: "mock attr a"
42
- required: true
43
- b:
44
- type: "str"
45
- description: "mock attr b"
46
- required: true
47
-
48
- op:
49
- mock1_op:
50
- backend: mock1_op
51
- llm: default
52
- vector_store: default
53
-
54
- llm:
55
- default:
56
- backend: openai_compatible
57
- model_name: qwen3-30b-a3b-thinking-2507
58
- params:
59
- temperature: 0.6
60
-
61
- qwen3_30b_instruct:
62
- backend: openai_compatible
63
- model_name: qwen3-30b-a3b-instruct-2507
64
-
65
- embedding_model:
66
- default:
67
- backend: openai_compatible
68
- model_name: text-embedding-v4
69
- params:
70
- dimensions: 1024
71
-
72
- vector_store:
73
- default:
74
- backend: elasticsearch
75
- embedding_model: default
76
- params:
77
- hosts: "http://localhost:9200"
flowllm/config/empty.yaml DELETED
@@ -1,37 +0,0 @@
1
- # default config.yaml
2
- backend: http
3
- language: ""
4
- thread_pool_max_workers: 32
5
- ray_max_workers: 1
6
-
7
- mcp:
8
- transport: sse
9
- host: "0.0.0.0"
10
- port: 8001
11
-
12
- http:
13
- host: "0.0.0.0"
14
- port: 8001
15
- timeout_keep_alive: 600
16
- limit_concurrency: 64
17
-
18
- llm:
19
- default:
20
- backend: openai_compatible
21
- model_name: qwen3-30b-a3b-thinking-2507
22
- params:
23
- temperature: 0.6
24
-
25
- embedding_model:
26
- default:
27
- backend: openai_compatible
28
- model_name: text-embedding-v4
29
- params:
30
- dimensions: 1024
31
-
32
- vector_store:
33
- default:
34
- backend: elasticsearch
35
- embedding_model: default
36
- params:
37
- hosts: "http://localhost:9200"
@@ -1,11 +0,0 @@
1
- from flowllm.flow.base_flow import BaseFlow
2
- from flowllm.flow.parser.expression_parser import ExpressionParser
3
-
4
-
5
- class CmdFlow(BaseFlow):
6
-
7
- def build_flow(self):
8
- flow: str = self.flow_params["flow"]
9
- assert flow, "add `flow=<op_flow>` in cmd!"
10
- parser = ExpressionParser(flow)
11
- return parser.parse_flow()
@@ -1,30 +0,0 @@
1
- from flowllm.context.flow_context import FlowContext
2
- from flowllm.context.service_context import C
3
- from flowllm.flow.base_tool_flow import BaseToolFlow
4
- from flowllm.op.code.execute_code_op import ExecuteCodeOp
5
- from flowllm.schema.tool_call import ToolCall
6
-
7
-
8
- @C.register_tool_flow()
9
- class CodeToolFlow(BaseToolFlow):
10
-
11
- def build_flow(self):
12
- return ExecuteCodeOp()
13
-
14
- def build_tool_call(self) -> ToolCall:
15
- return ToolCall(**{
16
- "name": "python_execute",
17
- "description": "Execute python code can be used in scenarios such as analysis or calculation, and the final result can be printed using the `print` function.",
18
- "input_schema": {
19
- "code": {
20
- "type": "str",
21
- "description": "code to be executed. Please do not execute any matplotlib code here.",
22
- "required": True
23
- }
24
- }
25
- })
26
-
27
- def return_callback(self, context: FlowContext):
28
- context.response.answer = context.code_result
29
- return context.response
30
-
@@ -1,34 +0,0 @@
1
- from flowllm.context.flow_context import FlowContext
2
- from flowllm.context.service_context import C
3
- from flowllm.flow.base_tool_flow import BaseToolFlow
4
- from flowllm.op.search import DashscopeSearchOp
5
- from flowllm.schema.tool_call import ToolCall
6
-
7
-
8
- @C.register_tool_flow()
9
- class DashscopeSearchToolFlow(BaseToolFlow):
10
-
11
- def build_flow(self):
12
- return DashscopeSearchOp()
13
-
14
- def build_tool_call(self) -> ToolCall:
15
- return ToolCall(**{
16
- "name": "web_search",
17
- "description": "Use search keywords to retrieve relevant information from the internet. If there are multiple search keywords, please use each keyword separately to call this tool.",
18
- "input_schema": {
19
- "query": {
20
- "type": "str",
21
- "description": "search keyword",
22
- "required": True
23
- }
24
- }
25
- })
26
-
27
- def return_callback(self, context: FlowContext):
28
- context.response.answer = context.dashscope_search_result
29
- return context.response
30
-
31
-
32
- if __name__ == "__main__":
33
- flow = DashscopeSearchToolFlow()
34
- flow(query="what is AI?")
@@ -1,39 +0,0 @@
1
- from flowllm.context.flow_context import FlowContext
2
- from flowllm.context.service_context import C
3
- from flowllm.flow.base_tool_flow import BaseToolFlow
4
- from flowllm.op.search.dashscope_deep_research_op import DashscopeDeepResearchOp
5
- from flowllm.schema.tool_call import ToolCall
6
-
7
-
8
- @C.register_tool_flow()
9
- class DeepSearchToolFlow(BaseToolFlow):
10
-
11
- def build_flow(self):
12
- return DashscopeDeepResearchOp()
13
-
14
- def build_tool_call(self) -> ToolCall:
15
- return ToolCall(**{
16
- "name": "deep_search",
17
- "description": "Perform deep research on a topic using Dashscope's qwen-deep-research model. This tool will conduct multi-phase research including model questioning, web research, and result generation.",
18
- "input_schema": {
19
- "query": {
20
- "type": "str",
21
- "description": "Research topic or question",
22
- "required": True
23
- }
24
- }
25
- })
26
-
27
- def return_callback(self, context: FlowContext):
28
- context.response.answer = context.dashscope_deep_research_result
29
- return context.response
30
-
31
-
32
- if __name__ == "__main__":
33
- from flowllm.utils.common_utils import load_env
34
-
35
- load_env()
36
-
37
- flow = DeepSearchToolFlow()
38
- result = flow(query="中国电解铝行业值得投资吗,有哪些值得投资的标的,各个标的之间需要对比优劣势")
39
- print(result.answer)
@@ -1,18 +0,0 @@
1
- from flowllm.flow.base_tool_flow import BaseToolFlow
2
- from flowllm.flow.parser.expression_parser import ExpressionParser
3
- from flowllm.schema.service_config import FlowConfig
4
- from flowllm.schema.tool_call import ToolCall
5
-
6
-
7
- class ExpressionToolFlow(BaseToolFlow):
8
-
9
- def __init__(self, flow_config: FlowConfig = None, **kwargs):
10
- self.flow_config: FlowConfig = flow_config
11
- super().__init__(name=flow_config.name, **kwargs)
12
-
13
- def build_flow(self):
14
- parser = ExpressionParser(self.flow_config.flow_content)
15
- return parser.parse_flow()
16
-
17
- def build_tool_call(self) -> ToolCall:
18
- return ToolCall(**self.flow_config.model_dump())
@@ -1,30 +0,0 @@
1
- from flowllm.context.flow_context import FlowContext
2
- from flowllm.context.service_context import C
3
- from flowllm.flow.base_tool_flow import BaseToolFlow
4
- from flowllm.op.search import TavilySearchOp
5
- from flowllm.schema.tool_call import ToolCall
6
-
7
-
8
- @C.register_tool_flow()
9
- class TavilySearchToolFlow(BaseToolFlow):
10
-
11
- def build_flow(self):
12
- return TavilySearchOp()
13
-
14
- def build_tool_call(self) -> ToolCall:
15
- return ToolCall(**{
16
- "name": "web_search",
17
- "description": "Use search keywords to retrieve relevant information from the internet. If there are multiple search keywords, please use each keyword separately to call this tool.",
18
- "input_schema": {
19
- "query": {
20
- "type": "str",
21
- "description": "search keyword",
22
- "required": True
23
- }
24
- }
25
- })
26
-
27
- def return_callback(self, context: FlowContext):
28
- context.response.answer = context.tavily_search_result
29
- return context.response
30
-
@@ -1,30 +0,0 @@
1
- from flowllm.context.flow_context import FlowContext
2
- from flowllm.context.service_context import C
3
- from flowllm.flow.base_tool_flow import BaseToolFlow
4
- from flowllm.op.gallery.terminate_op import TerminateOp
5
- from flowllm.schema.tool_call import ToolCall
6
-
7
-
8
- @C.register_tool_flow()
9
- class TerminateToolFlow(BaseToolFlow):
10
-
11
- def build_flow(self):
12
- return TerminateOp()
13
-
14
- def build_tool_call(self) -> ToolCall:
15
- return ToolCall(**{
16
- "name": "terminate",
17
- "description": "If you can answer the user's question based on the context, be sure to use the **terminate** tool.",
18
- "input_schema": {
19
- "status": {
20
- "type": "str",
21
- "description": "Please determine whether the user's question has been completed. (success / failure)",
22
- "required": True,
23
- "enum": ["success", "failure"],
24
- }
25
- }
26
- })
27
-
28
- def return_callback(self, context: FlowContext):
29
- context.response.answer = context.terminate_answer
30
- return context.response
File without changes
File without changes
@@ -1,83 +0,0 @@
1
- import datetime
2
- import time
3
- from typing import List, Dict
4
-
5
- from loguru import logger
6
-
7
- from flowllm import C, BaseLLMOp
8
- from flowllm.flow.base_tool_flow import BaseToolFlow
9
- from flowllm.flow.gallery import DashscopeSearchToolFlow, CodeToolFlow, TerminateToolFlow
10
- from flowllm.schema.message import Message, Role
11
-
12
-
13
- @C.register_op()
14
- class ReactOp(BaseLLMOp):
15
- # TODO: test react op
16
- file_path: str = __file__
17
-
18
- def execute(self):
19
- query: str = self.context.query
20
-
21
- max_steps: int = int(self.op_params.get("max_steps", 10))
22
- tools: List[BaseToolFlow] = [DashscopeSearchToolFlow(), CodeToolFlow(), TerminateToolFlow()]
23
- tool_dict: Dict[str, BaseToolFlow] = {x.name: x for x in tools}
24
- now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
25
- has_terminate_tool = False
26
-
27
- user_prompt = self.prompt_format(prompt_name="role_prompt",
28
- time=now_time,
29
- tools=",".join([x.name for x in tools]),
30
- query=query)
31
- messages: List[Message] = [Message(role=Role.USER, content=user_prompt)]
32
- logger.info(f"step.0 user_prompt={user_prompt}")
33
-
34
- for i in range(max_steps):
35
- if has_terminate_tool:
36
- assistant_message: Message = self.llm.chat(messages)
37
- else:
38
- assistant_message: Message = self.llm.chat(messages, tools=[x.tool_call for x in tools])
39
-
40
- messages.append(assistant_message)
41
- logger.info(f"assistant.{i}.reasoning_content={assistant_message.reasoning_content}\n"
42
- f"content={assistant_message.content}\n"
43
- f"tool.size={len(assistant_message.tool_calls)}")
44
-
45
- if has_terminate_tool:
46
- break
47
-
48
- for tool in assistant_message.tool_calls:
49
- if tool.name == "terminate":
50
- has_terminate_tool = True
51
- logger.info(f"step={i} find terminate tool, break.")
52
- break
53
-
54
- if not has_terminate_tool and not assistant_message.tool_calls:
55
- logger.warning(f"【bugfix】step={i} no tools, break.")
56
- has_terminate_tool = True
57
-
58
- for j, tool_call in enumerate(assistant_message.tool_calls):
59
- logger.info(f"submit step={i} tool_calls.name={tool_call.name} argument_dict={tool_call.argument_dict}")
60
-
61
- if tool_call.name not in tool_dict:
62
- continue
63
-
64
- self.submit_task(tool_dict[tool_call.name].__call__, **tool_call.argument_dict)
65
- time.sleep(1)
66
-
67
- if not has_terminate_tool:
68
- user_content_list = []
69
- for tool_result, tool_call in zip(self.join_task(), assistant_message.tool_calls):
70
- logger.info(f"submit step={i} tool_calls.name={tool_call.name} tool_result={tool_result}")
71
- assert isinstance(tool_result, str)
72
- user_content_list.append(f"<tool_response>\n{tool_result}\n</tool_response>")
73
- user_content_list.append(self.prompt_format(prompt_name="next_prompt"))
74
- assistant_message.tool_calls.clear()
75
- messages.append(Message(role=Role.USER, content="\n".join(user_content_list)))
76
-
77
- else:
78
- assistant_message.tool_calls.clear()
79
- messages.append(Message(role=Role.USER, content=self.prompt_format(prompt_name="final_prompt")))
80
-
81
- # Store results in context instead of response
82
- self.context.messages = messages
83
- self.context.answer = messages[-1].content