Skip to content

[AIC-py] cli rage#870

Merged
jonathanlastmileai merged 1 commit intomainfrom
pr870
Jan 12, 2024
Merged

[AIC-py] cli rage#870
jonathanlastmileai merged 1 commit intomainfrom
pr870

Conversation

@jonathanlastmileai
Copy link
Copy Markdown
Contributor

@jonathanlastmileai jonathanlastmileai commented Jan 10, 2024

[AIC-py] cli rage

This just tells the user how to open an issue. I don't want to do anything automatically
because (a) user trust, and (b) it's much harder to implement without additional bugs.

This is mostly bedside manner. If the user is raging, they are angry.
Troll them a little bit to lighten the mood first.

rage2.mov

Stack created with Sapling. Best reviewed with ReviewStack.

Comment thread python/src/aiconfig/editor/server/server.py Outdated
except Exception as e:
return core_utils.ErrWithTraceback(e)

cli_config_object = core_utils.read_text_file(state.cli_config_path).and_then(_yaml_deserialize)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool is and_then another python quirk?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, it's a Result quirk :)

https://github.com/rustedpy/result

In turn it's basically borrowed from Haskell. Some of the theory

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol fun
Screenshot 2024-01-10 at 21 33 50

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that link 404s.

Comment thread python/src/aiconfig/editor/server/server.py Outdated
Comment thread python/src/aiconfig/editor/server/server.py Outdated
Comment thread python/src/aiconfig/editor/server/server.py Outdated
Comment thread python/src/aiconfig/editor/server/server_utils.py Outdated
Comment thread python/src/aiconfig/scripts/aiconfig_cli.py
Comment thread python/src/aiconfig/scripts/aiconfig_cli.py Outdated
Comment on lines +57 to +59
for edit_config in res_edit_config
for cli_config in res_cli_config
for res_servers_ok in _run_editor_servers(edit_config, cli_config.config_path)
Copy link
Copy Markdown
Contributor

@rossdanlm rossdanlm Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do? This goes with my earlier comment about variable names not being clear and intuitive to understand

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is admittedly arcane syntax that unpacks the result of _run_editor_servers (if it's an Ok). You can think of it kind of like a Result comprehension, sort of like a list comprehension that flattens a 2d list.

Does that answer the question? What would you name differently?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See do notation in the readme: https://github.com/rustedpy/result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me take a look and read to understand, I've never seen 3 for loops list comprehension within the same inline (still not super familiar how inline tabs work in Python tbh, so it's just not clear to me what parts are nested or not)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comprehensions with more than one for are indeed confusing. I was confused about this piece of plain ordinary Python for many years:

image

Surprisingly, learning about the equivalent thing for Result, which as I mentioned is very FP and unpythonic, made me understand this Python quirk better.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh thanks, this example makes it super clear to me!


results: list[Result[str, str]] = []
backend_res = run_backend_server(edit_config)
backend_res = run_backend_server(edit_config, cli_config_path)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I really do not like using res. Can we pls use response or result so it's clear which it is?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, actually we should pick a convention that doesn't do the "maybe_..." thing that @rholinshead pointed out.

One suggestion:

backend_server_outcome = ... 
match backend_server_outcome:
    Ok(backend_server_outcome_ok)
        ... 
    Err(e)
        ... 

print("Do you know how many Zuckerbucks I should be charging for this?")
rage.spin(5)
print("I'm glad we're finally spending time together.")
rage.spin(4, type="music")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this end up repeating after we get to the end?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeating what?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhhhhh, so we're just like spending 20s trolling the people who are upset and want to rage shake? We're not actually "waiting" on anything? lmao ok uh.... hmmmmmmmm, I don't know if that's the best user experience. Either way I think we can remove if we really want to and just get this unblocked for now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Counterintuitively, I actually think this might be better UX than just doing it. I really think rage might be mostly bedside manner and a little engineering.

print("I'm glad we're finally spending time together.")
rage.spin(4, type="music")

res_rage_config = core_utils.parse_args(main_parser, argv[1:], rage.RageConfig)
Copy link
Copy Markdown
Contributor

@rossdanlm rossdanlm Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so this adds the "rage" arg to the rage.RageConfig object? https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.parse_args

How does this work? Does this mean a new field/property is created for this class (and all objects that now instantiate rage.RageConfig now possess this field)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a handy wrapper that uses argparse under the hood to return a struct directly.

It can be made a little clearer: e.g. we have to manually give argv[1:] and specify the config type twice, once inside subparser_record_types and once in parse_args().

rage.spin(4, type="music")

res_rage_config = core_utils.parse_args(main_parser, argv[1:], rage.RageConfig)
res_rage = res_rage_config.and_then(rage.rage)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we making rage.rage() a class method which requires us to create a res_rage_config instead of using a static method? Is it becuase we want to re-use state/object in case user calls multiple rages in the same session?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we want to re-use state/object

I would never do such a thing - how dare you.

it's just a module with a function. rage module has rage function.

def rage(config: RageConfig) -> Result[None, str]:

Comment thread python/src/aiconfig/scripts/rage/rage.py Outdated
logger.setLevel(config.log_level)
print("\n\n\n\n............\n\n")
print("Please open an issue! :) Here are some tips on how to do that:")
for logfile in ["editor_flask_server.log", "aiconfig.log"]:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do two logfiles? I think this could be confusing to users having to submit 2 separate logfiles + issues

Copy link
Copy Markdown
Contributor

@rossdanlm rossdanlm Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to merge logfiles together if possible

Copy link
Copy Markdown
Contributor Author

@jonathanlastmileai jonathanlastmileai Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, but that should be a follow up. This is enough to get us started

Comment on lines +29 to +45
print("\nPlease run the following commands and also include their output:")
print("\nwhich pip; which pip3; which python; which python3; pip3 list | grep aiconfig; python --version; python3 --version")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be followup diff, but think we should do this ourselves and add to one of the logfiles

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, but it's really easy for the user to just copy/paste this one-liner. I don't want to create room for new bugs during the flow for reporting bugs. It should be simple reliable and predictable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually agree now and I did a lot of this in #903

Comment thread python/src/aiconfig/scripts/rage/rage.py Outdated
Comment thread python/src/aiconfig/scripts/aiconfig_cli.py Outdated
Comment thread python/src/aiconfig/scripts/aiconfig_cli.py Outdated
Comment thread python/src/aiconfig/scripts/aiconfig_cli.py Outdated


class RageConfig(core_utils.Record):
log_level: str | int = "WARNING"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? I don't see it being used

Or is it an abstract field we need to override for core_utils.Record?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to use this in a subsequent PR. It's nice to have every subcommand have a controllable logging level.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move it to subsequent PR then until it's needed? Keeps things easier to logic together and review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want we can keep the line just commented out

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, I am using it

Comment thread python/src/aiconfig/scripts/rage/rage.py
Comment thread python/src/aiconfig/scripts/rage/rage.py
Comment thread python/src/aiconfig/scripts/rage/rage.py
This just tells the user how to open an issue. I don't want to do anything automatically
because (a) user trust, and (b) it's much harder to implement without additional bugs.

This is mostly bedside manner. If the user is raging, they are angry.
Troll them a little bit to lighten the mood first.

https://github.com/lastmile-ai/aiconfig/assets/148090348/2369306f-3af7-49f5-96bb-0ac9be323b51
spin(4, type="music")
print("Turning up the heat...")
spin(2)
print("If I had a dollar for every time I've seen this error...")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wanted to mention I love this kind of playfulness. I hope we do more of this in the future! It brings a bit of personality and a piece of ourselves in the products we build. Really nice idea @jonathanlastmileai !

Copy link
Copy Markdown
Contributor Author

@jonathanlastmileai jonathanlastmileai Jan 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Glad you like it! I felt like this was a risk. I volunteer to serve as the LastMile Secretary of Keeping it Real.

Copy link
Copy Markdown
Contributor

@rossdanlm rossdanlm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for syncing on all questions. Please add comment in code why we need to use "x" filemode to avoid potential race condition

@jonathanlastmileai
Copy link
Copy Markdown
Contributor Author

Thanks for syncing on all questions. Please add comment in code why we need to use "x" filemode to avoid potential race condition

added https://docs.google.com/document/d/1YwUlIQZX8CiuvtbVR4OvpFQ2nphFITRD_XZR3CDNtoE/edit#bookmark=id.8h0jqqaolx9z

@jonathanlastmileai jonathanlastmileai merged commit 3b91a53 into main Jan 12, 2024
@rossdanlm rossdanlm deleted the pr870 branch January 12, 2024 21:53
jonathanlastmileai added a commit that referenced this pull request Jan 15, 2024
[AIC-py] cli rage part 2: issue draft

Try to do a lot of stuff automatically. Run it and you'll see exactly
what I mean :)


`aiconfig rage`

<img width="503" alt="Screenshot 2024-01-12 at 1 33 48 PM"
src="https://github.com/lastmile-ai/aiconfig/assets/148090348/0415e458-681d-446f-b8ed-91b7a7c4bf1b">

---
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with
[ReviewStack](https://reviewstack.dev/lastmile-ai/aiconfig/pull/903).
* __->__ #903
* #870
* #869
rossdanlm pushed a commit that referenced this pull request Feb 26, 2024
Super simple for now. Tried at first to connect to Jonathan's rage functiona but that was defined in the editor package: #870

## Test Plan
rossdanlm pushed a commit that referenced this pull request Feb 26, 2024
Super simple for now. Tried at first to connect to Jonathan's rage functiona but that was defined in the editor package: #870

## Test Plan

https://github.com/lastmile-ai/aiconfig/assets/151060367/1ab905d0-dec8-4168-9a4c-995b7af0cd28
rossdanlm added a commit that referenced this pull request Feb 26, 2024
…ack (#1362)

[ez] Redirect users to our issues creation page when submitting feedback

Super simple for now. Tried at first to connect to Jonathan's rage
functiona but that was defined in the editor package:
#870

## Test Plan


https://github.com/lastmile-ai/aiconfig/assets/151060367/1ab905d0-dec8-4168-9a4c-995b7af0cd28

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with
[ReviewStack](https://reviewstack.dev/lastmile-ai/aiconfig/pull/1362).
* __->__ #1362
* #1360
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants